Thread: Validade input for integers, but a space is messing it up

  1. #1
    Registered User FernandoBasso's Avatar
    Join Date
    Oct 2011
    Location
    Brazil
    Posts
    45

    Validade input for integers, but a space is messing it up

    This is the code I have so far:
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    /* TODO: Fazer a validação para quando o usuário digita um espaço,
     * pois está dando um resultado inesperado, como se um <Enter> estivesse
     * sendo pressionado. */
    
    /* TODO: Problem when the user  a <Space> followed by <Enter> */
    
    #define TRUEINT 1
    
    void clear_screen ( void );
    
    int main ( void ) {
    
        int iNum1 = 0;
        int iNum2 = 0;
    
        clear_screen();
    
        printf("A program that asks for two numbers and show them.\n\n");
    
        /* First integer. */
        printf("Enter an -integer-: ");
        while (scanf("%d", &iNum1) != TRUEINT) {
            while  ( getchar() != '\n' ); // Limpa o buffer.
            printf("Not an integer: ");
        }
    
        /* Second integer. */ 
        printf("Enter the second -integer-: ");
        while (scanf("%d", &iNum2) != TRUEINT) {
            while ( getchar() != '\n' ); // Limpa o buffer.
            printf("Not an integer: ");
        }
        printf("\t%d, %d\n", iNum1, iNum2);
    
        return EXIT_SUCCESS;
    }
    
    void clear_screen(void) {
        if (system("clear")) system("cls");
    }
    The problem is that when I hit <Space> followed by <Enter>, I get I new line in the prompt, and not the message that it is not an integer.

    Any help would be appreciated. Thanks in advance.

  2. #2
    SAMARAS std10093's Avatar
    Join Date
    Jan 2011
    Location
    Nice, France
    Posts
    2,694
    scanf() reads the input, matching the characters from format. When a control character is read, it puts the value in the next variable. Whitespace (tabs, spaces, etc) are skipped.
    So when the input is just a space and then you hit enter then you get trapped at the loop of line 25

  3. #3
    Registered User FernandoBasso's Avatar
    Join Date
    Oct 2011
    Location
    Brazil
    Posts
    45
    Quote Originally Posted by std10093 View Post
    scanf() reads the input, matching the characters from format. When a control character is read, it puts the value in the next variable. Whitespace (tabs, spaces, etc) are skipped.
    So when the input is just a space and then you hit enter then you get trapped at the loop of line 25
    What what could I use instead of scanf? Or perhaps a different kind of check... ?

  4. #4
    SAMARAS std10093's Avatar
    Join Date
    Jan 2011
    Location
    Nice, France
    Posts
    2,694
    If i were you,i would keep scanf on play.However you should eat all the whitespaces(you can extend it to eating tabs as well).So,read the input ,eat whitespaces and enter's and then check if it is an int or not.
    Code:
        #include <stdio.h>
    #include <stdlib.h>
     
    /* TODO: Fazer a validação para quando o usuário digita um espaço,
     * pois está dando um resultado inesperado, como se um <Enter> estivesse
     * sendo pressionado. */
     
    /* TODO: Problem when the user <enters> a space and then <Enter> */
     
    #define TRUEINT 1
     
    void clear_screen ( void );
     
    int main ( void ) {
     
        int iNum1 = 0;
        int iNum2 = 0;
        int c;
     
        clear_screen();
     
        printf("A program that asks for two numbers and show them.\n\n");
     
        /* First integer. */
        printf("Enter an -integer-: ");
        
        do//check for whitespaces
        {
            c = getchar();//grab the first character of the input
            if( c == '\n')//we reached the end of input and no number was found
                printf("Please insert an integer\n");//so print message
        }while( c == ' ' || c == '\n');//if it enter or whitespace,eat them
        ungetc(c,stdin);//something we need to read so put back in stream stdin
        while (scanf("%d", &iNum1) != TRUEINT) {
            while  ( getchar() != '\n' ); // Limpa o buffer.
            printf("Not an integer: ");
        }
        
        c = getchar();//eat the '\n' from the first input
        /* Second integer. */
        printf("Enter the second -integer-: ");
        do
        {
            c = getchar();
            if( c == '\n')//we reached the end of input and no number was found
                printf("Please insert an integer\n");
        }while( c == ' ' || c == '\n');
        ungetc(c,stdin);
        while (scanf("%d", &iNum2) != TRUEINT) {
            while ( getchar() != '\n' ); // Limpa o buffer.
            printf("Not an integer: ");
        }
        printf("\t%d, %d\n", iNum1, iNum2);
     
        return EXIT_SUCCESS;//why not use return 0; instead?
    }
     
    void clear_screen(void) {
        if (system("clear")) system("cls");
    }
    If you have any questions,please ask me

  5. #5
    Registered User FernandoBasso's Avatar
    Join Date
    Oct 2011
    Location
    Brazil
    Posts
    45
    std10093, that was an improvement. Thanks. But, try hitting <Tab> several times before <Enter>.
    I just see empty new lines, and no messages any more.


    EDIT:
    Oh, I just added || c == '\t':

    Code:
    // ....
        } while ( c == ' ' || c == '\n' || c == '\t'); // If it is an enter or whitespace or tab, eat them.
    Last edited by FernandoBasso; 08-04-2012 at 09:35 AM.

  6. #6
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by FernandoBasso
    Code:
    #define TRUEINT 1
    
    scanf("%d", &iNum1) != TRUEINT
    scanf returns the number of input items assigned, or EOF if there was an error before conversion. As such, TRUEINT is a misleading macro name. I would directly compare to 1.

    Quote Originally Posted by FernandoBasso
    What what could I use instead of scanf? Or perhaps a different kind of check... ?
    I suggest reading line by line as a string into an array of char. Then, use strtol to convert the string to long, with error checking.
    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

  7. #7
    Registered User FernandoBasso's Avatar
    Join Date
    Oct 2011
    Location
    Brazil
    Posts
    45
    Quote Originally Posted by laserlight View Post
    scanf returns the number of input items assigned, or EOF if there was an error before conversion. As such, TRUEINT is a misleading macro name. I would directly compare to 1.
    I suggest reading line by line as a string into an array of char. Then, use strtol to convert the string to long, with error checking.
    I'll take a look at that. Thanks.

  8. #8
    SAMARAS std10093's Avatar
    Join Date
    Jan 2011
    Location
    Nice, France
    Posts
    2,694
    Quote Originally Posted by FernandoBasso View Post
    std10093, that was an improvement. Thanks. But, try hitting <Tab> several times before <Enter>.
    I just see empty new lines, and no messages any more.


    EDIT:
    Oh, I just added || c == '\t':

    Code:
    // ....
        } while ( c == ' ' || c == '\n' || c == '\t'); // If it is an enter or whitespace or tab, eat them.
    That's why i wrote on my previous post
    "However you should eat all the whitespaces(you can extend it to eating tabs as well)"

  9. #9
    Registered User FernandoBasso's Avatar
    Join Date
    Oct 2011
    Location
    Brazil
    Posts
    45
    Quote Originally Posted by std10093 View Post
    That's why i wrote on my previous post
    "However you should eat all the whitespaces(you can extend it to eating tabs as well)"
    Sure. Sorry for my C n00bness.

    I promise I'll improve my skills.

    Thanks.

  10. #10
    Registered User
    Join Date
    Aug 2005
    Location
    Austria
    Posts
    1,990
    Quote Originally Posted by FernandoBasso View Post
    I promise I'll improve my skills.
    You are already. Aren't you ?
    Kurt

  11. #11
    Registered User
    Join Date
    May 2012
    Posts
    1,066
    You can simplify your expression by using isspace().

    Bye, Andreas

  12. #12
    Registered User FernandoBasso's Avatar
    Join Date
    Oct 2011
    Location
    Brazil
    Posts
    45
    Well, I'm trying to use strtol to convert a string to long int, following
    FAQ > How do I get a number from the user (C) - Cprogramming.com

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    int getInt(char msg[40], long int *theNum);
    
    int main(void) {
    
        long int theNum;
    
        getInt("Type a num: ", &theNum);
    
        printf("theNum: %ld\n\n", theNum);
    
        return 0;
    }
    
    int getInt(char msg[40], long int *theNum) {
    
        char buf[BUFSIZ];
        char *endPtr;
          
        printf (msg);
    
        if (fgets(buf, sizeof(buf), stdin) != NULL) {
            theNum = strtol(buf, (void *)&endPtr, 10);
    
            if (buf[0] != '\n' && (*endPtr == '\n' || *endPtr == '\0'))
                printf ("Valid number of %ld entered\n", (long int)theNum); 
            else  printf ("The number was %ld, followed by %s\n", (long int)theNum, endPtr);
        }  
    
        return theNum;
    }
    My intention is the have theNum to be updated without having
    to do
    Code:
    theNum = getInt(arg, arg);
    but rather just passing its
    address, like in
    Code:
    getInt("msg", &theNum);
    I'm not being able to change the value of theNum (it always has garbage), and the compiler is giving me the following warnings:

    getIntStrtol.c: In function ‘getInt’:
    getIntStrtol.c:25:16: warning: assignment makes pointer from integer without a cast [enabled by default]
    getIntStrtol.c:32:5: warning: return makes integer from pointer without a cast [enabled by default]

    I understand what the messages mean, but I don't understand why.
    By the way, If I assign the return value to a long int variable, then I can print that variable just fine.


    EDIT: This version seems to work:
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    int getInt(char msg[40], long int *theNum);
    
    int main(void) {
    
        long int theNum;
        long int num;
    
        num = getInt("Type a num: ", &theNum);
    
        printf("theNum: %ld\n\n", theNum);
        printf("num: %ld\n\n", num);
    
        return 0;
    }
    
    int getInt(char msg[40], long int *theNum) {
    
        char buf[BUFSIZ];
        char *endPtr;
          
        printf (msg);
    
        if (fgets(buf, sizeof(buf), stdin) != NULL) {
            *theNum = strtol(buf, &endPtr, 10);
    
            if (buf[0] != '\n' && (*endPtr == '\n' || *endPtr == '\0'))
                printf ("Valid number of %ld entered\n", *theNum); 
            else  printf ("The number was %ld, followed by %s\n", *theNum, endPtr);
        }  
    
        return *theNum;
    }
    Last edited by FernandoBasso; 08-13-2012 at 04:02 AM.

  13. #13
    Registered User
    Join Date
    May 2012
    Posts
    1,066
    Code:
    int getInt(char msg[40], long int *theNum) {
    ...
        return *theNum;
    }
    If you want to return *theNum (a long int) your function definition should also return a long int. Otherwise you'll get a wrong return value for big numbers on systems where int is not the same size as long int.
    I personally would also change "char msg[40]" to "const char *msg" (the array size of 40 is ignored by the compiler anyway).

    Bye, Andreas

  14. #14
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    The code posted does not generate the second warning. The actual code that causes the warning that you pasted here would probably be:
    Code:
    return theNum;
    I.e. you are missing the *, but you put it in when pasting the code here.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  15. #15
    Registered User FernandoBasso's Avatar
    Join Date
    Oct 2011
    Location
    Brazil
    Posts
    45
    You guys are right. Thanks for all the tips.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 4
    Last Post: 10-29-2011, 07:02 PM
  2. space between input
    By dNNNY in forum C Programming
    Replies: 8
    Last Post: 07-15-2008, 12:52 PM
  3. EOF messing up my input stream?
    By Decrypt in forum C++ Programming
    Replies: 4
    Last Post: 09-30-2005, 03:00 PM
  4. Messing with Large Integers
    By johnnie2 in forum Windows Programming
    Replies: 3
    Last Post: 11-16-2002, 01:22 PM
  5. Reading integers until end of input
    By nivo in forum C Programming
    Replies: 7
    Last Post: 10-20-2001, 04:18 PM