Problems with fgets and reading in a number

Discussion in 'C Programming' started by FakeAddress, Jun 25, 2003.

  1. FakeAddress

    FakeAddress Guest

    I have two problems with a program. One is related to fgets reading
    in the new line and the other is reading in a number that begins with
    a zero.

    ===============================================
    The dialog with the user should be as follows:
    ===============================================

    Enter name: Minnie Mouse
    Enter street address: 100 Disney Drive
    Enter city: Orlando
    Enter state: FL
    Enter zip code: 99990
    Enter age: 25
    Enter gender (M or F): F

    Enter name: Big Bird
    Enter street address: 10 Sesame Street
    Enter city: Funtown
    Enter state: MA
    Enter zip code: 01222
    Enter age: 20
    Enter gender (M or F): M

    The information you entered is:

    Minnie Mouse
    100 Disney Drive
    Orlando, FL 99990
    She is 25 years old.

    Big Bird
    10 Sesame Street
    Funtown, MA 01222
    He is 20 years old.

    ==================================================
    When I input the information, I get the following results:
    ==================================================

    The information you entered is:

    Minnie Mouse
    100 Disney Drive
    Orlando
    , FL 01222
    She is 25 years old.

    Big Bird
    10 Sesame Street
    Funtown
    , MA 01222
    He is 20 years old.

    There are two problems. First, I don’t want the new line after the
    city. I know it is because the fgets function is reading in the
    newline, but I don't know how to delete it from the string. Also,
    when I enter a zip code with a leading zero, it takes up both spots
    (the first zip code should be 99990 not 01222). Here are the
    suggestions regarding the input and output of the zip code given by my
    instructor:

    * If you use %li (instead of %ld) as the format specifier for the "zip
    code" and if you enter your zip code starting with the number 0
    (zero), C will interpret that number as "octal" and which will cause
    erroneous results. The "%i" format specifier says to interpret any
    number starting with a zero as octal. For this reason, I recommend
    that you use %ld in the scanf statement when prompting the user for
    the zip code.

    * The above hint handles the zip code as it is being "input" using a
    scanf statement. You have a different problem when you want to
    "output" the zip code using a printf statement. C does not store
    leading zeros. So, if the user in fact enters a zip code starting with
    a zero, you need to do some extra formatting when you output the zip
    code to display leading zeros if any. We have not yet covered this, so
    I will give you the solution. You have 2 choices: Either: "%.5ld" or
    "%05ld". Both of those format specifiers indicate that you want C to
    reserve 5 spaces for the output, and if the integer value is less than
    5 characters, to pad the integer with leading zeros.

    ========================
    Here is my code so far:
    ========================

    #include <stdio.h>
    #include <string.h>

    struct info
    {
    char name[30];
    char address[30];
    char city[20];
    char state[3];
    long int zip;
    int age;
    char gender;
    };

    int main (void)
    {

    int i;
    char M = 'M';
    struct info people[2];

    for (i = 0; i < 2; i++)
    {

    fflush (stdin);
    printf ("Enter Name: ");
    fgets(people.name, sizeof(people.name), stdin);

    fflush (stdin);
    printf ("Enter street address: ");
    fgets(people.address, sizeof(people.address),
    stdin);

    fflush (stdin);
    printf ("Enter city: ");
    fgets(people.city, sizeof(people.city), stdin);

    fflush (stdin);
    printf ("Enter state: ");
    fgets(people.state, sizeof(people.state),
    stdin);

    fflush (stdin);
    printf ("Enter zip code: ");
    scanf ("%ld", &people.zip);

    fflush (stdin);
    printf ("Enter age: ");
    scanf ("%i", &people.age);

    fflush(stdin);
    printf ("Enter gender (M or F): ");
    scanf ("%c", &people.gender);
    fflush(stdin);

    printf ("\n");

    } /* End for loop */

    printf ("The information you entered is:\n\n");

    for (i = 0; i < 2; i++)
    {

    printf ("%s",people.name);
    printf ("%s",people.address);
    printf ("%s, ",people.city);
    printf ("%s",people.state);
    printf (" %.5ld\n", people[1].zip);

    if (people.gender == 'M')
    {
    printf ("He is %i years old.\n",
    people.age);
    }
    else
    {
    printf ("She is %i years old.\n",
    people.age);
    }

    printf ("\n");

    } /* End for loop */

    return 0;

    } /* End main */
     
    FakeAddress, Jun 25, 2003
    #1
    1. Advertisements

  2. FakeAddress

    Zoran Cutura Guest

    something along:

    char *tmp = strchr( bufferusedinfgets, '\n');
    if(tmp) tmp = '\0';
    else /* fgets returned befor a \n occurred in the input, so my buffer was
    to short for the input, probably more data needs to be read. */
    The suggestions from your instructor are good and you should follow
    them, but they are not related to the bug you are at. See the comments
    in the code.
    The variable M is never used in this function.
    fflush may only be used with output streams. Using it with a input
    stream causes undefined behavior. You need to remove all of there
    fflush(stdin) calls if you want to write standard conforming code.

    Instead of using fflush you might probably want to consume all
    characters in the input stream up to the next \n with something along:

    int c;
    while( (c=getchar()) != '\n' && c != EOF);

    The output you intend here might not actually appear to the console or
    whatever is connected to the standard output stream, because the
    standard output stream usually is line buffered (as long as we're talking
    about some interactive device) so output might only be written when a \n
    character occurs in the stream. But here you can force output by
    calling

    fflush(stdout);


    I've shown above how a trailing \n character can be removed, and you
    should remove it from any input as long as the \n character does not
    contribute to the "value" that is read. Obviously that is the case with
    a name, a street or a city.



    When you change the input part to remove trailing newline characters
    from the input, you'll have to finish line output by inserting \n
    characters in your format strings.


    ^^^
    this ought to be




    HTH, HAND
     
    Zoran Cutura, Jun 25, 2003
    #2
    1. Advertisements

  3. FakeAddress

    Zoran Cutura Guest

    Yes I did.
     
    Zoran Cutura, Jun 25, 2003
    #3
  4. wrote in 4ax.com:
    Your input related issues were answered by Zoran quite well, so I am not
    going to comment on them. However, these remarks above really irk for one
    simple reason: ZIP codes are not numbers! They are strings consisting
    solely of digits, but they are not numeric values that you can add,
    subtract etc. I really think you could avoid a lot of problems by treating
    ZIP codes as what they are: Strings of 5 digits. Of course, strictly
    speaking, there is also an optional 4 digit part. Anyway, unless you are
    really hurting for memory, I wouldn't recommend using integers to store
    things such as phone numbers, zip codes etc. Just my 2 cents.

    Sinan.
     
    A. Sinan Unur, Jun 25, 2003
    #4
  5. FakeAddress

    goose Guest

    wrote in message
    do you know how to *find* the character in the string ?
    once you find it, you can then replace it with '\0'.
    it does *not*. i've pointed out possible bugs in the
    code below.

    what do you use this for ?
    this, I believe is undefined behaviour, you cannot
    "flush" an input stream.


    it is not necessary to use sizeof with parenthesis, you
    can do :
    fgets (people.name, sizeof people.name, stdin);


    I would use fgets and sscanf here, but thats just a stylistic
    issue, I would say.

    ^^^^^^^^^

    thats your problem, i think you meant
    people
    and not
    people[1]

    [QUOTE]
    ]
    if (people[i].gender == 'M')
    {
    printf ("He is %i years old.\n",
    people[i].age); i years old.\n",
    }
    else
    {
    printf ("She is %i years old.\n",
    people[i].age);
    }[/i][/i][/i][/QUOTE][i][i][i]

    personally, I would use a switch statement here,
    and print out "he" for case 'M', "she" for case 'F'
    and "it" for everything else.

    this is because the user might have entered
    something other than an 'F' or an 'M' for gender,
    and you never checked the input to make sure that
    it was sane.
    [QUOTE]
    printf ("\n");
    printf ("\n");
    } /* End for loop */
    } /* End for loop */
    return 0;

    } /* End main */[/QUOTE]

    hth
    goose,[/i][/i][/i]
     
    goose, Jun 25, 2003
    #5
  6. And I will add, "have you seen zip codes in Great Britain?". There are
    composed of 6 alphanumerics characters. Also, zip code can be prefixed with
    the country code:

    F-75005
    CH-4005
    B-1234

    etc.
     
    Emmanuel Delahaye, Jun 25, 2003
    #6
  7. Often seven, possibly even eight AFAIR. SE23 1EW is where I used to
    live, many moons ago.
     
    Mark McIntyre, Jun 25, 2003
    #7
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.