a newbie question.

Discussion in 'C Programming' started by Mike, Mar 12, 2008.

  1. Mike

    Mike Guest

    Hi

    #include<stdio.h>
    main()
    {
    char s[]="Taiwan University.";
    float a;
    scanf("%f",&a);
    printf("%f",a);
    printf("input string:");
    gets(s);
    puts("%s",s);
    }

    After compiled by Visual Studio, the above program can input a.
    But after it shows a, then I cannot enter s string.
    Why?

    Mike
    Mike, Mar 12, 2008
    #1
    1. Advertising

  2. Mike

    DDD Guest

    On Mar 12, 2:27 pm, Mike <> wrote:
    > Hi
    >
    > #include<stdio.h>
    > main()
    > {
    > char s[]="Taiwan University.";
    > float a;
    > scanf("%f",&a);
    > printf("%f",a);
    > printf("input string:");
    > gets(s);
    > puts("%s",s);
    >
    > }
    >
    > After compiled by Visual Studio, the above program can input a.
    > But after it shows a, then I cannot enter s string.
    > Why?
    >
    > Mike


    The routine scanf will stop when met Enter key, then gets() get the
    Enter key.
    DDD, Mar 12, 2008
    #2
    1. Advertising

  3. Mike

    Micah Cowan Guest

    Mike <> writes:

    > After compiled by Visual Studio, the above program can input a.
    > But after it shows a, then I cannot enter s string.


    Maybe yes, maybe no. The way you've written your code, you might never
    be able to tell.

    > #include<stdio.h>
    > main()


    int main(void)

    would be significantly better.

    > {
    > char s[]="Taiwan University.";


    Why fill s[] with a value just to overwrite it?

    > float a;
    > scanf("%f",&a);
    > printf("%f",a);


    If scanf() encounters a conversion error (say you enter "a" instead of
    a float value), a will still be uninitialized when you print it, in
    which case anything could happen.

    > printf("input string:");


    If stdout is line-bufered, you won't see this prompt before it starts
    expecting input.

    > gets(s);
    > puts("%s",s);


    Since gets() strips newlines, puts() won't print one, so you may not
    see this output either.

    Aside from that, gets() is unsafe.

    Aside from reading further into your C book, you might take a peek at
    the comp.lang.c FAQ http://c-faq.com/ for better understanding of
    what's wrong with your code.

    --
    Micah J. Cowan
    Programmer, musician, typesetting enthusiast, gamer...
    http://micah.cowan.name/
    Micah Cowan, Mar 12, 2008
    #3
  4. Mike <> writes:
    > #include<stdio.h>
    > main()
    > {
    > char s[]="Taiwan University.";
    > float a;
    > scanf("%f",&a);
    > printf("%f",a);
    > printf("input string:");
    > gets(s);
    > puts("%s",s);
    > }
    >
    > After compiled by Visual Studio, the above program can input a.
    > But after it shows a, then I cannot enter s string.
    > Why?


    The comp.lang.c FAQ is at <http://www.c-faq.com/>. You've just asked
    question 12.18a.

    Some more points:

    "main()" is more or less ok in some circumstances, but
    "int main(void)" is better.

    You should probably print a new-line after each item that you print.
    For example,
    printf("%f\n", a);
    Otherwise your output will be illegibly joined together on a single
    line.

    Never use the gets() function. See question 12.23 in the
    aforementioned FAQ.

    The puts() function takes one argument, not two. Since you have the
    required "#include <stdio.h>" (good for you), the compiler should have
    caught this error. In other words, it's very likely that the code you
    posted is not the same as your actual code. Always copy-and-paste the
    *exact* code you're having trouble with; don't paraphrase it, and
    don't try to re-type it. Recommended reading:
    <http://www.catb.org/~esr/faqs/smart-questions.html>.

    It's a good idea to add a "return 0;" at the end of the main function.

    --
    Keith Thompson (The_Other_Keith) <>
    Nokia
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Mar 12, 2008
    #4
  5. Mike

    user923005 Guest

    On Mar 11, 11:27 pm, Mike <> wrote:
    > Hi
    >
    > #include<stdio.h>
    > main()
    > {
    >   char s[]="Taiwan University.";
    >   float a;
    >   scanf("%f",&a);
    >   printf("%f",a);
    >   printf("input string:");
    >   gets(s);
    >   puts("%s",s);
    >
    > }
    >
    > After compiled by Visual Studio, the above program can input a.
    > But after it shows a, then I cannot enter s string.
    > Why?


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

    char *getsafe(char *buffer, int count)
    {
    char *result = buffer,
    *np;
    if ((buffer == NULL) || (count < 1))
    result = NULL;
    else if (count == 1)
    *result = '\0';
    else if ((result = fgets(buffer, count, stdin)) != NULL)
    if (np = strchr(buffer, '\n'))
    *np = '\0';
    return result;
    }

    int main(void)
    {
    char s[256] = "Taiwan University.";
    int converted;
    float a;
    puts("Enter a floating point number:");
    if (getsafe(s, sizeof s)) {
    converted = sscanf(s, "%f", &a);
    if (converted == 1)
    printf("%f\n", a);
    else
    puts("Failed to collect a float from standard input.");
    puts("input string:");
    if (getsafe(s, sizeof s))
    puts(s);
    else
    puts("Failed to collect a string from standard input.");
    } else {
    puts("Failed to collect a floating point input from standard
    input.");
    }
    return 0;
    }
    user923005, Mar 12, 2008
    #5
  6. Mike wrote:
    > Hi
    >
    > #include<stdio.h>
    > main()
    > {
    > char s[]="Taiwan University.";
    > float a;
    > scanf("%f",&a);
    > printf("%f",a);
    > printf("input string:");
    > gets(s);
    > puts("%s",s);
    > }
    >
    > After compiled by Visual Studio, the above program can input a.
    > But after it shows a, then I cannot enter s string.
    > Why?
    >
    > Mike


    Just to add to the other posts, your string literal "Taiwan University."
    is of type const char *. You should not assign anything to it, because
    it might be stored in a place in memory to which your program cannot
    write, at which point it will crash (this idea can be summarized easily:
    never cast away the constness of string literals). Have a look at
    malloc() and free() instead, or just declare an array of char, eg. char
    s[81].

    If you're feeling a bit overwhelmed with all these replies, being a
    newbie, note that strings are much more complicated than other variables
    in C.

    --
    --Falcon Kirtaran
    Falcon Kirtaran, Mar 12, 2008
    #6
  7. Falcon Kirtaran <> writes:

    > Mike wrote:
    >>
    >> #include<stdio.h>
    >> main()
    >> {
    >> char s[]="Taiwan University.";

    <snip>
    >> }

    <snip>
    > Just to add to the other posts, your string literal "Taiwan
    > University." is of type const char *.


    Not in C. The elements have type char and are read-only but the
    standard stops just short of saying that they have type "const char".

    > You should not assign anything
    > to it,


    It is just as well, then, that the OP does not do that! 'char s[] =
    "...";' is not the same as 'char *s = "...";' -- I am sure this is
    covered in the FAQ.

    To the OP: apart from using gets (never do that) it is perfectly OK
    to change the contents of your array 's'. The string literal is used
    only to initialise it, after that, you can change it as much as you
    want.

    Had you written 'char *s = "something";' then you can not change the
    data pointed to by 's' -- the arrays created by string literals are
    read-only and any attempt to change them is undefined (i.e. bad things
    could happen).

    > because it might be stored in a place in memory to which your
    > program cannot write, at which point it will crash (this idea can be
    > summarized easily: never cast away the constness of string
    > literals).


    I think a less confusing rule (for C) is that one should treat string
    literals as if there were const.

    --
    Ben.
    Ben Bacarisse, Mar 12, 2008
    #7
  8. Mike

    Richard Bos Guest

    Falcon Kirtaran <> wrote:

    > Just to add to the other posts, your string literal "Taiwan University."
    > is of type const char *.


    No, it's not. It's of type char * (not const), but the text is not
    (reliably) writable. This is illogical, but it's for hysterical raisins.

    Richard
    Richard Bos, Mar 12, 2008
    #8
  9. Mike <> writes:
    > #include<stdio.h>
    > main()
    > {
    > char s[]="Taiwan University.";

    [...]
    > }

    [...]

    At least one person has remarked on the fact that the code set the
    array s to the value "Taiwan University." and then overwrites it.

    In fact, given the empty square brackets, the initializer does two
    things: it determines the initial value of s and it determines its
    size (19 bytes in this case). Copying the string "Taiwan University."
    into s is a bit wasteful, but it's a fairly concise way to say that
    you want s to be big enough to hold that particular string value.

    An alternate way to do the same thing is:

    char s[sizeof "Taiwan University." + 1];

    but it's easy to forget the "+ 1" (needed to allow for the terminating
    '\0').

    I'm resisting the temptation to propose adding a new feature to the
    language so you can write:
    char s[] != "Taiwan University."; /* :cool:} */
    to set the size without initializing the array.

    (Of course, 19 bytes isn't big enough to make the program immune to
    buffer overruns, but we've covered that.)

    --
    Keith Thompson (The_Other_Keith) <>
    Nokia
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Mar 12, 2008
    #9
  10. Keith Thompson wrote:

    > Mike <> writes:


    >> char s[]="Taiwan University.";


    > it's a fairly concise way to say that
    > you want s to be big enough to hold that particular string value.
    >
    > An alternate way to do the same thing is:
    >
    > char s[sizeof "Taiwan University." + 1];
    >
    > but it's easy to forget the "+ 1" (needed to allow for the
    > terminating '\0').


    Oops, it seems as easy to confuse sizeof with strlen, too.

    Ralf
    Ralf Damaschke, Mar 12, 2008
    #10
  11. Mike

    John Bode Guest

    On Mar 12, 1:27 am, Mike <> wrote:
    > Hi
    >
    > #include<stdio.h>
    > main()
    > {
    > char s[]="Taiwan University.";
    > float a;
    > scanf("%f",&a);
    > printf("%f",a);
    > printf("input string:");
    > gets(s);
    > puts("%s",s);
    >
    > }
    >
    > After compiled by Visual Studio, the above program can input a.
    > But after it shows a, then I cannot enter s string.
    > Why?
    >
    > Mike


    When you type in your floating point number (3.14159, for example) and
    hit Enter, the input stream looks like this:

    {'3','.','1','4','1','5','9',\n}

    After the call to scanf(), the newline character is still left in the
    input stream:

    {\n}

    because scanf() with the %f conversion specifier stops reading at the
    first character that isn't part of a valid floating-point constant.

    gets() reads up to the next newline character; since there's already a
    newline character in the input stream left over from the last input
    operation, it returns immediately.

    There are two ways around this. The easy way is to stick a getchar()
    after the scanf() to consume the newline. A somewhat more involved
    (but ultimately safer) way is to read your floating-point number in as
    a string using fgets() (*NOT* gets()), and then convert using sscanf()
    or strtod().

    Do not use gets(); it *WILL* introduce a point of failure in your
    code. Use fgets() instead:

    fgets(s, sizeof s, stdin);

    Unlike gets(), fgets() writes the trailing newline to your buffer.
    John Bode, Mar 12, 2008
    #11
  12. Ralf Damaschke <> writes:
    > Keith Thompson wrote:
    >> Mike <> writes:
    >>> char s[]="Taiwan University.";

    >
    >> it's a fairly concise way to say that
    >> you want s to be big enough to hold that particular string value.
    >>
    >> An alternate way to do the same thing is:
    >>
    >> char s[sizeof "Taiwan University." + 1];
    >>
    >> but it's easy to forget the "+ 1" (needed to allow for the
    >> terminating '\0').

    >
    > Oops, it seems as easy to confuse sizeof with strlen, too.


    Absolutely; good catch. (sizeof "string literal" already includes the
    trailing '\0'; the +1 is unnecessary.)

    (As it happens, I realized I had made this error as I was driving to
    work this morning; I haven't had a chance to post until now.)

    --
    Keith Thompson (The_Other_Keith) <>
    Nokia
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Mar 13, 2008
    #12
  13. On Wed, 12 Mar 2008 06:59:36 GMT, Micah Cowan <>
    wrote:

    > Mike <> writes:

    <snip other points>
    > > printf("input string:");

    >
    > If stdout is line-bufered, you won't see this prompt before it starts
    > expecting input.
    >

    Actually, you probably will; see 7.19.3p3 about "input is requested".
    (Barring the UB earlier for an uninit float.) But you _might_ not.

    > > gets(s);
    > > puts("%s",s);

    >
    > Since gets() strips newlines, puts() won't print one, so you may not
    > see this output either.
    >

    _printf_, which the OP apparently meant, wouldn't add a newline,
    but _puts()_ would -- but would be called as puts(s) .

    > Aside from that, gets() is unsafe.
    >

    That too.

    - formerly david.thompson1 || achar(64) || worldnet.att.net
    David Thompson, Mar 24, 2008
    #13
    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. Jerry C.
    Replies:
    8
    Views:
    228
    Uri Guttman
    Nov 23, 2003
  2. Kruno Saho
    Replies:
    0
    Views:
    134
    Kruno Saho
    Apr 7, 2013
  3. Dave Angel
    Replies:
    0
    Views:
    116
    Dave Angel
    Apr 7, 2013
  4. rusi
    Replies:
    0
    Views:
    106
  5. Miki Tebeka
    Replies:
    0
    Views:
    81
    Miki Tebeka
    Apr 7, 2013
Loading...

Share This Page