• 字符串分割成单词


        输出一行字符串,根据空白符来分隔单词。先看如何输出一行(带空白)

     int main()
    {
        string s;
        //read and split  each line of input
        while(getline(cin,s))
        {
            vector<string> v=split(s);
            for(vector<string.;:size_type i=0;i!=v.size();i++)
                cout<<v[i]<<endl;
        }
    
    
    }

      如何写split函数呢? 首先常规的思维如下:

    vector<string> split(const string& s)
    {
        vector<string> ret;
        typedef string::size_type string_size;
        string_size i = 0;
    
        // invariant: we have processed characters `['original value of `i', `i)'
        while (i != s.size()) {
            // ignore leading blanks
            // invariant: characters in range `['original `i', current `i)' are all spaces
            while (i != s.size() && isspace(s[i]))
                ++i;
    
            // find end of next word
            string_size j = i;
            // invariant: none of the characters in range `['original `j', current `j)' is a space
            while (j != s.size() && !isspace(s[j]))//j!=s.size()很容易忽略
                ++j;
    
            // if we found some nonwhitespace characters
            if (i != j) {
                // copy from `s' starting at `i' and taking `j' `\-' `i' chars
                ret.push_back(s.substr(i, j - i));
                i = j;
            }
    
        }
        return ret;
    }

    isspace在cctype头文件中。这个程序有很多值得注意的地方。

      while (i != s.size() && isspace(s[i]))   ++i;

     &&有短路特性。先判断左边的是否为真,若为假就不会判断后面的了。首先必须先检查i!=s.size();只有当这个检测为真时,才可以使用i来查看s中的一个字符是否为空白符。

      若使用标准库算法,更接近人的思维。

    // `true' if the argument is whitespace, `false' otherwise
    bool space(char c)
    {
        return isspace(c);
    }
    
    // `false' if the argument is whitespace, `true' otherwise
    bool not_space(char c)
    {
        return !isspace(c);
    }
    
    vector<string> split(const string& str)
    {
        typedef string::const_iterator iter;
        vector<string> ret;
    
        iter i = str.begin();
        while (i != str.end()) {
    
            // ignore leading blanks
            i = find_if(i, str.end(), not_space);
    
            // find end of next word
            iter j = find_if(i, str.end(), space);
    
            // copy the characters in `[i,' `j)'
            if (i != str.end())
                ret.push_back(string(i, j));
            i = j;
        }
        return ret;
    }

    这个程序也有很多值得注意的地方。首先,

    ret.push_back(string(i, j)); 不能写成 ret.push_back(str.substr(i,j));
    因为c++不能将迭代器转换成整形。
    外层循环有了一个i!=str.end()的判断,里面为什么还有有i!=str.end()的判断?
    是因为字符串末尾可能有很多空白符。如“abc "; 但最后一次j赋值给i时。i指向第一个空白符,i!=str.end()为true,i继续找,最终指向了str.end(), 而j=find_if(str.end(),str.end(),space);

    还有特别要注意的是:
    函数形参中 const string& str; str.begin()
    if the conatiner is a const object ,返回的迭代器类型是const_iterator
    在定义迭代时typedef string::const_iterator iter;
    若形参不写const,

    string& str;

    typedef string::const_iterator iter;

    则find_if函数模板调用出错,错误信息:模板 参数“_InIt”不明确
    原因,find_if里面的迭代器是iterator类型,返回的也是iterator类型,而直接赋值给了const_iterator是不行的。


  • 相关阅读:
    MySQL源代码解读(二)
    MySQL源代码解读(一)
    C语言中如何对串口进行操作
    mysql 运行概图
    Yacc 与 Lex
    外键建索引
    提高SQL查询效率
    MySQL源代码分析:(1)Main函数
    Linux "could not open default font 'fixed'."
    转帖 浅析ARM汇编语言子例程设计方法
  • 原文地址:https://www.cnblogs.com/youxin/p/2502323.html
Copyright © 2020-2023  润新知