本题考虑了字符串的操作,很多细节的问题需要考虑,还是很值得一做的。下面列出我在做本题时的一些关键注意点。值得一提的,利用C++标准模板库中的各类容器可以有效方便的解决很多细节问题。 1.循环输入一系列字符串的时候,如果每一行的字符串中有空格,应该如何输入? 利用while(cin)循环输入,但是由于cin遇到空格时会过滤掉后面的字符串,因此可以创建两个变量来接收空格前后的字符串。 2.利用哈希表解决此题时,需要考虑的变量包括:文件名、行号和次数,但是哈希表只能存储两个变量,如何解决? 将文件名和行号看作是一个变量即可。在输出的时候再将文件名和行号分开 3.如何从文件路径中提取出文件名? 利用getline()函数,以"\"为分隔符来分割字符串 4.如何提取出文件名最后的16个有效字符? 利用substr()函数 5.如何只输出八条最新的错误记录? 利用队列queue,如果数据大于八个,则只保留最新入队的八个数据;再将数据依次出队即可输出。

#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <unordered_map>
#include <queue>
using namespace std;

vector<string> processing_filename(const string &s) {
	istringstream is(s);
	string seg;
	vector<string> vec;
	while (getline(is, seg, ' ')) vec.push_back(seg);
	return vec;
}

int main() {
    string path, num;                      // 输入文件名和行号
    unordered_map<string, int> record;      // 各个错误文件和对应的出现次数(该文件同时包含文件名和行号)
    queue<string> res;                      // 利用队列统计文件出现的时间
    
    while (cin >> path >> num) {
        if (path.size() > 16) {
			// 只保留文件的最后有效16个字符
			int rem = path.size() - 16;
			path = path.substr(rem, 16);
		}
        string full = path + " " + num;
		istringstream is(full);
		string seg;
		vector<string> vec;
		// 分割路径和文件名
		while (getline(is, seg, '\\')) {
			vec.push_back(seg);
		}
		
		string file_name = vec[vec.size() - 1];
		if (record.find(file_name) != record.end()) {
			// 该文件名已经被记录了,这是一个旧记录
			record[file_name]++;   // 次数加一
		}
		else {
			// 该文件名第一次出现,说明这是一个新的记录
			record[file_name] = 1;          // 该错误的出现次数初始化为1
			res.push(file_name);            // 第一次出现,将该错误文件入队列
		}
    }
    
    if (res.size() <= 8) {
		int len = res.size();
		// 错误文件数目小于或者等于8
		for (int i = 0; i < len; i++) {
			string temp = res.front();
			vector<string> file_pro = processing_filename(temp);
			cout << file_pro[0] << " " << file_pro[1] << " " << record[temp] << endl;
			res.pop();
		}
	}
	else {
		// 错误文件数目大于8
		int len = res.size();
		int rem = len - 8;
		for (int k = 0; k < rem; k++) res.pop();   // 将大于8的文件剔除队列
		for (int i = 0; i < 8; i++) {
			string temp = res.front();
			vector<string> file_pro = processing_filename(temp);
			cout << file_pro[0] << " " << file_pro[1] << " " << record[temp] << endl;
			res.pop();
		}
	}
    
    return 0;
}