2016-05-15 2 views
0

Я хочу написать код, чтобы пользователь вводил только 1 цифру. Если пользователь вводит что-то вроде «0 1 3», я хочу, чтобы моя программа прочитала сообщение об ошибке, которое я понятия не имею, как это сделать. У кого-нибудь есть идея, как подойти к этому? Мой текущий код просто принимает первый номер, если пользователь вводит кучу чисел с промежутком между ними.Проверка данных в C - обеспечение ввода в правильном формате

См. Мой код ниже. Спасибо: D

//Prompt the user to enter the low radius with data validation 
printf("Enter the low radius [0.0..40.0]: "); 
do 
{ 
    ret = scanf("%lf", &lowRadius); 
    //type validation 
    if (ret != 1) 
    { 
     int ch = 0; 
     while (((ch = getchar()) != EOF) && (ch != '\n')); 
     printf("Wrong input. Please enter one numerical value: "); 
    } 
    //range validation  
    else if((lowRadius < 0 || lowRadius > 40)) 
    { 
     printf("Incorrect value. Please enter in range 0-40: "); 
    } 
    else break; 
} while ((ret != 1) || (lowRadius < 0 || lowRadius > 40));//end while lowRadius 
+3

У вас уже есть код. Используйте 'getchar' для чтения с ввода до тех пор, пока не будет найдена новая строка. Если любые символы небелого пробела перед символом новой строки, вход недействителен. Кроме того, вам не нужен цикл 'do {} while', так как вы используете' break' в любом случае. Простой цикл while (1) {} 'или' for (;;) {} будет работать. Просто «перерыв» цикла, когда вход действителен. – user3386109

+0

Это потому, что scanf небезопасен на многих уровнях. См. [Этот пост] (http://stackoverflow.com/questions/30577519/error-c4996-scanf-this-function-or-variable-may-be-unsafe-in-c-programming) о том, почему не рекомендуется используйте его, а также альтернативу. Также вы должны рассмотреть возможность использования внешней или третьей части библиотеки для безопасного анализа ваших входов. – Joel

+2

Как пользователи могут вводить значение типа '39' с использованием одной цифры? Вы имеете в виду «один номер»? Как насчет фракций (39.23423)? Как вам уже сказали, вероятно, что 'scanf()' не является инструментом; используйте 'fgets()' для чтения строки, а затем, возможно, 'sscanf()' или, возможно, 'strtod()', чтобы преобразовать значение, тщательно обработать условия ошибки и проверить, нет ли мусора после числа и перед новой строкой. –

ответ

0

Прочтите всю строку и преобразуйте ее с помощью strtod.

+1

Это не очень хороший ответ. Вы должны хотя бы предоставить пример вызова strdod. – Adam

2

Если вы читаете строку в строке, то анализируете ее, вы избегаете проблемы с зависанием на неподдерживаемом входе. Вы уже проделали большую часть работы, но это показывает, как ловить слишком много ресурсов. Он работает, сканируя строку после double, чтобы получить больше ввода. Возвращаемое значение от sscanf сообщает вам, было ли это, потому что оно возвращает количество успешно проверенных элементов.

#include <stdio.h> 
#include <stdlib.h> 

void err(char *message) 
{ 
    puts(message); 
    exit(1); 
} 

int main(void) 
{ 
    double lowRadius = 0.0; 
    char inp[100]; 
    char more[2]; 
    int conv; 
    if(fgets(inp, sizeof inp, stdin) == NULL) { 
     err("Input unsuccesful"); 
    } 
    conv = sscanf(inp, "%lf %1s", &lowRadius, more); // conv is number of items scanned 
    if(conv != 1) { 
     err("One input value is required"); 
    } 
    if(lowRadius < 0.0 || lowRadius > 40.0) { 
     err("Number out of range"); 
    } 
    printf("%f\n", lowRadius); 
    return 0; 
} 

Я не уверен, что ты обусловленности одной цифры, так что не позволит вашему максимальное значение, которое будет введено.

0

Александр имеет правильный подход, но не дает подробностей. Вот как бы я это сделал, используя getline() для чтения ввода, а затем strspn() плюс strtod() для синтаксического анализа введенного ввода. Если вы не знакомы с работой с указателями, это будет трудно понять, но если вы изучаете C, вы попадете туда в конце концов:

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

int main(void) { 
    double lowRadius; 
    char *lineptr = NULL; 
    size_t n; 
    char *startptr; 
    char *endptr; 
    char *ws = " \t\n"; /* possible whitespace characters */ 

    printf("Enter the low radius [0.0..40.0]: "); 

    while(1) { 
    /* free lineptr if set - neeeded if we iterate on error input */ 
    if(lineptr) { 
     free(lineptr); 
     lineptr = NULL; 
    } 

    /* now read a line of input */ 
    while(getline(&lineptr, &n, stdin) == -1) { 
     /* error returned, just retry */ 
     continue; 
    } 

    /* skip over any leading whitespace */ 
    startptr = lineptr + strspn(lineptr,ws); 

    /* Now try to convert double */ 
    lowRadius = strtod(startptr, &endptr); 

    if(endptr==startptr || endptr[strspn(endptr,ws)] != 0) { 
     /* either no characters were processed - e.g., the 
     line was empty, or there was some non-whitespace 
     character found after the number. */ 
     printf("Wrong input. Please enter one numerical value: "); 
    } else if((lowRadius < 0.0) || (lowRadius > 40.0)) { 
     printf("Incorrect value. Please enter in range 0-40: "); 
    } else { 
     if(lineptr) free(lineptr); 
     break; 
    } 
    } 
    printf("value entered was %lf\n", lowRadius); 
} 
Смежные вопросы