输出一行字符串,根据空白符来分隔单词。先看如何输出一行(带空白)
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是不行的。