开发者

What's the idiomatic way of parsing text by using ifstream?

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.
        }
    }


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.
    }
}


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.
    }
}


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

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜