2016-09-13 3 views
1

Выполняя некоторую практику для предстоящего назначения, я столкнулся с проблемой, использующей fscanf, и попытался вызвать уведомление, когда неправильный формат введен в программу. Я уверен, что мне нужно использовать возврат fscanf, но не могу понять, как использовать его внутри цикла while. В настоящее время программа пеет непрерывно, когда вводится значение, такое как «a3», но «3e» работает почти отлично, за исключением того, что он дважды выдает номер 3.Использование fscanf: Поиск символа во входе

РАБОЧАЯ Scanf код:

int intGet(int min, int max) { 

int input = 0; 
char temp = ' '; 
printf("Enter a number in between [%d-%d]: ", min, max); 

if (scanf("%d%c", &input, &temp) != 2){ 
    errorNo = 1; 
    return EXIT_FAILURE; 
} 
if (temp != '\n'){ 
    errorNo = 2; 
    return EXIT_FAILURE; 
} 
if (input < min || input > max){ 
    errorNo = 3; 
    return EXIT_FAILURE; 
} 
else { 
    printf("Read %d\n", input); 
} 
return EXIT_SUCCESS; 

fscanf код по той же идее, что петли непрерывно:

int intGet(int min, int max) { 
int counterValid = 0; 
int counterInvalid = 0; 
int entry = 0; 
int total = 0; 
int input = 0; 
int check = 0; 
char temp = ' '; 
FILE *fp; 

fp = fopen("02_num.txt", "r"); 
if (!fp) 
{ 
    perror("fopen()"); 
    exit(EXIT_FAILURE); 
} 
printf("----------------------------------------------------------\n"); 
printf("Entry\tInvalid\tValid\tNumber\n"); 
printf("----------------------------------------------------------\n"); 

fscanf(fp, "%*[^\n]\n"); //skips first line (min and max) 


    while (check != EOF){ 

check = fscanf(fp, "%d%c", &input, &temp); 

    if (check == EOF){ 
     exit(EXIT_SUCCESS); 
    } 
    if (check != 2){ 
     counterInvalid += 1; 
     entry += 1; 
     printf("%d\t*\t\t%d\tIncorrect Format\n", entry, input); 
    } 
    if (temp != '\n'){ 
     counterInvalid += 1; 
     entry += 1; 
     printf("%d\t*\t\t%d\tExtra Characters\n", entry, input); 
    } 
    if (input < min || input > max){ 
     counterInvalid += 1; 
     entry += 1; 
     printf("%d\t*\t\t%d\tInput Number out of Range\n", entry, input); 
    } 
    else{ 
     counterValid += 1; 
     entry +=1; 
     total += input; 
     printf("%d\t\t*\t%d\n", entry, input); 
    } 
} 
    printf("----------------------------------------------------------\n"); 
entry +=1; 
printf("%d\t%d\t%d\t%d\n", entry, counterInvalid, counterValid, total); 
return EXIT_SUCCESS; 
} 

Этот код будет выводить таблицу, которая выглядит примерно так:

***************************************************** 
     Entry Invalid Valid Number 
     1   *     32 
***************************************************** 
// adds invalid and valid entry totals, displays then here, adds totals of valid numbers and also outputs them here. 

02_num.txt файл, который использовался в этом коде, первые два номера - это мин. И макс. , читать в другой функции.

1 15 //min and max 
23 
45 
67 
8990 
3e 
12 
a3 

Вещи, которые я пытался работать с, если/время цикла:

Определение переменной для записи возвращаемое значение fscanf (в настоящее время ближе всего):

while (check != EOF){ 

check = fscanf(fp, "%d%c", &input, &temp); 
    if (check != 2){ 
     counterInvalid += 1; 
     entry += 1; 
     printf("%d\t*\t\t%d\tIncorrect Format\n", entry, input); 
    } 

Проверка возврата значение в операторе if (сканирует файл дважды и не выводится должным образом):

while (fscanf(fp, "%d", &input) != EOF){ 

    if (fscanf(fp, "%d%c", &input, &temp) != 2){ 
     counterInvalid += 1; 
     entry += 1; 
     printf("%d\t*\t\t%d\tIncorrect Format\n", entry, input); 
    } 

Если есть какая-либо информация, которую я пропускаю, сообщите мне, я просто немного застрял здесь .. был в течение последних двух дней. Наверное, просто глупая ошибка, которую я пропускаю, но спасибо заранее!

+0

Прежде всего, если вы хотите прочитать целую строку, почему бы вам не использовать, например. 'fgets' вместо' scanf'? Во-вторых, большинство спецификаторов формата 'scanf' (например, все числовые форматы) считывают и отбрасывают ведущее белое пространство. –

+0

Когда 'a3' считывается,'% d' терпит неудачу в 'a', а затем следующая попытка не выполняется на' a', а также следующая. Случай '3e' работает, потому что'% c' читает 'e', а'% d' на следующей итерации пропускает пробел (новая строка). Не используйте 'scanf()' et al для ввода на основе строки; он не заботится о границах линии. Вместо этого используйте 'fgets()' (или 'getline()') и 'sscanf()'. –

+0

@JoachimPileborg Я знаю, что fgets будет работать лучше, но цель - познакомиться с более примитивными формами ввода-вывода. Я ограничен в этом случае fscanf – Sentience

ответ

3

Проблема с циклом - это то, что вы делаете, когда fscanf возвращает ноль. Между прочим, это означает, что если вы снова вызовете fscanf с той же строкой формата, результат будет равен нулю, потому что проблема во входном сигнале, которая приводит к тому, что вы получаете нуль в первую очередь, не была устранена.

Вам нужно добавить код для пропуска линии, когда вы получаете нулевой обратно от fscanf - например, ваш fscanf(fp, "%*[^\n]"); fscanf(fp, "%*1[\n]"); с изменениями, внесенными Jonathan Leffler и chux, будет работать.

+0

Обратите внимание, что завершающее '\ n' (или любое конечное белое пространство) в строке формата будет читать пробел (включая символы новой строки) до тех пор, пока не встретится что-то, что не является белым. Это ужасно, если вход интерактивен. Было бы лучше использовать '% * [\ n]', я полагаю; это не присвоение чтения одной новой строки. Единственное, что вы получили, это то, что вы не можете определить, соответствует ли '% * [\ n]' фактическому совпадению - это не учитывается в возвращаемом значении. (OTOH: вряд ли это имеет значение - он может только потерпеть неудачу на EOF без окончательной новой строки.) –

+0

Это сработало отлично - спасибо за вашу помощь :) – Sentience

+0

(я удалил свой «смешной (своеобразный)» комментарий - 'scanf() 'не удалось на пустой строке (ни один символ не удовлетворяет первой спецификации преобразования«% »[^ \ n]% * 1 [\ n]" 'на пустой строке. Я с облегчением, мне намного легче исправить ошибку в моем мышлении, чем исправить ошибку в o/s.) Это тоже скоро должно закончиться. –

Смежные вопросы