2015-08-08 3 views
0

как я могу обеспечить следующее ограничение ввода в c?Строка мудрый вход в c

Первая строка содержит поплавок, Второй строки содержит поплавок, Третьей строку INT,

после нажатия ввести три раза в консоли, программа должна быть в состоянии прочитать каждую строку и поместить содержимое в соответствующем Int, Int, плавающие переменные.

После трехкратного ввода программы нажатия клавиш не следует ждать ввода пользователя и запуска проверки.

некоторые тестовые случаи

line1: 34 
line2:4 
line3:12 
result: ok 

line1: 
line2:4 
line3:12 
result: not ok 

line1: Hi 
line2:4 
line3:12 
result: not ok 

до сих пор я использовал основы

scanf("%f",&p); 
    scanf("%f",&r); 
    scanf("%d",&t); 

она отлично работает для теста 1 и 3, но терпит неудачу, когда я оставляю пустую строку.

+0

вы должны сделать это с 'scanf'? –

+1

показать свои усилия – snr

+0

Прочитайте строки с 'fgets'. Преобразование с помощью 'sscanf' или' strto_' семейства функций. – user3386109

ответ

2

Вы должны всегда проверить возвращаемое значение scanf.

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

Возвращаемое значение будет состоять из числа элементов, которые были успешно присвоены. Например,

char str[128]; 
int x, y = scanf("%d %127s", &x, str); 

Если y является 1, то следует считать, что x безопасно использовать. Если y равно 2, то следует предположить, что как x, так и str являются безопасными в использовании.

Это часть ответа на ваш вопрос. Следующая часть - это то, как вы можете следить за тем, чтобы входной сигнал находился в форме строк. scanf строго не относится к линиям; он относится к другим единицам, таким как %d, являющийся int, закодированным как последовательность десятичных цифр (и знак); он вернется, как только последовательность десятичных цифр закончится ... Нет никакой гарантии, что десятичные цифры будут занимать всей строки.

Здесь есть две проблемы: ведущие и конечные пробелы. Все спецификаторы формата, за исключением [, c, C и n, приведут к отбрасыванию ведущих пробелов. Если вы хотите обрабатывать ведущие пробелы по-разному, вам нужно будет кодифицировать, как вы ожидаете, что будет обрабатываться ведущее значение whitespace.

Учитывайте, что отбрасывание ввода пользователем почти всегда (если не всегда) является плохим. Если вам все равно, что содержит оставшаяся часть строки, вы можете использовать что-то вроде scanf("%*[^\n]"); getchar();, чтобы отбросить все, что тянется до символа новой строки '\n' ... Первое утверждение попытается прочитать как можно больше символов без символов новой строки , а второй будет отбрасывать завершающий символ новой строки.Однако, если вы хотите убедиться, что вход занимает всю строку, тогда вам нужно проверить значение, возвращаемое getchar.

Пример использования всех этих соображений:

/* Test for leading whitespace (including newlines) */ 
int c = getchar(); 
if (c != '-' && !isdigit(c)) { 
    /* Leading whitespace found */ 
} 
ungetc(c); 

/* Test for correct data conversion */ 
int x, y = scanf("%d", &x); 
if (y != 1) { 
    /* Something non-numeric was entered */ 
} 

/* Test for trailing newline */ 
c = getchar(); 
if (c != '\n') { 
    /* Trailing newline found */ 
} 

Вооруженный этой информацией, возможно, вы можете придумать попытку и обновить свой вопрос с какой-то код, если у вас есть какие-то проблемы ...

PS Я заметил в коде, который вы написали, у вас, кажется, есть %f и %d confused; %f для чтения в float с, и %d для чтения в int с, а не наоборот ...

+0

.. @CoolGuy Спасибо за исправление грамматики :) – Sebivor

+0

Добро пожаловать. Удивительный ответ. +1 конечно. –

+0

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

0

Как только я прочитал линий мудрого входа, я знаю, что fgets + sscanf должны быть использован вместо прямых scanf. Конечно, вы можете использовать getc/getchar в качестве обходного пути, но вы можете получить угловые шкафы, где я нахожу fgets + sscanf уборщик. Пример, чтобы получить поплавок только на линии:

char line[80], dummy[2]; 
float val; 
if (fgets(line, sizeof(line), stdin) == NULL)... 
if (sscanf(line, "%f%1s", &val, dummy) != 1)... 
// Ok val was alone on the line with optional ignored blanks before and/or after 

Вы также можете добавить тест для линий: займет слишком много

if ((line[0] != 0) && (line[strlen(line)-1 != '\n'))... 
+0

Как это чище, чем 'float val; int n = scanf ("% f", &val); scanf ("% * [^ \ n]"); getchar(); if (n! = 1) {/ * некоторая обработка ошибок * /} '? Добавление теста для * loooong lines * добавляет больше беспорядка в ваш код, чем вы можете понять. Вам нужно учитывать, когда 'fgets' встречает строку длиннее, чем символы' sizeof (line) ', например ... Вы можете использовать' scanf ("% * [^ \ n] "); getchar();', но тогда вы будете использовать 'scanf' ... и это просто глупо, правильно? Зачем использовать наиболее подходящий инструмент для задания? – Sebivor

+0

@ Freenode- newbostonSebivor ваш код действительно намного короче ... И молча принимает 3 поплавки на той же строке, которая была запрещена OP.Если вы не нуждаетесь в линейном ориентированном вводе, 'fgets' ** ** overkill. Но если вам это нужно, является более надежным способом. –

+0

Этот код не будет «молча принимать 3 поплавки в одной строке» ... 'int n = scanf («% f », &val);' будет читать значение в 'val', а затем' scanf ("% * [^ \ n]"); getchar(); 'отбрасывает re которая является чем-то, что вы не можете делать чисто и надежно с помощью 'fgets' +' sscanf', потому что, когда строка длиннее 'sizeof (строка)', она разделит строку на два чтения , Вы можете использовать тот же код, который я использовал, чтобы отбросить оставшуюся часть строки, когда это произойдет, но тогда вы можете просто использовать 'scanf', а не' fgets' + 'sscanf'. 'getchar' может сделать все это за счет беспорядка. – Sebivor

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