首页 > 其他分享 >哈希表之单词查找并输出其上下文

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

时间:2022-12-27 18:33:31浏览次数:43  
标签:单词 NULL 哈希 char 表之 ch str newnode 上下文

哈希表之单词查找

  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;
}

标签:单词,NULL,哈希,char,表之,ch,str,newnode,上下文
From: https://www.cnblogs.com/hantin/p/17008739.html

相关文章

  • HashMap实现细节,hash对key为 null的处理,对重哈希的处理
     一、解HashMap源码解读1、HashMap的存储结构2、HashMap的初始化 3、元素Hash值获取及通过hash值找到talbe下标索引 4、元素添加方法addEntry 5、HashMap扩容 6、老tab......
  • 哈希表的处理冲突方法
                 ......
  • 哈希表
    3.5.3.1哈希表的概念及作用3.5.3.2哈希表的构造方法3.5.3.3哈希表的处理冲突方法3.5.3.4ARMLinux中哈希表使用实例            ......
  • C++进阶(哈希)
    vector容器补充(下面会用到)我们都知道vector容器不同于数组,能够进行动态扩容,其底层原理:所谓动态扩容,并不是在原空间之后接续新空间,因为无法保证原空间之后尚有可配置的空间......
  • 哈希表
    哈希表1. 两数之和给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。你可以假设......
  • 内存泄漏、块级格式化上下文、语义化标签的作用
    一、内存泄漏?定义:申请到的一块内存既不能被使用,也不能被回收,直到浏览器进程结束。哪些常见的内存泄漏?1.意外的全局变量一个函数体内的变量没有使用var或let关键字......
  • redis hset 哈希表操作添加json串为单引号且客户端窗口需要最大化,字符串不能断行
    redishset哈希表操作添加json串为单引号且客户端窗口需要最大化,字符串不能断行语法:1.HGETkeyfield获取存储在哈希表中指定字段的值。DEMO:单个查询hget"微服务名称:......
  • 皕杰报表之隐藏处理
    第一步,新建报表,然后新建参数参数type设置成中文描述为统计类型、数据类型为字符串。参数year设置成中文描述为年、数据类型为日期、时间日期格式为yyyy。参数month设置成中......
  • 皕杰报表之性能管理
    1报表缓存当某个客户端访问某个报表,引擎将其计算出来后,会将运算结果缓存下来,之后如果再有别的客户端用相同的参数访问同一个报表,引擎会将缓存下来的报表结果直接返回给该客......
  • 皕杰报表之语义层
    1语义层定义语义层——是处于数据源与报表之间的一个概念,是用户和数据库之间的一个代码翻译层,通俗的讲是将数据库中的比较凌乱、复杂的数据对象(例如:存储在table中的各个字......