Problem with scanf

Discussion in 'C Programming' started by diegotorquemada@gmail.com, Mar 8, 2013.

  1. Guest

    Hello,

    I am wondering why scanf is not reading my data properly:

    #include<stdio.h>

    // gcc -Wall -std=c99 -o 07_struct 07_struct.c

    typedef struct
    {
    int cod;
    char name[50];
    char sex;
    } person;

    int main()
    {
    int i, n;

    printf("How many people = ");
    scanf("%d", &n);

    person p[n];
    for (i=0; i<n; i++)
    {
    printf("PERSON %d:\n", i+1);
    printf("Code = "); scanf("%d", &(p.cod));
    printf("Name = "); fgets(p.name, sizeof(p.name), stdin);
    printf("Sex M/F = "); scanf("%c", &(p.sex));
    printf("\n");
    }

    puts("\n----------------------------------------------------------------\n");

    for (i=0; i<n; i++)
    {
    printf("PERSON %2d:\n", i+1);
    printf("Cod = %d\n", p.cod);
    printf("Name = %s\n", p.name);
    printf("Sex M/F = %c\n\n", p.sex);
    }

    return 0;
    }



    The output of my program is:

    diego@earendil:~/programas$ gcc -Wall -std=c99 -o 07_struct 07_struct.c
    diego@earendil:~/programas$ ./07_struct
    How many people = 3
    PERSON 1:
    Code = 12
    Name = Sex M/F = Andrew

    PERSON 2:
    Code = Name = Sex M/F = Maria

    PERSON 3:
    Code = Name = Sex M/F = Robert


    ----------------------------------------------------------------

    PERSON 1:
    Cod = 12
    Name =

    Sex M/F = A

    PERSON 2:
    Cod = -1208399088
    Name = ndrew

    Sex M/F = M

    PERSON 3:
    Cod = -1081416063
    Name = aria

    Sex M/F = R



    can somebody please help me?

    Thanks

    Diego
    , Mar 8, 2013
    #1
    1. Advertising

  2. Ivan Shmakov Guest

    >>>>> diegotorquemada <> writes:

    > Hello, I am wondering why scanf is not reading my data properly:


    [...]

    > printf("Code = "); scanf("%d", &(p.cod));
    > printf("Name = "); fgets(p.name, sizeof(p.name), stdin);
    > printf("Sex M/F = "); scanf("%c", &(p.sex));


    That's simple. In the example, the input data contains:

    12<NEWLINE>
    Andrew<NEWLINE>

    First scanf () reads "12", the following fgets () reads
    <NEWLINE>, and then the second scanf () reads "A".

    The next iteration gives "no data" for the first scanf () (thus
    p[1].cod remains uninitialized -- that's why one'd /always/
    check the scanf's return value!), then "ndrew\n" for the name,
    and "M" for the second scanf ().

    Kaj tiel plu.

    [...]

    --
    FSF associate member #7257
    Ivan Shmakov, Mar 8, 2013
    #2
    1. Advertising

  3. John Gordon Guest

    In <> writes:

    > Hello,


    > I am wondering why scanf is not reading my data properly:


    When you do something like this:

    scanf("%d", &n);

    The user types a number and presses Enter. scanf looks at the format
    string, sees %d, and converts the typed number to an integer. However,
    you didn't tell scanf to do anything with the Enter ekypress, so it is
    left sitting in the input buffer.

    Then the call to fgets sees the leftover Enter keypress in the input
    stream and gets a blank line.

    Generally the best way to fix this is to use fgets() for all your input.

    --
    John Gordon A is for Amy, who fell down the stairs
    B is for Basil, assaulted by bears
    -- Edward Gorey, "The Gashlycrumb Tinies"
    John Gordon, Mar 8, 2013
    #3
  4. Guest

    On Friday, March 8, 2013 3:30:35 PM UTC-5, Ivan Shmakov wrote:
    > >>>>> diegotorquemada <> writes:

    >
    >
    >
    > > Hello, I am wondering why scanf is not reading my data properly:

    >
    >
    >
    > [...]
    >
    >
    >
    > > printf("Code = "); scanf("%d", &(p.cod));

    >
    > > printf("Name = "); fgets(p.name, sizeof(p.name), stdin);

    >
    > > printf("Sex M/F = "); scanf("%c", &(p.sex));

    >
    >
    >
    > That's simple. In the example, the input data contains:
    >
    >
    >
    > 12<NEWLINE>
    >
    > Andrew<NEWLINE>
    >
    >
    >
    > First scanf () reads "12", the following fgets () reads
    >
    > <NEWLINE>, and then the second scanf () reads "A".
    >
    >
    >
    > The next iteration gives "no data" for the first scanf () (thus
    >
    > p[1].cod remains uninitialized -- that's why one'd /always/
    >
    > check the scanf's return value!), then "ndrew\n" for the name,
    >
    > and "M" for the second scanf ().
    >
    >


    You are right Ivan. However, I still do not know how to remove that <NEWLINE> before putting the next scanf() or fgets().

    >
    > Kaj tiel plu.
    >
    >
    >
    > [...]
    >
    >
    >
    > --
    >
    > FSF associate member #7257
    , Mar 8, 2013
    #4
  5. On Mar 8, 2:41 pm, wrote:
    > On Friday, March 8, 2013 3:30:35 PM UTC-5, Ivan Shmakov wrote:
    > > >>>>> diegotorquemada  <> writes:

    >
    > >  > Hello, I am wondering why scanf is not reading my data properly:

    >
    > > [...]

    >
    > >  >       printf("Code    = ");   scanf("%d", &(p.cod));

    >
    > >  >       printf("Name    = ");   fgets(p.name, sizeof(p.name), stdin);

    >
    > >  >       printf("Sex M/F = ");   scanf("%c", &(p.sex));

    >
    > >    That's simple.  In the example, the input data contains:

    >
    > > 12<NEWLINE>

    >
    > > Andrew<NEWLINE>

    >
    > >    First scanf () reads "12", the following fgets () reads

    >
    > >    <NEWLINE>, and then the second scanf () reads "A".

    >
    > >    The next iteration gives "no data" for the first scanf () (thus

    >
    > >    p[1].cod remains uninitialized -- that's why one'd /always/

    >
    > >    check the scanf's return value!), then "ndrew\n" for the name,

    >
    > >    and "M" for the second scanf ().

    >
    > You are right Ivan. However, I still do not know how to remove that <NEWLINE> before putting the next scanf() or fgets().



    Section 12 in C FAQ might help.

    - Anand
    Anand Hariharan, Mar 8, 2013
    #5
  6. Guest


    > Section 12 in C FAQ might help.
    >
    >
    >
    > - Anand


    Thanks Anand... I found the solution there. It was:

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

    typedef struct
    {
    int cod;
    char nombre[100];
    char sexo;
    } persona;

    void vaciar_buffer_teclado(void);
    void leer_cadena(int n, char cad[n]);

    int main()
    {
    int i, n;
    char tmp[100];

    printf("Numero de personas = ");
    scanf("%d", &n); vaciar_buffer_teclado();

    persona p[n];
    for (i=0; i<n; i++)
    {
    printf("PERSONA %d:\n", i+1);
    printf("Codigo = ");
    scanf("%d", &(p.cod)); vaciar_buffer_teclado();

    printf("Nombre = ");
    leer_cadena(sizeof(p.nombre), p.nombre);

    printf("Sexo M/F = ");
    scanf("%s", tmp); vaciar_buffer_teclado();
    p.sexo = toupper(tmp[0]);

    printf("\n");
    }

    puts("\n----------------------------------------------------------------\n");

    for (i=0; i<n; i++)
    {
    printf("PERSONA %2d:\n", i+1);
    printf("Codigo = %d\n", p.cod);
    printf("Nombre = %s\n", p.nombre);
    printf("Sexo M/F = %c\n\n", p.sexo);
    }

    return 0;
    }

    void vaciar_buffer_teclado(void)
    {
    int c;
    while((c = getchar()) != '\n' && c != EOF);
    return;
    }

    void leer_cadena(int n, char cad[n])
    {
    char *p;
    if (fgets(cad, n, stdin) == NULL) exit(EXIT_FAILURE);
    if ((p = strchr(cad, '\n')) != NULL) *p = '\0'; // remueva el \n
    return;
    }
    , Mar 9, 2013
    #6
  7. On Mar 9, 8:48 am, wrote:
    > > Section 12 in C FAQ might help.

    >
    > > - Anand

    >
    > Thanks Anand... I found the solution there. It was:
    >


    Some errors/flaws in your solution, am afraid.

    (...)
    >    scanf("%d", &n); vaciar_buffer_teclado();
    >


    Check scanf's return value. See Ivan Shmakov's post upthread.

    (...)
    >       scanf("%s", tmp); vaciar_buffer_teclado();


    Using scanf with a %s is as bad as gets(). In your case, since you
    have
    decided that the user's input could never be more than 99 characters
    long,
    you could just as well put that in the format specifier.


    In general, doing I/O (especially the 'I' in I/O) in C is cumbersome,
    very easy to go wrong and worse, not even know that you went wrong.
    If you
    are learning C, there are other constructs and concepts in the
    language that
    you can invest your time in learning. Rather than get the inputs from
    the
    console, consider hard-coding your inputs within the code.

    my $0.02,
    - Anand
    Anand Hariharan, Mar 9, 2013
    #7
  8. In article <>,
    <> wrote:
    >On Friday, March 8, 2013 3:30:35 PM UTC-5, Ivan Shmakov wrote:
    >> >>>>> diegotorquemada <> writes:

    >>
    >> First scanf () reads "12", the following fgets () reads
    >> <NEWLINE>, and then the second scanf () reads "A".

    >
    >You are right Ivan. However, I still do not know how to remove that <NEWLINE> before
    >putting the next scanf() or fgets().


    I generally avoid scanf() for reasons like this. I prefer fgets() followed
    by sscanf()

    char line[MAXLINE];

    if (fgets(line, sizeof(line), stdin) == NULL) die();
    if (sscanf(line, "%d", &code) != 1) die();
    if (fgets(name, sizeof(name), stdin) == NULL) die();
    if (fgets(line, sizeof(line), stdin) == NULL) die();
    if (sscanf(line, "%c", &sex) != 1) die();

    You'll also have to trim the trailing newline from name. Actually, do it
    right and trim *all* trailing whitespace from name. That's an exercise for
    another day, however.

    You can also get a little fancy with conversion suppression and scansets:

    if (scanf("%d%*[^\n]\n", &code) != 1) die();
    if (fgets(name, sizeof(name), stdin) == NULL) die();
    if (scanf("%c%*[^\n]\n", &sex) != 1) die();

    but it's kind of unreadable. I generally try to avoid excessive
    cleverness when I code. As Brian Kernighan once wrote:

    Everyone knows that debugging is twice as hard as writing a program in
    the first place. So if you're as clever as you can be when you write
    it, how will you ever debug it?

    --
    -Ed Falk,
    http://thespamdiaries.blogspot.com/
    Edward A. Falk, Mar 9, 2013
    #8
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Replies:
    21
    Views:
    1,206
    Richard Herring
    Apr 20, 2005
  2. code_wrong

    Re: printf scanf problem

    code_wrong, Aug 2, 2003, in forum: C Programming
    Replies:
    1
    Views:
    411
    /dev/null
    Aug 2, 2003
  3. Dan Pop

    Re: printf scanf problem

    Dan Pop, Aug 4, 2003, in forum: C Programming
    Replies:
    0
    Views:
    642
    Dan Pop
    Aug 4, 2003
  4. =?ISO-8859-1?Q?Martin_J=F8rgensen?=

    scanf (yes/no) - doesn't work + deprecation errors scanf, fopen etc.

    =?ISO-8859-1?Q?Martin_J=F8rgensen?=, Feb 16, 2006, in forum: C Programming
    Replies:
    185
    Views:
    3,386
    those who know me have no need of my name
    Apr 3, 2006
  5. =?ISO-8859-1?Q?Martin_J=F8rgensen?=

    difference between scanf("%i") and scanf("%d") ??? perhaps bug inVS2005?

    =?ISO-8859-1?Q?Martin_J=F8rgensen?=, Apr 26, 2006, in forum: C Programming
    Replies:
    18
    Views:
    673
    Richard Bos
    May 2, 2006
Loading...

Share This Page