读取尺寸受限的输入线,忽略尾部

时间:2015-11-02 19:15:08

标签: c scanf fgets

是否有库函数从stdin读取输入行并满足以下要求?

  1. 我有一个特定大小的有限静态缓冲区(大小可能是已知常量)。
  2. 不允许动态分配。因此不能使用像getline()这样的库函数。
  3. 对于长度超出缓冲区大小的行,将忽略该行的未读尾部。
  4. 我读取一行的解决方案是使用fgets和一个循环来读取和忽略尾部。代码如下

    char buffer[80], tail_buffer[80];
    char * line, * tail;
    line = tail = fgets(buffer, 80, stdin);
    /* Read the tail part to ignore it */
    while (tail != NULL && tail[strlen(tail)-1] != '\n')
    {
        tail = fgets(tail_buffer, 80, stdin);
    }
    /* Use 'line' as needed */
    

3 个答案:

答案 0 :(得分:1)

在查看scanf的文档后,我自己找到了解决方案。

char buffer[80];
scanf(" %79[^\n]%*[^\n]", buffer);

编辑:使用@chux的注释,这在解析空行和初始空格时有一些限制,并且使用@ user3386109的解决方案,我将如下所示增强扫描所有行直到EOF。

char buffer[80] = "";

while (scanf("%79[^\n]%*[^\n]", buffer) != EOF)
{
    /* Process the line in buffer */

    if (feof(stdin)) break;
    getchar(); /* Remove end of line */
    buffer[0] = 0;
}

答案 1 :(得分:1)

fgets()有一些极端情况,无法在完全解决OP的目标时使用它。
只需使用fgetc()循环。

// Return count of `char` read - not including potential \n.
int read_line(char *dest, int size) {
  int i = 0;
  if (size > 0) {
    size--;
    int ch;
    while ((ch = fgetc(stdin)) != '\n' && ch != EOF) {
      if (i < size) {
        dest[i++] = ch;
      }
    }
    dest[i] = '\0';
    if (ch == EOF && i == 0) return EOF;
    }
  return i;
}

强制使用fgets()看起来像

bool was_there_extra(char *buf, size_t size) {
  char *lf = strchr(buf, '\n');
  if (lf) {
    *lf = '\0';  // optional: lop off potential trailing \n
    return false;
  }
  int ch;
  bool extra = false;
  while ((ch = fgetc(stdin)) != '\n' && ch != EOF) {
    extra = true;
  }
  return extra;
}

while (fgets(buf, sizeof buf, stdin)) {
  if (was_there_extra(buf, sizeof buf)) ...
  else ...
}

如果代码读取'\0',这种方法会被愚弄。

答案 2 :(得分:1)

使用scanf读取直到找到换行符的替代解决方案,以及getchar来读取换行符。

char buffer[80];
if ( fgets( buffer, sizeof buffer, stdin ) != NULL )
{
    if ( strchr( buffer, '\n' ) == NULL )   // if the buffer does not contain the newline
    {
        scanf( "%*[^\n]" );                 // read up to the newline
        getchar();                          // read the newline
    }
}