0

I am trying to take RGB codes entered by a user in the format #1, #2, #3. I error check the input to make sure it matches the ', ' format and can extract the numbers from the string. However, I am having trouble checking if the input is a number after that.

Ex: If the user enters: 255, 0, 0f the program still runs.

Any help would be appreciated!

char input[100];
printf("Enter RGB code \n");
scanf(" %[^\n]s", input);

//function to error check ', ' format

int c1,c2,c3;
//formats the input into three ints. 
sscanf(input, "%d, %d, %d\n", &c1,&c2,&c3);

I just need to check if these are in fact integers

  • 1
    There is no `'s'` at the end of `" %[^\n]s"` unless you are typing format `"#1, #2, #3s"` -- remove it `:)` The *conversion specifier* is `%[...]`. Also, you cannot use any user-input function or conversion function correctly unless you ***check the return***... Use `fgets( input, sizeof input, stdin)` instead of `scanf(" %[^\n]s", input);` -- eliminate the `scanf` pitfalls. (also remove the `'\n'` from `"%d, %d, %d\n"`) – David C. Rankin Feb 19 '20 at 04:04
  • "I error check the input to make sure it matches the ', ' format" --> code does not do that as it does not check the return value of `scanf()`. – chux - Reinstate Monica Feb 19 '20 at 04:07

3 Answers3

1

An approach that should be at least a bit more robust:

char input[100];
/* use fgets - it's the safer way to read a line.
   scanf("%[^\n]", input); can result in a buffer overflow! */
fgets(input, sizeof(input), stdin);

int c1, c2, c3, end;
/* Check the return value of sscanf to ensure we read exactly three ints.
   We then use %n to check that we read up to the end of the string.
   The \n before the %n skips all whitespace at the end of the string.
*/
if(sscanf(input, "%d,%d,%d\n%n", &c1, &c2, &c3, &end) != 3 || input[end] != '\0') {
    printf("invalid input!\n");
}
...

What this does: read a line using fgets (safer and no buffer overflow, unlike your scanf), then parses it using sscanf. Here I used the %n format option, which writes the number of characters read so far into the corresponding int parameter (here, end). Then we simply check that we hit the end of the string - if not, there must be trailing garbage so we can reject the input. Also, we check the return value of sscanf to ensure it has read exactly three numbers (%n doesn't count).

nneonneo
  • 171,345
  • 36
  • 312
  • 383
0

If you want to do any serious format checking, I'd suggest you incorporate PCRE into your code. Then you can simply get a line (more robustly than you currently do (scanf is can be unreliable), such as the one from this answer), then use a regex like:

^\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*$

to both check and extract the fields you desire, with each field being one to three (inclusive) digits.

You'll probably then want to check that the extracted fields are less than 256 but that should be relatively easy. Or, if you want all that done by the regex itself, you can replace each occurrence of (\d{1,3}) in the regex above, with:

(0|[1-9]\d?|1\d\d|2[0-4]\d|25[0-5])

This guarantees a 0..255 number in the field rather than an arbitrary one-to-three digit number, using the following possibilities:

0          : 0
[1-9]\d?   : 1-99
1\d\d      : 100-199
2[0-4]\d   : 200-249
25[0-5]    : 250-255
paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
0

Ok. So you need to check if the input values inside the character array input are in fact numbers before putting them in c1, c2 and c3 integer variables. Good idea.

There is a function in C which helps you do that unless you want to write your own one (Which I will not venture into here but you may want to research the Ascii table if this appeals to you). It is called isdigit and you can learn more about it here: https://www.tutorialspoint.com/c_standard_library/c_function_isdigit.htm. It has the following form int isdigit (int c) and it returns a non-zero value if the argument passed is a digit. You can pass it the character value inside the input array as for example isdigit(input[x]); where x is the position of the character in the character array input. Hope this helps.

Soliman Soliman
  • 159
  • 1
  • 4
  • 17