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

C fgets()如何判断行是否大于指定的大小,c,line,fgets,C,Line,Fgets,我正在使用fgets()从popen(“ps-ev”,“r”)读取行,我无法知道如何知道fgets()是否部分或全部读取行,以及如何部分读取/丢弃多余的行 当从popen()中读取每一行时,我正在读取前1024个字符,并从中获得所需的信息,这非常好。当行数大于1024个字符,然后我读取的下一行是前一行的延续,这不是我需要的格式(即每行开头每列的值),就会出现问题。如果我能知道我是否只读了一行的一部分(即该行包含1024个或更多字符),我希望每读1024个字符并将其丢弃,直到它结束。在结束时,我可

我正在使用
fgets()
popen(“ps-ev”,“r”)
读取行,我无法知道如何知道
fgets()
是否部分或全部读取行,以及如何部分读取/丢弃多余的行

当从
popen()
中读取每一行时,我正在读取前1024个字符,并从中获得所需的信息,这非常好。当行数大于1024个字符,然后我读取的下一行是前一行的延续,这不是我需要的格式(即每行开头每列的值),就会出现问题。如果我能知道我是否只读了一行的一部分(即该行包含1024个或更多字符),我希望每读1024个字符并将其丢弃,直到它结束。在结束时,我可以再次调用
fgets()
,这次它将从下一行的开始读取,而不是从上一行的继续读取

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

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

非常感谢您的任何帮助

#包括
#包括
#包括
#包括
#定义换行符()printf(“\n”);
#定义DIVIDER()printf(“================================================================================================================\n”);
#定义PL(l)printf(“行:%s\n”,l);
int const MAX_进程=20;
int const BUFFER_SIZE=1024;
内部排气管线(字符*管线){
if(第[sizeof-line-1]行=='\0'和第[sizeof-line-2]行)!='\n'){
printf(“n:%c0:%c\n”,第[sizeof line-2]行,第[sizeof line-1]行);
换行符();
返回-1;
}
返回0;
}
int main(int argc,char const*argv[]{
文件*fp=popen(“ps-ev”,“r”);
char buf[缓冲区大小];
字符*行=(字符*)1;
while(行){
分隔符();
行=fgets(buf,缓冲区大小,fp);
PL(线);
如果(排气管路(管路)!=0){
printf(“行结束\n”);
}
}
返回0;
}

您的问题在于:

line[sizeof line - 1]
line
在本例中是一个
char*
,因此
sizeof line
的计算结果是指针的大小,而不是字符串的大小。您需要执行以下操作:

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

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

您的想法是正确的:如果读取了完整的行,则缓冲区包含一个换行符。否则,该行可能长于缓冲区大小,或者我们位于文件末尾,最后一行未终止

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

另外,如果读取了较短的行,则
行[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\u SIZE]
被视为可变长度数组,因为大小不是常量

要获得C中的真整数常量,您需要使用
enum

enum { BUFFER_SIZE = 1024 };

如果您只阅读了任何
fgets
文档或参考资料(例如)它会告诉你,如果完整的行被读取,最后一个字符将是一个换行符。@一些程序员为什么不考虑这个答案?在<代码>穷途末路< /代码>中,<代码> Sigeof Prime<代码>是字符指针的大小,因此它不是你想要的。如果行没有被换行终止,则代码>行[N - 1 ]。将保留空终止符和
行[n-2]
将保留除换行符以外的非空字符。@MOehm您也一样。@Someprogrammerdude如果达到EOF,最后一行将被完全读取,但不会被换行符终止。如果发生这种情况,并且最后一行恰好比缓冲区大小短1字节,则需要小心。
定义缓冲区大小1024
也将enum方法更适合于符号调试器,因为
BUFFER\u SIZE
符号在编译时就存在,而#define方法在预处理阶段用文本数字替换
BUFFER\u SIZE
,因此调试器不会识别符号l、 @Ray我想说使用
#define
更常见,但我不会说它是惯用的(或者至少我不会说它是