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 linesizeof产生其操作数表达式类型的大小,所以sizeof line表示sizeof (char *),这是一个指针的大小,而不是line指向的数组的大小进入.

此外,如果读取的行较短,则 line[SIZE - 1] 将访问未初始化的内存。

最简单的解决方案:

int is_full_line(const char *line) {
    return strchr(line, '\n') != NULL;
}

只需使用 strchr 在字符串中搜索 '\n'

要丢弃超长行的其余部分,您有几种选择:

  • 您可以在循环中再次调用 fgets
  • 您可以循环调用 fgetcint c; while ((c = fgetc(fp)) != EOF && c != '\n') {}
  • 您可以使用 fscanffscanf(fp, "%*[^\n]"); fscanf(fp, "%*1[\n]");

关于

int const BUFFER_SIZE = 1024;

注意 const 不在 C 中声明常量;它声明只读变量。 char buf[BUFFER_SIZE] 被认为是可变长度数组,因为大小不是常量。

要在 C 中获得真正的整数常量,您需要使用 enum 代替:

enum { BUFFER_SIZE = 1024 };