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

问题描述 投票:4回答:2

我正在使用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;
}
c line fgets
2个回答
3
投票

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

你的实现的主要问题是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 };

2
投票

你的问题是这样的:

line[sizeof line - 1]

在这种情况下,line是一个char*,所以sizeof line计算指针的大小,而不是字符串的大小。你需要做这样的事情:

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

你不需要测试那个line[len] == '\0';对所有字符串都是如此。 (请注意,并非所有字符数组都有,但任何返回字符串的标准库函数都将返回以null结尾的数组。)

© www.soinside.com 2019 - 2024. All rights reserved.