ANSI C - 如何逐字逐句读取stdin?

时间:2012-04-13 20:54:16

标签: c

代码:

#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;
}

一个问题是代码没有按预期执行。如果我输入:

abc def ghi.

它会输出:

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

我该如何解决?目标是从stdin读取每个单词,直到它达到“ENTER”或“。”。 (点)。

4 个答案:

答案 0 :(得分:5)

@cnicutar非常接近,但你显然只想开始阅读除白色空间以外的东西,并且想要在到达空白时停止阅读单个单词,所以对于你的scanset,你可能想要更像:

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

在此,初始空间会跳过任何前导空格。然后扫描集将一直读取,直到它到达空格,制表符,换行符或句点。然后%* c读取(但丢弃)下一个字符(通常是停止扫描的字符)。

但是,如果你到达缓冲区的末尾,这可以丢弃一个字符,所以你可能想要使用%c,并提供一个字符来读入。这样你就可以从比你提供的缓冲区更长的单个字恢复。

答案 1 :(得分:4)

怎么样:

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

或类似的东西。

答案 2 :(得分:2)

完全抛弃scanf,然后选择fgets

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

有以下警告:

  1. 如果目标缓冲区中有空间,fgets会将尾随换行符存储为输入的一部分;

  2. 如果您想停止阅读.,您必须添加一些逻辑以在输入字符串中查找它,例如:

  3. 
        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);
        }

答案 3 :(得分:-1)

最简单的方法是使用flex。否则你会重复一系列艰难而复杂的工作,而且可能会犯错误。

另外,请阅读lex and yacc, 2nd edition