zoukankan      html  css  js  c++  java
  • 第 2 章 第 6 题 通讯录模糊检索问题 标识法实现

    问题分析

      输入:名字的数字标识

      输出:通讯录中所有和该标识匹配的记录

      约束:错误匹配的概率不能太高

    解答思路

      1. 给通讯录中的记录附加上标识字段( 数字 )

      2. 将通讯录中的记录按照标识字段进行排序

      3. 用户输入要查找的人的名字的标识字段( 这里的标识字段类型要经过整理才能转换为 1 中的标识字段类型 详见下面代码的相关部分注释 )

      4. 顺序输出所有和 3 中标识字段匹配的记录

    代码实现

      1 #include <iostream>
      2 #include <fstream>
      3 #include <string>
      4 #include <map>
      5 
      6 using namespace std;
      7 
      8 // 初始化通讯录函数
      9 // --- 为每个记录附加一个标识符字段
     10 void init( multimap<string, string> &m, fstream &io );
     11 
     12 // 标识符获取函数
     13 // --- 将名字字符串转化为对应的标识符
     14 string getST( const string & name );
     15 
     16 // 查询记录函数
     17 // --- 根据用户给定的标识符,检索通讯录并输出结果。
     18 void search( multimap<string, string> &m, string &st );
     19 
     20 int main(void)
     21 {
     22     // 打开通讯录
     23     string filename;
     24     cout << "输入要创建的数据文件名: " << endl;
     25     cin >> filename;
     26 
     27     fstream io;
     28     io.open(filename.c_str());
     29     if (!io) {
     30         cout << "打开文件失败!" << endl;
     31         return 1;
     32     }
     33 
     34     // 初始化通讯录
     35     multimap<string, string> m;
     36     init(m, io);
     37 
     38     // 获取用户输入标识符
     39     string st;
     40     cout << "请输入要查找人名的数字标识符: ";
     41     cin >> st;
     42 
     43     // 检索通讯录并输出结果
     44     search(m, st);
     45 
     46     // 关闭文件流
     47     io.close();
     48 
     49     return 0;
     50 }
     51 
     52 void init(multimap<string, string> &m, fstream &io) {
     53     string name;
     54     string st;
     55 
     56     // 遍历通讯录,并将各组信息及对应标识符存入 multimap 表中。
     57     while (io >> name) {
     58         st = getST(name);
     59         m.insert(make_pair(st, name));
     60     }
     61 
     62     return;
     63 }
     64 
     65 string getST(const string & name) {
     66     string st = "000000000";
     67 
     68     for (int i=0; i<name.length(); i++) {
     69         if (name[i] == 'a' || name[i] == 'b' || name[i] == 'c') 
     70             st[0]++;
     71         if (name[i] == 'd' || name[i] == 'e' || name[i] == 'f') 
     72             st[1]++;
     73         if (name[i] == 'g' || name[i] == 'h' || name[i] == 'i') 
     74             st[2]++;
     75         if (name[i] == 'j' || name[i] == 'k' || name[i] == 'l') 
     76             st[3]++;
     77         if (name[i] == 'm' || name[i] == 'n' || name[i] == 'o')
     78             st[4]++;
     79         if (name[i] == 'p' || name[i] == 'q' || name[i] == 'r')
     80             st[5]++;
     81         if (name[i] == 's' || name[i] == 't' || name[i] == 'u')
     82             st[6]++;
     83         if (name[i] == 'v' || name[i] == 'w' || name[i] == 'x')
     84             st[7]++;
     85         if (name[i] == 'y' || name[i] == 'z') 
     86             st[8]++;
     87     }
     88 
     89     return st;
     90 }
     91         
     92 void search( multimap<string, string> &m, string &st )
     93 {
     94     // 将用户输入的标识符格式转换成内存中存放的标识符格式
     95     string st1 = "000000000";
     96     for (int i=0; i<st.length(); i++) {
     97         int t = (int)st[i] - (int)'0';
     98         st1[t]++;
     99     }
    100 
    101     // 检索通讯录,并获取结果范围。
    102     multimap<string, string> :: iterator up, low;
    103     low = m.lower_bound(st1);
    104     up = m.upper_bound(st1);
    105 
    106     // 切记要加入以下程序段,否则可能会因为无法读取下面的 low->first 而发生错误。
    107     if (low == up && low == m.end()) {
    108         cout << "无任何匹配记录" << endl;
    109         return;
    110     }
    111 
    112     // 打印检索到的记录
    113     cout << endl << "找到如下人名: " << endl;
    114     while (low->first != up->first) {
    115         cout << low->second << endl;
    116         low++;
    117     }
    118 
    119     cout << endl << endl;
    120 
    121     return;
    122 }

    运行测试

      1. 建立带有如下记录的通讯录( 普通文本格式 )

      

      2. 按照以下规则:

      abc  0  def  1  ghi  2  jkl  3  mno  4

      pqr  5  stu  6  vwx  7  yz  8

      建立并输入要查询的人名的标识符,如要查 fangmeng ,则可输入 10424142 并获取查询结果:  

      

    小结

      1. 通过修改标识符的生成格式比对规则,可以形成不同的模糊匹配规则。使用何种模糊匹配规则应结合具体情况决定。

      2. 标识法的灵活性体现在可以根据不同的需要建立不同意义的标识

  • 相关阅读:
    关于SimpleDateFormat安全的时间格式化线程安全问题
    JAVA多线程和并发基础面试问答
    探秘Java中的String、StringBuilder以及StringBuffer
    Java开发岗位面试题归类
    Java并发编程:阻塞队列
    Shell基本概述
    Ansible--06 ansible roles
    Ansible --05 ansible jinja2
    Ansible--04 ansible 流程控制
    Ansible--03 ansible 变量
  • 原文地址:https://www.cnblogs.com/scut-fm/p/3639499.html
Copyright © 2011-2022 走看看