ANSI C - как читать из stdin слово за словом?

Код:

#include <stdio.h>
int main(void) {
 char i[50];
 while(scanf("%s ", i)){
 printf("You've written: %s \n", i);
 }
 printf("you have finished writing\n");
 return 0;
}
</stdio.h>

Одна из проблем заключается в том, что код не работает так, как ожидается. Если я набрал:

abc def ghi.

Он выводит:

You've written: abc
You've written: def

Как я могу это исправить? Цель состоит в том, чтобы прочитать каждое слово из stdin, пока оно не достигнет "ENTER" или "." (Точка).

4 ответа

@cnicutar довольно близко, но вы, видимо, хотите только начать читать что-то, кроме белого, и хотите прекратить чтение одного слова, когда вы попадаете в пробел, поэтому для вас, сканирование, вы, вероятно, хотите что-то большее

while(scanf(" %49[^ \t.\n]%*c", i)) {

В этом начальное пространство пропускается по любому ведущему пробелу. Затем сканирующий набор считывает данные до тех пор, пока не получит пробел, вкладку, новую строку или период. Затем% * c считывает (но удаляет) следующий символ (обычно тот, который остановил сканирование).

Это может, однако, выбросить символ, когда/если вы достигнете конца буфера, так что вы можете использовать% c и снабдить вместо него символ, который нужно читать. Это позволит вам восстанавливаться с одного слова дольше, чем указанный вами буфер.


Как насчет:

scanf("%49[ ^\n.]", str)

Или что-то в этом роде.


Отключить scanf в целом и перейти с fgets:

while (fgets(i, sizeof i, stdin))
{
 printf("you've written: %s\n", i);
}

со следующими оговорками:

  • Если в целевом буфере есть место, fgets будет хранить конечную новую строку как часть ввода;

  • Если вы хотите прекратить чтение при поиске ., вам придется добавить некоторую логику, чтобы найти ее во входной строке, например:

int foundDot = 0;
 while (fgets(i, sizeof i, stdin) && !foundDot)
 { 
 char *dot = strchr(i, '.');
 char *newline = strchr(i, '\n');
 if (dot != NULL)
 {
 foundDot = 1;
 *dot = 0; // overwrite the '.' character with the 0 terminator
 }
 if (newline != NULL)
 {
 *newline = 0; // overwrite newline character with 0 terminator
 }
 /**
 * Assuming you don't want to print a blank line if you find a dot
 * all by itself. 
 */
 if (strlen(i) > 0) 
 printf("you've written: %s\n", i);
 }


Самый простой способ сделать это - flex. В противном случае вы повторяете сложную сложную работу и, вероятно, ошибаетесь.

Кроме того, прочитайте lex и yacc, 2nd edition.

licensed under cc by-sa 3.0 with attribution.