By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
448,837 Members | 1,660 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 448,837 IT Pros & Developers. It's quick & easy.

Strange issue with fscanf and fgets

P: 52
Hey bytes community!

this one is a really strange issue I ran into and I'm hoping you all can shine some light on it for me.

This is written in C, not C++

I'm working on a program that reads in information from a txt file and outputs it sorted into another txt file.

the code to read from the file looks like this

Expand|Select|Wrap|Line Numbers
  1.     fscanf(fin, "%d", &size);
  2.     deptList = (struct dept*)(malloc(size*sizeof(struct dept)));
  3.  
  4.     for (i=0; i<size; i++) {
  5.  
  6.         fgets(line, MAXLEN, fin);
  7.         strtok(line, delims);
  8.         strcpy(deptList[i].name, line);
  9.  
  10.         p = (char*)strtok(NULL, delims);
  11.         deptList[i].numFaculty = atoi(p);
  12.  
  13.         p = (char*)strtok(NULL, delims);
  14.         deptList[i].totalSalary = atoi(p);  
  15.  
  16.         // Not used.
  17.         p = (char*)strtok(NULL, delims);
  18.  
  19.     }
  20.  
first it reads a number on the first line that lets it know how many lines are to follow. then it allocates memory and reads each line and breaks it up.

Here's the problem. When it starts reading the items into the array the first index (0) doesn't get any information and the second index (1) gets the information from the second line in the file (information that should be in the first index(0))

for the life of me I can't figure out why this isn't working, but i have a suspision that the cursor is left on the first line of the file after the fscanf() call and thus the first fgets() is reading the end of that line and not the second... but like i said... i have no idea.

Any help would be appreciated!
May 19 '08 #1
Share this Question
Share on Google+
3 Replies


gpraghuram
Expert 100+
P: 1,275
Hey bytes community!

this one is a really strange issue I ran into and I'm hoping you all can shine some light on it for me.

This is written in C, not C++

I'm working on a program that reads in information from a txt file and outputs it sorted into another txt file.

the code to read from the file looks like this

Expand|Select|Wrap|Line Numbers
  1.     fscanf(fin, "%d", &size);
  2.     deptList = (struct dept*)(malloc(size*sizeof(struct dept)));
  3.  
  4.     for (i=0; i<size; i++) {
  5.  
  6.         fgets(line, MAXLEN, fin);
  7.         strtok(line, delims);
  8.         strcpy(deptList[i].name, line);
  9.  
  10.         p = (char*)strtok(NULL, delims);
  11.         deptList[i].numFaculty = atoi(p);
  12.  
  13.         p = (char*)strtok(NULL, delims);
  14.         deptList[i].totalSalary = atoi(p);  
  15.  
  16.         // Not used.
  17.         p = (char*)strtok(NULL, delims);
  18.  
  19.     }
  20.  
first it reads a number on the first line that lets it know how many lines are to follow. then it allocates memory and reads each line and breaks it up.

Here's the problem. When it starts reading the items into the array the first index (0) doesn't get any information and the second index (1) gets the information from the second line in the file (information that should be in the first index(0))

for the life of me I can't figure out why this isn't working, but i have a suspision that the cursor is left on the first line of the file after the fscanf() call and thus the first fgets() is reading the end of that line and not the second... but like i said... i have no idea.

Any help would be appreciated!

Can you post the file which is being read by the code?

Raghuram
May 20 '08 #2

Expert 100+
P: 671
thus the first fgets() is reading the end of that line and not the second...
Good guess. Let me explain what your code actually does, because of how fscanf and fgets work.

fscanf takes input you give it, and tries to format and store it appropriately. Let's say I wanted to enter the number 5. I hit the keys, 5, and then enter. That's two characters: the character for 5, and the character that matches a newline. fscanf works on this input; it processes the '5' as the number 5. But the newline is not a number, so it's left right in the input stream.

Now fgets runs. Fgets stops reading (and storing the input) when it reaches a newline. But wait, what about the newline already in the stream? It's still there, so fgets picks that up...and then stops. Not what you wanted. You really wish that newline would not stay there.

What I really recommend you do, is avoid using the scanf family. You can always manually parse input as a number using atoi or preferrably strtol. So just use fgets/strtol to do the number input.

What's with the char* cast for strtok? Also, I don't recommend you cast malloc. Casting malloc isn't actually necessary. Furthermore, the cast cannot help you, but it may hurt. The recommended form for malloc is
Expand|Select|Wrap|Line Numbers
  1. p = malloc(n * sizeof *p)
May 20 '08 #3

P: 52
Good guess. Let me explain what your code actually does, because of how fscanf and fgets work.

fscanf takes input you give it, and tries to format and store it appropriately. Let's say I wanted to enter the number 5. I hit the keys, 5, and then enter. That's two characters: the character for 5, and the character that matches a newline. fscanf works on this input; it processes the '5' as the number 5. But the newline is not a number, so it's left right in the input stream.

Now fgets runs. Fgets stops reading (and storing the input) when it reaches a newline. But wait, what about the newline already in the stream? It's still there, so fgets picks that up...and then stops. Not what you wanted. You really wish that newline would not stay there.

What I really recommend you do, is avoid using the scanf family. You can always manually parse input as a number using atoi or preferrably strtol. So just use fgets/strtol to do the number input.

What's with the char* cast for strtok? Also, I don't recommend you cast malloc. Casting malloc isn't actually necessary. Furthermore, the cast cannot help you, but it may hurt. The recommended form for malloc is
Expand|Select|Wrap|Line Numbers
  1. p = malloc(n * sizeof *p)
YAY! I was close! thank you so much for clearing that up for me I'll test using another fgets after i post this.

Also, the casting done in the program was actually done by my professor so don't look at me :\

Thanks again!

p.s. the professor also had this same problem in his program that he showed to the class XP
May 20 '08 #4

Post your reply

Sign in to post your reply or Sign up for a free account.