字符串分割成单词

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

 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是不行的。


原文地址:https://www.cnblogs.com/youxin/p/2502323.html