How to write to file using fwrite? - c++

I am new in C++ 98 .I want to write to FILE data type in C++ using netbeans 8.0. Here is my code that show that load the data in form
Here is the main.cpp
#include <QApplication>
#include <newForm.h>
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
newForm *a = new newForm();
a->show();
return app.exec();
}
#include "newForm.h"
#include <stdio.h>
#include <stdlib.h>
#include <QDebug>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#define MAX 128
int i, n = 2;
char str[50], Name[50], Class[50], Grade[50], Section[50], Number[50], Total[50], var1[50], var2[50];
FILE *fptr;
int count = 0;
newForm::newForm() {
widget.setupUi(this);
connect(widget.pushButton_1, SIGNAL(clicked()), this, SLOT(Load()));
connect(widget.pushButton_2, SIGNAL(clicked()), this, SLOT(Update()));
}
void newForm::Load() {
fptr = fopen("/root/Desktop/simple.conf", "r");
if (fptr == NULL) {
printf("Could not open file");
}
for (int i = 0; i < 10; i++) {
if (EOF == fscanf(fptr, "%s", var1)) {
break;
}
if (EOF == fscanf(fptr, "%s", var2)) {
break;
}
if (strcmp(var2, "Name") == 0) {
sprintf(Name, "%s", var1);
widget.lineEdit_1->setText(QString::fromStdString(Name));
}
if (strcmp(var2, "Class") == 0) {
sprintf(Class, "%s", var1);
widget.lineEdit_2->setText(QString::fromStdString(Class));
}
if (strcmp(var2, "Section") == 0) {
sprintf(Section, "%s", var1);
widget.lineEdit_3->setText(QString::fromStdString(Section));
}
if (strcmp(var2, "Number") == 0) {
sprintf(Number, "%s", var1);
widget.lineEdit_4->setText(QString::fromStdString(Number));
}
if (strcmp(var2, "Total") == 0) {
sprintf(Total, "%s", var1);
widget.lineEdit_5->setText(QString::fromStdString(Total));
}
}
fclose(fptr);
}
enter image description here
Here is my code for updating the form
#include <stdio.h>
#include <fstream>
#include <sstream>
#include <iomanip>
#include <iostream>
#include <bits/stdc++.h>
#include <stdio.h>
const int StrSize = 49;
typedef char textStr[StrSize + 1];
void newForm::Update(){
fptr = fopen("/root/Desktop/simple.conf","r" );
textStr str,name,section,number,class1,total,grade,var1,var2;
strcpy(name, widget.lineEdit_1->text().toLocal8Bit());
strcpy(class1, widget.lineEdit_2->text().toLocal8Bit());
strcpy(section, widget.lineEdit_3->text().toLocal8Bit());
strcpy(number, widget.lineEdit_4->text().toLocal8Bit());
strcpy(total, widget.lineEdit_5->text().toLocal8Bit());
const char * text = NULL;
for (int i = 0; i < 10; i++){
if( EOF == fscanf(fptr, "%s", var1)){
break;
}
if( EOF == fscanf(fptr, "%s", var2)){
break;
}
const char * text = NULL;
if(strcmp(var2,"Name") == 0){
fwrite(name, sizeof(name) , sizeof(name) , fptr);
}
if(strcmp(var2,"Class") == 0){
fwrite(class1, sizeof(class1) , sizeof(class1) , fptr);
}if(strcmp(var2,"Name") == 0){
fwrite(section, sizeof(section) , sizeof(section) , fptr);
}
if(strcmp(var2,"Section") == 0){
fwrite(class1, sizeof(class1) , sizeof(class1) , fptr);
}
if(strcmp(var2,"Number") == 0){
fwrite(grade, sizeof(grade) , sizeof(grade) , fptr);
}
if(strcmp(var2,"Total") == 0){
fwrite(grade, sizeof(grade) , sizeof(grade) , fptr);
}
else if((strcmp(var2, "Name") != 0) && (strcmp(var2, "Class") != 0) && (strcmp(var2, "Grade") != 0) && strcmp(var2,"Number") !=0 && strcmp(var2,"Total") != 0) {
fwrite(var1, sizeof(var1) , sizeof(var1) , fptr);
}
}
fclose(fptr);
}
It is not writing string,IP,float and int at all ? How to make it write thw this text file ?
simple.conf
AAA Name
192.168.9.33 Class
A10 Section
72.777 Number
100 Total

Your approach to updating the file is dangerous and confusing. You should update the file completely, rewriting it from scratch.
First, you need to open the file for writing instead of reading. When you issue an fopen(...,"w"); it will truncate the file to zero length for you so you don't need to care about resizing it.
Then you can just use fprintf() instead of fwrite() to deal better with text outputs, like in the example below.
Note that I have NOT compiled the example below and the actual format you presented is actually confusing so adapt to it.
#include <fstream>
#include <sstream>
#include <iomanip>
#include <iostream>
#include <cstdio>
static void writeField( FILE* f, const char* name, const char* value ) {
fprintf( f, "%s,%s\n", name, value );
}
void newForm::Update(){
const char* filename = "/root/Desktop/simple.conf";
FILE* fptr = fopen( filename,"w" );
writeField( fptr, "Name", widget.lineEdit_1->text().toLocal8Bit());
writeField( fptr, "Class", widget.lineEdit_2->text().toLocal8Bit());
writeField( fptr, "Section", widget.lineEdit_3->text().toLocal8Bit());
writeField( fptr, "Number", widget.lineEdit_4->text().toLocal8Bit());
writeField( fptr, "Total", widget.lineEdit_5->text().toLocal8Bit());
fclose(fptr);
}

Related

macOS iostream on a pseudo tty does not work

GCC has a stdio_filebuf extension that lets you wrap an iostream around a file descriptor while clang's basic_filebuf has an __open() method that lets open a file descriptor. I've tested both on regular files on both linux and macos. Works as expected.
However, for a pseudo tty file descriptor, it works for linux but not macos. I've confirmed that the file descriptor on macos does work by using read(2) on it. Here's my code.
#include <fmt/format.h>
#include <getopt.h>
#include <vector>
#include <functional>
#include <future>
#include <fcntl.h>
#include <cstdlib>
#if defined(__linux__)
#include <ext/stdio_filebuf.h>
#elif defined(__APPLE__)
#include <fstream>
#else
#error "unsupported os"
#endif
#include <iostream>
#include <unistd.h>
int get_ptym(int oflags)
{
int fd;
if ((fd = posix_openpt(oflags)) == -1
or grantpt(fd) == -1
or unlockpt(fd) == -1)
return -1;
return fd;
}
ssize_t getdelim(int fd, char *buf, size_t bufsz,
char delim='\n', bool store_delim=false)
{
size_t j = 0;
while (j < bufsz-2) {
char c;
ssize_t rc;
if ((rc = ::read(fd, &c, 1)) == -1) return rc;
if (rc == 0) break;
if (c != delim) { buf[j++] = c; continue; }
// Break if we get the delimiter.
if (store_delim) buf[j++] = c;
break;
}
buf[j] = '\0';
return j+1;
}
std::string m0(int fd)
{
#if defined(__linux__)
__gnu_cxx::stdio_filebuf<char> fb(fd, std::ios::in|std::ios::out);
std::iostream ioob(&fb);
#endif
#if defined(__APPLE__)
std::basic_filebuf<char> fb;
std::iostream ioob(fb.__open(fd, std::ios::in|std::ios::out));
#endif
std::string s;
if (!std::getline(ioob, s, '\n').good())
throw std::runtime_error("m0: getline failed");
return s;
}
std::string m1(int fd)
{
char buf[4096];
ssize_t nrd;
if ((nrd = getdelim(fd, buf, sizeof(buf))) == -1)
throw std::runtime_error("getlim error");
return std::string(buf);
}
void testing(const std::string &foonm, std::function<std::string(int)> foo)
{
using namespace std::chrono_literals;
int mfd, sfd;
// Open pty master and slave.
if ((mfd = get_ptym(O_RDWR)) == -1) return;
if ((sfd = open(ptsname(mfd), O_RDWR)) == -1) return;
#if defined(__linux__)
__gnu_cxx::stdio_filebuf<char> fb(sfd, std::ios::in|std::ios::out);
std::iostream ioob(&fb);
#endif
#if defined(__APPLE__)
std::basic_filebuf<char> fb;
std::iostream ioob(fb.__open(sfd, std::ios::in|std::ios::out));
#endif
fmt::print("testing {}\n", foonm);
std::string s;
if (!std::getline(std::cin, s, '\n').good()) {
fmt::print("{}: getline failed\n", __func__);
return;
}
auto f = std::async(std::launch::async, foo, mfd);
ioob << s << '\n';
ioob.flush();
try {
std::string fget;
std::future_status fstatus;
fstatus = f.wait_for(8s);
switch (fstatus) {
case std::future_status::timeout:
fmt::print("{}: f.wait_for(8s) timed out\n", __func__);
break;
case std::future_status::ready:
fget = f.get();
fmt::print("{}: fstatus ready, f.get={}\n", __func__, fget);
break;
default:
fmt::print("{}: fstatus default??\n", __func__);
}
}
catch (std::exception &e) {
fmt::print("{}: exception \"{}\"\n", __func__, e.what());
}
}
int main(int argc, char *argv[])
{
testing("m1", m1);
testing("m0", m0);
return 0;
}
Any ideas?

unshare user namespace, fork, map uid then execvp failing

I am trying to do the following sequence of actions:
unshare the user namespace;
Map the user in child process to root;
execvp.
However, when running id, my code outputs the user as a nobody or fails without error.
#include <sched.h>
#include <cstdio>
#include <cstring>
#include <cerrno>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/mount.h>
#include <system_error>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
void unshare_user_namespace() {
if (0 != unshare(CLONE_NEWUSER)) {
fprintf(stderr, "%s\n", "USER unshare has failed");
exit(1);
}
}
void map_id() {
int pid = getpid();
char file[100];
if (0 > sprintf(file, "/proc/%d/uid_map", pid)) {
printf("Couldn't sprintf uid_map path.");
exit(1);
}
int fd;
fd = open(file, 1);
if (fd < 0) {
printf("Coudln't open file for writing.\n");
exit(1);
}
int uid = getuid();
char * buf;
if (0 > sprintf(buf, "0 %d 1", uid)) {
printf("Couldn't sprintf uid_map content.");
exit(1);
}
if (write(fd, buf, strlen(buf))) {
printf("Coudln't write mapping into file.\n");
exit(1);
}
free(buf);
close(fd);
}
void start(char * command, char ** args) {
unshare_user_namespace();
int fork_pid = fork();
if (-1 == fork_pid) {
fprintf(stderr, "%s\n", "couldn't fork");
exit(1);
}
if (0 == fork_pid) {
map_id();
if (-1 == execvp(command, args)) {
fprintf(stderr, "%s\n", "couldn't execvp");
exit(1);
}
}
}
int main(int argc, char ** argv) {
start(argv[1], & argv[1]);
int status;
wait( & status);
return 0;
}
I tried reading the man pages for namespaces, unshare etc but couldn't figure out what's wrong with my code.
To run the code:
$ g++ <file_containing_code> && ./a.out id
Pretty sure you've already found the answer, but this is a minimal sample I could come up with:
// gcc -Wall -std=c11
#define _GNU_SOURCE
#include <stdio.h>
#include <unistd.h>
#include <sched.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <stdarg.h>
void write_to_file(const char *which, const char *format, ...) {
FILE * fu = fopen(which, "w");
va_list args;
va_start(args, format);
if (vfprintf(fu, format, args) < 0) {
perror("cannot write");
exit(1);
}
fclose(fu);
}
int main(int argc, char ** argv) {
// array of strings, terminated with NULL entry
char **cmd_and_args = (char**) calloc(argc, sizeof(char*));
for (int i = 1 ; i < argc; i++) {
cmd_and_args[i-1] = argv[i];
}
uid_t uid = getuid();
gid_t gid = getgid();
// first unshare
if (0 != unshare(CLONE_NEWUSER)) {
fprintf(stderr, "%s\n", "USER unshare has failed");
exit(1);
}
// remap uid
write_to_file("/proc/self/uid_map", "0 %d 1", uid);
// deny setgroups (see user_namespaces(7))
write_to_file("/proc/self/setgroups", "deny");
// remap gid
write_to_file("/proc/self/gid_map", "0 %d 1", gid);
// exec the command
if (execvp(cmd_and_args[0], cmd_and_args) < 0) {
perror("cannot execvp");
exit(1);
}
// unreachable
free(cmd_and_args);
return 0;
}

Using iconv translit to convert from UTF-8 to CP1251

I'am trying to convert string "aÜ" from UTF-8 to CP1251 via C++ library iconv.h using TRANSLIT and as a result I get string "a?", when expecting "aU".
When I use php script <?php echo iconv("UTF-8", "Windows-1251//TRANSLIT", "Ü");> on this computer, I get "aU" string as result.
Here's the code:
#include <cstdlib>
#include <iconv.h>
#include <locale.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
using namespace std;
int IConvert(char *buf,char *outbuf, size_t len, const char *from, const char *to)
{
iconv_t iconv_cd;
if ((iconv_cd = iconv_open(to, from)) == (iconv_t) -1) {
printf("Cannot open iconv from %s to %s\n", from, to);
return 0;
}
char *inbuf = buf;
size_t inlen = len;
size_t outlen = len;
size_t res = 0;
while (inlen > 0 && outlen > 0) {
res = iconv(iconv_cd, &inbuf, &inlen, &outbuf, &outlen);
if (res == 0)
break;
if (res == (size_t) (-1)) {
if (errno != EILSEQ && errno != EINVAL) {
iconv_close(iconv_cd);
*outbuf = '\0';
printf("Erorr %s (%s)\n", strerror(errno), from);
return 0;
} else if (inbuf < outbuf) {
iconv_close(iconv_cd);
*outbuf = '\0';
printf("Erorr %s (inbuf < outbuf)\n", strerror(errno));
return 0;
}
}
if (inlen > 0 && outlen > 0) {
*outbuf++ = *inbuf++;
inlen--;
outlen--;
}
}
iconv_close(iconv_cd);
*outbuf = '\0';
return 1;
}
int main(int argc, char** argv) {
char* line = "\u00C0a\u00DC";
char* from = (char*) malloc(strlen(from)+1);
char* to = (char*) malloc(strlen(from)+1);
strcpy(from, line);
printf("%s\n", from);
IConvert(from, to, strlen(from)+1, "UTF-8", "CP1251//TRANSLIT");
printf("%s\n", to);
return 0;
}
Any idea what problem could be?
The solution is
setlocale(LC_ALL, "");
at the beginning of your program. Yes, the locale influences the transliteration. In a German locale Ü would be transliterated to UE not U.

Unix file descriptor

Today I found very interesting behavior of file descriptors in Linux. Look at that code:
#include <dirent.h> /* Defines DT_* constants */
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <errno.h>
#define handle_error(msg) \
do { trace(msg); exit(0); } while (0)
#define trace printf
int createFile(const char* name) {
int r;
r = ::open( name, 0 );
if (r < 0)
{
trace("create file : %s\n", name);
r = ::open( name, O_CREAT, 0666 );
if (r < 0)
trace("error r < 0 %d\n",errno);
}
return r;
}
int createDir(const char* name) {
int r = ::mkdir( name, 0777 );
if (r != 0) {
trace("error r!=0\n");
}
r = open(name, 0);
if (r < 0) {
trace("error create dir r <0\n");
}
return r;
}
struct linux_dirent {
long d_ino;
off_t d_off;
unsigned short d_reclen;
char d_name[];
};
#include <sys/types.h>
#include <dirent.h>
void test123(int fd) {
int nread;
char buf[1024];
unsigned char buffer[1024];
struct linux_dirent *d;
int bpos,r;
char d_type;
if (fd == -1)
handle_error("open");
for ( ; ; ) {
nread = syscall(SYS_getdents, fd, buf, 1024);
if (nread == -1)
handle_error("getdents");
if (nread == 0)
break;
trace("--------------- nread=%d ---------------\n", nread);
trace("i-node# file type d_reclen d_off d_name\n");
for (bpos = 0; bpos < nread;) {
d = (struct linux_dirent *) (buf + bpos);
trace("%8ld ", d->d_ino);
d_type = *(buf + bpos + d->d_reclen - 1);
trace("%4d %10lld %s\n", d->d_reclen,
(long long) d->d_off, d->d_name);
bpos += d->d_reclen;
}
}
}
int main(int argc, const char * argv[]) {
int dir = createDir("test");
int file = createFile("test/file.gg");
test123(dir);
close(dir);
close(file);
return 0;
}
in that code I create folder, save its file descriptor, create file in that folder and after I want to print all files in that directory via file descriptors. However I get this output:
create file : test/file.gg
--------------- nread=32 ---------------
i-node# file type d_reclen d_off d_name
48879 16 1 .
48880 16 2 ..
There is no file.gg file in that folder. So, my question is - how it can be and how to work correctly with file descriptors? As I understand file descriptor is just an index in local for process table with all opened files and directories. But it is looks like that folder descriptor caches somehow files in that folder.
How to work correctly with descriptors in my case?
Try to do an fsync on your directory. You should open directory with O_RDONLY flags. O_WRONLY will fail. Create a file and sync may not sync metadata for this file. More informations in this article

Input from a text file to get a char C++

I am having trouble with getting input after a modifier in the text of a .txt file.
What I want to do is if the .txt file has the word "type:" then anything after that will be put into a char.
My code so far:
#include "stdafx.h"
#include <windows.h>
#include "VKH.h"
#include "Strmif.h"
#include <iostream>
#include <stdio.h>
#include <string>
#include <fstream>
void GetDocumentandRead() {
string line;
ifstream myfile (line1);
if (myfile.is_open())
{
while ( !myfile.eof() )
{
getline (myfile,line);
char aline[100];
strcpy(aline, line.c_str());
printf(aline, "\n");
if (line.compare("mouseup") == 0){
MouseUp(10);
}
if (line.compare("mousedown") == 0){
MouseDown(10);
}
if (line.compare("mouseright") == 0){
MouseRight(10);
}
if (line.compare("mouseleft") == 0){
MouseLeft(10);
}
if (line.compare("mouseclick") == 0){
MouseClick();
}
if (line.compare("enter") == 0){
Enter();
}
if (line.compare("ctrltab") == 0){
CtrlTab();
}
if (line.compare("tab") == 0){
Tab();
}
if (line.compare("altf4") == 0){
AltF4(0);
}
if (line.compare("alttab") == 0){
AltTab();
}
if (line.compare("mousecenter") == 0){
MouseCenter();
}
if (line.compare(6,5,"type:") == 0){
//Don't know what to put here...
}
}
myfile.close();
}
else printf("\nUnable to open file\n\n");
}
So after the "type:" in a text file it would type that using a function I have called TypeStr();
void TypeStr(char *lpszString)
{
char cChar;
while((cChar=*lpszString++)) // loops through chars
{
short vk=VkKeyScan(cChar); // keycode of char
if((vk>>8)&1){keybd_event(VK_LSHIFT,0,0,0);} // hold shift if necessary
keybd_event((unsigned char)vk,0,0,0); // key in
keybd_event((unsigned char)vk,0,KEYEVENTF_KEYUP,0); // key out
if((vk>>8)&1){keybd_event(VK_LSHIFT,0,KEYEVENTF_KEYUP,0);} // release shift if necessary
}
}
Any help would be appreciated. Thanks!
First you should rewrite your TypeStr function so that it takes a const char *. Like this
void TypeStr(const char *lpszString)
{
...
}
no other changes needed.
Then you should call that function from your code like this
if (line.compare(6,5,"type:") == 0){
TypeStr(line.c_str() + 11);
}
The reason that you have to change your TypeStr function to const char* (apart from it being general good style) is that the c_str() method of std::string returns a const char* not a char*.