华为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尴尬,大家别太。。。重在参观啊

0 0
原创粉丝点击