fscanf() skips the first line in text file [C]

I have a text file that contains simple account information like this:

1234567890
234567
345678.90

First line is a 10-digit account number. Second line is the 6-digit account PIN (it's a simple program, so no encryption needed yet, whatsoever), and the last is the account balance. Now, when I try to read the text file, it skips the first line (account number), only the PIN and the balance are printed out.

Also, I read in some articles that fscanf() returns a number "every time it reads a line in a document" (correct me if I'm wrong). So, for example:

fscanf(fp, "%s\n%s\n%ld", account, pin, balance);

If it reads the sample lines in the text file above, it would return 1, right (because it read 1 line that matched the format in the fscanf())? And will return a -1 once the EOF is reached, right?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
void loadAccount(){
	char account[10];
	char pin[10];
	float balance;
	
	FILE *fp
	
	fp = fopen("/acctinfo.txt", "r+");
	
	if (fp != NULL) {
		while(fscanf(fp, "%s", account) != -1){
			fscanf(fp, "%s\n%s\n%f", account, pin, balance);
			
			printf("%s\n", account);
			printf("%s\n", pin);
			printf("%f\n", balance);
		}
	} else {
		printf("Account info not found.");
	}

	fclose(fp);	
	getch();	
}


EDIT:

I think the problem is with my while() condition. I removed it (turned into a comment) and was able to retrieve the right information from the text, with the exception of the balance. Here was the output:

1234567890
234567
345678.906250

Not sure where the .006250 came from.

EDIT 2:

I changed the while condition back to !feof(fp) and I was able to fetch the right content from the text file. But. I'd really want to implement this without using !feof() because, as said by many people from the forums here, it's wrong to use !feof()...
Last edited on
From the C Standard

The fscanf function returns the value of the macro EOF if an input failure occurs
before the first conversion (if any) has completed. Otherwise, the function returns the number of input items assigned, which can be fewer than provided for, or even zero, in the event of an early matching failure.


As for your code then you are trying to read account twice. The first one is in the while condition and the second one in the next statement.

1
2
		while(fscanf(fp, "%s", account) != -1){
			fscanf(fp, "%s\n%s\n%f", account, pin, balance);
Last edited on
I see, so that's why it "skipped" the first line. So, is it better for me to just use !feof in this case?
You can use feof. But in any case I think you should assign initial values for the elements that in case of EOF they would have some defined values.
By that, you mean initialize the variables yes? Okay, will do that. Then just one more question. When I try to run the following code,

1
2
3
4
5
6
7
8
9
10
void loadAccount(){
	...
	float balance = 0;
	...	
	if (fp != NULL) {
		while(!feof(fp)){
			fscanf(fp, "%s\n%s\n%f\n", &account, &pin, &balance);
			printf("%f\n", balance);
...
}


If for example, the balance variable should contain 345678.90, instead of printing the right value out, it always prints out 345678.906250. I don't understand why there is an additional .006250 in the value of the balance variable.
Last edited on
The problem is that float types are unable to represent exactly the fraction part.
Never use
while(!feof(fp)){
, that's almost always an error.

Never use naked %s, you're begging to get hacked. Always specify the length of the buffer you're writing to. In fact, your example already involves overflow: the array "account" can hold only a 9 character C-string, while the string "1234567890" has ten.

Also, the \n's are redundant (both %f and %s skip leading whitespace)

Your initial approach (checking the result of fscanf) was much better, you just didn't check the result of the right scanf:

1
2
3
4
char account[11]; // enough to hold ten characters!
...
while( fscanf(fp, "%10s%9s%f", account, pin, &balance) == 3)
                printf("%s\n%s\n%f\n", account, pin, balance);
Last edited on
@Cubbi: Sorry, since I'm a beginner at this, do you mind explaining what this line means?

 
"%10s%9s%f"


And how come only the balance has the & sigil in it? I tried adding & to account, pin and balance and the program /didn't/ run (or rather, it ended prematurely or something -- bottom line, didn't work).

@vlad from moscow: http://www.cplusplus.com/forum/beginner/107452/#msg582896

I don't know what you mean by this. Before, I would naturally be able to working with floating type points with ease. This is the first time I've encountered something this odd. Now, I tried getting the string counterpart instead, but when I try to use atof(), it either gives me a +NAN or some other random value.
Last edited on
The compiler is unable to represent the fraction of number 345678.90 that is 90 exactly in memory. It can it do approximately.
If you will use for example function atof you will get the same result.

1
2
3
4
char s[] = "345678.90";
float x = atof( s );

printf( "%f", x );


As for your first question then this format specifier %10s points out that the function shall enter only 10 characters. All other characters will be ignored.
do you mind explaining what this line means?
"%10s%9s%f"

That line instructs fscanf to
1. read from file and ignore zero or more spaces, tabs, or newlines (whitespace)
2. read from file no more than 10 non-whitespace characters and store them in the array whose first element is pointed to the next argument to fscanf() (account in that case). Write a terminating zero to the array to make it a C string
3. same as 1
4. same as 2, but only 9 non-whitespace characters and the next argument is used (pin in this case)
5. same as 1
6. read from file the characters that form one of the recognized formats for floating-point numbers and store it in the float pointed to by the next argument

Read up on C I/O functions. They are complicated, you need to know exactly what each character means and does before running the program.

how come only the balance has the & sigil in it?

the %f specifier expects a pointer to a float. The address-of operator constructs one from the float object.

Read up on C operators.
Topic archived. No new replies allowed.