2015-08-31 4 views
0

У меня возникли некоторые трудное время, пытаясь распознать пустую строку на стандартный ввод в C. У меня следующий код:Признавая пустую строку из стандартного ввода в C

char *line = NULL; 
int done = 0; 
while (!done) { 
    scanf("%m[^\n]", &line); 
    if (line != NULL) 
     //do something with line 
    else 
     done = 1; 
scanf("\n"); 
free(line); 

Линии должны чтобы быть пользовательскими командами. Допустим, что он только позволил назвать

insert something 
delete something 

или

exit 

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

+2

Если вы хотите читать целые строки, то вы, вероятно, лучше использовать [ 'fgets'] (http://en.cppreference.com/w/c/io/fgets) вместо этого. И если вы используете 'fgets', тогда пустая строка будет содержать только новую строку, и все. –

ответ

2

Вся информация в этом ответе была извлечена из man scanf.

Код формата %[ не будет соответствовать пустой:

[ Спички последовательность непустое символов из определенного набора принятых символов

Помните, что scanf имеет очень полезный возвращаемое значение:

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

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

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


Как показано, что ваш код имеет утечки памяти (при условии, что более чем одна строка читается), так как модификатор m вызывает память выделяться, даже не глядя на значение первоначально запасенной в соответствующий аргумент. Поэтому, если аргумент содержит адрес ранее выделенного хранилища, он будет перезаписан адресом вновь выделенного хранилища, а предыдущее распределение будет протекать.

Петля должна быть:

while (!done) { 
    line = NULL; /* Not strictly necessary */ 
    if (scanf("%m[^\n]", &line) == 1) { 
    /* Do something with line */ 
    free(line); 
    } else { 
    /* Handle an empty line */ 
    } 
    /* skip trailing newline. See below. */ 
    getchar(); 
} 

scanf("\n") не только пропустить ни одного символа новой строки. Он не отличается от scanf(" "); любые пробелы в формате scanf:

соответствует любому количеству пробелов, в том числе отсутствующих, на входе.

Если вы хотите просто пропустить символ новой строки, используйте getchar().

+0

@chux: yup, thanks – rici

+0

Насколько мне бы хотелось, ваше решение, похоже, не работает. Он по-прежнему пропускает все пустые строки. Я считаю, что функция scanf не заботится о пустых строках – Jytug

+0

@jytug: как я уже сказал, scanf ("") пропускает пустые строки. Я заменил его в примере кода на getchar. – rici

3

Вместо использования scanf(), fgets() или * nix getline().

scanf() предназначен для считывания форматированных данных - он отлично работает с линиями.
fgets() предназначен для считывания линию (0 или более символов до и включая окончательный '\n') и преобразование, что в строку C путем добавления нулевого символа '\0' в буфер назначения.

char line[100]; 
while (!done) { 
    // scanf("%m[^\n]", &line); 
    if (fgets(line, sizeof line, stdin) == NULL) { 
    // EOF or input error occurred, for now let us just clear line 
    line[0] = 0; 
    } 
    // get rid of potential trailing \n 
    line[strcspn(line, "\n")] = 0; 
    if (line[0]) 
    //do something with line 
    else 
    done = 1; 
} 
Смежные вопросы