使用 ifstream 解析文本的惯用方法是什么?

发布于 2024-10-13 03:15:13 字数 466 浏览 6 评论 0原文

我正在尝试解析文本文件以查找模式,然后获取子字符串。该代码片段工作正常,但是我可以改进吗?我可以尽量减少这里的复制吗?即我得到一行并将其存储在buf中然后构造一个字符串,可以消除这种复制吗?

简而言之,实现这一目标的惯用方法是什么?

    std::ifstream f("/file/on/disk");
    while (!f.eof()) {
        char buf[256];
        f.getline(buf, sizeof(buf));
        std::string str(buf);
        if (str.find(pattern) != std::string::npos)
        {
            // further processing, then break out of the while loop and return.
        }
    }

I'm trying to parse a text file to find a pattern then grab a substring. This code fragment works fine, however can I improve this? Can I minimize copying here? I.e. I get a line and store it in the buf then construct a string, can this copying be eliminated?

In short what's the idiomatic way of achieving this?

    std::ifstream f("/file/on/disk");
    while (!f.eof()) {
        char buf[256];
        f.getline(buf, sizeof(buf));
        std::string str(buf);
        if (str.find(pattern) != std::string::npos)
        {
            // further processing, then break out of the while loop and return.
        }
    }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

一抹苦笑 2024-10-20 03:15:13

这是一种可能的重写:

std::ifstream f("/file/on/disk");
char buffer[256];
while (f.getline(buffer, sizeof(buf))) { // Use the read operation as the test in the loop.
    if (strstr(buffer, pattern) != NULL) { // Don't cast to string; costs time
        // further processing, then break out of the while loop and return.
    }
}

主要更改被标记为内联,但总结一下:

  1. 使用读取操作作为 while 循环中的测试。这使得代码变得更短、更清晰。
  2. 不要将 C 样式字符串转换为 std::string;只需使用 strstr 进行扫描即可。

进一步说明,您可能不想在此处使用 C 样式字符串,除非您确定这就是您想要的。 C++ string 可能更好:

std::ifstream f("/file/on/disk");
std::string buffer;
while (std::getline(f, buffer)) { // Use the read operation as the test in the loop.
    if (buffer.find(pattern) != std::string::npos) {
        // further processing, then break out of the while loop and return.
    }
}

Here's one possible rewrite:

std::ifstream f("/file/on/disk");
char buffer[256];
while (f.getline(buffer, sizeof(buf))) { // Use the read operation as the test in the loop.
    if (strstr(buffer, pattern) != NULL) { // Don't cast to string; costs time
        // further processing, then break out of the while loop and return.
    }
}

The main changes are marked inline, but to summarize:

  1. Use the read operation as the test in the while loop. This makes the code a lot shorter and clearer.
  2. Don't cast the C-style string to a std::string; just use strstr to do the scan.

As a further note, you probably don't want to use a C-style string here unless you're sure that's what you want. A C++ string is probably better:

std::ifstream f("/file/on/disk");
std::string buffer;
while (std::getline(f, buffer)) { // Use the read operation as the test in the loop.
    if (buffer.find(pattern) != std::string::npos) {
        // further processing, then break out of the while loop and return.
    }
}
Saygoodbye 2024-10-20 03:15:13

在代码中,首先将文件中的字符复制到 char 数组中。这应该是所有必要的复制。如果您需要阅读每个字符一次,那么甚至不需要该副本。

接下来,从您填充的数组构造一个 std::string 。再说一遍,没有必要。如果您想要一个字符串,请直接从流中复制到字符串中。

std::ifstream f("/file/on/disk");
for( std::string line; std::getline(f, line); ) {
    if (str.find(pattern) != std::string::npos) {
        // further processing, then break out of the while loop and return.
    }
}

In your code, you first copy characters from the file into a char array. That should be all the copying necessary. If you'd need to read each character once then even that copy wouldn't be necessary.

Next, you construct a std::string from the array you filled. Again, unnecessary. If you want a string then copy from the stream directly into a string.

std::ifstream f("/file/on/disk");
for( std::string line; std::getline(f, line); ) {
    if (str.find(pattern) != std::string::npos) {
        // further processing, then break out of the while loop and return.
    }
}
少跟Wǒ拽 2024-10-20 03:15:13

您根本不需要那个 char[]

string line;
std::getline(f, line);
if (line.find(pattern) != std::string::npos)
{
    ....
}

You don't need that char[] at all.

string line;
std::getline(f, line);
if (line.find(pattern) != std::string::npos)
{
    ....
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文