fscanf won't read the integer values in text file - c

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?

Related

Skipping strings between separator with sscanf()

I've got a couple of strings structed like this:
1|36901|O|173665.47|1996-01-02|5-LOW|Clerk#000000951|0|nstructions sleep furiously among |
I want to extract the fields in position 0, 1, 3, 7, in this case 1, 36901, 173665.47 and 0.
I've tried
sscanf(line, "%d|%d|%*c|%lf|%*s|%*s|%*s|%d|%*s|", &rec.order_key, &rec.cust_key, &rec.total_price, &rec.ship_priority);
printf("%d %d %lf %d", rec.order_key, rec.cust_key, rec.total_price, rec.ship_priority);
and expecting to get
1 36901 173665.470000 0
instead I got
1 36901 173665.470000 1
so I guess I did something wrong with the skipping, but I just can't figure it out.
I figure this out: the sscanf() does greedy matching, so the string being skipped is too long. Using
sscanf(line, "%d|%d|%*c|%lf|%*[^|]|%*[^|]|%*[^|]|%d|%*[^|]|",
&rec.order_key, &rec.cust_key, &rec.total_price, &rec.ship_priority);
solved the problem.

fgetc not starting at beginning of file - c [duplicate]

This question already has an answer here:
fgetc not starting at beginning of large txt file
(1 answer)
Closed 9 years ago.
Problem solved here:
fgetc not starting at beginning of large txt file
I am working in c and fgetc isn't getting chars from the beginning of the file. It seems to be starting somewhere randomly within the file after a \n. The goal of this function is to modify the array productsPrinted. If "More Data Needed" or "Hidden non listed" is encountered, the position in the array, productsPrinted[newLineCount], will be changed to 0. Any help is appreciated.
Update: It works on smaller files, but doesn't start at the beginning of the larger,617kb, file.
function calls up to category:
findNoPics(image, productsPrinted);
findVisible(visible, productsPrinted);
removeCategories(category, productsPrinted);
example input from fgetc():
Category\n
Diagnostic & Testing /Scan Tools\n
Diagnostic & Testing /Scan Tools\n
Hidden non listed\n
Diagnostic & Testing /Scan Tools\n
Diagnostic & Testing /Scan Tools\n
Hand Tools/Open Stock\n
Hand Tools/Sockets and Drive Sets\n
More Data Needed\n
Hand Tools/Open Stock\n
Hand Tools/Open Stock\n
Hand Tools/Open Stock\n
Shop Supplies & Equip/Tool Storage\n
Hidden non listed\n
Shop Supplies & Equip/Heaters\n
Code:
void removeCategories(FILE *category, int *prodPrinted){
char more[17] = { '\0' }, hidden[18] = { '\0' };
int newLineCount = 0, i, ch = 'a', fix = 0;
while ((ch = fgetc(category)) != EOF){ //if fgetc is outside while, it works//
more[15] = hidden[16] = ch;
printf("%c", ch);
/*shift char in each list <- one*/
for (i = 0; i < 17; i++){
if (i < 17){
hidden[i] = hidden[i + 1];
}
if (i < 16){
more[i] = more[i + 1];
}
}
if (strcmp(more, "More Data Needed") == 0 || strcmp(hidden, "Hidden non listed") == 0){
prodPrinted[newLineCount] = 0;
/*printf("%c", more[0]);*/
}
if (ch == '\n'){
newLineCount++;
}
}
}
Let computers do the counting. You have not null terminated your strings properly. The fixed strings (mdn and hdl are initialized but do not have null terminators, so string comparisons using them are undefined.
Given this sample data:
Example 1
More Data Needed
Hidden non listed
Example 2
Keeping lines short.
But as they get longer, the overwrite is worse...or is it?
Hidden More Data Needed in a longer line.
Lines containing "Hidden non listed" are zapped.
Example 3
This version of the program:
#include <stdio.h>
#include <string.h>
static
void removeCategories(FILE *category, int *prodPrinted)
{
char more[17] = { '0' };
char hidden[18] = { '0' };
char mdn[17] = { "More Data Needed" };
char hnl[18] = { "Hidden non listed" };
int newLineCount = 0, i, ch = '\0';
do
{
/*shift char in each list <- one*/
for (i = 0; i < 18; i++)
{
if (i < 17)
hidden[i] = hidden[i + 1];
if (i < 16)
more[i] = more[i + 1];
}
more[15] = hidden[16] = ch = fgetc(category);
if (ch == EOF)
break;
printf("%c", ch); /*testing here, starts rndmly in file*/
//printf("<<%c>> ", ch); /*testing here, starts rndmly in file*/
//printf("more <<%s>> hidden <<%s>>\n", more, hidden);
if (strcmp(more, mdn) == 0 || strcmp(hidden, hnl) == 0)
{
prodPrinted[newLineCount] = 0;
}
if (ch == '\n')
{
newLineCount++;
}
} while (ch != EOF);
}
int main(void)
{
int prod[10];
for (int i = 0; i < 10; i++)
prod[i] = 37;
removeCategories(stdin, prod);
for (int i = 0; i < 10; i++)
printf("%d: %d\n", i, prod[i]);
return 0;
}
produces this output:
Example 1
More Data Needed
Hidden non listed
Example 2
Keeping lines short.
But as they get longer, the overwrite is worse...or is it?
Hidden More Data Needed in a longer line.
Lines containing "Hidden non listed" are zapped.
Example 3
0: 37
1: 0
2: 0
3: 37
4: 37
5: 37
6: 0
7: 0
8: 37
9: 37
You may check which mode you opened the file, and you may have some error-check to make sure you have got the right return value.
Here you can refer to man fopen to get which mode to cause the stream position.
The fopen() function opens the file whose name is the string pointed to
by path and associates a stream with it.
The argument mode points to a string beginning with one of the follow‐
ing sequences (Additional characters may follow these sequences.):
r Open text file for reading. The stream is positioned at the
beginning of the file.
r+ Open for reading and writing. The stream is positioned at the
beginning of the file.
w Truncate file to zero length or create text file for writing.
The stream is positioned at the beginning of the file.
w+ Open for reading and writing. The file is created if it does
not exist, otherwise it is truncated. The stream is positioned
at the beginning of the file.
a Open for appending (writing at end of file). The file is cre‐
ated if it does not exist. The stream is positioned at the end
of the file.
a+ Open for reading and appending (writing at end of file). The
file is created if it does not exist. The initial file position
for reading is at the beginning of the file, but output is
always appended to the end of the file.
And there is another notice, that the file you operated should not more than 2G, or there maybe problem.
And you can use fseek to set the file position indicator.
And you can use debugger to watch these variables to see why there are random value. I think debug is efficient than trace output.
Maybe you can try rewinding the file pointer at the beginning of your function.
rewind(category);
Most likely another function is reading from the same file. If this solves your problem, it would be better to find which other function (or previous call to this function) is reading from the same file and make sure rewinding the pointer won't break something else.
EDIT:
And just to be sure, maybe you could change the double assignment to two different statements. Based on this post, your problem might as well be caused by a compiler optimization of that line. I haven't checked with the standard, but according to best answer the behavior in c and c++ might be undefined, therefore your strange results. Good luck

Can't write int to file using fwrite

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/

Reading from binary file is unsuccessful in C

I am using C programming language and am trying to read the first string of every line in a binary File .
Example of data in the binary file (I have written to a txt file in order to show you)
Iliya Iliya Vaitzman 16.00 israel 1 0 1
I want to read to first Iliya in the line (or what ever the first word in the line will be).
I am trying the following code but it keeps returning NULL to the string variable I gave him
The following code:
FILE* ptrMyFile;
char usernameRecieved[31];
boolean isExist = FALSE;
ptrMyFile = fopen(USERS_CRED_FILENAME, "a+b");
if (ptrMyFile)
{
while (!feof(ptrMyFile) && !isExist)
{
fread(usernameRecieved, 1, 1, ptrMyFile);
if (!strcmp(userName, usernameRecieved))
{
isExist = TRUE;
}
}
}
else
{
printf("An error has encountered, Please try again\n");
}
return isExist;
I used typedef and #define to a boolean variable (0 is false, everything else is true (TRUE is true, FALSE is false))
usernameRecieved keeps getting NULL from the fread .
What should I do in order to solve this?
Instead of this:
fread(usernameRecieved, 1, 1, ptrMyFile);
try this:
memset(usernameRecieved, 0, sizeof(usernameRecieved));
fread(usernameRecieved, sizeof(usernameRecieved)-1, 1, ptrMyFile);
As it is, you are reading at most only one byte from the file.
Documentation on fread
A couple things: you're setting the count field in fread to 1, so you'll only ever read 1 byte, at most (assuming you don't hit an EOF or other terminal marker).
It's likely that what you want is:
fread(usernameRecieved, 1, 31, ptrMyFile);
That way you'll copy into your whole char buffer. You'll then want to compare only up to whatever delimiter you're using (space, period, etc).
It's not clear what "usernameRecieved keeps getting NULL" means; usernameRecieved is on the stack (you aren't using malloc). Do you mean that nothing is being read? I highly suggest that you always check the return value from fread to see how much is read; this is helpful in debugging.

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.

Resources