- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
typedef enum { SUCCESS = 0, NOTNUMBER = 1, BOUNDS = 2, EOFREACHED = 3 } rdstat_t;
int flush_line(FILE *stream) {
int ch;
do {
ch = fgetc(stream);
} while (ch != EOF && ch != '\n');
return ch;
}
/* enough to contain (1 + length of ASCII string of SIZE_MAX
decimal representation) characters */
#define SIZE_T_BUF_SIZE 100
/* reads until newline or EOF, writes (size_t *out) if success */
rdstat_t read_size_t(FILE *stream, size_t *out) {
char str_SIZE_MAX[SIZE_T_BUF_SIZE];
snprintf(str_SIZE_MAX, SIZE_T_BUF_SIZE, "%zu", SIZE_MAX);
char buf[SIZE_T_BUF_SIZE];
if (!fgets(buf, SIZE_T_BUF_SIZE, stream))
return EOFREACHED;
if (buf[strlen(buf) - 1] != '\n') {
flush_line(stream);
return NOTNUMBER;
}
buf[strlen(buf) - 1] = 0;
char *ch;
for (ch = buf; *ch; ++ch)
if (!isdigit(*ch))
return NOTNUMBER;
if (strlen(buf) == strlen(str_SIZE_MAX) && strcmp(buf, str_SIZE_MAX) > 0)
return BOUNDS;
sscanf(buf, "%zu", out);
return SUCCESS;
}
Наваял функцию для чтения size_t из файла с защитой от дурака (писал код будучи больным, чесслово).
Ничего умнее печати SIZE_MAX в строчку и лексикографического сравнения для проверки границ введенного числа не придумал %)
vlitomsk 06.03.2015 22:41 # 0
guest 07.03.2015 18:24 # −2
kegdan 07.03.2015 18:31 # 0
guest 07.03.2015 19:15 # 0
vlitomsk 07.03.2015 19:39 # +2
kegdan 07.03.2015 19:50 # +4
LispGovno 07.03.2015 21:59 # +3
gost 08.03.2015 15:14 # +4
Dummy00001 08.03.2015 12:48 # +1
верю.
sscanf() + "%n" + проверки постафактумом.
bormand 08.03.2015 16:28 # 0
Тогда уж strtoul/strtoull, к ним проверки проще привернуть.
P.S. Я вот слабо представляю, как проверять диапазон по количеству символов, прочтённых scanf'ом.
Dummy00001 08.03.2015 16:35 # 0
bormand 08.03.2015 16:39 # 0
Пример для 32-битного числа: 8589934591. scanf() спарсит его как 4294967295. Количество цифр абсолютно одинаковое.
Dummy00001 08.03.2015 17:10 # 0
просто забить на эту глупую проверку.
все равно не помогает, если пользователь вводит неправильное число (типа 2 вместо 1). и это случается на несколько порядков чаще чем ввод числа близкого к пределу значений.
к слову. у меня на одном прошлом проекте, чудаки в конфигах этим страдали: они писали "none"/"not available" вместо "0" (что atoi() послушно парсил) в тех местах где значения было запрещено менять с дефолтов. для кого то возможность неправильного ввода это баг - для других это фича.
vlitomsk 09.03.2015 01:24 # 0
Dummy00001 09.03.2015 02:36 # 0
если у тебя такой юз-кейс есть, то это уже говно само по себе.
тут уже про "наименьшее удивление" пользователя говорить поздно: скорее всего пользователь каждый раз материться когда система хочет что бы он 9-ти-значное число (посчитал и) ввел.
wvxvw 09.03.2015 09:17 # 0
Dummy00001 09.03.2015 11:53 # +1
это обработка ввода пользователя, в той или иной форме.
ввод пользователя должен обрабатыватся толерантно и временами с умом и гибкостью.
на шкале толерантности, я может быть слегка перехожу типичные границы. но это же опять навеяно личным опытом работы с пользователями и консультантами, которые этот ввод должны делать постоянно. и которые должны эти мессаджбоксы ошыбок ввода постоянно закрывать.
и к слову в моем случае это больше из Перла, нежели чем С. на Перле я начинал с харкорных проверок всего что только можно (потому что в перле легко делаются). но годы спустя, я в некоторых местах скатывался почти до ввода на естественном языке (было больше шуткой, но работало).
vlitomsk 09.03.2015 13:21 # 0
wvxvw 10.03.2015 01:21 # 0
Dummy00001 10.03.2015 01:58 # +1
Это всегда зависит от контеста. В каком процес-ориентед приложении, это 100% нормальный код. (Да, есть еще области и люди которые линейную последовательность действий программируют как линейную последовательность действий, а не (типичный для жабы) кластерфак иерархий классов.)
vlitomsk 10.03.2015 18:06 # 0
wvxvw 10.03.2015 21:22 # 0
bormand 08.03.2015 16:49 # 0
http://ideone.com/01QhDE
guest 10.03.2015 01:43 # 0
Аааааа.
vlitomsk 10.03.2015 18:07 # 0
vlitomsk 10.03.2015 18:40 # 0
и заменить на