哈希查找的应用之打印c++源文件中关键字和函数名

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

using namespace std;

/*unsigned int BKDRHash(const string str)
{
 unsigned int seed=131;
 unsigned int hash=0;
 string::const_iterator it;
 cout<<sizeof(unsigned int)<<endl;
 for(it=str.begin();it!=str.end();it++)
 {
  hash=hash*seed+*it;
 }
 return hash & 0x7FFFFFFF;
}
*/

//c++关键字列表
const unsigned int M=66; //关键字个数
const string KeyList[M]={"asm","auto","bad_cast","const_cast","dynamic_cast","reinterpret_cast","static_cast",
"bad_typeid","bool","break","case","catch","throw","try","char","class","type","const","continue","delete",
"do","double","else","enum","explicit","export","extern","false","true","float","for","friend","goto","if"
,"inliine","int","long","mutable","namespace","new","operator","private","protected","public","register",
"return","short","signed","unsigned","static","struct","switch","template","typedef","typeid","typename",
"union","using","void","volatile","wchar_t","while","this","for","cout","cin"};

vector<string>kl(KeyList,KeyList+M);

typedef struct HashNode //哈希节点
{
 string key;
 struct HashNode *link;
};

const unsigned int N=26;
typedef HashNode *array[N]; //哈希数组

class HashofAlphabet
{
private:
 array HashList; 
 unsigned int HashFuction(const string& str); //哈希函数
public:
 HashofAlphabet();
 HashNode* Locate(const string& str); //查找关键字
 bool Insert(const string& str); //插入关键字
 bool Create(const vector<string>& keylist); //创建Hash表
 void show() const;
};

HashofAlphabet::HashofAlphabet()
{
 int i;
 for(i=0;i<N;i++)
 {
  this->HashList[i]=0; //初始化使得每个指针为空
 }
}

bool HashofAlphabet::Create(const vector<string>& keylist)
{
 vector<string>::const_iterator it;
 for(it=keylist.begin();it!=keylist.end();it++)
 {
  if(!this->Insert(*it))
  {
   cerr<<"内存空间不足,插入失败!"<<endl;
   return false;
  }
 }
 return true;
}

unsigned int HashofAlphabet::HashFuction(const string& str)
{
 return static_cast<int>(str[0]-'a');
}

HashNode* HashofAlphabet::Locate(const string& str)
{
 unsigned int index=this->HashFuction(str);
 if(index<0 || index>=N) return 0; // 下标超出合法范围
 HashNode *p=this->HashList[index];
 while(p)
 {
  if(p->key==str) return p;
  p=p->link;
 }
 return 0;
}

bool HashofAlphabet::Insert(const string &str)
{
 HashNode *p=new HashNode;
 if(!p) return false;
 p->key=str;
 p->link=0;
 unsigned int pos=this->HashFuction(str);
 p->link=this->HashList[pos]; //采用前插
 this->HashList[pos]=p;
 return true;
}

void HashofAlphabet::show() const
{
 int i;
 HashNode *p;
 for(i=0;i<N;i++)
 {
  cout<<"哈希值是"<<i<<"的有:";
  for(p=this->HashList[i];p;p=p->link)
  {
   cout<<p->key<<" ";
  }
  cout<<endl;
 }
}

class FileNotOpen //文件无法打开异常类
{
public:
 string what()
 {
  string str="文件无法打开,没有此文件或目录!";
  return str;
 }
};
 
class Convert //转换类
{
private:
 bool HasKuohao(const string& str); //判断字符串是不是含有括号
 bool HasJianKuohao(const string& str); //判断字符串是不是含有尖括号
public:
 void ReadFile(const string& filename,vector<string>& tmp);//将文件内容读入到向量tmp中

};
 
bool Convert::HasKuohao(const string& str)
{
 string::const_iterator it;
 for(it=str.begin();it!=str.end();it++)
 {
  if(*it=='(') return true;
 }
 return false;
}

bool Convert::HasJianKuohao(const string& str)
{
 string::const_iterator it;
 for(it=str.begin();it!=str.end();it++)
 {
  if(*it=='<') return true;
 }
 return false;
}

void Convert::ReadFile(const string& filename,vector<string>& tmp)
{
 ifstream infile; //定义输入流文件
    try
 {
  infile.open(filename.c_str(),ios::in); //以读方式打开此文件
  if(!infile) throw FileNotOpen();
 }
 catch(FileNotOpen& e)
 {
  cerr<<e.what()<<endl;
  exit(-1);
 }
    catch(...)
 {
  cerr<<"Something unexpected!"<<endl;
 }
 string s;
 while(getline(infile,s)) //获取每一行
 {
  stringstream line(s); //初始化字符串流对象
  string word;
  while(line>>word)
  {
   if(!this->HasKuohao(word) && !this->HasJianKuohao(word)) tmp.push_back(word); //此单词不含有左括号
                    //也不含有<,括号直接放入向量tmp中
   else if(this->HasKuohao(word))//含有左括号
   {
    string prekuohao=""; //括号前的内容
    string::iterator it=word.begin();
    while(*it!='(') prekuohao+=*it++;
    tmp.push_back(prekuohao); //将左口号前的内容放入
    tmp.push_back("(");
    it++;
    string betweenkuohao=""; //左右括号间的内容
    while(it!=word.end() && *it!=')') betweenkuohao+=*it++;
    if(betweenkuohao.empty()==false)  //左右括号间的内容确实有内容
    {
     stringstream ss(betweenkuohao);
     string word;
     while(ss>>word)
     {
      tmp.push_back(word); //将左右括号间的内容放入
     }
    }
    if(*it==')') tmp.push_back(")");
   }
   else //含有<括号
   { 
    string prekuohao=""; //括号前的内容
    string::iterator it=word.begin();
    while(*it!='<') prekuohao+=*it++;
    tmp.push_back(prekuohao); //将左口号前的内容放入
    tmp.push_back("<");
    it++;
    string betweenkuohao=""; //左右括号间的内容
    while(it!=word.end() && *it!='>') betweenkuohao+=*it++;
    if(betweenkuohao.empty()==false)  //左右括号间的内容确实有内容
    {
     stringstream ss(betweenkuohao);
     string word;
     while(ss>>word)
     {
      tmp.push_back(word); //将左右括号间的内容放入
     }
    }
    if(*it=='>') tmp.push_back(">");
   }
  }
 }
 infile.clear(); //清除文件流
 infile.close(); //关闭文件
}

class Print_FileContent //打印文件内容抽象类
{
protected:
 vector<string>storevector; //存储文件内容的向量
 Convert c;
 string filename;
 HashofAlphabet hash; //哈希对象
public:
 virtual void print()=0;
};

class Print_Keyword:public Print_FileContent
{
private:
 bool Occurance[M]; //表示关键字是不是已经出现过,在打印时去除重复的关键字
 unsigned int PositionOfKl(const string& key); //关键字在kl向量中的位置
public:
 Print_Keyword();
 void print();
};

Print_Keyword::Print_Keyword()
{
 hash.Create(kl); //创建Hash
 int i;
 for(i=0;i<M;i++) Occurance[i]=false; //表示第i个关键字没有出现过
}

unsigned int Print_Keyword::PositionOfKl(const string& key)
{
 vector<string>::const_iterator it;
 for(it=kl.begin();it!=kl.end();it++)
 {
  if(*it==key)
  {
   return it-kl.begin();
  }
 }
}
void Print_Keyword::print()
{
 cout<<"请输入c++源文件完整路径(如c:\\study\ss\aa.cpp):";
 cin>>filename;
 c.ReadFile(filename,storevector);
 vector<string>::const_iterator it;
 cout<<"此源文件中C++的关键字是:"<<endl;
 int pos; //关键字在Occurance中位置
 for(it=storevector.begin();it!=storevector.end();it++)
 {
  if(hash.Locate(*it))  //是关键字
  {
   pos=this->PositionOfKl(*it); //找到这个关键字的
   if(!this->Occurance[pos])
   {
    cout<<*it<<endl;
    this->Occurance[pos]=true;
   }
  }
 }
}


class Print_FunctionName:public Print_FileContent //打印函数名类
{
private:
 set<string>name; //存放已经打印的文件名
public:
 Print_FunctionName();
 void print();
};

Print_FunctionName::Print_FunctionName()
{
 this->hash.Create(kl);
}

void Print_FunctionName::print()

 cout<<"请输入c++源文件完整路径(如c:\\study\ss\aa.cpp):";
 cin>>filename;
 c.ReadFile(filename,storevector);
 vector<string>::const_iterator it;
 cout<<"此源文件中C++的函数是:"<<endl;
 int pos; //关键字在Occurance中位置
 for(it=storevector.begin();it!=storevector.end();it++)
 {
  if(*it=="(" && it>storevector.begin())  //左括号前可能是函数名
  {
   if(hash.Locate(*(it-1))) break; //左括号前是关键字
   else
   {
    if(name.count(*(it-1))==0)
    {
     cout<<*(it-1)<<endl;
     name.insert(*(it-1));
    }
   }
  }
 }
}

void main()
{
 Print_Keyword pk;
 pk.print();
 Print_FunctionName pf;
 pf.print();
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值