Thread: Having trouble with structs

  1. #1
    Registered User
    Join Date
    Nov 2012
    Posts
    51

    Having trouble with structs

    I am reading text from a file and trying to set names to structs. Here is the input file
    Code:
    2
    3
    Quincy Richard Steven
    Donna Elizabeth Francine
    5 2 9
    4 5 7
    5 9 6
    4 6 5
    7 8 9
    6 9 1
    Here is the code that I have so far
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    
    #define MAX_CHARS 20
    
    
    // Structure that has 2 properties: name and scores.
    struct person
    {
        char *name;
        int *scores;
    };
    
    
    int main()
    {
        // Opens the file and test to see if the file successfully opens.
        FILE *ifp = fopen("matching.txt", "r");
        if (!ifp)
        {
            printf("Unable to read file!\n");
            return -1;
        }
    
    
        // Variables: i is the initializer; num_pairs is the number of pairs; num_events is the number of speed dating events.
        int i, num_pairs, num_events;
    
    
        // These two lines read in the number of events and the number of pairs, respectively. TESTED AND READS NUMBER PROPERLY!!!
        fscanf(ifp, "%d", &num_events);
        fscanf(ifp, "%d", &num_pairs);
    
    
        // Declares the variable for men, of type struct person.
        struct person *men;
        men = malloc(num_pairs * sizeof(struct person));
        for (i=0; i< num_pairs; i++)
        {
            // This loop creates allocates memory for name and scores for each men.
            men[i].name = malloc(sizeof(char)*MAX_CHARS);
            men[i].scores = malloc(num_pairs * sizeof(int));
        }
    
    
        struct person *women;
        women = malloc(num_pairs * sizeof(struct person));
        for (i=0; i< num_pairs; i++)
        {
            // This loop creates allocates memory for name and scores for each women.
            women[i].name = malloc(MAX_CHARS * sizeof(char));
            women[i].scores = malloc(num_pairs * sizeof(int));
        }
    
    
        for (i=0; i< num_events; i++)
        {
            int j;
            for (j=0; j< num_pairs; j++)
            {
                fscanf(ifp,"%s", men[j].name);
                printf("%s", men[j].name);
    
    
            }
    
    
        }
    
    
        fclose(ifp);
        return 0;
    }
    In the nested for-loop it should read in the name of each men and print it out, like so:
    Code:
    Quincy Richard Steven
    However it is printing out:
    Code:
    QuincyRichardStevenDonnaElizabethFrancine
    Any idea whats going on?

    PS. Yes this is homework, but this is one small piece of a much LARGER complex problem, in other words, the answer given here will NOT complete my homework, will just teach a noob something new about structs :-)

  2. #2
    Registered User
    Join Date
    Jun 2011
    Posts
    4,513
    Your problem here isn't with structures, but how you're reading strings.

    Quote Originally Posted by fscanf()
    C string that contains a sequence of characters that control how characters extracted from the stream are treated:

    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). A single whitespace in the format string validates any quantity of whitespace characters extracted from the stream (including none).
    Try replacing it with a function that doesn't care about whitespace (i.e. "fgets()").

  3. #3
    Registered User
    Join Date
    Nov 2012
    Posts
    51
    Quote Originally Posted by Matticus View Post
    Try replacing it with a function that doesn't care about whitespace (i.e. "fgets()").
    I literally changed this
    Code:
    fscanf(ifp, "%s", men[j].name);
    to
    Code:
    fgets(ifp, "%s", men[j].name);
    Sorry if this is a dumb mistake, I have NEVER used fgets, ever it wasn't even taught in our intro to C class.

  4. #4
    Registered User
    Join Date
    Jun 2011
    Posts
    4,513
    If you read the link, you'll see that the arguments are in a different order.

    1. Where you want to store it (in this case, your struct)
    2. How much you want to read (in this case, your #define)
    3. From what stream you want to read it (in this case, "ifp")

  5. #5
    Registered User
    Join Date
    Nov 2012
    Posts
    51
    I just changed it to
    Code:
    for (j=0; j< num_pairs; j++)        {
                fgets(men[j].name, MAX_CHARS, ifp);
                printf("%s", men[j].name);
            }
    The output is:
    Code:
    Quincy Richard Steven Donna Elizabeth Francine 5 2 9 4 5 7 5 9 6
    men[i].name should have the names of the men and same with the name of the women. Any clue?

  6. #6
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    Note, the OP wants to use fscanf. The names are white space separated (mix of space and newline), not strictly newline separated. fgets would read all 3 names into one men[i].name.

    The first, little problem is that you simply don't print a space character between names. Just change the printf to "%s " (note the space after %s). That will at least make it a bit more legible.

    The second problem is due to you using nested loops. A few helpful printf statements to debug:
    Code:
        int count = 0;
        for (i=0; i< num_events; i++)
        {
            int j;
            for (j=0; j< num_pairs; j++)
            {
                printf("i = %d, j = %d, loop iterations so far = %d\n", i, j, count);
                fscanf(ifp,"%s", men[j].name);
                printf("%s ", men[j].name);
                printf("scanned into men[%d].name\n", j);
                count++;
            }
        }
    And the new output of your program:
    Code:
    i = 0, j = 0, loop iterations so far = 0
    Quincy scanned into men[0].name
    i = 0, j = 1, loop iterations so far = 1
    Richard scanned into men[1].name
    i = 0, j = 2, loop iterations so far = 2
    Steven scanned into men[2].name
    i = 1, j = 0, loop iterations so far = 3
    Donna scanned into men[0].name
    i = 1, j = 1, loop iterations so far = 4
    Elizabeth scanned into men[1].name
    i = 1, j = 2, loop iterations so far = 5
    Francine scanned into men[2].name
    Notice that j repeats going from 0 to 2 twice. The first time it reads the men's names, the second time the women's, which overwrites the men's names. That is a total of 6 iterations, in which you reading and print all of the names. Structure it like your malloc loops, two separate loops, not nested, one for men, one for women.
    Code:
    // no outer loop, one loop for men
    for i from 0; < num_pairs
        fscanf into men[i].name
    // one loop for women
    for i from 0; < num_pairs
        fscanf into women[i].name

  7. #7
    Registered User
    Join Date
    Jun 2011
    Posts
    88
    it is printing out QuincyRichardStevenDonnaElizabethFrancine becuase that's what you told it to do.
    printf("%s", men[j].name); prints out the string with no added white space ( spaces, tabs , new lines ,etc ).
    try printf("%s ",...) to add a space and printf("\n") to add a new line.

    Code:
     for (i=0; i< num_events; i++)
        {
            int j;
            for (j=0; j< num_pairs; j++)
            {
                fscanf(ifp,"%s", men[j].name);
                printf("%s", men[j].name);
     
     
            }
     
     
        }

  8. #8
    Registered User
    Join Date
    Jun 2011
    Posts
    4,513
    Note, the OP wants to use fscanf.
    Yah, noted a bit too late (was working on a correction reply). I was thrown off by the initial proposition, "In the nested for-loop it should read in the name of each men and print it out, like so:"

    You're completely right. While not correcting the main problem, I realized that a simple newline in the print statement would make the output more clear for the OP.

    My apologies to the OP.

  9. #9
    Registered User
    Join Date
    Nov 2012
    Posts
    51
    Alright solved that little problem, thanks for your guys help! Now I have another little problem...
    Code:
    5 2 9 // QUINCY'S SCORES
    4 5 7 // RICHARD'S SCORES
    5 9 6 // STEVEN'S SCORES
    I am trying to do this, I have been trying to figure out this little problem. I created a generic for-loop:
    Code:
    for (i=0; i< num_pairs; i++
    {
        fscanf(ifp, "%d", &men[i].scores);
        printf("%s's scores are %d\n, men[i].name, men[i].scores);
    
    }
    For obvious reasons this does not work, but its all I have. Another approach that I was going to take was reading in the whole line as a string and then converting the string into seperate integers. However, I rather avoid this approach. Any hints on solving this problem? I hate asking for all this help, but I really need all the help I can get.

  10. #10
    Registered User
    Join Date
    May 2012
    Posts
    1,066
    Code:
    for (i=0; i< num_pairs; i++
    {
        fscanf(ifp, "%d", &men[i].scores);
        printf("%s's scores are %d\n, men[i].name, men[i].scores);
    }
    You want to read three numbers for each man, thus you need two nested for-loops (the outer loop for the men, the inner one for the scores)
    men[i].scores is an array, so you are missing the index when you work with one of its elements.

    Bye, Andreas

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 2
    Last Post: 01-08-2013, 07:55 AM
  2. Trouble with reading in data to an array of structs
    By ljgerr93 in forum C Programming
    Replies: 6
    Last Post: 01-22-2012, 01:57 PM
  3. Replies: 7
    Last Post: 06-04-2008, 10:39 PM
  4. trouble with structs..
    By cs32 in forum C Programming
    Replies: 1
    Last Post: 01-22-2008, 11:48 PM
  5. passing structs & pointers to structs as arguments
    By Markallen85 in forum C Programming
    Replies: 6
    Last Post: 03-16-2004, 07:14 PM