zoukankan      html  css  js  c++  java
  • string中的单词查找与左右字符剪切

      需求源于为博客文章添加tag的字符串处理: tag之间以“,”分隔,要根据这个分隔符分离出各个tag;另外处于习惯用户可能敲入多余的空格,所以需要对tag的左右空格进行剪切。STL的string类没有现成的方法只好自己写一个。第一版函数原型如下: 

    void find_all_words(const string& str, char decollator, vector<string> words);

    其中参数decollator表示分隔符,words用于存储分离出来的各个单词(tag)。

      考虑到vector没有排序的功能,调用者有可能期望把单词存储在list中,也可能根据需求的不同选择map或者其他类型的容器。所以第三个参数应该更灵活才行,可以考虑泛型但功能依然受限因为只能选择STL标准容器。

      需求是多种多样的,可能用户想存放成静态数组也可能想直接打印,那么这多种多样的需求究竟能否满足呢?答案是肯定的,别忘了在C++ 0x中有两样强大的武器function和lambda表达式,所以我们第二版的函数原型如下: 

    void find_all_words(const string& str, char decollator, function<void(string&)> push);

     

      它的调用看起来是下面这个样子的:

    list<string> words;
    find_all_words(str,
    ',', [&words](string& s){ words.push_back(); });

      另外我们还需要对分离出来的单词做剪切操作,正常的处理逻辑是:“分离单词->剪切处理->存储单词”,当然我们可以拿到单词列表之后再挨个做剪切处理,但是这个逻辑就反了不太符合直觉而且会带来一定的效率开销(至少要再遍历一次列表),所以我们再次拿起c++ 0x的强大武器增加一个function类型的参数用于单词的预处理。函数的的调用就变成了下面的样子:

    list<string> words;
    auto push_word
    = [&words](string& s){ words.push_back(); };
    auto trim_word
    = [](string& s){ trim(word, ''); };
    find_all_words(str,
    ',', push_word, trim_word);

      函数原型已经确定剩下的算法问题就是小菜一碟了。函数的完整实现如下:

    1 void find_all_words(const string& str, char decollator, function<void(string&)> push, function<void(string&)> pre = NULL)
    2 {
    3 string::size_type start_pos =0;
    4 do
    5 {
    6 string::size_type dec_pos = str.find_first_of(decollator, start_pos);
    7 string word = str.substr(start_pos, dec_pos - start_pos);
    8 if (pre != NULL) pre(word);
    9 if (word.length() >0) push(word);
    10 start_pos = dec_pos !=string::npos ? dec_pos +1 : dec_pos;
    11
    12 } while (start_pos < str.length());
    13 }

     

      剪切string左右字符的两个函数都比较简单,实现如下:

    1 void trim_left(string& s, char c)
    2 {
    3 if(s.length() ==0) return;
    4 string::size_type pos = s.find_first_not_of(c);
    5 s.erase(0, pos);
    6 }
    7
    8 void trim_right(string& s, char c)
    9 {
    10 if (s.empty()) return;
    11 string::size_type pos = s.find_last_not_of(c);
    12 pos ==string::npos ? s.clear() : s.erase(pos +1, s.length() - pos -1);
    13 }
    14
    15 void trim(string& s, char c)
    16 {
    17 trim_right(s, c);
    18 trim_left(s, c);
    19 }
    20  

     

      以前很少写字符串处理的程序,就是偶尔要写也习惯了用标准C函数,好处是你完全清楚每一步的操作是怎样完成的,不像string是一个神奇的黑盒子。当然更主要的原因懒得去学STL string中的一大堆方法(更郁闷的是一个方法可以有十几种重载),现在初步尝试了一下确实还是挺方便的。看来做程序员还是要抱着开放的心态多尝试新东西才好。

     

     

    作者:小时了了
    原创文章,欢迎转载,但请以链接形式注明本文地址.
  • 相关阅读:
    详解threading模块:Condition类的使用
    concurrent.futures 模块使用说明
    细读Spring源码(四)什么是IOC?
    OAuth 2.0系列(六) OAuth令牌
    OAuth 2.0系列(七) OAuth 2.0可能存在的安全漏洞及预防方法
    细读Spring源码(一)refresh()方法概览
    HashMap源码解读() put方法的实现过程
    跟着字节码追踪JAVA中的基本运算
    细读Spring源码(六)Spring源码设计架构
    细读Spring源码(五)AOP从实战到源码
  • 原文地址:https://www.cnblogs.com/xrunning/p/1941986.html
Copyright © 2011-2022 走看看