Thread: Problem with fgets()

  1. #1
    Registered User
    Join Date
    Nov 2013
    Posts
    11

    Problem with fgets()

    Hi everybody!!
    I have this code:
    Code:
    #include <stdio.h>#include <string.h>
    #include <stdlib.h>
    
    
    struct lesson {
    	char name[50];
    	int grade;
    };
    
    
    struct student {
    	char name[30];
    	char surname[30];
    	int AM;
    	int year;
    	int lessons_num;
    	struct lesson *lessons;
    };
    
    
     void print_data_base(struct student Students[],int n);
    
    
    int main () {
     FILE *f;
     int n,m,i,j;
     char buff[100]="";
     struct student *Students;
    
    
    
    
        f=fopen("in.txt","r");
        if (f==NULL) {printf("error reading file!!");exit(1);}
        fscanf(f,"%d",&n);
        Students = (struct student*)malloc(n*sizeof(struct student));
    
    
        for (i=0;i<n;i++) {
            fscanf(f,"%s",Students[i].name);
            fscanf(f,"%s",Students[i].surname);
            fscanf(f,"%d",&Students[i].AM);
            fscanf(f,"%d",&Students[i].year);
    
    
            printf("%d ",Students[i].AM);
            printf("%s ",Students[i].name);
            printf("%s ",Students[i].surname);
            printf("%d ",Students[i].year);
    
    
            fscanf(f,"%d",&Students[i].lessons_num);//Πλήθος μαθημάτων
            printf("lessons_num=%d\n",Students[i].lessons_num);
            Students[i].lessons = (struct lesson*)malloc(Students[i].lessons_num * sizeof(struct lesson));
    
    
            int lessons_count;
            for(lessons_count=0; lessons_count<Students[i].lessons_num; lessons_count++){
                //fscanf(f, "%[^\n]s",Students[i].lessons[lessons_count].name);
                fgets(buff,100,f);
                printf("buff=%s\n",buff);
                strcpy(Students[i].lessons[lessons_count].name, buff);
                //fscanf(f, "%s" , Students[i].lessons[lessons_count].name);
                fscanf(f,"%d",&Students[i].lessons[lessons_count].grade);
                printf("%d. lesson: %s ",lessons_count,Students[i].lessons[lessons_count].name);
                printf("grade: %d\n",Students[i].lessons[lessons_count].grade);
            }
            getchar();
        }
        fclose(f);
        printf("print data base function...\n");getchar();
        //print_data_base(Students, n);
    
    
    return 0;
    }
    void print_data_base(struct student Students[],int n){
        int i,j;
    
    
        for (i=0;i<n;i++) {
            printf("%d ",Students[i].AM);
            printf("%s ",Students[i].name);
            printf("%s ",Students[i].surname);
            printf("%d ",Students[i].year);
            printf("\n");
            for(j=0; j<Students[i].lessons_num; j++){
                printf("%s ",Students[i].lessons[j].name);
                printf("%d\n",Students[i].lessons[j].grade);
            }
        }
        printf("\n");
    }//end print_data_base
    and the attached text file as input file.
    But something is going wrong with fgets()...
    I cannont solve this problem..
    please help!!
    Attached Files Attached Files

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by Jim Iwannou
    But something is going wrong with fgets()...
    What might that "wrong" be?
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #3
    Registered User
    Join Date
    Nov 2013
    Posts
    11
    please run the program with the input file I have attached.
    fgets() is reading nothing one time and the second time reads the data....

  4. #4
    Registered User
    Join Date
    Jun 2011
    Posts
    4,513
    Insert this code immediately after your "fgets()" call:

    Code:
    if(strcmp(buff,"\n")==0)
        printf("*** newline in buffer! ***\n");
    Does this help you understand what's going on?

  5. #5
    Registered User
    Join Date
    Nov 2013
    Posts
    11
    Quote Originally Posted by Matticus View Post
    Insert this code immediately after your "fgets()" call:

    Code:
    if(strcmp(buff,"\n")==0)
        printf("*** newline in buffer! ***\n");
    Does this help you understand what's going on?
    I think that after this part of code:
    Code:
    fscanf(f,"%d",&Students[i].lessons_num);
    fscanf() didn't "get" the '\n' character, and the first time fgets is executed, I just read the newline char.
    What, in your opinion, is the best way to write this part of code?

    thanks in advance...

  6. #6
    Registered User
    Join Date
    Jun 2011
    Posts
    4,513
    Try to avoid mixing formatted data reads (fscanf) and line reads (fgets).

    There are several ways to approach this - one is to "fgets()" each line of the file, then parse that string with "sscanf()".

  7. #7
    Registered User
    Join Date
    Nov 2013
    Posts
    11
    thanks for the answer...
    I'll try it...
    But where is the problem???
    I cannot understand it!!!

  8. #8
    Registered User
    Join Date
    Jun 2011
    Posts
    4,513
    "fscanf()" ignores whitespace: fscanf()

    Whitespace character: the function will read and ignore any whitespace characters encountered before the next non-whitespace character (whitespace characters include spaces, newline and tab characters -- see isspace)...
    In your code, line 35 reads an integer from the file, but the file position indicator is now at the following newline. Your next call to "fscanf()" (line 40) ignores that newline and continues until it finds the string "nikos".

    This continues until you get to line 52. You read the integer, and the file position indicator is at the following newline. But your next read is "fgets()", which does not ignore whitespace. Instead, it reads characters until it encounters a newline (or the maximum specified buffer size is exhausted).

    Since we're at a newline in the file, "fgets()" reads this character and says "okay, I'm done". That is why it appears to "skip" the "fgets()" call the first time around.

    Understand?
    Last edited by Matticus; 02-12-2014 at 02:33 PM. Reason: corrected line number reference

  9. #9
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    The problem is where you change over from fscanf() to fgets(). fscanf() scans and saves (hopefully) the file data UP TO BUT NOT INCLUDING, the newline char. So when fgets() begins saving data, it finds the newline char, first thing, and that makes it STOP - since fgets always stops when it reaches a newline char.

    When the next fgets() is reached, there is no more newline at the file pointer position, so things work normally again.

  10. #10
    Registered User
    Join Date
    Nov 2013
    Posts
    11
    thanks men!!

  11. #11
    Registered User
    Join Date
    Nov 2013
    Posts
    11
    thanks a lot Matticus.... I'done some experiments with file indicator, and I saw these "strange" behavior of fscanf() and fgets().
    Finally I fixed the problem, running an fgetc() command after fscanf().
    But this is not a "general" solution.
    Which do you think is the best and programmatically correct way to read such files?

    thanks in advance
    Jimmy
    Last edited by Jim Iwannou; 02-13-2014 at 07:20 AM. Reason: correct spelling

  12. #12
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    Quote Originally Posted by Jim Iwannou View Post
    Which do you think is the best and programmatically correct way to read such files?

    thanks in advance
    Jimmy
    Most people use a combination of fgets and sscanf; that is, they read with fgets and then call sscanf to parse the string. Since you are only reading the file with fgets, there are no behavior-related problems.
    Last edited by whiteflags; 02-13-2014 at 07:37 AM.

  13. #13
    Registered User
    Join Date
    Jun 2011
    Posts
    4,513
    The "fgetc()" solution will work for your purposes, but keep in mind that this is merely a hack to make the program work as you need it to. If you change some things down the line, that line of code might no longer be relevent, and has the potential to upset other code you add.

    I offered a more appropriate solution in post #6.

    "fgets()" to read an entire line into a buffer, then use "sscanf()" to scan the data from that buffer. This approach is often used in lieu of using "scanf()" on the standard input - it would work equally as well from reading/parsing data from a file.

  14. #14
    Registered User
    Join Date
    Jun 2011
    Posts
    4,513
    @whiteflags - typing error in your post ("fscanf" instead of "fgets")

  15. #15
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    Quote Originally Posted by Matticus View Post
    @whiteflags - typing error in your post ("fscanf" instead of "fgets")
    Oh geez, that was dumb, thank you.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. fgets problem
    By ncode in forum C Programming
    Replies: 10
    Last Post: 03-02-2012, 10:39 PM
  2. fgets() Problem
    By kihina in forum C Programming
    Replies: 3
    Last Post: 02-08-2010, 11:03 AM
  3. Fgets problem
    By lolguy in forum C Programming
    Replies: 20
    Last Post: 01-18-2009, 11:09 AM
  4. fgets problem
    By belhifet in forum C Programming
    Replies: 14
    Last Post: 11-29-2006, 05:07 PM
  5. fgets problem
    By gambitmj in forum C Programming
    Replies: 5
    Last Post: 02-26-2002, 08:55 AM

Tags for this Thread