C fgets() 如何判断行是否大于指定大小
C fgets() how to tell if line is greater than specified size
我正在使用 fgets()
来读取来自 popen("ps -ev", "r")
的行,但我不知道如何知道 fgets()
是部分还是全部读取一行,以及如果部分读取如何 read/throw 去掉多余的。
在阅读 popen()
的每一行时,我正在阅读前 1024 个字符并从中获取我需要的信息,这非常有效。当行大于 1024 个字符时,问题就出现了,然后我读取的下一行是上一行的延续,这不是我需要的格式(即每行开头每列的值)。如果我能知道我是否只部分阅读了一行(即该行有 1024 个或更多字符,我想每 1024 个字符读取并丢弃一次,直到它到达末尾。一旦到了最后,我可以调用 fgets()
再次,这次它将从下一行的开头读取,而不是上一行的继续。
我知道 fgets()
一直往上读,直到它找到一个换行符或直到它达到提供的限制,然后继续阅读该行的剩余部分。我试过检查最后一个字符是“\0”,行中倒数第二个字符是“\n”,但这不起作用。我将 post 下面的代码以防有帮助。
如果您 运行 代码,您将看到 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] == '[=10=]' && 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;
}
你的问题是这个:
line[sizeof line - 1]
line
在这种情况下是一个 char*
,因此 sizeof line
计算为 指针 的大小,而不是 的大小细绳。你需要做这样的事情:
size_t len = strlen(line);
if (len && '\n' == line[len - 1]) ...
你不需要测试那个line[len] == '[=15=]'
;这对所有字符串都是正确的。 (请注意,并非所有字符数组都适用,但 return 字符串的任何标准库函数都将 return 为空终止数组。)
你的想法是正确的:如果读取了整行,则缓冲区包含一个换行符。否则该行要么比缓冲区大小长,要么我们在文件末尾并且最后一行未终止。
您实施的主要问题是 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 };
我正在使用 fgets()
来读取来自 popen("ps -ev", "r")
的行,但我不知道如何知道 fgets()
是部分还是全部读取一行,以及如果部分读取如何 read/throw 去掉多余的。
在阅读 popen()
的每一行时,我正在阅读前 1024 个字符并从中获取我需要的信息,这非常有效。当行大于 1024 个字符时,问题就出现了,然后我读取的下一行是上一行的延续,这不是我需要的格式(即每行开头每列的值)。如果我能知道我是否只部分阅读了一行(即该行有 1024 个或更多字符,我想每 1024 个字符读取并丢弃一次,直到它到达末尾。一旦到了最后,我可以调用 fgets()
再次,这次它将从下一行的开头读取,而不是上一行的继续。
我知道 fgets()
一直往上读,直到它找到一个换行符或直到它达到提供的限制,然后继续阅读该行的剩余部分。我试过检查最后一个字符是“\0”,行中倒数第二个字符是“\n”,但这不起作用。我将 post 下面的代码以防有帮助。
如果您 运行 代码,您将看到 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] == '[=10=]' && 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;
}
你的问题是这个:
line[sizeof line - 1]
line
在这种情况下是一个 char*
,因此 sizeof line
计算为 指针 的大小,而不是 的大小细绳。你需要做这样的事情:
size_t len = strlen(line);
if (len && '\n' == line[len - 1]) ...
你不需要测试那个line[len] == '[=15=]'
;这对所有字符串都是正确的。 (请注意,并非所有字符数组都适用,但 return 字符串的任何标准库函数都将 return 为空终止数组。)
你的想法是正确的:如果读取了整行,则缓冲区包含一个换行符。否则该行要么比缓冲区大小长,要么我们在文件末尾并且最后一行未终止。
您实施的主要问题是 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 };