引言
字符串类型:
- C语言的char型字符串
- C++语言的string类型字符串
二者区别:
- string类型更节省空间,用多少申请多少,而char类型的数组必须申请最大值。
- C++中的map容器等不支持char型数组,但支持map<string,int> mp
1. C++标准程序库中的string类
#include<string>
2. 定义和初始化
string s; //生成一个空字符串s
string s(str); //生成str的复制品
string s(str, beg); //将字符串str内“始于位置beg”的部分当作s的初值
string s(str, beg, len); //将字符串str内“始于beg且长度顶多len”的部分作为s的初值
string s(cstr); //将C语言字符串作为s的初值
string s(cstr,len); //将C语言字符串cstr前len个字符作为字符串s的初值。
string s(num,c); //生成一个字符串,包含num个c字符
string s(cstr[beg],cstr[end]); //以cstr区间beg~end(不包含end)内的字符作为s的初值,左闭右开
s.~string(); //销毁所有字符,释放内存
3. 赋值
s.assign(str, beg,len); // 取值区间 [beg, beg+len)
s.assign(str, beg, string::npos); // 取值区间 从beg到结尾
s.assign(str); //
s.assign(str, len); // 若超出长度会?
s.assign(num, c'); // num个c字符
4. 交换
s2.swap(s1); // 交换两个字符串的内容
getchar(); //stdio.h中的库函数,用于从stdin流中读入1个字符,相当于getc(stdin),返回类型为int型,为用户输入的ASCII码或EOF
5. 尾部添加字符
s += str; //加个字符串
s += "aa bb cc"; //加个C字符串
s += ’a’; //加个字符a
s.append(str);
s.append(str,beg,len);
s.append(str,beg,string::npos) //从str的beg到str的尾部所有字符
s.append(“my name is jiayp”);
s.append(str,beg);
s.append(num,c); //num个c字符
s.push_back(‘a’); //增加单个字符且仅能增加单个字符
6. 在指定位置插入字符
(1)下面不支持插入单个字符,仅支持插入字符串:
s.insert(beg,”xxx”);
s.insert(beg,str); // str="xxx"
(2) 插入单个字符,用下面两个重载函数:
insert(size_type beg, size_type num, chart c); //size_type是无符号整数
insert(iterator pos, size_type num, chart c); //iterator是char*
/*调用方法举例*/
s.insert((string::size_type)0, 1, ’j’); //在s的位置0后插入1个j字符
7. 删除字符
s.erase(beg); //从索引beg开始往后全删除
s.erase(beg,len); //从索引beg开始往后删len个
s.clear(); //删除全部字符
8. 替换字符
s.replace(beg,len,str); //从索引beg开始的len个替换成后面的str
9. 串联字符串
s = s1 + s2;
10. 比较字符串
- 支持string与C-string的比较。
- 在使用>,>=,<,<=比较字符串时是根据“当前字符特性”将字符按字典顺序进行逐一比较。
- 字典排序靠前的字符小。
- 比较的顺序是从前向后比较,遇到不相等的字符就按这个位置上的两个字符的比较结果确定两个字符串的大小。
- 成员函数compare():支持多参数处理,支持用索引值和长度定位子串来进行比较。
- compare()返回一个整数来表示比较结果,返回值意义:0-相等 >0-大于 <0-小于。
==, !=, <, <=, >, >=
s.compare(str); //相等
s.compare(beg,len,str,beg2,len2);
11. 字符串大小
size(); //返回字符数量
length(); //返回字符数量
max_size(); //返回当前C++字符串最多能包含的字符数,和机器本身的限制或者字符串所在位置连续内存的大小有关系,不够用的话,会抛出length_error异常
empty(); //判断字符串是否为空
capacity(); //返回重新分配内存之前 string所能包含的最大字符数
reserve(); //为string重新分配内存,重新分配的大小由其参数决定,默认参数为0,这时候会对string进行非强制性缩减
12. 存取单一字符
- 使用下标操作符[]和函数at()对元素包含的字符进行访问。
- 操作符[]并不检查索引是否有效(有效索引0~str.length()),如果索引失效,会引起未定义的行为。
- at()会检查索引是否有效,如果使用 at()的时候索引无效,会抛出out_of_range异常。
cout<<s[i]<<endl;
cout<<s.at(i)<<endl;
string buf;
getline(cin, buf); // 输入一行字符赋值给stuff,从stream读取某值,相当于>>
getline(cin, buf,'q'); // 输入一行字符以“q”结束
cout<<buf<<endl;
13. string to C_string
C++字符串并不以’\0’结尾, 建议在程序中尽量使用C++字符串,不选用c_string
s = str.copy(); //把字符串的内容复制或写入既有的c_string或字符数组内
s = str.c_str(); //返回一个以‘\0’结尾的字符数组
s = str.data(); //以字符数组的形式返回字符串内容,但并不添加’\0’
14. 获取子串
s = str.substr(); //返回s的全部内容
s = str.substr(beg); //从索引beg往后的子串
s = str.substr(beg,len); //从索引beg开始len个字符
15. 查找(有点重要)
- 都返回符合搜索条件的字符区间内的第一个字符的索引,没找到目标就返回string::npos
- string::npos的类型是string::size_type, 如果要把一个索引与npos相比,这个索引值必须是string::size)type类型,
- 一般可以直接把函数和npos进行比较,如:if(s.find(“xxx”) == string::npos)
- 可以在一个字符串里找另一个字符串,如: str1.find(str2),如果没有找到,str1.find(str2) 返回string::npos
//都返回符合搜索条件的字符区间内的第一个字符的索引,没找到目标就返回string::npos
//第一个参数是被搜寻的对象
//第二个参数(可有可无)指出string内的搜寻起点索引
//第三个参数(可有可无)指出搜寻的字符个数
s.find(); //str1.find(str2)
s.rfind();
s.find_first_of();
s.find_last_of();
s.find_first_not_of(arg1, arg2, arg3);
s.find_last_not_of();
int pos = s.find_first_not_of(' '); //返回s中从头部开始遍历找到的第一个非空字符的索引
16. C++ 中几种类型相互转换
1.string 转 int 等
--------------------------------
(1) 利用 stringstream
long str2long(string& str)----------// string to long
{
stringstream ss;
long i;
ss << str;
ss >> i;
return i;
}
--------------------------------
(2) 利用 C++ 函数 stoi() 等
long str2long(string& str)//----------string to long
{
long l = stoi(str); //stol() ? stoi()
return l;
}
float str2float(string& str)//----------str to float
{
float f = stof(str);
return f;
}
2. int 等转换为 string
--------------------------------
(1) 利用 stringstream
string long2str(long l)//----------long to string
{
string str;
stringstream ss;
ss << l;
str = ss.str();
//ss >> str;
return str;
}
--------------------------------
(2) 利用 C++ 11 新特性 to_string() 函数
string long2str(long l)//----------long to string
{
string str = to_string(1);
return str;
}
3. string 转换为 C 字符串
--------------------------------
(1) 利用 stringstream
void* string2chars(string& str, char* ch)//----------string to C 字符串
{
stringstream ss;
ss << str;
ss >> ch;
} //char 数组长度不做考虑
--------------------------------
(2) 利用 string 类的成员函数 c_str()
!!!注意不能直接用 const char* 对 char* 类型进行初始化或赋值
void string2chars(string& str, char* ch)
{
//char* ch = str.c_str();//错误,因为无法将 用 const char* 对 char* 实例进行初始化
strcpy(ch, str.c_str());
}
4. C 字符串转换为 string
--------------------------------
(1) C++ 已对 string 进行了重载 可以在定义时直接初始化,或者赋值
此时 C 字符串分为两种,一种是 "abc" 这种 const char*, 另一种是 char 数组,即 char*。实际上区别就是 没有从 const char* 到 char* 的自动转换。
1)//对于 const char*
string chars2string(const char* ch)
{
string str(ch);
//string str = ch;
//string str;
//str = ch;
return str;
}
2)//对于 char*
string chars2string(char* ch)
{
string str(ch);
//string str = ch;
//string str;
//str = ch;
return str;
}
--------------------------------
(2) 也可使用 stringstream
//???
5. C 字符串转换为 int 等
--------------------------------
(1) 利用 stringstream
long chars2long(char* ch)
{
stringstream ss;
long l;
ss << ch;
ss >> l;
return l;
}
--------------------------------
(2) 利用 C 函数 atoi 等
long chars2long(char* ch)
{
int i = atoi(ch);
return i;
}
--------------------------------
(3) 利用 sscanf
long chars2long(char* ch)
{
int i;
sscanf("17","%D",&i); // 17
//sscanf("17","%X",&i); // 23
//sscanf("0X17","%X",&i); // 23
return i;
}
--------------------------------
(4) 利用 C 函数 strtol
原型:
long int strtol (const char* str, char** endptr, int base);
解释:
strtol() 函数用来将字符串转换为长整型数(long)。str 为要转换的字符串,endstr 为第一个不能转换的字符的指针,base 为字符串 str 所采用的进制。运行原理:strtol() 会将参数 str 字符串根据参数 base 来转换成长整型数(long)。参数 base 范围从2 至36,或0。参数base 代表 str 采用的进制方式,如base 值为10 则采用10 进制,若base 值为16 则采用16 进制等。strtol() 会扫描参数 str 字符串,跳过前面的空白字符(例如空格,tab缩进等,可以通过 isspace() 函数来检测),直到遇上数字或正负符号才开始做转换,再遇到非数字或字符串结束时('\0')结束转换,并将结果返回。
注意:当 base 的值为 0 时,默认采用 10 进制转换,但如果遇到 '0x' / '0X' 前置字符则会使用 16 进制转换,遇到 '0' 前置字符则会使用 8 进制转换。 若endptr 不为NULL,则会将遇到的不符合条件而终止的字符指针由 endptr 传回;若 endptr 为 NULL,则表示该参数无效,或不使用该参数。
返回值:返回转换后的长整型数;如果不能转换或者 str 为空字符串,那么返回 0(0L);如果转换得到的值超出 long int 所能表示的范围,函数将返回 LONG_MAX 或 LONG_MIN(在 limits.h 头文件中定义),并将 errno 的值设置为 ERANGE。
实际上:
ANSI C 规范定义了 stof()、atoi()、atol()、strtod()、strtol()、strtoul() 共6个可以将字符串转换为数字的函数。另外在 C99 / C++11 规范中又新增了5个函数,分别是 atoll()、strtof()、strtold()、strtoll()、strtoull()。
long chars2long(char* ch, int base)
{
char* end = nullptr;
long l = strtol(ch, &end, base);
return l;
}
6. int 等转换为 C 字符串
--------------------------------
(1) 利用 stringstream
void int2chars(int i, char* ch)
{
stringstream ss;
ss << i;
ss >> ch;
}
(2) 利用 sprintf
void int2chars(int i, char* ch)
{
sprintf(ch,"%d", i);
}
注:
1.stringstream 总体来说是不够智能的,例如
stringstream ss;
int i;
ss << "hello world";
ss >> i;
这样的代码是可以无异常运行的,如果想做出改变可以选择使用 Boost 库中的转换方法,不过一般情况下 Boost 太过复杂并不是一个很好的选择。
虽然 stringstream 在某些情况下不安全,但至少在内存管理方面是相对安全的,不像 atoi atol 或者 printf sprintf 等函数一样,不对内存进行任何安全检测
2.将 const 字符串 转换为 字符串
使用 sprintf()
int sprintf ( char * str, const char * format, ... );
sprintf 在打印字符串时,会自动在后一内存块上补 '\0',但是并不会对这块内存是否溢出进行检测。
此时可以使用 sprintf 的安全版本,sprintf_s
int sprintf_s(char *buffer, size_t sizeOfBuffer, const char *format [,argument]...);
通过指定缓冲区长度来避免sprintf()存在的溢出风险
17. 字符串的迭代器
string::iterator its = s.begin(); //*its 相当于 s[0]
string::iterator ite = s.end();
sort(s.begin(), s.end());
rbegin(); //逆向迭代器
rend(); //逆向迭代器
18. 还未用过的
get_allocator() //返回配置器
19. C++纯数字字符串变为整数
string = "12345678";
index=2;
string s = str.substr(index,3);//s = "345";
int x = atoi(s.c_str());//int x = 345;
参考:https://blog.csdn.net/fenxinzi557/article/details/51457829