Я пытаюсь взять коды RGB, введенные пользователем в формате # 1, # 2, # 3. Я проверяю ошибку на входе, чтобы убедиться, что он соответствует формату ',' и может извлечь числа из строки. Тем не менее, у меня возникают проблемы с проверкой, является ли ввод после этого числа.

Пример: Если пользователь вводит: 255, 0, 0, если программа все еще работает.

Любая помощь была бы признательна!

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);

Мне просто нужно проверить, если это на самом деле целые числа

c
0
techsupport123 19 Фев 2020 в 06:47

2 ответа

Лучший ответ

Подход, который должен быть хотя бы немного более надежным:

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");
}
...

Что это значит: прочитать строку с помощью fgets (безопаснее и без переполнения буфера, в отличие от вашего scanf), а затем проанализировать ее с помощью sscanf. Здесь я использовал параметр формата %n, который записывает количество прочитанных символов в соответствующий параметр int (здесь end). Затем мы просто проверяем, достигли ли мы конца строки - если нет, то должен быть завершающий мусор, чтобы мы могли отклонить ввод. Кроме того, мы проверяем возвращаемое значение sscanf, чтобы убедиться, что оно прочитало ровно три числа (%n не считается).

1
nneonneo 19 Фев 2020 в 04:09

Если вы хотите провести серьезную проверку формата, я предлагаю вам включить PCRE в ваш код. Тогда вы можете просто получить строку (более надежную, чем в настоящее время (scanf может быть ненадежной), например, из этот ответ), затем используйте регулярное выражение, например:

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

Чтобы проверить и извлечь нужные поля, каждое из которых должно содержать от одной до трех (включительно) цифр.

Возможно, вы захотите проверить, что извлеченные поля меньше 256, но это должно быть относительно просто. Или, если вы хотите, чтобы все это было сделано самим регулярным выражением, вы можете заменить каждое вхождение (\d{1,3}) в приведенном выше регулярном выражении на:

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

Это гарантирует число 0..255 в поле, а не произвольное одно-трехзначное число, используя следующие возможности:

0          : 0
[1-9]\d?   : 1-99
1\d\d      : 100-199
2[0-4]\d   : 200-249
25[0-5]    : 250-255
0
paxdiablo 19 Фев 2020 в 04:16