+ Reply to Thread
Results 1 to 3 of 3

Thread: User Input: Strings and Numbers [C]

  1. #1
    dcs
    dcs is offline
    Guru dcs is just really nice dcs is just really nice dcs is just really nice dcs is just really nice
    Join Date
    Mar 2008
    Posts
    768

    User Input: Strings and Numbers [C]

    User Input: Strings and Numbers [C]

    Very early on when attempting to learn programming in C, you often do exercises that read in and print out strings and numbers. Now you might assume that C has a simple function that will get user input, and indeed it does, but there are a couple of gotchas that can easily trip up those new to programming in C.

    There are two things to vigorously avoid, and unfortunately they are all too commonly seen:
    Code:
    char text[20];
    gets(text); /* NEVER USE gets() */
    scanf("%s", text); /* MANY HIDDEN GOTCHAS */
    So how do you do it right? The short answer is to use fgets to read a line of text. However, please note that when you enter text, you press the [Enter] or [Return] key and this character does not just vanish, it remains in the input buffer. For example:

    Code:
    #include <stdio.h>
     
    int main(void)
    {
       char text[20];
       fputs("enter some text: ", stdout);
       fflush(stdout); /* Question 12.4 */
       fgets(text, sizeof text, stdin);
       printf("text = \"%s\"\n", text);
       return 0;
    }
    enter some text: hello world
    text = "hello world
    "
    So when reading strings, you often want to remove this newline. Be careful though, because it is not always there! When the incoming text is one less than the size of the buffer, the newline is retained. You can search for the newline and overwrite it with a null terminator.

    --- skimmers start here ---
    Code:
    #include <stdio.h>
    #include <string.h>
     
    int main(void)
    {
       char text[20];
       fputs("enter some text: ", stdout);
       fflush(stdout);
       if ( fgets(text, sizeof text, stdin) != NULL )
       {
          char *newline = strchr(text, '\n'); /* search for newline character */
          if ( newline != NULL )
          {
             *newline = '\0'; /* overwrite trailing newline */
          }
          printf("text = \"%s\"\n", text);
       }
       return 0;
    }
    enter some text: hello world
    text = "hello world"
    There are many other ways to do this, but this is very frequently recommended and always correct.

    --- skimmers stop here ---

    If you are reading a number, then first read in the input string and consequently follow it with a call to sscanf or strtol to convert it to a number.

    Code:
    #include <stdio.h>
     
    int main(void)
    {
       char text[20];
       fputs("enter some number: ", stdout);
       fflush(stdout);
       if ( fgets(text, sizeof text, stdin) )
       {
          int number;
          if ( sscanf(text, "%d", &number) == 1 )
          {
             printf("number = %d\n", number);
          }
       }
       return 0;
    }
    enter some number: 42
    number = 42
    The newline does not need to be removed, unless you choose to, because it is whitespace and is not part of a valid number. You may find the following related code snippets regarding the input of numbers and text useful:


    To recap, here is why not to do what I said not to do! First, never use gets. It is included as a standard library function only as a holdover from pre-C89 code (the standards committee opted in the interest of not breaking existing code). But it is inherently and notoriously unsafe because there is no way to tell it the size of the buffer into which data will be read. So it is always a risk for buffer overflow, which may be used as an exploit. If you ever want to be employed as a programmer, it's best not to ever let a potential employer see you use this function!

    As for scanf it is a truly complicated beast, and should certainly not be the first choice for someone just starting out programming in C. One of the first issues with scanf("%s", str); is it suffers from a very similar problem as gets, which is the incoming buffer size is not specified. If you didn't look up the description of %s you may not have known that this directive is whitespace-delimited. Which means that it if the user enters hello world, then str will be hello. There are more gotchas, such as if you are also using scanf to read integers, perhaps using scanf("%d", &i);, then the same whitespace issue may bite you. Remember that when you enter text you press the [Enter] or [Return] key and it remains in the input buffer. This can cause issues when mixed with other input functions such as getchar. There is also another insidious issue that comes up when using scanf: the "need" to flush the input buffer.

    Or again, it is widely known by good programmers and potential employers that these are things to avoid. But if you still aren't convinced, listed below are many FAQs that say pretty much the same thing (mostly because I'm saying pretty much what they are saying).


    And don't think I presented a comprehensive list of gotchas associated with scanf, these were merely some common ones!

    There is another insidious issue that comes up when using scanf: the "need" to flush the input buffer. All too often we see fflush(stdin); used to "fix" this. But actually this one problem with scanf breeds another:

    Last edited by dcs; 09-27-2008 at 09:44 PM.

  2. #2
    Guru Aereshaa is just really nice Aereshaa is just really nice Aereshaa is just really nice Aereshaa is just really nice Aereshaa is just really nice Aereshaa's Avatar
    Join Date
    Apr 2008
    Posts
    784
    Blog Entries
    5

    Re: User Input: Strings and Numbers [C]

    Very nice, +repped.

  3. #3
    Programming God outsid3r has a spectacular aura about outsid3r has a spectacular aura about outsid3r's Avatar
    Join Date
    Jul 2008
    Location
    Portugal
    Posts
    564

    Re: User Input: Strings and Numbers [C]

    I consider this post really important, many people start C doing gets and other very unsafe functions, like i started, and i have read books of university teachers using many unsafe functions, which is a lot strange for a person of that graduation.
    Rep+

    Edit: well, i can't rep now after all :S

+ Reply to Thread

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

     

Similar Threads

  1. Clipboard Game
    By Jordan in forum Games
    Replies: 3479
    Last Post: 02-18-2010, 04:10 PM
  2. CodeCall Contest #6
    By Jordan in forum Announcements
    Replies: 143
    Last Post: 11-21-2008, 05:55 AM
  3. Strings (CrashCourse)
    By LogicKills in forum C Tutorials
    Replies: 3
    Last Post: 09-17-2008, 07:28 PM
  4. Replies: 5
    Last Post: 07-07-2008, 09:54 PM
  5. [C++] Validating user input
    By Xochiquetzal in forum C and C++
    Replies: 2
    Last Post: 07-08-2007, 05:18 PM

Bookmarks

Bookmarks

     
        Algorithms and Data Structures

        Java tutorials

        Algorithms Forum

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts