Thread: Can someone please help me with reading strings in structures please?

  1. #1
    Registered User
    Join Date
    Oct 2011
    Location
    Ottawa
    Posts
    17

    Can someone please help me with reading strings in structures please?

    Hey there,
    In this component of a program I'm working on, the first four commands in my else statement are sticking together without letting me input the information I'm asking for. I had the same problem yesterday, but only the first two were sticking together. Then suddenly I open it this morning and now FOUR are stuck.
    Any suggestions would be Fantastic thanks!
    Cheers

    Code:
    char AddStudent()
    {
        FILE *fptr;
    
    
        struct Students
        {
            char FirstName[SIZE];
            char LastName[SIZE];
            char StudentNumber[8];
            char Assignments[5][4];
            char Labs[5][4];
            char Midterm[4];
            char Final[4];
        };
    
    
        struct Students GNG1106[200];
    
    
        fptr=fopen("E://StudentFile.txt", "a+");
    
    
        if (fptr == NULL)
            printf("Unable to open file");
    
    
        else
        {
            printf("File was opened\n");
    
    
            printf("Please enter the first name of the student: ");
            fgets(GNG1106[0].FirstName, SIZE, fptr);
    
    
            printf("\nPlease enter the last name of the student: ");
            fgets(GNG1106[0].LastName, SIZE, fptr);
    
    
            printf("\nPlease the student's student number: ");
            fgets(GNG1106[0].StudentNumber, 8, stdin);
    
    
            printf("\nPlease enter the grade out of 100 for the first assignment: ");
            fgets(GNG1106[0].Assignments[0], 4, stdin);
    
    
            printf("\nPlease enter the grade out of 100 for the second assignment: ");
            fgets(GNG1106[0].Assignments[1], 4, stdin);
    
    
            printf("\nPlease enter the grade out of 100 for the third assignment: ");
            fgets(GNG1106[0].Assignments[2], 4, stdin);
    
    
            printf("\nPlease enter the grade out of 100 for the fourth assignment: ");
            fgets(GNG1106[0].Assignments[3], 4, stdin);
    
    
            printf("\nPlease enter the grade out of 100 for the fifth assignment: ");
            fgets(GNG1106[0].Assignments[4], 4, stdin);
    
    
            printf("\nPlease enter the grade out of 100 for the first lab: ");
            fgets(GNG1106[0].Labs[0], 4, stdin);
    
    
            printf("\nPlease enter the grade out of 100 for the second lab: ");
            fgets(GNG1106[0].Labs[1], 4, stdin);
    
    
            printf("\nPlease enter the grade out of 100 for the the third lab: ");
            fgets(GNG1106[0].Labs[2], 4, stdin);
    
    
            printf("\nPlease enter the grade out of 100 for the fourth lab: ");
            fgets(GNG1106[0].Labs[3], 4, stdin);
    
    
            printf("\nPlease enter the grade out of 100 for the fifth lab: ");
            fgets(GNG1106[0].Labs[4], 4, stdin);
    
    
            printf("\nPlease enter the grade out of 100 for the midterm exam: ");
            fgets(GNG1106[0].Midterm, 4, stdin);
    
    
            printf("\nPlease enter the grade out of 100 for the final exam: ");
            fgets(GNG1106[0].Final, 4, stdin);
    
    
    
    
            fprintf(fptr, "%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s", GNG1106[0].FirstName, GNG1106[0].LastName, GNG1106[0].StudentNumber, GNG1106[0].Assignments[0], GNG1106[0].Assignments[1], GNG1106[0].Assignments[2], GNG1106[0].Assignments[3], GNG1106[0].Assignments[4],
                    GNG1106[0].Labs[0], GNG1106[0].Labs[1], GNG1106[0].Labs[2], GNG1106[0].Labs[3], GNG1106[0].Labs[4], GNG1106[0].Midterm, GNG1106[0].Final);
    
    
        }
    
    
        fclose(fptr);
    }

  2. #2
    Registered User
    Join Date
    Oct 2011
    Location
    Ottawa
    Posts
    17
    sorry, quick-fix. In lines 34 and 38 I changed fptr to stdin. However, those first two commands are still sticking together and not allowing me to input the First Name.
    Any suggestions?

  3. #3
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    So what do you actually type in (for example).

    > char Final[4];
    ...
    > fgets(GNG1106[0].Final, 4, stdin);
    Bear in mind that fgets() will also try to store a \n as well.
    So if you type in "100\n", it will try and store "100\n\0" in 4 characters (in other words, no).

    You'll get "100\0" alright, but the \n will be left for the next fgets() to deal with (which it will - without reading anything else).

    Do this for each step
    Code:
    char buff[BUFSIZ]
    fgets( buff, BUFSIZ, stdin );
    // strip the newline (if you want to - see the FAQ for how to do it)
    // validate and assign.
    For example, validation is making sure no more than 3 characters are typed in, representing an integer in the range 0 to 100.
    So you would reject input like "123455566" or "barney rubble" or any other nonsense.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  4. #4
    Registered User
    Join Date
    Oct 2011
    Location
    Ottawa
    Posts
    17
    Thanks! I'll give this a try

  5. #5
    Registered User
    Join Date
    Oct 2011
    Location
    Ottawa
    Posts
    17
    Unfortunately this didn't really solve the problem.
    The main issue is that line
    Code:
    printf("Please enter the first name of the student: ");
    fgets(GNG1106[0].FirstName, SIZE, stdin);
    doesn't seem to be happening at all. It skips straight to the next command. I don't understand this problem because it is written just like all my other fgets commands.

    Code:
    char AddStudent() { FILE *fptr; struct Students { char FirstName[SIZE]; char LastName[SIZE]; char StudentNumber[8]; char Assignments[5][4]; char Labs[5][4]; char Midterm[4]; char Final[4]; }; struct Students GNG1106[200]; fptr=fopen("E://StudentFile.txt", "a+"); if (fptr == NULL) printf("Unable to open file"); else { printf("File was opened\n"); printf("Please enter the first name of the student: "); fgets(GNG1106[0].FirstName, SIZE, stdin); printf("\nPlease enter the last name of the student: "); fgets(GNG1106[0].LastName, SIZE, stdin); printf("\nPlease the student's student number: "); fgets(GNG1106[0].StudentNumber, 8, stdin); } }

    Do you see what I mean?
    Last edited by daynorb; 11-27-2011 at 11:43 AM.

  6. #6
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    You're still trying to read directly from the file (or stdin) into where you want to store the data, WITHOUT first going through any kind of validation.

    If there is more data than you expect - even a single character, then your code is broken.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  7. #7
    Registered User
    Join Date
    Oct 2011
    Location
    Ottawa
    Posts
    17
    Do you mean something like this?

    Code:
    char AddStudent()
    {
        FILE *fptr;
    
    
        struct Students
        {
            char FirstName[SIZE];
            char LastName[SIZE];
            char StudentNumber[8];
            char Assignments[5][4];
            char Labs[5][4];
            char Midterm[4];
            char Final[4];
        };
    
    
        struct Students GNG1106[200];
    
    
        fptr=fopen("E://StudentFile.txt", "a");
    
    
        if (fptr == NULL)
            printf("Unable to open file");
    
    
        else
        {
            printf("File was opened\n");
    
    
            fputs("\nPlease enter the first name of the student: ", stdout);
            fflush(stdout);
            if (fgets(GNG1106[0].FirstName, 30, stdin) != NULL)
            {
                char *newline = strchr(GNG1106[0].FirstName, '\n');
                if ( newline != NULL )
                {
                    *newline = '\0';
                    printf("\nNewline removed");
                }
            }
    
    
            fputs("\nPlease enter the last name of the student: ", stdout);
            fflush(stdout);
            if (fgets(GNG1106[0].LastName, 30, stdin) != NULL)
            {
                char *newline = strchr(GNG1106[0].LastName, '\n');
                if ( newline != NULL )
                {
                    *newline = '\0';
                    printf("\nNewline removed");
                }
            }
    }
    This straightened things up in my file, but I still have the issue of not having the opportunity to input a value for the First Name

  8. #8
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    My guess is that you have a newline char, already in your input stream. So when you come to the first fgets(), (which takes any input UP TO THE FIRST NEWLINE CHAR), it receives the newline and says "OK, I'm outta here!".

    Add a getchar() before the first fgets(), and see if that doesn't stop this nonsense.

  9. #9
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    Well it still has the same problem as it's always had - you're reading directly into where you want the answer to be.

    The problem is when your answer exactly fills the buffer and the \n spills over to screw up the next fgets call.

    Something like this.
    Code:
    int readMyString ( char *answer, size_t answersize, FILE *fp ) {
      char buff[BUFSIZ];
      if ( fgets( buff, BUFSIZ, fp ) != NULL ) {
        char *newline = strchr(buff, '\n');
        if ( newline != NULL ) {
          *newline = '\0';
        }
        if ( strlen(buff) >= answersize ) {
          printf("Input too long - max expected=%u\n", answersize );
        } else {
          strcpy(answer,buff);
          return 1; // success
        }
      } else {
        return -1; // file error/eof
      }
    
      return 0; // failure
    }
    Which you would call in main with something like
    Code:
            fputs("\nPlease enter the first name of the student: ", stdout);
            fflush(stdout);
            readMyString(GNG1106[0].FirstName, sizeof(GNG1106[0].FirstName), stdin);
            fputs("\nPlease enter the last name of the student: ", stdout);
            fflush(stdout);
            readMyString(GNG1106[0].LastName, sizeof(GNG1106[0].LastName), stdin);
    You can even make use of the return result to try again, continue with the next question, or give up.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  10. #10
    Registered User
    Join Date
    Mar 2011
    Posts
    546
    or
    fgets(with a buffer bigger than the expected input)
    strtok to get the first token
    sscanf to get its value
    error if any of these fail

  11. #11
    Registered User
    Join Date
    Oct 2011
    Location
    Ottawa
    Posts
    17
    Great thanks to all of you, it's working quite nicely now!

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. C Structures and Strings
    By jeanermand in forum C Programming
    Replies: 5
    Last Post: 11-26-2011, 07:41 PM
  2. Looking for Advice on Strings and Structures
    By daynorb in forum C Programming
    Replies: 2
    Last Post: 11-26-2011, 02:35 PM
  3. C Strings in Structures.
    By SlyMaelstrom in forum C++ Programming
    Replies: 15
    Last Post: 10-12-2005, 04:29 PM
  4. Strings and Structures
    By Kinasz in forum C Programming
    Replies: 3
    Last Post: 02-23-2003, 03:46 AM
  5. Comparing strings w/in structures
    By vehl in forum C++ Programming
    Replies: 1
    Last Post: 10-01-2001, 10:59 AM

Tags for this Thread