C++ string 学习笔记

2020/02/05 C++

单独把 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中。

Search

    Table of Contents