string是STL的字符串类型,通常用来表示字符串。而在使用string之前,字符串通常是用char*表示的。string与char*都可以用来表示字符串,那么二者有什么区别呢。
string和char*的比较string是一个类, char*是一个指向字符的指针。
string封装了char*,管理这个字符串,是一个char*型的容器。
string不用考虑内存释放和越界。
string管理char*所分配的内存。每一次string的复制,取值都由string类负责维护,不用担心复制越界和取值越界等。
string提供了一系列的字符串操作函数(这个等下会详讲)
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
//1 string 的构造
void func1()
{
//string(); //默认构造函数,构造一个空的字符串string s1
string s1("123");
string s2 = "adc";//带参数的构造函数string(const char *s);用字符串s初始化
cout << s1 << ", " << s2 << endl;
string s3 = s1;//拷贝构造函数:string(const string &str);构造一个与str一样的string
string s4;
s4 = s2;//赋值, string &operator=(const string &s); 把字符串s赋给当前的字符串
cout << s3 << ", " << s4 << endl; /*ps:
string &assign(const char *s) 、
string &assign(const string &s) 把字符串s赋给当前字符串
string &assign(int n,char c); 用n个字符c赋给当前字符串
string &assign(const string &s,int start, int n); 把字符串s中从start开始的n个字符赋给当前字符串
string &assign(const char *s, int n); 把字符串s的前n个字符赋给当前的字符串
*/
string s5(10, 'a');//用多个字符初始化(构造)string(int n,char c);// 用n个字符c初始化
cout << s5 << endl;
}
//2、string 的遍历存取
void func2()
{
string s1 = "hello world";
//1、通过数组下标进行遍历
for (unsigned int i = 0; i < s1.length(); i++)//int length() const;返回当前字符串的长度。长度不包括字符串结尾的'\0'。
cout << s1[i];
cout << endl; // ps: bool empty() const; //当前字符串是否为空
//2、通过at()函数进行遍历
for (unsigned int i = 0; i < s1.length(); i++)
cout << s1.at(i);
cout << endl;
//3、string也有迭代器,通过迭代器遍历,拥有迭代器的容器都有两个函数
//----begin():返回指向当前容器的第一个元素的迭代器,
//----end():返回指向当前容器最后一个元素的下一个元素的迭代器(类似字符串结尾\0的位置)
string::iterator it = s1.begin();
while (it != s1.end())
{
cout << *it;
it++;
}
cout << endl;
//4、operator[]和at()均返回当前字符串中第n个字符,但 []和at函数 有区别
// [] 如果访问越界,[]在刚好越界时会返回(char)0,再继续越界时,编译器直接出错终止程序运行,不会抛出异常。
// at 如果访问越界,会抛出一个异常
try
{
for (unsigned int i = 0; i < s1.length()+1; i++)//让数组越界
cout << s1.at(i);
cout << endl;
}
catch(exception &e)
{
printf("抓到一个异常:%s\n", e.what());
}
}
//3、string 和 char* 的转换
//const char *c_str() const; //返回一个以'\0'结尾的字符串的首地址
void func3()
{
string str = "123456";
printf("str = %s\n", str.c_str());
}
//4、字符串的连接、拷贝、比较
void func4()
{
string s1 = "hello ";
string s2 = "world";
s1 = s1 + s2;/*连接 string &operator+=(const string &s)、
string &operator+=(const char *s);、
string &append(const char *s)、
string &append(const string &s);把字符串s连接到当前字符串结尾
string &append(int n, char c); //在当前字符串结尾添加n个字符c
string &append(const string &s,int pos, int n);//把字符串s中从pos开始的n个字符连接到当前字符串结尾
string &append(const char *s,int n); //把字符串s的前n个字符连接到当前字符串结尾
*/
cout << s1 << endl;
s1 = "111" + s1 + "222";
cout << s1 << endl;
s1.append("asdaf");//把字符串s连接到当前字符串结尾
cout << s1 << endl;
/*拷贝: int copy(char *s, int n, int pos=0) const;
把当前串中以pos开始的n个字符拷贝到以s为起始位置的字符数组中,
返回实际拷贝的数目。
注意要保证s所指向的空间足够大以容纳当前字符串,不然会越界。*/
char str[100] = {0};
s1.copy(str, 6, 1);
cout << str << endl;
//比较
if (s1 == s2)
cout << "s1 == s2" << endl;
else
cout << "s1 != s2" << endl;
/*ps
int compare(const string &s) const; //与字符串s比较
int compare(const char *s) const; //与字符串s比较
compare函数在>时返回 1,<时返回 -1,==时返回 0。
比较区分大小写,比较时参考字典顺序,排越前面的越小。大写的A比小写的a小。
*/
}
//5、查找和替换
void func5()
{
string s1 = "111 hello 222 hello 333 hello 444 hello";
/*
查找:
int find(const char *s, int pos=0) const;
或
int find(const string &s, int pos=0) const;
从pos下标位置开始查找字符串s在当前字符串中的位置
如果存在则返回第一个子串的下标,不存在则返回-1
int rfind(const char *s, int pos=npos) const;
int rfind(const string &s, int pos=npos) const;
//rfind是反向查找的意思,如果查找不到, 返回-1
*/
int index = s1.find("hello", 0);
if (index == -1)
cout << "不存在该字符串" << endl;
else
cout << "存在" << endl;
/*替换:先删除,再插入
string &replace(int pos, int n, const char *s);
或
string &replace(int pos, int n, const string &s);
//删除从pos开始的n个字符,然后在pos处插入串s
void swap(string &s2); //交换当前字符串与s2的值
*/
s1.replace(4, 1, "adc");
cout << s1 << endl;
/*
string s2 = "fizz";
s1.swap(s2);
cout << s1 << endl;
*/
//将s1 中的hello 替换成大写的 HELLO
index = s1.find("hello", 0);
while (index != -1)
{
s1.replace(index, 5, "HELLO");//在原先hello的位置删除5个字节长度(即hello),再插入HELLO
index = s1.find("hello", index+5);//继续往后找下一个hello
}
cout << s1 << endl;
}
//6、删除和插入
void func6()
{
string s1 = "111 hello 222 hello 333 hello 444 hello 555 hello";
//1、通过迭代器
//删除单个元素
s1.erase(s1.begin());
cout << s1 << endl;
//删除多个元素:左闭右开 [s1.begin(), s1.begin()+3)
s1.erase(s1.begin(), s1.begin()+3);
cout << s1 << endl;
//string &erase(int pos=0, int n=npos);
//删除pos开始的n个字符,返回修改后的字符串
string s2 = s1.erase(1, 2);
cout << s1 << endl;
cout << s2 << endl;
//插入
//第一个参数是插入位置的下标,第二个参数是要插入的元素
s1.insert(0, "111");
s1.insert(5, "adc");
s1.insert(s1.length(),"AAA");
cout << s1 << endl;
}
//7、可以用算法函数操作字符串
void func7()
{
string s1 = "111 hello 222 hello 333 hello 444 hello 555 hello";
//转换算法
//要转换的起始位置,截止位置,存放转换结果的地址,转大写
transform(s1.begin(), s1.end(), s1.begin(), toupper);//转成大写
cout << s1 << endl;
transform(s1.begin(), s1.end(), s1.begin(), tolower);//转成小写
cout << s1 << endl;
//逆序
reverse(s1.begin(), s1.end());
cout << s1 << endl;
}
//应用例题: 逆序长句,不逆序单词
void func8()
{
string s = "You are from shanghai";
reverse(s.begin(), s.end());//先整体逆序
int begin = 0;
int index = s.find(" ");//index为空格的下标位置,find不传第二个参数,默认是0(find第二个参数有默认值0)
while (index != -1)//找到空格的情况下
{
reverse(s.begin()+begin, s.begin()+index);
begin = index+1;//空格只占一个字节,从上个空格的后面开始继续找
index = s.find(" ", index+1);
}
//最后一个单词不以空格结尾,最后一个单词在上面的循环中没有逆序
reverse(s.begin()+begin, s.end());//逆序最后一个单词
cout << s << endl;
}
int main()
{
/*
func1();
func2();
func3();
func4();
func5();
func6();
func7();
*/
func8();
/*ps:返回由pos开始的n个字符组成的子字符串
string substr(int pos=0, int n=npos) const;
*/
return 0;
}