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
- 您可以在循环中调用
:int c;while((c=fgetc(fp))!=EOF&&c!='\n'){}fgetc
- 您可以使用
: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
更常见,但我不会说它是惯用的(或者至少我不会说它是