C fgets()如何判断行是否大于指定的大小

时间:2019-04-24 06:03:56

标签: c line fgets

我正在使用fgets()来读取popen("ps -ev", "r")中的行,但我不知道如何知道fgets()是否部分或全部读取了行,以及是否部分读取/丢弃了多余的。

popen()读取每一行时,我正在读取前1024个字符,并从中获取所需的信息,效果很好。当行数大于1024个字符,然后我读取的下一行是上一行的延续,而不是我需要的格式(即每行开头的每一列的值)时,就会出现问题。如果我知道是否仅部分读取一行(该行包含1024个或更多字符,那么我想读取并丢弃每1024个字符,直到到达末尾。一旦结束,我可以致电{{1} },这次它将从下一行的开始而不是上一行的继续读取。

我知道fgets()会进行读取,直到找到换行符或达到所提供的限制为止,然后继续读取该行的其余部分。我尝试检查最后一个字符是否为'\ 0',并且该行中的倒数第二个字符为'\ n',但这不起作用。如果有帮助,我将在下面发布该代码。

如果运行代码,您将看到fgets()(其中LINE: num S num:num.num ...是一个数字),这是每行应以的开头。相反,有些行看起来像num。这些是前一行多余的行,也是导致问题的原因,因为它们的格式不正确。

任何人和所有帮助都将受到高度赞赏。

LINE: AAAAAAQAAABMAAAAQAAAAAAAAAAMAAAAFAAAAEAAAAAAAAAADAAAACwAAABA...

2 个答案:

答案 0 :(得分:3)

您有一个正确的主意:如果读取了整行,则缓冲区包含换行符。否则,该行要么比缓冲区大小长,要么我们位于文件末尾,并且最后一行未终止。

实现的主要问题是char* line ... sizeof linesizeof产生其操作数表达式类型的大小,因此sizeof line的意思是sizeof (char *),它是指针的大小,而不是数组line所指向的大小

此外,如果读取了较短的行,那么line[SIZE - 1]将访问未初始化的内存。

最简单的解决方案:

int is_full_line(const char *line) {
    return strchr(line, '\n') != NULL;
}

只需使用strchr在字符串中搜索'\n'

要丢掉剩余的超长线,您有几种选择:

  • 您可以循环调用fgets
  • 您可以循环调用fgetcint c; while ((c = fgetc(fp)) != EOF && c != '\n') {}
  • 您可以使用fscanffscanf(fp, "%*[^\n]"); fscanf(fp, "%*1[\n]");

关于

int const BUFFER_SIZE = 1024;

请注意,const没有在C中声明常量;它声明了只读变量。 char buf[BUFFER_SIZE]被认为是可变长度数组,因为大小不是常数。

要在C语言中获取真整数常量,您需要使用enum来代替

enum { BUFFER_SIZE = 1024 };

答案 1 :(得分:2)

您的问题是这个位:

line[sizeof line - 1]

line在这种情况下是char*,因此sizeof line的计算结果是指针的大小,而不是字符串的大小。您需要执行以下操作:

size_t len = strlen(line);
if (len && '\n' == line[len - 1]) ...

您不需要测试line[len] == '\0';所有的字符串都是如此。 (请注意,并非所有字符数组都适用,但是任何返回字符串的标准库函数都将返回以null终止的数组。)