我正在使用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...
答案 0 :(得分:3)
您有一个正确的主意:如果读取了整行,则缓冲区包含换行符。否则,该行要么比缓冲区大小长,要么我们位于文件末尾,并且最后一行未终止。
实现的主要问题是char* line
... sizeof line
。 sizeof
产生其操作数表达式类型的大小,因此sizeof line
的意思是sizeof (char *)
,它是指针的大小,而不是数组line
所指向的大小
此外,如果读取了较短的行,那么line[SIZE - 1]
将访问未初始化的内存。
最简单的解决方案:
int is_full_line(const char *line) {
return strchr(line, '\n') != NULL;
}
只需使用strchr
在字符串中搜索'\n'
。
要丢掉剩余的超长线,您有几种选择:
fgets
。fgetc
:int c; while ((c = fgetc(fp)) != EOF && c != '\n') {}
fscanf
:fscanf(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终止的数组。)