华为2015机试--记录出错的代码所在的文件名称和行号
来源:互联网 发布:安徽航信网络发票2.0 编辑:程序博客网 时间:2024/06/05 06:52
我没机会参加今年华为的提前招聘(都不知道有这个渠道)题目如下:
开发一个简单错误记录功能小模块,能够记录出错的代码坐在的文件名称和行号。
处理:
1.记录最多8条错误记录,对相同的错误记录(即文件名称和行号完全匹配)只记录一条,错误计数增加;
(文件所在的目录不同,文件名和行号相同也要合并)
2.超过16个字符的文件名称,只记录文件的最后有效16个字符;(如果文件名不同,而只是文件名的后16个字符和行号相同,也不要合并)
3.输入的文件可能带路径,记录文件名称不能带路径
输入描述:
一行或多行字符串。每行包括带路径文件名称,行号,以空格隔开。
文件路径为windows格式
如:E:\V1R2\product\fpgadrive.c 1325
输出描述:
将所有的记录统计并将结果输出,格式:文件名代码行数数目,一个空格隔开,如: fpgadrive.c 1325 1
结果根据数目从多到少排序,数目相同的情况下,按照输入第一次出现顺序排序。
如果超过8条记录,则只输出前8条记录.
如果文件名的长度超过16个字符,则只输出后16个字符
题目本身看起来不难,但动手做起来还是花了几个小时才弄出来,在某网测试超时啦(汗,我好菜),下面贴出我的实现代码,本着练习C/C++的心态,使用了C++的非标准容器hash_map,标准容器string,multimap,字符串流stringstream(很喜欢这个类,一些类型转换成字符串或字符串转其他类型不要太方便,比什么itoa,sprintf,sscanf之流方便多了)以及函数对象,还有C的字符串处理函数等。虽然用了这么多工具 ,但没什么用,测试说超时了(100个测试用例,花了6、7秒钟),但结果是正确的,在这里写成博客,只要是总结经验,留给将来自己复习,而分享给大家,是给大家一个参照吧。上代码。。。
#include <iostream>#include <sstream>#include <string>#include <cstring>#include <hash_map>#include <map>#include <functional>using namespace std;using namespace __gnu_cxx;class errorItem{public: errorItem() {}; errorItem(int index, int num, const char* fileName, int nCount = 1) { _index = index; _num = num; strcpy(_fileName, fileName); _nCount = nCount; } errorItem(const errorItem& eItem) { _index = eItem._index; _num = eItem._num; _nCount = eItem._nCount; strcpy(_fileName, eItem._fileName); }public: int _index; //记录行输入的顺序号 int _num; //行号 char _fileName[17]; //文件名 ,长度不超过16字符 int _nCount; //该记录的重复次数};struct Idx{ int nCount; int index;};struct Comp{ bool operator()(const Idx& idx1, const Idx& idx2)const { if(idx1.nCount == idx2.nCount) return idx1.index < idx2.index ? true:false; else return idx1.nCount > idx2.nCount ? true:false; }};struct eqStr{ bool operator() (const string& str1, const string& str2) const{ return str1 == str2; }};struct str_hash{ size_t operator()(const string& str) const { unsigned long __h = 0; for (size_t i = 0 ; i < str.size() ; i ++) __h = 65535*__h + str[i]; return size_t(__h); }};int main(){ int index = 0; string errorStr; hash_map<string, errorItem, str_hash, eqStr> hashMap; multimap<Idx, string, Comp> itemsMap; while(getline(cin, errorStr)){ ++index; string keyStr, fileName, numStr; char ftFileName[17] = {'\0'}; string::size_type idx1 = errorStr.find_last_of('\\'); string::size_type idx2 = errorStr.find_last_of(' '); if(idx2 == string::npos) continue; if(idx1 == string::npos){ keyStr = errorStr.substr(0); fileName = errorStr.substr(0, idx2-1); } else{ keyStr = errorStr.substr(idx1+1); fileName = errorStr.substr(idx1+1, idx2-idx1-1); } numStr = errorStr.substr(idx2+1); int num = atoi(numStr.c_str()); int fileNameLen = fileName.length(); if(fileNameLen > 16){ //文件名长度大于16,取最后16个有效字符 string::size_type st = 0; string::size_type st16 = st; while(st != string::npos){ if(st >= 16) st16 = st16 + 1; st = st + 1; } strcpy(ftFileName, fileName.substr(st16).c_str()); } else strcpy(ftFileName, fileName.c_str()); if(hashMap.count(keyStr) < 1) hashMap.insert(make_pair(keyStr, errorItem(index, num, ftFileName))); else hashMap[keyStr]._nCount++; } typedef hash_map<string, errorItem, str_hash, eqStr>::iterator hashIter; //cout << hashMap.size() << endl; for(hashIter iter = hashMap.begin(); iter != hashMap.end(); ++iter){ ostringstream is; is << iter->second._fileName << " " << iter->second._num << " " << iter->second._nCount; string retStr = is.str(); Idx newIdx = {iter->second._nCount, iter->second._index}; itemsMap.insert(make_pair(newIdx, retStr)); } typedef multimap<Idx, string, Comp>::iterator mulIter; int i = 1; for(mulIter iter = itemsMap.begin(); i <= 8 && iter != itemsMap.end(); ++i,++iter) { //cout << iter->first.nCount << " " << iter->first.index << " "; cout << iter->second << endl; } return 0;}
先总结上面代码中非标准容器hash_map的使用过程中,需要注意的地方,上面代码是在codeblock上的gcc编译的。
a、需要引用头文件#include <hash_map>
b、需要引用命名空间:using namespace __gnu_cxx;
c、定义hash_map对象时,按照你设置的key类型,若不是默认类型,需要重新定义hash函数、equal_to函数.对于值类型,若是自定义类型,该自定义类型的类中必须有拷贝构造函数、显示的无参构造函数,原因看hash_map源码可知,hash_map成员函数会调用值类型的拷贝构造函数和无参构造函数,具体可看hash_map的源码。
hash_map原型是:
template hash_map< class key, class T, class HashFcn = hash<key>, class EqualKey = equal_to<key>, class Alloc = alloc>
class hash_map { ..... };
C++标准中默认定义的hash函数的类型包括:char, int, long, char*, const char*, unsigned char, signed char, short, unsigned short, unsigned int , unsigned long,它们定义在<stl_hash_fun.h>中,有兴趣可以看看其中实现。所以对于string类型的key,就需要自己重新定义hash啦,不难。
自己定义string类型hash函数对象:
struct str_hash{
size_t operator()(const string& str) const
{
unsigned long __h = 0;
for (size_t i = 0 ; i < str.size() ; i ++)
__h = 65535*__h + str[i];
return size_t(__h);
}
};
或者调用现成的,注意要引用<stl_hash_fun.h>
struct str_hash{
size_t operator()(const string& str) const
{
return (size_t)__stl_hash_string(str.c_str());
}
}
对于值类型,若是自定义的,你也必须重新定义equal_to,自定义成函数对象
struct eqStr{
bool operator() (const string& str1, const string& str2) const{
return str1 == str2;
}
};
最后说下我测试的100条数据,运行结果吧:
测试数据:
e:\1\aa3.txt 3
e:\3\aa1.txt 2
e:\2\aa2.txt 3
e:\3\aa1.txt 1
e:\1\aa1.txt 3
e:\3\aa1.txt 2
e:\1\aa3.txt 3
e:\2\aa3.txt 2
e:\1\aa1.txt 2
e:\3\aa3.txt 2
e:\1\aa2.txt 2
e:\1\aa3.txt 1
e:\1\aa3.txt 1
e:\2\aa3.txt 2
e:\1\aa2.txt 1
e:\3\aa1.txt 2
e:\1\aa1.txt 3
e:\2\aa1.txt 1
e:\3\aa3.txt 2
e:\1\aa1.txt 1
e:\2\aa2.txt 2
e:\3\aa3.txt 2
e:\1\aa2.txt 1
e:\1\aa3.txt 2
e:\1\aa3.txt 3
e:\1\aa2.txt 3
e:\3\aa1.txt 3
e:\2\aa2.txt 2
e:\1\aa1.txt 1
e:\2\aa3.txt 1
e:\3\aa1.txt 1
e:\2\aa1.txt 3
e:\3\aa3.txt 2
e:\1\aa3.txt 3
e:\2\aa3.txt 3
e:\1\aa2.txt 3
e:\2\aa2.txt 1
e:\1\aa3.txt 1
e:\1\aa3.txt 1
e:\3\aa3.txt 3
e:\3\aa3.txt 2
e:\1\aa2.txt 3
e:\1\aa2.txt 3
e:\1\aa2.txt 3
e:\1\aa1.txt 1
e:\2\aa3.txt 1
e:\3\aa3.txt 1
e:\2\aa3.txt 2
e:\3\aa1.txt 3
e:\2\aa2.txt 2
e:\2\aa2.txt 2
e:\2\aa3.txt 1
e:\1\aa3.txt 3
e:\3\aa1.txt 2
e:\3\aa2.txt 2
e:\1\aa2.txt 1
e:\2\aa2.txt 1
e:\2\aa1.txt 2
e:\2\aa2.txt 1
e:\1\aa2.txt 1
e:\2\aa3.txt 1
e:\2\aa2.txt 1
e:\2\aa1.txt 2
e:\3\aa2.txt 3
e:\3\aa1.txt 3
e:\2\aa2.txt 3
e:\2\aa3.txt 1
e:\3\aa3.txt 2
e:\2\aa3.txt 1
e:\1\aa1.txt 2
e:\3\aa3.txt 1
e:\3\aa1.txt 1
e:\2\aa2.txt 3
e:\3\aa3.txt 2
e:\2\aa1.txt 3
e:\1\aa3.txt 3
e:\3\aa2.txt 1
e:\2\aa1.txt 3
e:\1\aa3.txt 3
e:\2\aa2.txt 2
e:\1\aa1.txt 2
e:\3\aa1.txt 1
e:\1\aa3.txt 1
e:\3\aa1.txt 2
e:\1\aa1.txt 2
e:\1\aa1.txt 3
e:\3\aa1.txt 1
e:\3\aa1.txt 1
e:\2\aa3.txt 3
e:\2\aa2.txt 1
e:\2\aa1.txt 2
e:\2\aa2.txt 1
e:\3\aa2.txt 3
e:\1\aa2.txt 1
e:\3\aa2.txt 2
e:\2\aa1.txt 1
e:\2\aa3.txt 3
e:\1\aa1.txt 2
e:\1\aa1.txt 1
e:\1\aa1.txt 2
测试结果如下:
。。。这次竟然10s,大家别太。。。重在参观啊
- 华为2015机试--记录出错的代码所在的文件名称和行号
- 开发一个简单错误记录功能小模块,能够记录出错的代码所在的文件名称和行号。
- 开发一个简单错误记录功能小模块,能够记录出错的代码所在的文件名称和行号。
- Java取得代码所在行号的方法
- 查看函数和所在的行号
- oracle数据库中求某条记录的所在的行号
- mysql 实现行号的方法——如何获取当前记录所在行号
- mysql 实现行号的方法——如何获取当前记录所在行号
- mysql 实现行号的方法——如何获取当前记录所在行号
- python 获取当前位置所在的函数名和行号
- python 获取当前位置所在的函数名和行号
- python中获取当前位置所在的行号和函数名
- [原创]VB程序 - 处理字符和文件名称的代码模块
- Android/Java获取当前代码执行时所在的文件名/方法名/行号
- edit得到光标所在处的行号和之前的字符个数
- 求出其中最大的元素值,以及其所在的行号和列号。
- android代码出错的零碎边角记录
- FW:在python中获取当前位置所在的行号和函数名
- 黑马入门教程笔记01-OC
- Android之测试前期那点事
- HDU 2037 今年暑假不AC(贪心)
- springmvc + freemarker 实现hello-world
- 软件测试初体验
- 华为2015机试--记录出错的代码所在的文件名称和行号
- 学习《算法导论》第八章 计数排序 总结
- HealthKit 框架体系
- [leetcode] 151.Reverse Words in a String
- linux系统中读写流程
- HDU 3501 Calculation 2(欧拉函数)
- HDOJ 1217 Arbirage(最短路)
- 基于spark1.4.1的sparkR的实例操作
- HDU 2039 三角形(水~)