我正在使用fgets()
读取来自popen("ps -ev", "r")
的行,我无法知道如何知道fgets()
是否部分或完全读取一条线,以及如果部分读取/丢弃多余的线。
当从popen()
读取每一行时,我正在读取前1024个字符,并从中获取我需要的信息,这非常合适。当行大于1024个字符然后我读取的下一行是前一行的延续时出现问题,该行不是我需要的格式(即每行开头的每列的值)。如果我可以知道我是否只是部分读取一行(该行有1024个或更多字符,我想读取并丢弃每1024个字符直到它到达结尾。一旦结束,我可以再次调用fgets()
这个它将从下一行的开头读取而不是前一行的延续。
我知道fgets()
读取它直到找到换行符或者直到它达到提供的限制,然后继续读取该行的剩余部分。我已经尝试检查最后一个字符是'\ 0',并且该行中的倒数第二个字符是'\ n',但这不起作用。如果有帮助,我会在下面发布该代码。
如果你运行代码,你会看到LINE: num S num:num.num ...
(其中num
是一个数字),这是每行应该开始的。有些线条看起来像LINE: AAAAAAQAAABMAAAAQAAAAAAAAAAMAAAAFAAAAEAAAAAAAAAADAAAACwAAABA...
。这些是超出前一行的行,这些是导致问题的行,因为它们的格式不正确。
任何和所有帮助都非常感谢。
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#define NEWLINE() printf("\n");
#define DIVIDER() printf("============================================================================\n");
#define PL(l) printf("LINE: %s\n", l);
int const MAX_PROCESSES = 20;
int const BUFFER_SIZE = 1024;
int exhaustedLine(char* line) {
if (line[sizeof line - 1] == '\0' && line[sizeof line - 2] != '\n') {
printf("n:%c 0:%c\n", line[sizeof line - 2], line[sizeof line - 1]);
NEWLINE();
return -1;
}
return 0;
}
int main(int argc, char const *argv[]) {
FILE* fp = popen("ps -ev", "r");
char buf[BUFFER_SIZE];
char* line = (char*)1;
while (line) {
DIVIDER();
line = fgets(buf, BUFFER_SIZE, fp);
PL(line);
if (exhaustedLine(line) != 0) {
printf("END OF LINE\n");
}
}
return 0;
}
您有正确的想法:如果读取完整的行,则缓冲区包含换行符。否则该行要么长于缓冲区大小,要么我们位于文件末尾,最后一行未终止。
你的实现的主要问题是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 };
你的问题是这样的:
line[sizeof line - 1]
在这种情况下,line
是一个char*
,所以sizeof line
计算指针的大小,而不是字符串的大小。你需要做这样的事情:
size_t len = strlen(line);
if (len && '\n' == line[len - 1]) ...
你不需要测试那个line[len] == '\0'
;对所有字符串都是如此。 (请注意,并非所有字符数组都有,但任何返回字符串的标准库函数都将返回以null结尾的数组。)