草庐IT

哈希表之单词查找并输出其上下文

hantin 2023-03-28 原文

哈希表之单词查找

  1. 英文文章,写入一个文本文档,作为基础测试数据。 建立一个待查关键字文件,存储待查询的单词。
  2. 输入查询的单词,输出该单词的出现次数,及每个出现位置的上下文(前一句,单词/短语所在的句子,下一句)。
  3. 目前只支持查询一个单词。

以下为代码:


#include <iostream>
#include <string.h>
#include<vector>
#include <map>
#include <set>
#include<sstream>
#include <fstream>
#include <windows.h>
const int HASHNUM = 29989;

typedef struct Hashtable{            //哈希表结构体
    char *word;
    int count;
    struct Hashtable * next;
}Hashnode;
Hashnode* hashtable[HASHNUM];       //HASHNUMBER大小的指针数组(储存指针的数组) 作为hash表

std::vector<std::string>lines;
std::map<std::string,std::set<int>> wordline;   //需要使用到迭代器匹配行号所以使用map嵌套set

unsigned int Hashfuntion(const char *str);
void Hashinsert(char *str);
void readintohash(char *path);
void findquery(char *path);
void getlinecplusplus(char *path,char *str);


void readintohash(char *path){
    char ch[1024] = {NULL};              //存储一行字符串
    char *p;
    FILE *fp = fopen(path,"r");
    if(fp == NULL)
        exit(-1);
    while(( fgets(ch,sizeof (ch),fp) != NULL ))                           //读取到换行符时,或者到达文件末尾时停止
    {
        if(strcmp( " " , ch ) == 0)                                       //空行继续
            continue;

        const char *ch1 = ", \n\t.";                                      //要分割的字符(逗号、空格、换行、制表符、句号)
        p = strtok(ch,ch1);                                               //用strtok函数从一行字符串中分离出每个单词,分隔符设置为(空格、逗号、换行、制表符)
        while(p != NULL)
        {
            Hashinsert(p);
            p = strtok(NULL, ch1);                              //每次找到一个分隔符后,一个空(NULL)就被放到分隔符处,strtok函数用这种方法来连续查找该字符串,此处的NULL是一个指向后面还未分割的单词的指针,因此,首次调用时,第一个元素必须指向要分解的字符串,随后调用要把元素设成NULL。
        }
    }
    fclose(fp);
}

void Hashinsert(char *str){
    int hashcode = Hashfuntion(str);
    Hashnode *newnode;
    for (newnode = hashtable[hashcode]; newnode != NULL ; ++newnode) {
        if(strcmp(str, newnode->word) == 0){       //查找单词是否已经在hash表中了
            (newnode->count)++;
            return;
        }
    }
    //如果上面没返回,也就是说hash表中没有这个单词,添加新节点,加入这个单词
    newnode = new Hashnode;
    newnode->count = 1;

    newnode->word = (char *)malloc(strlen(str) + 1);
    strcpy(newnode->word,str);

    newnode->next = hashtable[hashcode];        //将新生成的节点插入到hashcode为下标的链表中去
    hashtable[hashcode] = newnode;
}

unsigned int Hashfuntion(const char *str)
{
    unsigned int index = 0;
    for (; *str != '\0' ; str++) {
        index = index * 31 + *str;
    }
    return index % HASHNUM;
}

void findquery(char *path){
    char ch[50] = {NULL};
    FILE *fp = fopen(path,"r");
    std::ofstream outfile1("E:\\answer.txt");

    while(fgets(ch,sizeof (ch),fp)){                    //把待查关键字读入
        int hashcode2 = Hashfuntion(ch);
        outfile1 << hashtable[hashcode2]->word << "出现了" << hashtable[hashcode2]->count << "次" << std::endl;
    }
    getlinecplusplus("E:\\database.txt",ch);
    fclose(fp);
}

void getlinecplusplus(char *path,char *str){
    std::ifstream readfile(path);                                        //用ifstream读入txt文件path并与readfile相连
    std::ofstream outfile("E:\\answer.txt",std::ofstream::app);         //用ofstream将答案输出到answer.txt
    int linecount = 0;
    std::string line;
    std::string word;
    while(std::getline(readfile, line)){
        lines.push_back(line);                                        //将一行放入vector<string>中
        std::istringstream iss(line);                                 //获取一行
        ++linecount;                                                  //行号加1
        while(iss >> word){  
            wordline[word].insert(linecount);                        //加入词的行号
        }
    }
    std::set<int>::const_iterator itset;
    std::vector<std::string>::const_iterator itvector;              //新建两个迭代器

    int i;
    for(itset = (wordline.find(str)->second).begin();itset != (wordline.find(str)->second).end(); itset++)
    {
        outfile << "出现在第 "<< *itset <<"行" << std::endl;
        i = 0;
        for (itvector = lines.begin(); itvector != lines.end(); itvector++) {       //前一句,单词所在的句子,下一句
            if (*itset == ++i)          //行号与vector循环次数匹配上了
            {
                if(itvector != lines.begin()){                                      //第一句不能打印前一句
                    outfile << *(itvector-1) << std::endl;
                }
                if(itvector != lines.end()-1){                                      //最后一句不能打印后一句
                    outfile << *(itvector+1) << std::endl;
                }
                outfile << *itvector << std::endl;                                  //单词本身句
            }
        }
    }
    outfile.close();
}

int main(){
    SetConsoleOutputCP(65001);              //避免控制台中文乱码
    readintohash("E:\\database.txt");      //自行更改路径
    findquery("E:\\query.txt");
    return 0;
}

有关哈希表之单词查找并输出其上下文的更多相关文章

  1. ruby - 检查 "command"的输出应该包含 NilClass 的意外崩溃 - 2

    为了将Cucumber用于命令行脚本,我按照提供的说明安装了arubagem。它在我的Gemfile中,我可以验证是否安装了正确的版本并且我已经包含了require'aruba/cucumber'在'features/env.rb'中为了确保它能正常工作,我写了以下场景:@announceScenario:Testingcucumber/arubaGivenablankslateThentheoutputfrom"ls-la"shouldcontain"drw"假设事情应该失败。它确实失败了,但失败的原因是错误的:@announceScenario:Testingcucumber/ar

  2. ruby - 通过 erb 模板输出 ruby​​ 数组 - 2

    我正在使用puppet为ruby​​程序提供一组常量。我需要提供一组主机名,我的程序将对其进行迭代。在我之前使用的bash脚本中,我只是将它作为一个puppet变量hosts=>"host1,host2"我将其提供给bash脚本作为HOSTS=显然这对ruby​​不太适用——我需要它的格式hosts=["host1","host2"]自从phosts和putsmy_array.inspect提供输出["host1","host2"]我希望使用其中之一。不幸的是,我终其一生都无法弄清楚如何让它发挥作用。我尝试了以下各项:我发现某处他们指出我需要在函数调用前放置“function_”……这

  3. ruby - 如何进行排列以有效地定制输出 - 2

    这是一道面试题,我没有答对,但还是很好奇怎么解。你有N个人的大家庭,分别是1,2,3,...,N岁。你想给你的大家庭拍张照片。所有的家庭成员都排成一排。“我是家里的friend,建议家庭成员安排如下:”1岁的家庭成员坐在这一排的最左边。每两个坐在一起的家庭成员的年龄相差不得超过2岁。输入:整数N,1≤N≤55。输出:摄影师可以拍摄的照片数量。示例->输入:4,输出:4符合条件的数组:[1,2,3,4][1,2,4,3][1,3,2,4][1,3,4,2]另一个例子:输入:5输出:6符合条件的数组:[1,2,3,4,5][1,2,3,5,4][1,2,4,3,5][1,2,4,5,3][

  4. ruby - 如果指定键的值在数组中相同,如何合并哈希 - 2

    我有一个这样的哈希数组:[{:foo=>2,:date=>Sat,01Sep2014},{:foo2=>2,:date=>Sat,02Sep2014},{:foo3=>3,:date=>Sat,01Sep2014},{:foo4=>4,:date=>Sat,03Sep2014},{:foo5=>5,:date=>Sat,02Sep2014}]如果:date相同,我想合并哈希值。我对上面数组的期望是:[{:foo=>2,:foo3=>3,:date=>Sat,01Sep2014},{:foo2=>2,:foo5=>5:date=>Sat,02Sep2014},{:foo4=>4,:dat

  5. ruby-on-rails - 在 ruby​​ 中使用 gsub 函数替换单词 - 2

    我正在尝试用ruby​​中的gsub函数替换字符串中的某些单词,但有时效果很好,在某些情况下会出现此错误?这种格式有什么问题吗NoMethodError(undefinedmethod`gsub!'fornil:NilClass):模型.rbclassTest"replacethisID1",WAY=>"replacethisID2andID3",DELTA=>"replacethisID4"}end另一个模型.rbclassCheck 最佳答案 啊,我找到了!gsub!是一个非常奇怪的方法。首先,它替换了字符串,所以它实际上修改了

  6. ruby - 当使用::指定模块时,为什么 Ruby 不在更高范围内查找类? - 2

    我刚刚被困在这个问题上一段时间了。以这个基地为例:moduleTopclassTestendmoduleFooendend稍后,我可以通过这样做在Foo中定义扩展Test的类:moduleTopmoduleFooclassSomeTest但是,如果我尝试通过使用::指定模块来最小化缩进:moduleTop::FooclassFailure这失败了:NameError:uninitializedconstantTop::Foo::Test这是一个错误,还是仅仅是Ruby解析变量名的方式的逻辑结果? 最佳答案 Isthisabug,or

  7. ruby - 如何在 Grape 中定义哈希数组? - 2

    我使用Ember作为我的前端和GrapeAPI来为我的API提供服务。前端发送类似:{"service"=>{"name"=>"Name","duration"=>"30","user"=>nil,"organization"=>"org","category"=>nil,"description"=>"description","disabled"=>true,"color"=>nil,"availabilities"=>[{"day"=>"Saturday","enabled"=>false,"timeSlots"=>[{"startAt"=>"09:00AM","endAt"=>

  8. ruby - 查找字符串中的内容类型(数字、日期、时间、字符串等) - 2

    我正在尝试解析一个CSV文件并使用SQL命令自动为其创建一个表。CSV中的第一行给出了列标题。但我需要推断每个列的类型。Ruby中是否有任何函数可以找到每个字段中内容的类型。例如,CSV行:"12012","Test","1233.22","12:21:22","10/10/2009"应该产生像这样的类型['integer','string','float','time','date']谢谢! 最佳答案 require'time'defto_something(str)if(num=Integer(str)rescueFloat(s

  9. ruby - 在哈希的键数组中追加元素 - 2

    查看我的Ruby代码:h=Hash.new([])h[0]=:word1h[1]=h[1]输出是:Hash={0=>:word1,1=>[:word2,:word3],2=>[:word2,:word3]}我希望有Hash={0=>:word1,1=>[:word2],2=>[:word3]}为什么要附加第二个哈希元素(数组)?如何将新数组元素附加到第三个哈希元素? 最佳答案 如果您提供单个值作为Hash.new的参数(例如Hash.new([]),完全相同的对象将用作每个缺失键的默认值。这就是您所拥有的,那是你不想要的。您可以改用

  10. ruby - 将 spawn() 的标准输出/标准错误重定向到 Ruby 中的字符串 - 2

    我想使用spawn(针对多个并发子进程)在Ruby中执行一个外部进程,并将标准输出或标准错误收集到一个字符串中,其方式类似于使用Python的子进程Popen.communicate()可以完成的操作。我尝试将:out/:err重定向到一个新的StringIO对象,但这会生成一个ArgumentError,并且临时重新定义$stdxxx会混淆子进程的输出。 最佳答案 如果你不喜欢popen,这是我的方法:r,w=IO.pipepid=Process.spawn(command,:out=>w,:err=>[:child,:out])

随机推荐