Thread: How to determine if input is numerical

  1. #1
    Registered User
    Join Date
    Dec 2009
    Posts
    3

    How to determine if input is numerical

    I'm writing a program to work with complex numbers. It actually works well for what I need it for but there is a problem I would like to solve. Here is the code in question:
    Code:
        int option;
        do {
            printf("\nHere are the options for the complex number arithmetic program:");
            printf("\n1. Add two complex numbers.");
            printf("\n2. Subtract two complex numbers.");
            printf("\n3. Multiple two complex numbers.");
            printf("\n4. Divide two complex numbers.");
            printf("\n5. Find the conjugate of a complex number.");
            printf("\nEnter the number of your choice and press enter:");
            scanf("%d",&option);
    } while (option<1 || option>5);
    printf("SUCCESS");
    Right now if I enter a number it works quite well. But let's say I entered the word "banana". The program crashes. How can I avoid this?

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    You can check the return value of scanf(). If it is not 1, you handle the input error accordingly.

    Alternatively, you can use say, fgets() in conjunction with sscanf(), in which case "banana" would be read as a string, so there would be no need to discard the invalid input remaining on the standard input stream, and you can still check the return value of sscanf().
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #3
    Registered User jeffcobb's Avatar
    Join Date
    Dec 2009
    Location
    Henderson, NV
    Posts
    875
    Call atoi or atof on the string; if it fails, you are dealing w/non-numeric data...
    C/C++ Environment: GNU CC/Emacs
    Make system: CMake
    Debuggers: Valgrind/GDB

  4. #4
    Registered User
    Join Date
    Oct 2008
    Location
    TX
    Posts
    2,059
    Scan it as a string, then parse to determine if it's numerical or not.

  5. #5
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by jeffcobb
    Call atoi or atof on the string; if it fails, you are dealing w/non-numeric data...
    There is no string variable

    Anyway, although that will work in this case (if the input was stored in a string), more generally there is no way to distinguish between failure and a legitimate zero with atoi and company, so strtol and company should normally be used instead where input validation is desired.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  6. #6
    Registered User
    Join Date
    Dec 2009
    Posts
    3
    So how do I check the return value of scanf? Would I need to use %s or %1c instead of %i or is there something else I can do? I don't really care if I can't distinguish between a legitimate zero and failure, I only need to know if the input value is between 1 and 5. I tried using something like
    Code:
            if(scanf("%d",&option)!=1)
            option=0;
    But I don't think this will work... In fact it doesn't seem to do anything at all right now lol.

  7. #7
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by Fdisk
    But I don't think this will work... In fact it doesn't seem to do anything at all right now lol.
    It works, except that your error handling is incomplete. You need to discard the invalid input remaining on the standard input stream. This is why just reading it as a string to begin with is easier.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  8. #8
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    If you want to read the input as a string and then parse numbers from it:
    Code:
    char string[BUFSIZ];
    int number;
    if(!fgets(string, sizeof string, stdin)) {
        /* end of input detected, perhaps you want to quit the program */
    }
    else if(sscanf(string, "%d", &number) != 1) {
        /* invalid number entered */
    }
    else {
        printf("You entered %d.\n", number);
    }
    If you want to simply strip the remaining characters from the input: Trouble with assignment in C
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  9. #9
    Woof, woof! zacs7's Avatar
    Join Date
    Mar 2007
    Location
    Australia
    Posts
    3,459
    You'll probably want to do some range checking also...

    Code:
    /* return 0 on success */
    int parse_ulint(const char * buffer, unsigned long int * dest)
    {
       unsigned long int tmp = 0;
       char * ep = NULL;
    
       assert(buffer != NULL);
       assert(dest != NULL);
    
       /* reset errno and attempt to parse */
       errno = 0;
       tmp = strtoul(buffer, &ep, 10);
    
       if(buffer[0] == '\0' || *ep != '\0')
       {
          return -2;        /* not a number */
       }else if(errno == ERANGE && tmp == ULONG_MAX){
          return -3;        /* range error */
       }else if(errno != 0){
          return -1;        /* some other error */
       }
    
       /* store the parsed value */
       *dest = tmp;
       return 0; /* success */
    }
    Of course if you just want integers, then just check for INT_MAX or INT_MIN (and use strtol instead of strtoul) from limits.h and return failure if the long int is outside of that range.

    Then all you need to do is read with fgets() as others suggest.
    Last edited by zacs7; 02-11-2010 at 03:31 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Input class project (again)
    By Elysia in forum C++ Programming
    Replies: 41
    Last Post: 02-13-2009, 10:52 AM
  2. I would love some input on my BST tree.
    By StevenGarcia in forum C++ Programming
    Replies: 4
    Last Post: 01-15-2007, 01:22 AM
  3. About aes
    By gumit in forum C Programming
    Replies: 13
    Last Post: 10-24-2006, 03:42 PM
  4. Structure and Linked List User Input Question
    By kevndale79 in forum C Programming
    Replies: 16
    Last Post: 10-05-2006, 11:09 AM
  5. need help with some input
    By blindleaf in forum C Programming
    Replies: 2
    Last Post: 03-16-2003, 01:50 PM