#1
  1. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Nov 2012
    Posts
    132
    Rep Power
    2

    Help with a function


    i wrote a function that checks if the user typed in a valid integer number.
    the function works perfectly, but there's a little problem:

    whenever the user enters an invalid input (any non digit character) - the function returns the value 0.
    and if the input is valid (i.e a number - any number) - the function returns it to the main program.
    the problem is - 0 is a valid number, so if the user enters 0 or he enters a wrong input - either way - the function will return 0, so the main program can't tell between these two scenarios.
    is there a way to overcome this situation?

    Thanks and have a nice weekend!
  2. #2
  3. Lord of the Dance
    Devshed Expert (3500 - 3999 posts)

    Join Date
    Oct 2003
    Posts
    3,534
    Rep Power
    1906
    Please post the code for your function.

    Will negative number be valid as well? if no, you could return -1 for invalid number format.

    If the function should only check if number is valid, it would be enough to return true (1) or false (0).
  4. #3
  5. No Profile Picture
    Contributing User
    Devshed Intermediate (1500 - 1999 posts)

    Join Date
    Feb 2004
    Location
    San Francisco Bay
    Posts
    1,939
    Rep Power
    1313
    The standard library function strtol shows one way of overcoming this limitation: give the caller a pointer to the end of the valid input. Then the caller can check whether it coincides with the end of the string (for example, if the whole string was supposed to represent an integer).
  6. #4
  7. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Nov 2012
    Posts
    132
    Rep Power
    2
    Hi MrFujin.

    thanks for the help.

    yes, negative number is valid as well.

    here's the code:


    Code:
    int InputCheck()
    {
    
      char c;
      int num1=0, num2=0, i=1, minus=0;
    
       do
       {
        c=getchar();
        if ((c=='-')&&(i==1))  //checks if first char is minus - i.e if number is negative
          minus=1;
        if (isdigit(c))  //checks if char is a digit
         {
          num1+=(c-'0')*i;   //saves the digit as integer
          i*=10;
         }
        else if ((c!='\n')&&(c=='-')&&(i!=1))  //if char isn't a digit
          return 0;
       }while (c!='\n');
    
       for ( i/=10 ; i>=1 ; i/=10,num1/=10 )  //loop to flip the number backwards
          num2+=(num1%10)*i;
       return minus==1 ? -num2 : num2 ;
    }
  8. #5
  9. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Nov 2012
    Posts
    132
    Rep Power
    2
    Hi Lux Perpetua.
    im not allowed to use arrays, or anything outside the stdio.h library.
  10. #6
  11. Contributing User
    Devshed Demi-God (4500 - 4999 posts)

    Join Date
    Aug 2011
    Posts
    4,704
    Rep Power
    480
    ctypes.h declares isdigit . (Your instructions wouldn't prevent me from using isdigit.)

    /*
    * InputCheck returns status 0 if the
    * result is valid, otherwise returns 1.
    */

    int InputCheck(int *result);


    I'd also write

    int minus=1;
    ...
    *result = minus*num2;

    I've reduced the code complexity. It's simpler because there are fewer paths through the function.
    Last edited by b49P23TIvg; December 1st, 2012 at 01:20 PM.
    [code]Code tags[/code] are essential for python code and Makefiles!
  12. #7
  13. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,091
    Rep Power
    2222
    as you were
    Last edited by dwise1_aol; December 1st, 2012 at 01:40 PM.
  14. #8
  15. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Nov 2012
    Posts
    132
    Rep Power
    2
    Hi b49P23TIvg.
    thanks for the great help.

    sorry for not pointing that out earlier: i'm not allowed to use pointers either (nor recursion)... :chomp:
  16. #9
  17. Contributing User
    Devshed Demi-God (4500 - 4999 posts)

    Join Date
    Aug 2011
    Posts
    4,704
    Rep Power
    480
    I think c allows a function to return a structure. I've never explicitly written such code, but if you can then you could return 2 variables at once.

    Another option: save the success as a static variable. Since we love encapsulation,
    Code:
    int InputCheck(int mode) {
      static int successful;
      if (mode) {
        int temp = successful;
        successful = 0;
        return temp;
      }
      /* continue with rest of function */
      /* make sure to set successful to 1 if the data was ok */
    Are you quite sure you understand your assignment? Professional footballers aren't required to bind their legs in burlap sacks.

    Anyway, then you'd call InputCheck(0); to get an int, and InputCheck(1); to see if the value was valid. This is ridiculous.
    Last edited by b49P23TIvg; December 1st, 2012 at 02:16 PM.
    [code]Code tags[/code] are essential for python code and Makefiles!
  18. #10
  19. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Nov 2012
    Posts
    132
    Rep Power
    2
    Originally Posted by b49P23TIvg
    Are you quite sure you understand your assignment? Professional footballers aren't required to bind their legs in burlap sacks.
    i couldn't agree more.
    the idea to define a function to check the input was mine.
    the assignment is to write a program that obtain as input an integer number, and prints the fibonacci sequence up to the number given.
    for example, if the input is 9, the output should be:
    0 1 1 2 3 5 8
    if the input is -7, the output is an empty line.

    but that's the easy part.
    the real pain is that for any input that isn't a valid number, the program should print: "Wrong input!"
  20. #11
  21. Contributing User

    Join Date
    Aug 2003
    Location
    UK
    Posts
    5,074
    Rep Power
    1802
    Use the return value purely as a validity flag, and return the input value via a pointer argument that points to a caller variable.

    Code:
    int inputInteger( int* answer )
    {
      
        // Get and validate input...
        ....
    
        // If input OK, assign it to caller's variable
        if( input_valid )
        {
            *answer = value ;
        }
    
        // Return validity flag
        return input_valid ;
    }
    Where input_valid is zero for invalid and non-zero for valid. Then this is called thus (for example):
    Code:
    int value ;
    valid = inputInteger( &value ) ;
    if( valid )
    {
        // value has input
    }
    Since you did not specify I have assumed that you are using C code and lower-common denominator C89; i.e. no built-in boolean and no reference types. C99 and C++ have features that could improve this code a little.

    An alternative is to return a structure that has a validity flag and a value, but that is not really the most appropriate solution in this case.
  22. #12
  23. Contributing User

    Join Date
    Aug 2003
    Location
    UK
    Posts
    5,074
    Rep Power
    1802
    Originally Posted by b49P23TIvg
    Another option: save the success as a static variable.
    But we might love reentrancy more! :eek:
  24. #13
  25. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,091
    Rep Power
    2222
    Here's a thought: what are the chances of the user entering the greatest magnitude negative number? Highly unlikely, so why not use that value to indicate wrong input?

    limits.h contains macros that define the limits of values for the various datatypes; eg:
    Code:
    /*
     * Maximum and minimum values for ints.
     */
    #define INT_MAX		2147483647
    #define INT_MIN		(-INT_MAX-1)
    
    #define UINT_MAX	0xffffffff
    You could use either INT_MAX or INT_MIN, both highly unlikely input values. The main point in choosing a value to indicate an invalid value is that it be one that should not otherwise appear.

    Another thought is that the stricture against pointers should not apply to using them in the parameter list of your function, which is not part of the assignment description. Most programming assignments are designed to have you practice what you have learned in class or in your reading assignments and that is why they will often restrict you from using a different technique. Since your assignment is apparently not supposed to be about other methods for returning certain information from a function, you should be free to use a pointer to return the input value via a pointer and the status as the return value, or vice-versa, especially if you annotate what you are doing and why in your comments and you do not use pointers elsewhere, thus demonstrating that you are conforming to the spirit of the assignment. Discussing this point with your instructor might also help; as I learned early on in military bureaucracy, rules are made to address a specific problem, but can have consequences unforeseen by the writers of those rules -- the same seems to apply to laws. If your problem is an unforeseen consequence of his restrictions, your instructor may give you permission to use a pointer in this one case. If unable to speak with him in order to obtain permission, then there's always the old adage: "Forgiveness is always easier to obtain than permission."

    Comments on this post

    • Lux Perpetua agrees
  26. #14
  27. No Profile Picture
    Contributing User
    Devshed Intermediate (1500 - 1999 posts)

    Join Date
    Feb 2004
    Location
    San Francisco Bay
    Posts
    1,939
    Rep Power
    1313
    Originally Posted by dwise1_aol
    Here's a thought: what are the chances of the user entering the greatest magnitude negative number? Highly unlikely, so why not use that value to indicate wrong input?
    This is a really great answer. Integers that are close to the limits of the data type are likely to cause overflow under subsequent manipulation, anyway, so it's hardly a huge loss to sacrifice INT_MIN as an error indicator. Moreover, two's-complement integers already have one more negative value than positive values, and INT_MIN specifically is pathological (for example, -INT_MIN == INT_MIN (the negative of the most negative integer is negative!)), but removing INT_MIN makes everything symmetric.

IMN logo majestic logo threadwatch logo seochat tools logo