[C++] 简单错误记录

输入采用了std::getline来输入整行,采用istringstream流来分解文件名和行号,采用vector<tuple>来存储记录元素。

分解并简化文件名采用的是find_last_of来分割子串,查找数组中可能有重复的记录采用find_if来实现,其中谓词函数采用lambda表达式实现,原因是普通的谓词函数只能是一元或者是二元,而本题中组内tuple元素,局部参数url和line_str共三个参数,所以采用lambda捕获两个局部变量。而如果查找存在则直接+1,不存在则采用emplace新增一个tuple元素,为什么不采用push_back呢,哈哈因为push_back采用的是拷贝构造,而emplace采用的是移动构造,当有大量记录时,效率会高很多。

#include<iostream>
#include<sstream>
#include<string>
#include<vector>
#include<algorithm>
#include<tuple>
using namespace std;


int main()
{
    string s;
    vector<tuple<string, string, int>> vt; //分别表示文件名,行号和数量
    // 读取每一行记录
    while(getline(cin, s)){
        // 分解文件名和行号
        istringstream iss(s);
        string total_url,line_str;
        getline(iss, total_url, ' ');
        getline(iss, line_str);
        string url = total_url.substr(total_url.find_last_of('\\')+1);
        if (url.size() > 16){
            url = url.substr(url.size()-16, 16);
        }
        vector<tuple<string,string, int>>::iterator it = find_if(vt.begin(), 
                                                                 vt.end(), 
                                                                 [url,line_str](const tuple<string,string, int> &r)->bool {
                                                                        return (std::get<0>(r) == url && std::get<1>(r) == line_str);
                                                                 }
                                                                );
        if(it != vt.end()){
            get<2>(*it) += 1;
        }
        else{
            vt.emplace(it, url, line_str, 1);
        }
    }
    // 输出最新的8个记录
    if( vt.size() > 8){
        for(int i = vt.size() -8; i < vt.size(); ++i){
            cout<< get<0>(vt[i]) <<" "<< get<1>(vt[i]) <<" "<< get<2>(vt[i]) <<" "<<endl;
        }
    }
    else{
        for(int i = 0; i < vt.size(); ++i){
            cout<< get<0>(vt[i]) <<" "<< get<1>(vt[i]) <<" "<< get<2>(vt[i]) <<" "<<endl;
        }
    }
    return 0;
}