缓冲区中类似于fgets的等价函数是什么?

6

我最初使用fgets()逐行解析文件。

现在我改变了策略,已经将整个文件存储在缓冲区中。但是我仍然希望按行读取该缓冲区以进行解析。是否有专门为此设计的东西,或者我需要编写一个循环来检查这一点处的0x0Achar


2
如果您正在使用C ++,可以查看istringstream,它允许您“从内存中的字符串读取”。 - Andre Holzner
2
你已经标记了 cc++ ... 那么它是哪个?你的缓冲区是如何定义的? - Brian Roach
决定你想写C代码还是C++代码。然后回来问如何做。如果你可能会认为它“不够C”,我不会浪费时间为你编写C++解决方案。 - sbi
我正在使用C ++,但在实现简单的情况下,我更喜欢使用类似fopen的C函数。 - Steven Lu
如果你正在编写词法分析器,为什么不用 flex 来编写呢?它非常快速和准确。它可以输出 C 和 C++ 代码,并且一旦接收到一个记号,你可以随心所欲地编写回调函数。 - Ahmed Masud
5个回答

7
memchr(加上一点自己的包装代码,以memcpy结束)是完全等效的——就像fgets一样,它需要一个最大长度来处理(应该是剩余输入缓冲区大小和输出缓冲区大小的最小值),并扫描直到找到所需的字符(将是'\n')或用尽了输入/输出空间。
请注意,对于已经在内存缓冲区中的数据,您可能希望跳过将其复制到单独的输出缓冲区的步骤,除非您需要在不修改输入的情况下使输出以null终止。许多初学C语言的程序员常犯的错误是认为他们需要零结尾,当真正需要做的是改进某些接口以接受(指针,长度)对,允许您传递/处理子字符串而无需复制它们。例如,您可以使用以下代码将它们传递给printfprintf("%.*s", (int)length, start);

感谢指出memchr。我以前从未使用过它,但我之前使用过strrchr,这非常方便。谢谢。 - Steven Lu

2
您可以使用sscanf函数来实现这一点。如果您确实需要整行内容,则可以尝试以下代码:
sscanf(your_buffer, "%50[^\n]", line);

(这将读取最多50个字符长的行。像往常一样,要注意长度和0 终止符。并检查sscanf的返回值,以防出现问题。)

您可以使用指针算术来移动您的缓冲区(只需添加“返回”行长度+1)。


0

对于 C,我想应该可以这样做:

// str (in/out): the unconsumed portion of the input string
static char *sgets(char *buf, int n, const char **str)
{
    const char *s = *str;
    const char *lf = strchr(s, '\n');
    int len = (lf == NULL) ? strlen(s) : (lf - s) + 1;

    if (len == 0)
        return NULL;
    if (len > n - 1)
        len = n - 1;

    memcpy(buf, s, len);
    buf[len] = 0;
    *str += len;
    return buf;
}

0

有一个叫做sscanf的函数,可能适用于你的情况,也可能不适用。


不过,sscanf 似乎没有为我提供匹配字符串结尾的指针。我仍需要进行搜索。 - Steven Lu
它返回处理的字节数int。 - Joshua
我相当确定它会返回它所做匹配的数量。 - Steven Lu

0
如果你正在寻找C函数,strtok()strsep()都可以在指定字符上分割字符串。

我确定 strtok 会修改底层字符串,这可能不太适合该任务,那么 strstep 怎么样? - Matthieu M.
1
是的,这两个函数都会直接修改字符串。如果你不想要这种情况,你需要使用 strchr / memcpy 来解决。 - user149341

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接