Повторить попытку ввода при неверном вводе с клавиатуры - C (СИ)
Формулировка задачи:
Здравствуйте. С клавиатуры вводятся элементы массива типом float. При ошибочном вводе, например при вводе символов или букв вместо элемента массива - программа выдает ошибку. Можно ли сделать так, чтобы при неверном вводе программа запросила повторный ввод? Желательно повторный ввод именно с того элемента, на котором возникла ошибка, но если это сложно реализуема - можно начинать ввод с самого начала. Нашел аункцию try, catch, throw, но как мне обьяснили классы в СИ не поддерживаются.
Решение задачи: «Повторить попытку ввода при неверном вводе с клавиатуры»
textual
Листинг программы
#include <errno.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <math.h>
#define CLI_BUFFER_SIZE 256
float get_float(void)
{
char *end;
char buff[CLI_BUFFER_SIZE] = "";
while (1) {
if (!fgets(buff, CLI_BUFFER_SIZE, stdin))
continue;
buff[strcspn(buff, "\n")] = '\0';
buff[strcspn(buff, ",")] = '.'; // а вообще числа с плав точкой вводят вроде как через точку =)
errno = 0;
float sl = strtof(buff, &end);
if (*buff == '\0') {
fprintf(stderr, "empty string\n");
} else if ((HUGE_VALF == sl || HUGE_VALF == sl) && ERANGE == errno) {
fprintf(stderr, "out of range of type float\n");
} else if ('\0' != *end) {
fprintf(stderr, "extra characters\n");
fprintf(stderr, "\t%s\n" , buff);
fprintf(stderr, "\t%*c\n", (int)(end - buff) + 1, '^');
} else {
return (float)sl;
}
fflush(stdin);
}
}
int get_int(void)
{
char *end;
char buff[CLI_BUFFER_SIZE] = "";
while (1) {
if (!fgets(buff, CLI_BUFFER_SIZE, stdin))
continue;
buff[strcspn(buff, "\n")] = '\0';
errno = 0;
long sl = strtol(buff, &end, 10);
if (*buff == '\0') {
fprintf(stderr, "empty string\n");
} else if ((LONG_MIN == sl || LONG_MAX == sl) && ERANGE == errno) {
fprintf(stderr, "out of range of type long\n");
} else if (sl > INT_MAX) {
fprintf(stderr, "%ld greater than INT_MAX\n", sl);
} else if (sl < INT_MIN) {
fprintf(stderr, "%ld less than INT_MIN\n", sl);
} else if ('\0' != *end) {
fprintf(stderr, "extra characters\n");
fprintf(stderr, "\t%s\n" , buff);
fprintf(stderr, "\t%*c\n", (int)(end - buff) + 1, '^');
} else {
return (int)sl;
}
fflush(stdin);
}
}
int main(void)
{
printf("a: %d\n", get_int());
printf("a: %f\n", get_float());
return 0;
}
Объяснение кода листинга программы
- В функции
get_floatиget_intиспользуется цикл while(1), который продолжается до тех пор, пока условие не будет выполнено. - Внутри цикла используется функция
fgetsдля чтения строки из стандартного ввода. - Если строка пустая, выводится сообщение об ошибке
empty string. - Если введенное значение выходит за пределы диапазона для типа
floatилиlong, выводится сообщение об ошибкеout of range of type floatилиout of range of type longсоответственно. - Если после успешного преобразования значения в
floatилиlongостаются дополнительные символы, выводится сообщение об ошибкеextra characters. - Если введенная строка не может быть преобразована в
floatилиlong, выводится сообщение об ошибкеinvalid conversion. - Если введенное значение больше
INT_MAXили меньшеINT_MIN, выводится сообщение об ошибкеnumber greater than INT_MAXилиnumber less than INT_MINсоответственно. - Если введенная строка не может быть преобразована в
int, выводится сообщение об ошибкеinvalid conversion. - Значения
CLI_BUFFER_SIZE,HUGE_VALF,LONG_MIN,LONG_MAX,INT_MAXиINT_MINопределены в стандартных заголовочных файлах. - Значение
ERANGEявляется константой, определенной в стандартном заголовочном файле<errno.h>. - Функция
fflushиспользуется для очистки буфера стандартного ввода. - Функция
strcspnиспользуется для определения количества символов в строке до первого вхождения символа новой строки. - Функция
strtolиспользуется для преобразования строки вlong. - Функция
strtofиспользуется для преобразования строки вfloat. - Функция
fprintfиспользуется для вывода сообщений об ошибках в стандартное средство вывода ошибок. - Функция
printfиспользуется для вывода значений в стандартное средство вывода. - Значения
*endиbuff[strcspn(buff,\n)]используются для определения позиции символа новой строки в строке. - Значение
*endиспользуется для определения позиции последнего символа в строке. - Значение
*buffиспользуется для определения первого символа в строке. - Значение
*buffиспользуется для определения символа, следующего за последним символом в строке.