如何在读取所有字母之前确定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++; } 

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

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

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

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

我只想读取小于或等于100个字符的行。 那些具有更多字符的,我想忽略并向“save”数组写一些特殊的消息

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

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

不要使用fgets() ,请使用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标准函数, 但它是POSIX 。

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

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

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

在“动作”中显示它的示例 。 前两个输出来自更长的读取行,而fgets没有读取所有行。 第二行输出是fgets读取整行。