Thread: Problems with struct members and for loop

  1. #1
    Registered User
    Join Date
    Jan 2017
    Posts
    12

    Question Problems with struct members and for loop

    Hi,
    Could you help me to figure out what is wrong with this chunk of code?


    Code:
     int i,j;
    
        struct office
        {
            char name;
            int desk_num;
        };
    
    
        struct office workers[3];
    
    
        for(i=0; i<3; i++)
        {
            printf("Enter the name for office worker %d: \n", i);
            scanf("%s", workers[i].name);
            printf("Enter the desk number for %s \n", workers[i].name);
            scanf("%d", workers[i].desk_num);
        }
    
    
        for(j=0; j<3; j++)
        {
            printf("%s \t %d \n", workers[j].name, workers[j].desk_num);
        }

  2. #2
    Registered User
    Join Date
    May 2010
    Posts
    4,632
    Part of the problem is that you are trying to use a single char to hold the name. Perhaps you should think about using a C-string instead?


    Jim

  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
    > Could you help me to figure out what is wrong with this chunk of code?

    Sure, you use a better compiler with lots of warnings enabled.
    Code:
    $ gcc -Wall foo.c
    foo.c: In function ‘main’:
    foo.c:19:14: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘int’ [-Wformat=]
            scanf("%s", workers[i].name);
                  ^
    foo.c:20:15: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘int’ [-Wformat=]
            printf("Enter the desk number for %s \n", workers[i].name);
                   ^
    foo.c:21:14: warning: format ‘%d’ expects argument of type ‘int *’, but argument 2 has type ‘int’ [-Wformat=]
            scanf("%d", workers[i].desk_num);
                  ^
    foo.c:27:15: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘int’ [-Wformat=]
            printf("%s \t %d \n", workers[j].name, workers[j].desk_num);
                   ^
    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
    Jan 2017
    Posts
    12
    Would call that a solution..

    Code:
        struct office
        {
            char name[32];
            int desk;
        };
        struct office worker[3];
        int i;
    
    
        for(i=0; i<3; i++)
        {
            printf("Enter the name for office worker %d: \n", i+1);
            scanf("%s", worker[i].name);
            printf("Enter the desk number:\n"); //%s \n", worker[i].name);
            scanf("%d", &worker[i].desk);
        }
    
    
        printf("\n#\tName\tDesk\n");
        for(i=0; i<3; i++)
        {
            printf("%d\t %s\t %d\n", i+1, worker[i].name, worker[i].desk);
        }

  5. #5
    Registered User rogster001's Avatar
    Join Date
    Aug 2006
    Location
    Liverpool UK
    Posts
    1,472
    You didn't really say what you had found was wrong to start with, but yes, it's improved there. Swap your magic number 3 for a decent variable - Its a bit pedantic to mention it in this example but better practice - store your 3 in a variable like totWorkers or wCount, if its a constant use capitals - MAX_WORKERS. Get rid of comment lines that remove code when posting- It aids readability.
    Last edited by rogster001; 01-27-2017 at 05:54 AM.
    Thought for the day:
    "Are you sure your sanity chip is fully screwed in sir?" (Kryten)
    FLTK: "The most fun you can have with your clothes on."

    Stroustrup:
    "If I had thought of it and had some marketing sense every computer and just about any gadget would have had a little 'C++ Inside' sticker on it'"

  6. #6
    Registered User
    Join Date
    Jun 2011
    Posts
    4,513
    A few general comments:

    • You should post a simplified yet complete program that can be compiled and run, and that demonstrates the problem.
    • scanf() is not the best way to read strings, for several reasons. Try using fgets().
    • rogster001 already mentioned not using magic numbers, so I'll just second that advice here.
    • The extra spaces in your final output (after the tabs) are causing your output to be misaligned.


    Code:
    printf("%d\t %s\t %d\n", i+1, worker[i].name, worker[i].desk);
    //          ^    ^
    Code:
    Enter the name for office worker 1:
    Alex
    Enter the desk number:
    2
    Enter the name for office worker 2:
    George
    Enter the desk number:
    4
    Enter the name for office worker 3:
    Dim
    Enter the desk number:
    6
    
    #       Name    Desk
    1        Alex    2
    2        George  4
    3        Dim     6
    Also note longer names will also throw off the formatting of the final output. Consider using field widths to print aligned output.

  7. #7
    Registered User
    Join Date
    Jan 2017
    Posts
    12
    Yes. When I would run my first program, it was crushing after the first input from scanf(). Finally solved it by replacing a char name with char name[NUM].

    I thought that fgets() is used to read from files or when reading input with spaces (John Smith, etc.). Tried to replace scanf() from my code with fgets(worker[i].name, NUM, stdin) to find out that it loops through it only once. The second time it skips it and asks to enter the desk number.



    Code:
    #define NUM 32
    #define len 5
    
    
    
    
    int main()
    {
    
    
        struct office
        {
            char name[NUM];
            int desk;
        };
        struct office worker[len];
        int i;
    
    
    
    
            for(i=0; i<len; i++)
            {
                printf("Enter the name for office worker %d: \n", i+1);
                scanf("%s", worker[i].name);
                printf("Enter the desk number:\n");
                scanf("%d", &worker[i].desk);
            }
    
    
        printf("\n%8c\t%8s\t%8s\n",'#',"Name","Desk");
        for(i=0; i<len; i++)
        {
            printf("%8d\t%8s\t%8d\n", i+1, worker[i].name, worker[i].desk);
        }
    
    
        return 0;
    }

  8. #8
    Registered User
    Join Date
    Jun 2011
    Posts
    4,513
    Quote Originally Posted by holler View Post
    I thought that fgets() is used to read from files or when reading input with spaces (John Smith, etc.).
    It's used to read an entire line from a stream (assuming the buffer is large enough to contain the entire line). As you've already shown, it can be called using stdin as the stream.

    It may be a good idea to read strings with the spaces; what if there's a John Smith and a John Higgins?

    Be aware that fgets() stores the newline (if there's room), which must be removed if you don't need it in the string.

    Quote Originally Posted by holler View Post
    Tried to replace scanf() from my code with fgets(worker[i].name, NUM, stdin) to find out that it loops through it only once. The second time it skips it and asks to enter the desk number.
    The newline left over from entering the number at the end of the first iteration is read by fgets() at the beginning of the second. This is one of the problems with mixing formatted- (e.g. scanf() ) and line-oriented (e.g. fgets() ) input.

    If what you have is suitable for your purposes, then it should be okay. I'll just offer an example for your consideration:

    Code:
    #include <stdio.h>
    #include <string.h>
    
    #define STRLEN  64
    #define WORKERS  3
    
    struct office
    {
        char name[STRLEN];
        int desk;
    };
    
    int main(void)
    {
        struct office worker[WORKERS];
        char input[STRLEN];
        int i;
    
        for(i = 0; i < WORKERS; i++)
        {
            printf("Name %d: ", i + 1);
            fflush(stdout);
            fgets(worker[i].name, sizeof(worker[i].name), stdin);
            worker[i].name[strcspn(worker[i].name, "\n")] = '\0'; /* remove newline */
    
            printf("Desk Number: ");
            fflush(stdout);
            fgets(input, sizeof(input), stdin);
            if(sscanf(input, "%d", &worker[i].desk) != 1)
                worker[i].desk = -1;  /* error condition, handle however you'd like */
        }
    
        printf("\n\n");
    
        for(i = 0; i < WORKERS; i++)
        {
            printf("%s sits at desk %d\n", worker[i].name, worker[i].desk);
        }
    
        return 0;
    }
    Note that both inputs are read as strings. The second one (to read the desk number) uses sscanf() to parse the input string for the number. If a number is not found, it defaults to a value of -1.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. manipulating struct members
    By nhiap6 in forum C++ Programming
    Replies: 2
    Last Post: 01-23-2014, 03:40 PM
  2. Iterating through Struct Members
    By Vespasian in forum C++ Programming
    Replies: 2
    Last Post: 04-04-2013, 03:20 PM
  3. accesing struct members
    By kennny2004 in forum C++ Programming
    Replies: 2
    Last Post: 05-23-2006, 11:31 PM
  4. Pointer to struct members
    By kybert in forum C Programming
    Replies: 7
    Last Post: 07-01-2003, 08:27 AM
  5. comparing struct members
    By breed in forum C Programming
    Replies: 4
    Last Post: 11-22-2001, 12:27 PM

Tags for this Thread