标准库定义了三种类型字符串流:istringstream,ostringstream,stringstream,看名字就知道这几种类型和iostream中的几个非常类似,分别可以读、写以及读和写string类型,它们也确实是从iostream类型派生而来的。要使用它们需要包含sstream头文件。
除了从iostream继承来的操作
- sstream类型定义了一个有string形参的构造函数,即:
stringstream stream(s);创建了存储s副本的stringstream对象,s为string类型对象 - 定义了名为str的成员,用来读取或设置stringstream对象所操纵的string值:
stream.str();返回stream中存储的string类型对象stream.str(s);将string类型的s复制给stream,返回void
类型转换
- string转char*
string str=“world”;
const char *p = str.c_str();//同上,要加const或者等号右边用char*- char * 转string
可以直接赋值。
string s;
char *p = "hello";//直接赋值
s = p;- int转string
c++11标准增加了全局函数std::to_string:
string to_string (int val);
string to_string (long val);
string to_string (long long val);
string to_string (unsigned val);
string to_string (unsigned long val);
string to_string (unsigned long long val);
string to_string (float val);
string to_string (double val);
string to_string (long double val);采用sstream中定义的字符串流对象来实现
int aa = 30;
stringstream ss;
ss<<aa;
string s1 = ss.str();
cout<<s1<<endl; // 30
string s2;
ss>>s2;
cout<<s2<<endl; // 30- string转换成int
stringstream可以吞下任何类型,根据实际需要吐出不同的类型。
string s = "17";
stringstream ss;
ss<<s;
int i;
ss>>i;
cout<<i<<endl; // 17采用sstream头文件中定义的字符串流对象来实现转换
istringstream is("12"); //构造输入字符串流,流的内容初始化为“12”的字符串
int i;
is >> i; //从is流中读入一个int整数存入i中c++ 11新标准
将n进制的字符串转化为十进制 stoi(字符串,起始位置,几进制);
bool isnum(string s){
//题目只保证第二个非空,第一个未说
if(s.length()<1)
return false;
for(int i = 0;i<s.length();i++){
if(!isdigit(s[i]))//不是数字,返回false
return false;
}
//遍历完后,可以断定是数字,但需要判断是否越界,测试点5和6
if(stoi(s)<1||stoi(s)>1000)
return false;
return true;
}如果是转换为**long**请用:**stol(字符串,起始位置,几进制)**
find函数
c++中string类中的find函数用于寻找字符串中是否包含子串,如果包含,那么函数返回第一个找到的子串的位置,如果不包含,返回-1.
用法例子:
#include<iostream>
#include<string>
using namespace std;
int main()
{
string a="testcodecodecode";
string b="code";
string c="lee";
int a_b=a.find(b);
int a_c=a.find(c);
cout<<a_b<<endl;
cout<<a_c<<endl;
return 0;
}输出:
4
-1
分割字符串
find_first_not_of()函数:
size_type find_first_not_of( const basic_string &str, size_type index = 0 );
size_type find_first_not_of( const char *str, size_type index = 0 );
size_type find_first_not_of( const char *str, size_type index, size_type num );
size_type find_first_not_of( char ch, size_type index = 0 );- 在字符串中查找第一个与str中的字符都不匹配的字符,返回它的位置。搜索从index开始。如果没找到就返回string::nops
- 在字符串中查找第一个与str中的字符都不匹配的字符,返回它的位置。搜索从index开始,最多查找num个字符。如果没找到就返回string::nops
- 在字符串中查找第一个与ch不匹配的字符,返回它的位置。搜索从index开始。如果没找到就返回string::nops
C++11之前只能自己写,我目前发现的史上最优雅的一个实现是这样的:
void split(const string& s, const string& delimiters = " ", vector<string>& tokens)
{
string::size_type first_pos = s.find_first_not_of(delimiters, 0);
string::size_type last_pos = s.find_first_of(delimiters, first_pos);
while (string::npos != first_pos || string::npos != last_pos) {
tokens.push_back(s.substr(first_pos, last_pos - first_pos));//use emplace_back after C++11
first_pos = s.find_first_not_of(delimiters, last_pos);
last_pos = s.find_first_of(delimiters, first_pos);
}
}从C++11开始,标准库中提供了regex,regex用来做split就是小儿科了,比如:
std::string text = "Quick brown fox.";
std::regex ws_re("\\s+"); // delimiter is whitespace
std::vector<std::string> v(
//-1 : 表示对分隔符之间的子序列感兴趣
std::sregex_token_iterator(text.begin(), text.end(), ws_re, -1),
std::sregex_token_iterator());
for(auto&& s: v)
std::cout<<s<<"\n";或者
std::string text = "Quick brown fox.";
std::regex ws_re("\\s+"); // delimiter is whitespace
std::sregex_token_iterator spos(text.begin(),text.end(),ws_re,-1);
std::sregex_token_iterator end;
for(++spos;spos!=end;++spos){
std::cout<<spos>str()<<"\n";
}字符串替换
C++的string库提供了专门的函数方法来实现字符串的替换:string.replace()
但是这个函数将源字符串中某个字符串只替换了一次,string类并没有实现对于源字符串中的某个字符串全部替换。
replace函数包含于头文件#include<string>中。
string& replace (size_t pos, size_t len, const string& str);
string& replace (const_iterator i1, const_iterator i2, const string& str);
string& replace (size_t pos, size_t len, const string& str, size_t subpos, size_t sublen);
string& replace (size_t pos, size_t len, const char* s);
string& replace (const_iterator i1, const_iterator i2, const char* s);
string& replace (size_t pos, size_t len, const char* s, size_t n);
string& replace (const_iterator i1, const_iterator i2, const char* s, size_t n);
string& replace (size_t pos, size_t len, size_t n, char c);
string& replace (const_iterator i1, const_iterator i2, size_t n, char c);
template <class InputIterator> string& replace (const_iterator i1, const_iterator i2, InputIterator first, InputIterator last);
string& replace (const_iterator i1, const_iterator i2, initializer_list<char> il);其中的泛型算法replace把队列中与给定值相等的所有值替换为另一个值,整个队列都被扫描,即此算法的各个版本都在线性时间内执行----其复杂度为\(O(n)\)。即replace的执行要遍历由区间[frist,last)限定的整个队列,以把 old_value 替换成 new_value
前3种的代码操作如下,每份代码前将其函数原型和参数含义给出方便理解:
/* 用法一:
* string& replace (size_t pos, size_t len, const string& str);
* 源字符串中从位置 pos 开始长度为 len 的字符串 被字符串 str 代替
*
* 功能:只替换一次
*/
int main()
{
string str_line("I love compile program with visual studio.");
cout << str_line.replace(str_line.find('e'), 1, "#") << endl;
// 答案: I lov# compile program with visual studio.
return 0;
}/* 用法二:
* string& replace (const_iterator i1, const_iterator i2, const string& str);
* 用 str 替换 迭代器起始位置 和 结束位置 之间的字符
*
* 功能:替换一段字符串
*/
int main()
{
string str_line("I love compile program with visual studio.");
// 用 str 替换 从begin位置开始的6个字符
cout << str_line.replace(str_line.begin(), str_line.begin()+6, "**")<< endl;
// 答案:** compile program with visual studio.
return 0;
}/* 用法三:
* string& replace (size_t pos, size_t len, const string& str, size_t subpos, size_t sublen);
* 源串指定位置上的子串(pos开始len长度)被替换为 str 的指定子串(给定起始位置和长度)
*/
int main()
{
string str_line("I love compile program with visual studio.");
string substr = "12345";
cout << str_line.replace(7, 7, substr, substr.find("2"), 3) << endl;
// 答案:I love 234 program with visual studio.
return 0;
}需要将源字符串中的某个字符(或某段子串)全部替换,而string库中未提供相关的库函数,这就需要我们自己进行编写实现:
/* 编写函数:
* string& replace_all (string& src, const string& old_value, const string& new_value);
* 参数:源字符串src 被替换的子串old_value 替换的子串new_value
*
* 功能:将 源串src 中 子串old_value 全部被替换为 new_value
*/
string& replace_all(string& src, const string& old_value, const string& new_value) {
// 每次重新定位起始位置,防止上轮替换后的字符串形成新的old_value
for (string::size_type pos(0); pos != string::npos; pos += new_value.length()) {
if ((pos = src.find(old_value, pos)) != string::npos) {
src.replace(pos, old_value.length(), new_value);
}
else break;
}
return src;
}
int main()
{
string str("I love compile program with visual studio.");
cout << replace_all(str, "o", "*0*") << endl;
// 答案:I l*0*ve c*0*mpile pr*0*gram with visual studi*0*.
return 0;
}当然,我们也可以利用正则表达式,将正则表达式内容替换为指定内容,regex库用模板函数std::regex_replace提供「替换」操作。
现在,给定一个数据为"he...ll..o, worl..d!", 思考一下,如何去掉其中误敲的“.”?
有思路了吗?来看看正则的解法:
char data[] = "he...ll..o, worl..d!";
std::regex reg("\\.");
// output: hello, world!
std::cout << std::regex_replace(data, reg, "");