[C]Validating Input

[C]Validating Input

Postby hakermakduf » October 24th, 2015, 2:10 am

hey every one im new to forums don't know if im posting in the right section or not
so forgive me XD

any way iv just started to code in C and i have a question on how to verify that the input form a user is a number and if its not i give i
him a message saying (error please input number) or something like that and then allowing the loop t restart allover again.


the whole program is in the link if your interested
basically what it dose it calculate the resistance on a electrical resistor after user inputs the colors on the resistor
:aww: 0:)

thanks in advance
Pirate Subordinate
Posts: 5
Joined: October 16th, 2015, 5:42 am

Re: C programming 101

Postby Rhino.Freak » October 24th, 2015, 4:24 am

At first I thought you really asked a super simple thing but apparently you got use a built in function
there are functions called "isdigit" and "isalpha" to check for numbers and letters.
An example which I found online:
scanf ("%s", input);
length = strlen (input);
for (i=0;i<length; i++)
if (!isdigit(input[i]))

You need ctype.h I think to use the function but I'm not sure.
Good luck with your program.
User avatar
Site Admin
Posts: 518
Joined: March 31st, 2015, 12:09 pm
Location: Somewhea~

Re: C programming 101

Postby A-Man » October 24th, 2015, 5:18 am

You are posting in the right forum, don't worry!

There are many different methods to do input validation, the most elegant being REGular EXpressions (or REGEX for short) which has only recently been standardized as a part of C++11's standard library. Using it is very easy, but is considered a C++ solution so it might not be an acceptable answer. But I strongly urge you to use it if possible:

Code: [Select all] [Expand/Collapse]
  1. #include <stdio.h> // printf(), scanf()
  2. #include <stdlib.h> // atoi(), atof()
  3. #include <regex> // regex, regex_match()
  5. char * input;
  6. unsigned int positive_int;
  7. float natural_number;
  9. int main()
  10. {
  11.   // regular expressions which has the format you desire to match later
  12.   regex is_positive_integer(R"(\+)?[[:d:]]+)");
  13.   regex is_natural_number(R"((\+|-)?(([[:d:]]+\.)|(\.))?[[:d:]]*)");
  15.   scanf("%s",&input);
  17.   if (regex_match(input, is_positive_integer))
  18.   {
  19.     // atof(): Array_TO_Float
  20.     natural_number = atof(input); //convert string input to float
  21.     printf("input is a natural number! %d", natural_number);
  22.   }
  24.   if (regex_match(input, is_natural_number))
  25.   {
  26.     // atof(): Array_TO_Float
  27.     natural_number = atof(input); //convert string input to float
  28.     printf("input is a natural number! %d", natural_number);
  29.   }
  30.   return 1;
  31. }
GeSHi © Codebox Plus

The pure C solution is a pretty ugly (hey! an oxymoron!) one, and would essentially be building from what Rhino has written in his post. You'll have to consider the following though:
[*]A number can start with either a sign, digit or a period. ("-321", "+516.3", "142.5", ".667")
[*]A period can only appear once in the number; in the beginning, after a sign (eg: "-.6") or somewhere after a digit.
[*]A digit can appear anywhere else.

Using the rules above, you can construct a "IsValidNaturalNumber( )" function which will return "true" if the string you pass to it is a a number:
Code: [Select all] [Expand/Collapse]
  1. //#include <stdio.h>
  2. //#include <stdlib.h>
  3. //#include <ctype.h>
  4. //#include <string.h>
  6. bool IsValidNaturalNumber( const char * test_string )
  7. {
  8.   // first we declare our flags
  9.   bool is_start; // true if the character we're dealing with is the first in the string
  10.   bool has_period; // true if the string has a period in it already
  12.   has_period = false;
  13.   for (int i = 0; i < strlen(test_string); i ++)
  14.   {
  15.     is_start = i == 0;
  16.     char character = test_string[i];
  17.     if (isdigit(character))
  18.       continue;
  19.     if (is_start && (character == '-' || character == '+'))
  20.       continue;
  21.     if (is_start && character == '.')
  22.     {
  23.       has_period = true;
  24.       continue;
  25.     }
  26.     if (character == '.' && !has_period)
  27.     {
  28.       has_period = true;
  29.       continue;
  30.     }
  31.     // if no condition is satisfied
  32.     return false; // verdict: isn't a number
  33.   }
  34.   // if all characters satisfy the conditions
  35.   return true; // verdict: is a natural number
  36. }
GeSHi © Codebox Plus

Then if the string you enter is a valid number, you can then use "atoi" or "atof" to convert them.
User avatar
Infamous Pirate
Posts: 381
Joined: March 31st, 2015, 11:40 am

Re: C programming 101

Postby hakermakduf » October 24th, 2015, 8:01 pm

Awsan wrote:Dude you suck, just quit already..

thanks Awsan, it means a lot coming from a non-programmer :aww:

To the people who actually helped (a-man and rhino) thank you for the assistance, i kinda already knew what you suggested but it seemed too long and hectic, i thought there would be an easier way but as a-man explained C is just a bit old and rusty
Last edited by hakermakduf on October 24th, 2015, 8:05 pm, edited 1 time in total.
Pirate Subordinate
Posts: 5
Joined: October 16th, 2015, 5:42 am

Re: C programming 101

Postby A-Man » October 25th, 2015, 5:00 am

C is old and probably should not be used alone simply because more convenient C++ features are often available. But this by no means is to say that C is a rusty language :P. It's just more bare-bones than most.

So I went over the snippet you posted, and I have a few remarks.
Code: [Select all] [Expand/Collapse]
  1. void printBand1Or2()
  2. {
  3.     printf("1. Black\n");
  4.     printf("2. Brown\n");
  5.     printf("3. Red\n");
  6.     printf("4. Orange\n");
  7.     printf("5. Yellow\n");
  8.     printf("6. Green\n");
  9.     printf("7. Blue\n");
  10.     printf("8. Violet\n");
  11.     printf("9. Gray\n");
  12.     printf("10. White\n");
  13. }
GeSHi © Codebox Plus

10 print statements are not necessary and look very ugly. You can either pass the entire string "1. Black \n2. Brown\n3. Red"..etc inside a single printf call in one line. If you still need to print a long string while typing it in several lines, then you could as well split the string without the need of the multiple printf statement, like so:
Code: [Select all] [Expand/Collapse]
  1. void printBand1Or2()
  2. {
  3.     printf(
  4.              "1. Black\n"
  5.              "2. Brown\n"
  6.              "3. Red\n"
  7.              "4. Orange\n"
  8.              "5. Yellow\n"
  9.              "6. Green\n"
  10.              "7. Blue\n"
  11.              "8. Violet\n"
  12.              "9. Gray\n"
  13.              "10. White\n"
  14.              );
  15. }
GeSHi © Codebox Plus

C/C++ compilers are completely fine with splitting a string into multiple lines and will merge them for you.
Although, it's a cancer to the eyes to see unnecessarily repeated code like that. As a rule of thumb, do your best to NEVER repeat anything, and resort to functions instead. For example, the functions printBand1Or2(), printBand3() and printBand4() all print a list of colors. Here is one better way of doing it:
Code: [Select all] [Expand/Collapse]
  1. const char *BAND1[] = {"Red", "Blue", "Green"}; // ..etc
  2. const char *BAND2[] = {"Gold", "Silver"};
  3. // ..etc
  5. void printList(const char *string_list )
  6. {
  7.   for (int i = 0; i < sizeof(string_list)/sizeof(string_list[0]); i ++)
  8.     printf("%d. string_list[i]\n", i);
  9. }
GeSHi © Codebox Plus

Calling printList(BAND1) will print the band-1 colors and so on.
Learn to create functions more to divide your program into smaller more-readable parts.

Keep this up! Feel free to drop any questions, and I will be more than happy to help with the best of my ability!
User avatar
Infamous Pirate
Posts: 381
Joined: March 31st, 2015, 11:40 am

Re: [C]Validating Input

Postby A-Man » April 11th, 2016, 7:42 pm

Just to clarify about this line (something which caused me trouble that I've just learnt myself):
Code: [Select all] [Expand/Collapse]
  1. for (int i = 0; i < sizeof(string_list)/sizeof(string_list[0]); i ++)
GeSHi © Codebox Plus

The sizeof(array)/sizeof(array[0]) syntax only works if array is allocated on the stack (aka not with malloc or new). Be careful.
User avatar
Infamous Pirate
Posts: 381
Joined: March 31st, 2015, 11:40 am

Return to Programming

Who is online

Users browsing this forum: No registered users and 1 guest