c++ - 在 C++ 中有效地解析日志文件的文本

标签 c++ parsing

我想构建一个日志浏览器。为此我需要有效地编码。给出了一个简单的解析代码。 请让我知道这段代码是否可以或需要进行任何改进。 下面给出的程序中的 strtok(o,delim) 函数也不清楚。所以请向我解释一下它的功能。

// parsing ex.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#define _CRT_SECURE_NO_WARNINGS

#include <iostream>
using std::cout;
using std::endl;

#include <fstream>
using std::ifstream;

#include <cstring>

const int MAX_CHARS_PER_LINE = 512;
const int MAX_TOKENS_PER_LINE = 20;
const char* const DELIMITER = " ";

int main()
{
    // create a file-reading object
    ifstream fin;
    fin.open("C:\\Personal\\data.txt"); // open a file
    if (!fin.good()) 
        return 1; // exit if file not found

    // read each line of the file
    while (!fin.eof())
    {
        // read an entire line into memory
        char buf[MAX_CHARS_PER_LINE];
        fin.getline(buf, MAX_CHARS_PER_LINE);

        // parse the line into blank-delimited tokens
        int n = 0; // a for-loop index

        // array to store memory addresses of the tokens in buf
        const char* token[MAX_TOKENS_PER_LINE] = {}; // initialize to 0

        // parse the line
        token[0] = strtok(buf, DELIMITER); // first token
        if (token[0]) // zero if line is blank
        {
            for (n = 1; n < MAX_TOKENS_PER_LINE; n++)
            {
                token[n] = strtok(0, DELIMITER); // subsequent tokens
                if (!token[n]) break; // no more tokens
            }
        }

        // process (print) the tokens
        for (int i = 0; i < n; i++) // n = #of tokens
            cout << "Token[" << i << "] = " << token[i] << endl;
        cout << endl;
    }
}

最佳答案

除了没有边界检查之外,您的代码可以正常工作。如果文件中的行长于 MAX_CHARS_PER_LINE,它将失败。 while (!fin.eof()){...} 还容易出现其他错误。

使用std::string可以轻松解决这个问题

如果一行包含超过 MAX_TOKENS_PER_LINE 个标记,该代码也会失败。您可以使用 std::vector

解决此问题

要进行改进,请使用 std::string 而不是字符数组。

使用 std::vector 而不是 C 样式数组。

使用std::stringstream代替strtok

优点是您不必担心最大行长度或每行的最大标记数。

#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <vector>

const char CDELIMITER = ' ';

int main()
{
    ...
    std::string buf;

    //read the file line by line
    while (std::getline(fin, buf))
    {
        //convert the line in to stream:
        std::istringstream ss(buf);

        //declare vector of string (instead of fixed array)
        std::vector<std::string> vec;

        //read the line, word by word
        while (std::getline(ss, buf, CDELIMITER))
            vec.push_back(buf);

        for (size_t i = 0; i < vec.size(); i++)
            std::cout << "Token[" << i << "] = " << vec[i] << "\n";
        std::cout << "\n";
    }
    return 0;
}

关于c++ - 在 C++ 中有效地解析日志文件的文本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39566662/

相关文章:

c++ - 重新定义 printf()、sprintf() 等 arm-none-eabi 工具链

android - 如何将数据库条目 "12"解析为日期格式为 "12"而不是 "0"

java - 返回 jsoup 中 div 之间的文本

vba - 优化Vba代码

C++ cin没有得到线

c++ - QPSQL 驱动程序未加载 Qt

c++ - g++ 2.9-gnupro-98r2,错误 : cannot declare references to functions; use pointer to function instead

c++ - 创建队列类时出错

php - 使用 PHP 从 URL 获取第一个目录

python - 通过元素树创建 xml 后解析时出现元素树错误