Can't write int to file using fwrite - c

I'm trying to format my keylog output so it shows time:
t = time(0);
now = localtime(&t);
if(now->tm_min != prevM && now->tm_hour != prevH)
{
prevM = now->tm_min;
prevH = now->tm_hour;
fwrite("[", 1, sizeof(WCHAR), keylog);
fwrite(&prevH, 1, sizeof(int), keylog);
fwrite("]", 1, sizeof(WCHAR), keylog);
fwrite(" ", 1, sizeof(WCHAR), keylog);
fflush(keylog);
}
but instead of readable number I get "[ DLE NUL ] " written in my file, where DLENUL is question mark.
How do I make it to write a readable number?

Use fprintf as others are also suggesting.
Reason:
fwrite is generally used to write in binary files to write blocks of same type of data.
The data you are writing looks like a character string, you can use fprintf with following syntax to write your complete data in the file.
fprintf(keylog, "[%d] ", prevH);
It seems you are writing wide characters (as you use wchar). You can use different format specifiers accordingly.

Instead of
fwrite(&prevH, 1, sizeof(int), keylog);
try
fprintf(keylog, "%d", prevH);

With fwrite you are storing the binary representation. If you want to store a textual representation you can use fprintf.

As others have already suggested, you could use fprintf when writing text to a file.
More specifically, when writing WCHARs you can use either:
fwprintf(file, L"%c\n",outputChar);
or:
fprintf(file, "%lc", outputChar);
For more information, have a look at the documentation of the function:
http://www.cplusplus.com/reference/cwchar/fwprintf/

Related

Expand integer macro inside quoted string

While contributing to exim, I saw many values where hard-coded :
uschar filebuffer[256];
(void)sprintf(CS filebuffer, "%.256s.db", filename);
rc = lf_check_file(-1, filebuffer, S_IFREG, modemask, owners, owngroups,
"dbm", errmsg);
if (rc < 0) /* stat() failed */
{
(void)sprintf(CS filebuffer, "%.256s.dir", filename);
rc = lf_check_file(-1, filebuffer, S_IFREG, modemask, owners, owngroups,
"dbm", errmsg);
if (rc == 0) /* x.dir was OK */
{
(void)sprintf(CS filebuffer, "%.256s.pag", filename);
rc = lf_check_file(-1, filebuffer, S_IFREG, modemask, owners, owngroups,
"dbm", errmsg);
}
}
}
As the code isn’t windows specific, every256values should be converted toPATH_MAX.
I know that expanding macros inside quoted strings isn’t possible, but that string concatenation is trivial :
#define STR "string"
size_t len=strlen("part"STR"part 2");
However, things like :
"%."PATH_MAX".db"
Shouldn’t work becausePATH_MAXexpands to an integer, not a string.
So is there a way to do this without calling a function that convert integers to C strings ?
The right way to do this is to use a * in your format string, which will cause it to take the value from your argument list. For example:
printf("%.*s\n", 3, "abcde");
This is equivalent to:
printf("%.3s\n", "abcde");
That way you can use PATH_MAX or any other value to control the format without having to worry about how they're defined (e.g., whether they contain parentheses or addition operators, etc.)
You can stringify a macro argument by using the # operator. But you need an indirect macro invocation to expand the argument:
#define Q(x) Q_(x)
#define Q_(x) #x
So you could do something like:
char filebuffer[PATH_MAX + 10];
sprintf(filebuffer, "%." Q(PATH_MAX)"s.db", filename);
The existing code limits the string sibstitution to 256 characters but then adds a file extension (and a NUL terminator) which will be a buffer overflow when the length is close to 256. I used an arbitrary 10-byte overallocation above, but it would be better to use a checked-length sprintf like snprintf. That would have the additional advantage of not requiring macro games.

fscanf won't read the integer values in text file

I am using an fscanf to read a sequence of 8 values of zero or one at the end of the line, but it looks like the array is never having a value read to it.
It is reading this from the text file:
Chilli Con Carne,Chilli_Con_Carne.txt, 15, 25, 100,0,0,0,0,0,0,0,0
Spaghetti Bolognese,Spaghetti_Bolognese.txt, 30, 75, 150, 0, 0, 0, 0, 0, 0, 1, 0
Frittata,Frittata.txt, 10, 15, 160, 1, 1, 0, 0, 0, 0, 0, 0
Korean Beef,Korean_Beef.txt, 20, 30, 100, 0, 0, 0, 0, 0, 1, 0, 1
Trawlers Pie, Trawlers_Pie.txt, 20, 30, 100,1,1,0,1,0,0,0,0
This is the loop I am using which contains the fscanf that is not reading the recipeAllergies:
while (!feof (cookBook)){
fscanf(cookBook, "%20[^,], %20[^,], %d, %d, %d", recipeName, recipeFileName, &prepTime, &cookTime, &calories);
printf("%s ", recipeName);
for (i = 0; i < 8; i++){
fscanf(cookBook, "%d,", &recipeAllergies[i]);
printf("%d %d\n", recipeAllergies[i], userAllergies[i]);
if ((userAllergies[i] + recipeAllergies[i]) == 2){
notSuitable = 1;
}
}
fgets(ignore_line, sizeof(ignore_line), cookBook);
if (notSuitable == 0){
(suitableRecipes[totalSuitable]. recipeName, recipeFileName, prepTime, cookTime, calories);
totalSuitable++;
}
}
Any help is greatly appreciated.
The inner loop has a format string "%d," so fscanf() is looking for integers followed by a comma. There is no comma on the end of the input lines, so scanf() will return indicating an error.
Either add commas at the end of the input lines, or change the loop so it doesn't look for a comma the 8th time. The latter is preferable.
Although you didn't ask, a few other concerns you might want to address with your code......
Looping on feof() is a really bad idea, because (among other problems) if no error is detected in the loop body, it will attempt to read one more
line of input from your file than exists.
Always check the return value of functions like fscanf() and fprintf(), since they can fail.
Mixing fgets() with fscanf() on the same file is a bad idea, because
they respond to file contents differently (e.g. in how they respond
to a newline) and using them in combination can result in spurious
loss of data. [More generally, the same goes for mixing styles of
input. Don't mix manners of input for the same file.
Mixing character oriented input (e.g. fgetc()), line oriented input
(e.g. fgets()), and/or formatted input (e.g. fscanf()) can all cause spurious problems if they are used on the same stream.]
The first statement in the if (notSuitable == 0) block doesn't do
anything. I assume you left out the name of the function to be
called.
First, process comma after calorie while using fgetc. After that, read each number.
You are also expecting comma from last digit where as this might not be the case.
Alternatively, you can discard each comma separately by using fgetc.
You can try following code snippets in your for loop.
for (i = 0; i < 8; i++){
fgetc(cookBook); //To discard/read comma
fscanf(cookBook, "%d", &recipeAllergies[i]);
printf("%d %d\n", recipeAllergies[i], userAllergies[i]);
if ((userAllergies[i] + recipeAllergies[i]) == 2){
notSuitable = 1;
}
}
Also see the link mentioned in question's comment. Why is “while ( !feof (file) )” always wrong?

Strangeness in reading a binary file in C

I've defined a binary file like this in C
FILE *gfp;
gfp = fopen(gridfiles, "wb");
The variable gridfiles stores the name of the file, and has been defined earlier. Now I write out two variables into the file.
for(yy = 0; yy < nfiley; yy++) {
for(xx = 0; xx < nfilex; xx++) {
filebx = beguv + xx*1E3;
fileby = enduv - yy*1E3;
fwrite(&filebx, sizeof(filebx), 1, gfp);
fwrite(&fileby, sizeof(fileby), 1, gfp);
}
}
If right after this code I
fseek(gfp, 0, SEEK_SET);
fread(&filebx, sizeof(filebx), 1, gfp);
fread(&fileby, sizeof(fileby), 1, gfp);
fprintf(stderr, "%f %f", filebx, fileby);
my output is
1000 15000
for the first two, which is as expected.
But if after some assorted other code (that doesn't involve these files at all) I repeat the fseek() etc., my output is
14000 14000
regardless of what I do.
I've been trying to figure this out for a while now... anyone know what I'm doing wrong?
It's Undefined Behaviour to read from a stream which has been opened in write mode. You should make it:
gfp = fopen(gridfiles, "wb+");
if you plan to both read and write.
Also, as pointed out by #Kyle Jones in the comments above, you should get into the habit of checking the return status of fread/fwrite when doing file I/O - this would have caught your problem a lot earlier.

C - Read in file according to a format

I am trying to read a file in a specific file format in c.
the file contains some data items. every data item is seprated by a flag.
the file should look look like this:
file-header: "FIL0"
file-id: 0x1020304
flag : 0|1 : uint8_t
length : uint32_t
char[length] : int utf-8
so its: [File-Header] [FileID] [Flag | Length | Data ] [Flag | Length | Data] ...
--> "FIL0" | 0xFFFFFF | 0 or 1 | Data as char[] | 0 or 1 | ... (next data item) ....
My Problem occurs when reading in the file. My idea is to open the file and scan through it using some sscanf-magic.
FILE *fp;
fp = fopen("data.dat". "r");
/* scan file for data components */
while (fgets(buffer, sizeof buffer, fp) != NULL) /* read in file */
{
/* scan for sequence */
if (sscanf(buffer, "%5s", fil0_header) == 1) /* if the "FIL0" header is found */
{
printf("FIL0-header found: %s\n", buffer);
// proceed and scan for [FLAG] [LENGTH] [DATA]
// sscanf()
if (sscanf(buffer, "%u", node) == 1)
{
// doesnt seem to work
}
// read in length of string and extract stringdata
else
{
printf("FIL0-Header not found, found instead: %s\n", buffer);
// do something
}
}
My problem that I have a hard time with my buffer and the varying data types in the file.
The comparision of fil0-header works alright, but:
how to read in the next hexadeciaml number (sscanf using %D)
how scan for the flag which is 1 byte
how to extract the length which is 4 bytes
A problem is, that the check for the flag starts at the beginning of the buffer.
but the pointer should be moved on, after the FIL0-header is found.
I'd be gratefull for any help!
Please help me to find the proper sscanf() -calls:
and want to read it in and retrieve the single parts of my file:
On single [File-Header]
and many {[FileID] [Flag | Length | Data ]} {...} items
well you could just read the file per byte using
line[0] = (char) fgetc(fp);
line[1] = (char) fgetc(fp);
and so on or leave out the cast to retrieve an int-value... should do the trick to do an easy right to left scan of the file (or line - as you say there arent any line breaks)...
You probably could use some standard parsing techniques, for instance have a lexer and a recursive parser. You should define your input syntax more in details. You could perhaps use parser generators (but it might be overkill for your simple example) like ANTLR ...
I suggest you to read some good textbook on parsing (& compiling), it will learn you a lot of useful stuff.

How to parse an xml file line by line with C libexpat on Linux?

I am looking for how to parse an XML file via a C libexpat and Linux. I'm looking for the parse does not load the entire file contents in memory, I want the parse is done by reading the xml document line by line.
Is there anyone I can propose a method using expat?
Thank you in advance for your help
XML_Parse just does that. See the sample code below:
actual_size = fread(xmlData, 1, 32, fp);
while (actual_size > 0) {
if (XML_Parse(parser, xmlData, actual_size, 0) == XML_STATUS_ERROR) {
printf("%s at line %l\n",
XML_ErrorString(XML_GetErrorCode(parser)),
(long) XML_GetCurrentLineNumber(parser));
return 1;
}
actual_size = fread(xmlData, 1, 32, fp);
}

Resources