Thread: scanf problem

  1. #1
    Registered User
    Join Date
    Nov 2006
    Posts
    58

    scanf problem

    Hi all,

    I have a problem but im not quite sure how to get over it. I will list these below:

    1) Im scanning an input from the keyboard and i want to check that it is not in a certain range on the ASCII table, but when i use scanf it does not work?? I tried using getchar, but the maths of my program functions goes crazy? Please could you advise me on how i can change my if statement so it works.

    Look forward to your advice

    Tuurbo46

  2. #2
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    First of all, instead of posting your (short) code as an attachment, post it inline with code-tags. It makes it easier to see (don't have to click again, which makes the likelyhood of an answer better).

    Code:
    char c = 0;
    
    scanf("%d", &c);
    
     if((c==32)||(c<48)||(c>57)) // ASCII table
     {
              printf("Invalid input\n");
     }
    The %d format is for reading integers, your data is a char. That will lead to some "undefined behaviour", which is a bad thing. For one thing, it will overwrite whatever is after teh char variable with the remaining bytes to the sizeof(int) [usually 4 - so 3 bytes of "overwritten data"].

    You should use %c for reading chars. Or use getchar().

    Second, it is redundant to check if your input is "space" (32) or less than 48 - since the former is true when the latter is true.

    I would also prefer to see
    Code:
    if (c < '0' || c > '9')
    ...
    It saves someone who isn't perfectly up to date with the ascii table to understand what is being checked, as well as making it portable to machines that doesn't specifically use the ASCII character set [this is less of an issue on modern systems, as EBCDIC and other non-ASCII character sets are fairly rare nowadays].

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  3. #3
    Dr Dipshi++ mike_g's Avatar
    Join Date
    Oct 2006
    Location
    On me hyperplane
    Posts
    1,218
    Code:
    char c = 0;
    
    scanf("&#37;d", &c);
    
     if((c==32)||(c<48)||(c>57)) // ASCII table
     {
              printf("Invalid input\n");
     }
    First off wheres your main function?

    To get a character with scanf you want to do: scanf("%c", &c);
    Or better yet; maybe use getchar() to get the character.

    Also if this part: (c==32) is redundant as 32 is less than 48.

    Edit: too late

  4. #4
    Woof, woof! zacs7's Avatar
    Join Date
    Mar 2007
    Location
    Australia
    Posts
    3,459
    why not use isprint() ?

  5. #5
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by zacs7 View Post
    why not use isprint() ?
    You mean "isdigit()" I suppose?

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  6. #6
    Registered User
    Join Date
    Nov 2006
    Posts
    58

    Lightbulb

    Hi,

    Thanks for your help. Such silly mistakes on my part, but important lessons.

    Also thanks for the advise on the ASCII trick.

    Cheers Tuurbo46

  7. #7
    Registered User
    Join Date
    Nov 2006
    Posts
    58
    Hi again,

    Sorry, i have just seen all the other posts;

    1) i used scanf, because this is what i have used before. Is isprint(), or isdigit() better?

    2) I did not include main, because i just added a snap shot to keep it simple.

  8. #8
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    isprint(), isdigit() an dother "is" functions take a character as an argument [1], and tell you if the argument "is a digit" or "is a printable character" [so, it's not a control character for example]. There are about 10 or so different functions that do similar things. It still means that you need to use getchar() or some such to read the character in.

    The "is" functions are excellent for checking if your input "is valid" - if it's a digit, an alpha, alphanumeric, hex digit, etc, etc. They also work on "any character set".

    [1] Technically, the function allows an integer as input - this is so that it's safe to use this funciton on EOF [which is -1]. However, for all intents and purposes, see the input as a char.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  9. #9
    Woof, woof! zacs7's Avatar
    Join Date
    Mar 2007
    Location
    Australia
    Posts
    3,459
    >You mean "isdigit()" I suppose?
    Yes... my bad. At least you got the point, and in the end that's all that really matters eh?

    Just trying to justify my error

  10. #10
    Registered User
    Join Date
    Nov 2006
    Posts
    58
    Hi again,

    After your help, the previous problem is cured, and now i have another problem:

    1) Scanf has to accept both numbers and letter, therefore a char has been used. However if greater than 3000 is entered by the user, the program should write back "number greater than 3000".

    However, my new problem is, if i use a char it will only go upto 256, and if i use an int which has the range, it will not accept letters?

    I have tried "unsigned long char", but this does not work.

    How do i over come this problem?

    Look forward to your advice.

    Tuurbo46

  11. #11
    Registered User
    Join Date
    Nov 2006
    Posts
    58
    Code:
    Something like this, but its out of range:
    
    char c = 0;
    
    scanf("%c", &c);
    
     if((c<'0')||(c>'9'))
     {
              printf("Invalid input\n");
     }
    else if(c>'3000')
    {
             printf("number greater than 3000");

  12. #12
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    I'm not sure what you are actually asking: I presume that what you are really looking for is either:
    1. A way to read an integer, checking each character to see if the character is valid.
    2. Check if what you read (using integer format to scanf()) was accepted by scanf().

    The second option is the easier one:
    The function scanf() will return "the number of correctly entered fields", so if you do
    Code:
      int n;
      int r;
      r = scanf("%d", &n);
      if (r == 1) {
         // Something got accepted as a number. 
      } else {
         // Error, nothing accepted. 
      }
    The above code will not accept "abc", but WILL accept "1234abc" as 1234, leaving "abc" in the input buffer. Another scanf() trying to read an integer from the input buffer of "abc" will not accept the further input of "abc".

    Alternatively, you use getchar() to read each character, and you "build" the number up yourself. This is possibly what you are supposed to do.
    Code:
       int c;
       int n;
       do {
          c = getchar();
          if (isdigit(c))   {
              // form a number
          } else if (c == '\n') {
             // done - but may be "empty" number. 
          } else {
              // Error - something that wasn't a digit entered.
          } 
        } while (moretodo);
    This will ensure that ALL the input was accepted, and that there was no input beyond the "number".

    Note that BOTH will require you to also remove any "garbage" from the input buffer if the input isn't accepted.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  13. #13
    Registered User
    Join Date
    Nov 2006
    Posts
    58
    Hi,

    Im trying to do a integer numbers to roman numeral conversion. I have the program working but i cannot get the error checking working with scanf. The requirements are as follows.

    1) Covert integer numbers to roman numerals - done

    2) If a letter or other none integer number is entered, display invalid input.

    3) If number is greater than 3000, display number greater than 3000.

    My problem is, if i use char, it does not have the range on 3000. If i use int, scanf will not read other letters, other than integers?

    Im sure im making this more compliated than it actually is?

    Should i use sscanf?

    Cheers tuurbo46

  14. #14
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    So, the decision is what constitutes "non-integer number".

    You will in one form or another, need to convert a string of characters into a number - but scanf() will in the "simple" case do that for you. However, that assumes we accept "1234abc" as a valid input, as there's no trivial check we can do to detect this particular error.

    If we have to print an error for "1234abc", then the most immediate solution is to read a character at a time - this character will have the ASCII code of one digit for each input, so although the data would be 1-byte, and have a range of -128..127 (or unsigned char 0..255), but the data you will get is a single digit '0'..'9' each time. So you will need to do a conversion into an integer - consider this as the same task as if you where given a number at a time and had to come up with what the whole number is. It is not very hard to do, but involves a little loop.

    Once you have an integer, you can easily check if it's above 3000 and print an error.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  15. #15
    Registered User
    Join Date
    Nov 2006
    Posts
    58
    Hi,

    Please can you break this down a bit for me, i just use scanf as a black box, and i dont really understand any further. As shown in the examples below, if i enter 1111, scanf returns 1111, but if i enter abcd, 0 is returned. I understand this means it is false, so therefore do i display "false input" if a zero is returned?

    Code:
    #include <cstdlib>
    #include <stdio.h>
    
    int main()
    { 
        int b = 0;
        int c = 0;
        
        /* 1111 is entered */
        printf("Please Enter integer number\n\n"); 
        scanf("%d", &b);
        printf("%d\n", b); /* 1111 is returned */
        
        
        /* abcd is entered */
        printf("Please Enter integer number\n\n"); 
        scanf("%d", &c);
        printf("%d\n", c); /* 0 is returned */
            
        system("PAUSE");
        return EXIT_SUCCESS;
    }

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Problem with RPC and scanf
    By Ricardo_R5 in forum C Programming
    Replies: 11
    Last Post: 01-08-2007, 06:15 PM
  2. Problem with scanf float..
    By aydin1 in forum C Programming
    Replies: 6
    Last Post: 03-06-2005, 01:35 PM
  3. scanf problem
    By gsoft in forum C Programming
    Replies: 3
    Last Post: 01-05-2005, 12:42 AM
  4. problem with looping scanf
    By crag2804 in forum C Programming
    Replies: 6
    Last Post: 09-12-2002, 08:10 PM
  5. scanf problem
    By Flikm in forum C Programming
    Replies: 2
    Last Post: 11-05-2001, 01:48 PM