单独把 C++ 的 std::string 拉出来记在一个本文中。本文另外还包含 std::istringstream 和 std::ostringstream 的一些常见用法。
string
判断一个字符是否是数字或者字母
int isalpha ( int c ); // 判断是否是字母(alphabetic)
int isdigit ( int c ); // 判断是否是数字(digit)
int isalnum ( int c ); // 判断是否是数字或字母(alphanumeric)
这些都是C语言中的函数。如果判断正确,则返回非零值(即true),否则返回0(即false)。注意这些都是针对一个输入字符的判断,多个的情况请用循环。
判断字符的大小写,以及转换字符到大小写
int islower(int c); // 判断是否小写
int isupper(int c); // 判断是否大写
int tolower(int c); // 转换为小写
int toupper(int c); // 转换为大写
这里面,后两者则返回转换后的字符。注意,如果输入字符格式已经正确,则返回值不变;如果输入并非字母,则会返回诡异结果,所以在使用之前,可以使用1)中介绍的isalpha()来判断是否是字母,然后再转换大小写。
insert()插入字符串
http://www.cplusplus.com/reference/string/string/insert/
string (1): string& insert (size_t pos, const string& str);
substring (2): string& insert (size_t pos, const string& str, size_t subpos, size_t sublen);
这里只列出了插入std::string的用法。另外还有插入C字符串char*的用法,参见上面链接。
erase()删除子串
http://www.cplusplus.com/reference/string/string/erase/
sequence (1): string& erase (size_t pos = 0, size_t len = npos);
character (2): iterator erase (iterator p);
range (3): iterator erase (iterator first, iterator last);
常用的是(1),即输入参数是起始位置和待删除的子串长度(默认是删除从pos开始之后的所有子串)。另外,第(3)中用法中,删除的是左闭右开区间[first, last),即最后一个并未删除。例如,last可以是str.end(),指向最后一个元素的后一个位置。
pop_back() 删除最后一个字符
就不举例了。如果只需要删除最后一个字符,pop_back()还是比erase()方便。
istringstream
istringstream的最大用途是分割字符串。
istringstream默认以white space分割字符串
其中, white space包括space, Space, tab, linefeed, carriage-return, formfeed, vertical-tab, and newline characters,包含了常见的空格符、TAB符和换行符等(https://msdn.microsoft.com/en-us/library/e9a023cx.aspx)。
例如:
std::string stringvalues = "125 320 512 750 333";
std::istringstream iss (stringvalues); // initialize istringstream with string
for (int n=0; n<5; n++){
int val;
iss >> val;
std::cout << val*2 << '\n';
}
Output:
250
640
1024
1500
666
注意
- istringstream分割字符串时,如果想以任意字符作为分隔符,参见下面第(3)个用法。一个具体的应用问题参见“Trees(树问题)”文档中的(297. Serialize and Deserialize Binary Tree)题。
- istringstream 和 ostringstream 都有str()函数,不过istringstream的str()输出的字符串就是初始的字符串,不会随着in输出string contents到其它变量后而减少,而ostringstream的str()则会随着读入数据增多而更新;
istringstream 将字符串分割成指定类型的数据
istringstream在读出数据时,如果已知字符串中存储的数据的分布形式,那么只要指定输出类型,便可读出相应类型数据而无需再进行其它转换。对于istringstream来说,这么做的一大优点是,数据之间即使无需white space分隔符也可以将其读出。这种特点使得istringstream非常适用于分割按照一定格式存储到字符串中的数据。
例如,已知一个字符串包含浮点数,浮点数相互之间被单个字符隔开(可以是任意单个字符),那么便能够用如下的简单方法得到数字:
istringstream in(" 1.2m5.1*365a");
float a;
char c;
while ( in >> a ){
// Do sth. on a
in >> c;
}
这种用法要比写个循环判断字符方便很多。
注意:
- 在未知字符串中的数据的分布规律时,最好不要使用这种方法,因为很容易造成读入数据的错误。具体参见后面介绍的 operator » argument 中的用法。
- 对于某一个数值型数据,如果采用该数据同一个类型但不同精度的变量(例如使用long long来读出int型数据),也能将数据读出,不过读出的数据会经过自动转换。当然,这种做法毫无意义,所以原则还是:在未知字符串中的数据的分布规律时,最好不要使用这种方法。
- LC385: Mini Parser 给出了一个很好的使用istringstream的例子。
使用 istringstream 来以任意一种分隔符来分割字符串
不过需要结合std::getline()来使用,其用法是:
std::getline(istringstream& iss, string& token, char delimiter)
注意这里的分隔符只能是一个字符,如果需要使用多个字符串进行分割,恐怕只能写一个循环了。
举例:
#include <iostream>
#include <sstream>
std::string input = "abc,def,ghi";
std::istringstream ss(input);
std::string token;
// Split the string by the delimiters
while(std::getline(ss, token, ',')) {
std::cout << token << '\n';
}
重要函数的使用
operator » (argument)
最常见用法,从stream中读出数据到变量中,其中变量可以是制定类型(之前用法(2))。注意该用法是有返回值的,返回istream指针。
注意
如果出现读出错误的情况(例如读出到了错误类型的变量中,或者stream中已经没有数据了),该返回值是null指针。更重要的是:该istringstream对象将来也无法再继续读出数据了。准确的说是,之后依然可以读,但是读出的数据会变成诡异的错误数值。这是因为,此时相当于给该istringstream对象设置了error flag。因此,该方法也可以用来判断是否正确读出数据了。
例如:
string s = "12b3c"
istringstream in(s);
int a;
while ( in >> a ){
cout << a << " ";
}
// Cannot read char 'b' to an int variable.
in.clear(); // call clear() first so it can be used again
char c;
in >> c; // now c = 'b'
get()
http://www.cplusplus.com/reference/istream/istream/get/
get()通常用来从stream中移除下一个字符并且不保存(如果要保存,直接用上面介绍的 operator » argument 即可)。
其用法是
(1) int get();
(2) istream& get (char& c);
第1个的返回值是该字符的ASCII value。如果istringstream的error flags被设置,则返回EOF value,通常是-1。第2个返回istream指针(和上面的operator »返回类型和用法类似),也就是说,它也可以像 (in » a) 这样来判断读入数据是否正确。
有关 EOF value
EOF is a macro which expands to an integer constant expression with type int and an implementation dependent negative value but is very commonly -1. http://www.cplusplus.com/reference/string/char_traits/eof/
peek()
http://www.cplusplus.com/reference/istream/istream/peek/
peek()用来查看stream中的下一个字符,但是不把它从中移除。用法是:
int peek()
返回值同get()第1个用法的返回值完全相同,即该字符的ASCII value。如果istringstream的error flags被设置,则返回EOF value,通常是-1.
判断istringstream是否为空
istringstream 并没有类似于 empty()的函数。不过,当istringstream为空时,get()和peek()都会返回EOF,通常是-1(不过一定是负数)。因此,该方法可以用来判断istringstream是否为空。
clear()
清除所有的error flags,使得该istringstream可以重新使用(当然还是从stream的当前位置继续使用)。结合上面的 » 和 get()使用,在它们出错时使用clear()。
ostringstream
ostringstream通常用来粘合字符串
这和istringstream正好是相反的。
举例:
ostringstream ost;
ost << "a " << "b" << " XX";
string str = ost.str(); // str is "a b XX"
注意
- ostringstream可以赋初值,例如 ostringstream ost(“123456789”),不过再使用如以上例子表示的 « 输入字符串后,其初始化的字符会被新字符所覆盖。例如,以上例子的ost.str()中的结果将是”a b XX789”
使用ostringstream 把其它类型数据转换成字符串
istringstream可以把数据读出为指定格式。与此相反,ostringstream把任意类型数据(主要是数字类型int,float等)自动转换为字符串读入。
例如:
ostringstream ost;
ost << "a = " << 1.456 << " b = " << 5;
最后结果全部为字符串存储到ost中。