如何在读取所有字母之前确定fgets是否停止?

时间:2016-04-26 14:22:25

标签: c file fgets

我这样做:

char buf[100];              
int n = 0;                  
char save[100][100];        

while (fgets(buf,100, file)!=NULL) {
    strcpy(save[n], buf);
    printf("%s",buf);
    n++;
}

之前我打开了FILE = *file错误处理。 我只想读取小于或等于100个字符的行。那些具有更多字符的,我想忽略并向“保存”数组或perrorstout流写一些特殊消息。

但是,我怎么可能知道我是否只有100个字符,或者我的fgets是否只是停止阅读?

我怎么知道我首先是否超过100?

3 个答案:

答案 0 :(得分:2)

请勿使用fgets()use getline()。使用fgets(),一旦您阅读了太长的行(无论您是否识别它),您就必须继续阅读该行并将其丢弃,直到您到达新行。换句话说,您需要跟踪状态,如果您使用getline()则不需要,因为它会为您提供整行,并告诉您它的持续时间:

FILE *fp = // fopen() however you need to

char *lineArray[ MAX_LINES ];
int ii = 0;

char *line = NULL;
size_t len = 0UL;

// loop until getline() fails
for ( ;; )
{
    ssize_t lineLen = getline( &line, &len, fp );
    if ( lineLen == -1L )
    {
        break;
    }

    if ( lineLen > 100L )
    {
        // handle too-long line
    }
    else
    {
        lineArray[ ii ] = strdup( line );
        ii++;
    }
}

在将行复制到数组之前,您可能希望从每行中删除任何尾随的newline字符。

请注意,我使用strdup()复制了该行 - 这不是C标准函数but it is POSIX

答案 1 :(得分:1)

首先让我们假设fgets()不会读取空字符。如果是这样,以下方法可能不够。

  

我只想读取小于或等于100个字符的行。那些有更多角色的人,我想忽略并写一些特别的信息给" save"阵列

问题1. 100个字符'\n'输入部分吗?让我们假设它不是。

OP似乎仍然希望读取该行,无论是长度还是短于100或COLS个字符,这只是一个如何处理它的问题。

推荐COLS+3的缓冲区。一个用于空字符,一个用于'\n',另一个用于超长线检测。

#define ROWS 100
#define COLS 100
char save[ROWS][COLS+1];  // +1 for \0      
char buf[COLS + 3];              
int n = 0;                  

while (n < ROWS && fgets(buf, sizeof buf, file)!=NULL) {
  size_t len = strlen(buf);
  bool EOLorEOFfound = false;

  // lop off potential \n
  if (len > 0 && buf[len - 1] == '\n') {
    buf[--len] = '\0';
    EOLorEOFfound = true;
  }

  // if line is too long ...
  if (len > COLS) {
    // consume rest of line
    while (!EOLorEOFfound) {
      int ch = fgetc(file);
      EOLorEOFfound = ch == '\n' || ch == EOF;
    }
    // write some special message to the "save" array
    assert(COLS >= 3);
    strcpy(save[n], "***");
  } 
  // Line not too long
  else {
    strcpy(save[n], buf);  // or memcpy(save[n], buf, len+1);
    printf("%s\n", buf);
  }
  n++;
}

答案 2 :(得分:0)

您可以检查字符串长度和最后一个字符。如果长度为99个字符且最后一个字符不是换行符,则fgets无法读取的行中有更多字符(尽管其余字符可能只是换行符)

如果fgets读取整行,则字符串的长度将小于99,或者最后一个字符将是换行符(如果fgets适合,则'\0'总是添加缓冲区)。

请注意,我说 99 个字符,因为100个字符的数组只能容纳99个字符加上字符串终结符fgets。如果你想读取(包括)100个字符,你的缓冲区需要大101个字符。

Example showing it in "action"。前两个输出来自更长的读取线,并且fgets没有读取所有线。第二行输出是FileInfo mostrecentlog = (from f in logDirectory.GetFiles("Receive") orderby f.LastWriteTime descending select f).First(); 读取整行。