what does strod return??

Discussion in 'C Programming' started by alternativa, Jan 1, 2006.

  1. alternativa

    alternativa Guest

    Hi,
    I have problem with the following function - it was intended to ask a
    user for a 4-digits number:

    double ask_for_number (void)
    {
    char *notint;
    char s2[3];
    double entered_number;

    do
    {
    printf("\tplease enter 4-digits number: ");
    scanf("%s", s2);
    if ( strlen (s2) !=4 )
    printf ("Wrong input - input must consist of 4 integer
    numbers.\n");
    else
    entered_numberr = strtod(s2, &notint);
    }
    while (*notint);
    printf ("you entered: %d", entered_number); /* ???? */
    return entered_number;
    };

    My question is: why in the line /* ???? */ we got something else that
    input number? I'd like to use entered_number in the other piece of
    program, so I have to be sure it works properly... I guess this is a
    matter of a strod function - could you give me a clue how it works or
    how to write some similar function without strod?
    best regards,
    a.
    alternativa, Jan 1, 2006
    #1
    1. Advertising

  2. "alternativa" <> writes:
    > I have problem with the following function - it was intended to ask a
    > user for a 4-digits number:
    >
    > double ask_for_number (void)
    > {
    > char *notint;
    > char s2[3];
    > double entered_number;

    [snip]
    > printf ("you entered: %d", entered_number); /* ???? */
    > return entered_number;
    > };


    "%d" expects an int. Passing a double invokes undefined behavior.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
    Keith Thompson, Jan 1, 2006
    #2
    1. Advertising

  3. alternativa

    Jack Klein Guest

    On 31 Dec 2005 16:13:51 -0800, "alternativa" <>
    wrote in comp.lang.c:

    > Hi,
    > I have problem with the following function - it was intended to ask a
    > user for a 4-digits number:
    >
    > double ask_for_number (void)
    > {
    > char *notint;
    > char s2[3];


    This is not a large enough array to hold four digits of input. It has
    three elements, s2[0], s2[1], and s2[2]. It can either hold three
    arbitrary character values -- not a string -- or a string consisting
    of two characters, with the '\0' that terminates the string being in
    the third and final char.

    > double entered_number;
    >
    > do
    > {
    > printf("\tplease enter 4-digits number: ");
    > scanf("%s", s2);


    Using the scanf "%s" conversion specifier without a length parameter
    is just plain suicidal. scanf() will attempt to pull characters from
    the standard input stream and store them in successive memory
    locations, then store a terminating '\0' at the end. If the input
    contains four characters, the first three will wind up in your array,
    then scanf() will try to write the fourth character and the
    terminating '\0' into memory that does not belong to you, past the end
    of the array. This is undefined behavior.

    And what do you think happens if the user types forty or fifty
    characters?

    > if ( strlen (s2) !=4 )


    Now you are asking the strlen() function to access memory past the end
    of your array.

    > printf ("Wrong input - input must consist of 4 integer
    > numbers.\n");
    > else
    > entered_numberr = strtod(s2, &notint);
    > }
    > while (*notint);
    > printf ("you entered: %d", entered_number); /* ???? */
    > return entered_number;
    > };
    >
    > My question is: why in the line /* ???? */ we got something else that
    > input number? I'd like to use entered_number in the other piece of
    > program, so I have to be sure it works properly... I guess this is a
    > matter of a strod function - could you give me a clue how it works or
    > how to write some similar function without strod?
    > best regards,
    > a.


    There is no requirement that anything at all be output by that line.
    In fact, there is no requirement that the program even reach that
    point. If the array overflows, there is undefined behavior and there
    are no requirements at all any more, there is no right or wrong
    behavior. But if there is no undefined behavior, strlen() on the
    input array will return either 0, 1, or 2, so your program will never
    reach the line.

    And, as Keith pointed out, your are passing a double to printf() with
    a "%d" conversion specifier, which is for int values. You need to use
    "%f" to output a double.

    But the bigger problem is your use of an array that's too small, your
    program logic insisting that the input is not valid unless it
    overflows the array, and using scanf("%n") without a length modifier.

    To fix your program, you need to change the definition of s2 from [3]
    to [5] elements. Then you need to use "%4s", as a conversion
    specifier to scanf() so it will accept only four characters, and still
    have room for the '\0'.

    And finally you need to use "%f" in place of "%d" as the conversion
    specifier to printf().

    --
    Jack Klein
    Home: http://JK-Technology.Com
    FAQs for
    comp.lang.c http://c-faq.com/
    comp.lang.c++ http://www.parashift.com/c -faq-lite/
    alt.comp.lang.learn.c-c++
    http://www.contrib.andrew.cmu.edu/~ajo/docs/FAQ-acllc.html
    Jack Klein, Jan 1, 2006
    #3
  4. alternativa a écrit :
    > Hi,
    > I have problem with the following function - it was intended to ask a
    > user for a 4-digits number:


    Do you mean 4-decimal-digit number ?

    > double ask_for_number (void)
    > {
    > char *notint;
    > char s2[3];


    This is good for a 2 characters string. Sounds too short for a
    "4-decimal-digit number", don't you think so ?

    > double entered_number;
    >
    > do
    > {
    > printf("\tplease enter 4-digits number: ");
    > scanf("%s", s2);


    Bad and dangerous use of scanf(). (No input limit, no return test, no
    purge...) You should have used fgets() that is much more safer.

    Try this, and ask for details if you don't understand.

    static long ask_for_number (void)
    {
    long entered_number = 0;
    int err = 1;

    do
    {
    char s2[16];
    printf("\tplease enter 4-decimal-digits number: ");
    fflush (stdout);

    fgets(s2, sizeof s2, stdin);

    /* check the input */
    {
    char *p = strchr(s2, '\n');

    if (p != NULL)
    {
    /* clean */
    *p = 0;
    }
    else
    {
    /* purge */
    int c;

    while ((c = getchar()) != '\n' && c != EOF)
    {
    }
    }
    }

    if (strlen (s2) != 4)
    {
    printf ("Wrong input - input must consist of 4 decimal digits
    numbers.\n");
    }
    else
    {
    char *notint;
    entered_number = strtol (s2, &notint, 10);

    if (*notint != 0)
    {
    printf ("Wrong input - input must consist of 4 decimal
    digits numbers.\n");
    }
    else
    {
    err = 0;
    }
    }
    }
    while (err);

    return entered_number;
    }


    int main (void)
    {
    long n = ask_for_number ();

    printf ("you entered: %ld\n", n);

    return 0;
    }


    --
    A+

    Emmanuel Delahaye
    Emmanuel Delahaye, Jan 1, 2006
    #4
  5. alternativa

    alternativa Guest

    thanks a lot, I'll work on it :)
    alternativa, Jan 1, 2006
    #5
  6. Emmanuel Delahaye wrote:
    > alternativa a écrit :
    >
    >> Hi,
    >> I have problem with the following function - it was intended to ask a
    >> user for a 4-digits number:

    >
    >
    > Do you mean 4-decimal-digit number ?
    >
    >> double ask_for_number (void)
    >> {
    >> char *notint;
    >> char s2[3];

    >
    >
    > This is good for a 2 characters string. Sounds too short for a
    > "4-decimal-digit number", don't you think so ?
    >
    >> double entered_number;
    >>
    >> do
    >> {
    >> printf("\tplease enter 4-digits number: ");
    >> scanf("%s", s2);

    >
    >
    > Bad and dangerous use of scanf(). (No input limit, no return test, no
    > purge...) You should have used fgets() that is much more safer.
    >
    > Try this, and ask for details if you don't understand.
    >
    > static long ask_for_number (void)
    > {
    > long entered_number = 0;
    > int err = 1;
    >
    > do
    > {
    > char s2[16];
    > printf("\tplease enter 4-decimal-digits number: ");
    > fflush (stdout);
    >
    > fgets(s2, sizeof s2, stdin);
    >
    > /* check the input */
    > {
    > char *p = strchr(s2, '\n');
    >
    > if (p != NULL)
    > {
    > /* clean */
    > *p = 0;
    > }
    > else
    > {
    > /* purge */
    > int c;
    >
    > while ((c = getchar()) != '\n' && c != EOF)
    > {
    > }
    > }
    > }
    >
    > if (strlen (s2) != 4)
    > {
    > printf ("Wrong input - input must consist of 4 decimal digits
    > numbers.\n");
    > }
    > else
    > {
    > char *notint;
    > entered_number = strtol (s2, &notint, 10);
    >
    > if (*notint != 0)
    > {
    > printf ("Wrong input - input must consist of 4 decimal
    > digits numbers.\n");
    > }
    > else
    > {
    > err = 0;
    > }
    > }
    > }
    > while (err);
    >
    > return entered_number;
    > }
    >
    >
    > int main (void)
    > {
    > long n = ask_for_number ();
    >
    > printf ("you entered: %ld\n", n);
    >
    > return 0;
    > }
    >
    >


    But, if the user enters a line such as
    xxx1
    where x represents a space or tab character,
    then your function will return the entered number
    although it is not a 4-digit number. Of course, the
    correction is trivial.
    M. Nejat AYDIN, Jan 1, 2006
    #6
  7. M. Nejat AYDIN a écrit :
    > But, if the user enters a line such as
    > xxx1
    > where x represents a space or tab character,
    > then your function will return the entered number
    > although it is not a 4-digit number. Of course, the
    > correction is trivial.


    Good catch.

    --
    A+

    Emmanuel Delahaye
    Emmanuel Delahaye, Jan 2, 2006
    #7
    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. PvdK
    Replies:
    0
    Views:
    2,968
  2. wl
    Replies:
    2
    Views:
    570
    Dimitri Maziuk
    Mar 5, 2004
  3. Ganesh Gella
    Replies:
    4
    Views:
    352
    Stuart Gerchick
    Nov 12, 2004
  4. Seong-Kook Shin
    Replies:
    1
    Views:
    482
    Richard Bos
    Jun 18, 2004
  5. Greenhorn
    Replies:
    15
    Views:
    797
    Keith Thompson
    Mar 6, 2005
Loading...

Share This Page