Thread: How to Validate an Input

  1. #1
    Registered User
    Join Date
    Jul 2006
    Posts
    49

    Question How to Validate an Input

    I'm teaching myself C, and I've never had to deal with user input before so I need some assistance. For the program I want to create, a user is allowed to input any amount of numbers (no negatives) and any amount of A's B's and/or C's. Letters D-Z are invalid. Example: 54321ABC is valid and 123DEA is invalid.

    K&R 2nd edition only seems to talk about user input of int's only, so I'm confused about what to have the input variable be (char, char *, etc)? And how do I validate the input to be only numbers and the letters A, B, and/or C?

    I know this is probably incredibly simple, but I'm very new to this language. Thanks for the help.

  2. #2
    Math wizard
    Join Date
    Dec 2006
    Location
    USA
    Posts
    582
    The char is a normal variable using 8-bits, often used for strings. The "char *" is a pointer to a char element. The * after the type indicates a pointer. For strings, you'd use an array of char variables as "char SampleString[50];". Use scanf for taking user input and printf is for displaying text. A string parser could check to see if input is valid. I'd suggest reading this tutorial for learning the basics of C.
    High elevation is the best elevation. The higher, the better the view!
    My computer: XP Pro SP3, 3.4 GHz i7-2600K CPU (OC'd to 4 GHz), 4 GB DDR3 RAM, X-Fi Platinum sound, GeForce 460, 1920x1440 resolution, 1250 GB HDD space, Visual C++ 2008 Express

  3. #3
    Registered User ssharish2005's Avatar
    Join Date
    Sep 2005
    Location
    Cambridge, UK
    Posts
    1,732
    If you need to read a alphanumeric char's u will have to read them through a string. So u dont needs to considere anything with int, floats.

    Read the input and store thme in a string. Use fgets for that. Then for validation i could just think of looping though the string and check for each char. I cant think of anything else.

    What you could do is

    Code:
    for(i=0;str[i] != '\0' && (str[i] >= 'A' && str[i] <= 'C'); i++);
    You could use that.

    ssharish2005

  4. #4
    Registered User
    Join Date
    Apr 2007
    Location
    Finland
    Posts
    16
    here's one idea:

    Code:
    #include <stdio.h>
    
    int main() {
    
    int  c, i ;
    char input [25];
    
    i = 0;
    
    while ((c = getchar()) != '\n') {
    	if (c > '0' && c < '9' || c == 'a' || c == 'b' || c =='c') {
    		input[i++] = c;
    	}
    	
    	else {
    		printf("invalid input");
    		break;
    		
    	}
    	
    }
    
    printf("&#37;s", input);
    
    
    return(0);   
    }
    It's not perfect but you get the idea and if you tweak it a little bit you can get what you want

  5. #5
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Code:
    const char validCharacters[] = "0123456789ABCabc";
    
    int isCharValid(int ch)
    {
        return strchr(validCharacters, ch) != NULL;
    }
    Adjust the validCharacters array as necessary.

  6. #6
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    Also, isdigit() from <ctype.h> might be helpful.
    Code:
    int is_valid(int c) {
        return isdigit(c) || c == 'a' || c == 'b' || c == '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.

  7. #7
    Registered User
    Join Date
    Jul 2006
    Posts
    49
    Thanks for everyone's input! It's greatly appreciated.

    I've gone through all the examples and have played around with the code to understand it better. The one question that came up was how can you predict the users input? For instance, Tehy had: char input [25]; and ulillillia had: char SampleString[50];

    What if the user input is larger than that? How would you get around that?

    Thanks!

  8. #8
    Math wizard
    Join Date
    Dec 2006
    Location
    USA
    Posts
    582
    "input[25]" means an array named "input" has 25 elements in it, supporting up to 24 regular characters and the last (25th) being the null character. The same goes for "SampleString[50]" where it has 50 elements (49 regular characters and the last being the null character). When you go over the limit, say accessing "input[28]" or "SampleString[80]", you'll get "unhandled exception" errors when writing to these and it causes the program to crash. It seems to work just fine when reading though, but what is read would be quite unpredictable.
    High elevation is the best elevation. The higher, the better the view!
    My computer: XP Pro SP3, 3.4 GHz i7-2600K CPU (OC'd to 4 GHz), 4 GB DDR3 RAM, X-Fi Platinum sound, GeForce 460, 1920x1440 resolution, 1250 GB HDD space, Visual C++ 2008 Express

  9. #9
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by slowcoder View Post
    What if the user input is larger than that? How would you get around that?
    To be able to handle arbitrary amounts of input, you have to allocate memory dynamically with calls like malloc(), calloc(), and realloc(). As you read characters of user input you keep track of how much has been read, and expand the dynamically allocated area when necessary. There have already been many discussions on this topic which you should be able to find with the search.

  10. #10
    Registered User
    Join Date
    Jul 2006
    Posts
    49
    brewbuck, I'm going to use something similar to what you had:

    Code:
    const char validCharacters[] = "0123456789ABCabc";
    
    int isCharValid(int ch)
    {
        return strchr(validCharacters, ch) != NULL;
    }
    However, if I want to allow a user to use " (quotes) in the input, what would I have to do to the validCharacters array? Thanks!

  11. #11
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    "\""
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  12. #12
    Registered User
    Join Date
    Jul 2006
    Posts
    49

    Question

    Thank you vart, that worked perfectly

    brewbuck, I did a search about allocating the memory dynamically and found this post below. However, is this the best way to do it? I have a hard time following it.

    post:

    The idea behind dynamic array allocation is that you can allocate new memory any time you want. So, lets say that you initially allocate an array of size 10, but you want to put in 30 elements... all you have to do is:

    char* temp;
    ...
    *temp = calloc(30, sizeof(char));
    strcpy(temp, character);
    free(character);
    character = temp;

    Now, in c, you will need to produce an analogue to the stl string class in c++. Probably the cleanest way to do this is with structs. Your struct would look something like this:

    Code:
    struct my_string {
       char *value;
       int size;
    };
    then, make sure you never directly access the structure - only access it with functions (which happens to be one of basic rules of a c++ class). So, you have a function call concat which will concatinate string to the end of a my_string structure:

    Code:
    void concat(struct my_string *str1, char *str2) {
       char *temp;
       if(strlen(str1->value)+strlen(str2) < size)
         strcat(str1->value, str2);
       else {
         str1->size = str1->size*2;
         temp = calloc(str1->size, sizeof(char));
         strcpy(temp, str1->value);
         free(str1->value);
         str1->value = temp;
         concat(str1, str2);
      }
    }
    Havent tested or compiled the code... so make sure you go over it if you plan on using it :P Either way, it's not the most efficient code (instead of just doubling the string size every time, it's possible to make the string exactly the right size).

  13. #13
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    I'm guessing that you want to either store one line, or every line, that you read in. And you want the lines to be of any length. And you don't know those length(s) beforehand.

    First, some background information. malloc() allocates a block of memory, the size of which can be specified at run-time, as opposed to (C89) array sizes, which must be specified at compile-time. It's very simple to use. You pass it the number of bytes to allocate, and it returns a pointer to the newly allocated memory (or NULL if there isn't enough free memory to satisfy your request):
    Code:
    char *p = malloc(10);
    realloc() takes a block of memory that was previously allocated with malloc() -- or NULL, in which case it acts just like malloc() -- and resizes how much memory is allocated for that block of memory. That is, you can allocated more or less memory for a block of memory that has already been allocated.
    Code:
    char *p = malloc(10);
    /* p points to 10 chars */
    p = realloc(p, 20);  /* bad idea to use p twice, but never mind */
    /* p now points to 20 chars */
    Finally, one should always free() any blocks of memory allocated with malloc():
    Code:
    char *p = malloc(10);
    /* p points to 10 chars */
    p = realloc(p, 20);  /* bad idea to use p twice, but never mind */
    /* p now points to 20 chars */
    free(p);  /* free the 20 characters */
    ----

    So, anyway, here's some code which will read data (one line) from an input stream such as a file or stdin, resizing the buffer whenever it gets full:
    Code:
    #include <stdio.h>
    #include <stdlib.h>  /* for malloc(), realloc(), and free() */
    
    char *get_string(FILE *fp) {
        size_t size = 1, pos = 0;
        char *p = malloc(size);
        int c;
        
        do {
            c = getc(fp);
            if(c == '\n' || c == EOF) c = 0;  /* add a NULL terminator */
            
            if(pos <= size) {
                size *= 2;  /* double the allocated memory */
                p = realloc(p, size);
            }
            
            p[pos ++] = c;
        } while(c);
        
        printf("get_string(): &#37;lu read, %lu allocated\n", (unsigned long)(pos-1), (unsigned long)size);
        
        return p;
    }
    
    int main() {
        char *str = get_string(stdin);
        printf("string: [%s]\n", str);
        free(str);
        
        return 0;
    }
    It's kind of like fgets(), except that it strips the newline.
    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.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. For loop problems, input please.
    By xIcyx in forum C Programming
    Replies: 2
    Last Post: 04-22-2007, 03:54 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