C++:string的介绍

本文详细介绍了C++STL中的string类,包括其各种构造方法、输入输出操作、访问及遍历、容量和修改、查找功能,帮助读者理解并熟练运用这一重要数据结构。
摘要由CSDN通过智能技术生成

C语言中,字符串是以'\0'结尾的一些字符的集合,为了操作方便,C标准库中提供了一些str系列的库函数,但是这些库函数与字符串是分离开的,不太符合面向对象的思想,而且底层空间需要用户自己管理,稍不留神可能还会越界访问。

所以在C++的STL库中提供了更加方便的string类。


string

string的常见构造

默认构造函数:string()

  • 创建一个空字符串对象。
  • 示例:
string str;

拷贝构造函数:string(const string& str)

  • 创建一个字符串对象,内容为另一个字符串对象str的拷贝。
  • 示例:
 string str1("hello");
 string str2(str1); // "hello"

重载构造函数:string(const string& str, size_t pos, size_t len = npos)

  • 创建一个字符串对象,内容为字符串对象str的pos位置开始的len个字符。
  • 示例:
  •  string str1("hello"); 
     string str2(str1, 1, 3); // "ell:
  • 注意:当不传入第三个参数时,其默认为npos,这个值是size_t的最大储存值,可以理解为是无穷大,也就是说,当不传入第三个参数,其会从pos位置开始拷贝到结束。

重载构造函数:string(const char* s)

  • 创建一个字符串对象,内容为字符串s
  • 示例:
  • string str("hello");
    
  • 由于单参数构造函数支持类型转换,也可以写为:
    string str = "hello";

重载构造函数:string(const char* s, size_t n)

  • 创建一个字符串对象,内容为字符串s的前n个字符。
  • 示例:
string str("hello", 3); //"hel"

重载构造函数:string(size_t n, char c)

  • 创建一个由n个字符c组成的字符串对象。
  • 示例:
string str(5, 'a'); // "aaaaa"

string的输入输出
operator<<

string<<进行了重载,我们可以直接对string对象使用<<,此时会输出这个string对象的字符串值。

示例:

string s1 = "hello world";
string s2 = " csdn";

cout << s1 << endl; //"hello world"
cout << s1 << s2 << endl; //"hello world csdn"
c_str

string还提供了一个函数,用于读取string对象中的字符串。

string s = "hello world";
cout << s.c_str() << endl; // "hello world"

c_str的返回值是一个字符串,而<<对于字符串的输出机制是遇到'\0'中止输出。而string类重载的<<输出机制则是完整输出整个字符串,如果遇到'\0',会把'\0'一起输出。 

 看一个案例:

string s = "hello world \0 csdn";
cout << s.c_str() << endl; // "hello world "
cout << s << endl; // "hello world 0 csdn"
operator>>

同样的,string也对>>进行了重载,我们可以使用>>输入字符串。

string s1;
string s2;

cin >> s1 >> s2; // 输入"hello world"
cout << s1 << endl; // "hello"
cout << s2 << endl; // "world"

但是如果我们输入的字符串中包含空格,那么>>就不是很好用。

由于输入字符串时,遇到空格会中止读取,所以包含空格的字符串不能用这个方式输入,此时就要用getline了. 

getline

getline可以获取一整行的字符串,包括空格,只有遇到换行符的时候才会中止。
不过要注意getline不是string类的成员函数,但是是string头文件的普通函数。
所以使用时不需要使用对象.getline()这样的格式,而是直接使用。

其第一个参数是istream的对象,比如cin
第二个参数是输入到的string对象。
第三个参数决定遇到什么字符的时候停止读取,默认值为'\n',即换行时停止读取。

示例:

string s;

getline(cin, s); // "hello world csdn"
cout << s << endl; // "hello world csdn"

string访问及遍历
operator[ ] & at

operator[ ] 和 at都是通过下标访问的成员函数,两者作用几乎一致。

示例:

string s = "hello world";

cout << s[2] << endl; // 'l'
cout << s[8] << endl; // 'r'

 示例:

string s = "hello world";

cout << s.at(2) << endl; // 'l'
cout << s.at(8) << endl; // 'r'

两者的参数完全一致,即pos下标,传入这个参数后,输出下标位置的字符。此外,他们各自都提供了const版本的重构,用于const对象。
两者唯一的区别就是越界的情况:
operator[ ]越界时,会通过assert报错,直接中止程序。
at越界时,会抛出异常。 

font & back

font 和 back用于返回字符串的首尾字符。

要注意,其返回值为引用返回char&,所以对其修改时,是会影响到原先的字符串的。


如果我们想遍历一个字符串,可以通过operator[ ] 或者 at,利用for循环来遍历,但是STL库还提供了迭代器,用于遍历对象。

迭代器
begin & end

在C++的string类中,beginend是两个成员函数,用于返回字符串的起始和结束迭代器。

 begin函数返回一个迭代器,该迭代器指向字符串的第一个字符。可以使用解引用运算符*获取迭代器指向的字符。例如,*str.begin()将返回字符串中的第一个字符。

 end函数返回一个迭代器,该迭代器指向字符串结尾的下一个位置。因此end()函数返回的迭代器不指向字符串中的任何字符。可以将end函数返回的迭代器与其他迭代器进行比较,以确定迭代器是否已达到字符串的末尾。

演示如何使用beginend函数遍历字符串中的字符并输出它们:

string str = "Hello World";
  
// 使用begin()和end()函数遍历字符串中的字符
string::iterrtor it = str.begin()
while(it != str.end())
{
	cout << *it;
	++it;
}

平常可以直接用auto来代替这个类型。

所以以上代码可以写为:

string str = "Hello World";
  
// 使用begin()和end()函数遍历字符串中的字符
auto it = str.begin()
while(it != str.end())
{
	cout << *it;
	++it;
}

rbegin & rend

迭代器不仅支持正向遍历,还支持反向遍历,此时就需要反向迭代器rbegin,rend了。其中r代表reverse,反转的意思。

 rbegin是一个反向迭代器,用于指向容器的最后一个元素,并向前迭代。rendrbegin的逆操作。rbegin返回容器的最后一个元素的迭代器,而rend返回容器的第一个元素之前的位置的迭代器,这是一个越界的位置,同样不允许修改。

string s1 = "54321";

string:reverse_iterator rit = s.begin();

while (rit != str.rend()) {
	cout << *rit << " ";
	++rit;
}
范围for

范围for循环也适用于string,其本质是基于迭代器的循环。

string s = "hello world";

for(auto ch : s)
{
	cout << ch;
}

string的容量操作
size & length&capacity

size返回当前字符串的长度。

length返回当前字符串的长度。

capacity函数用于返回字符串的当前容量(当前可以存储的最大字符数)。

两者的作用完全一致,没有区别,那么为什么STL要设计两种方式来返回string对象的长度呢?

这是因为早期的string还不属于STL,使用length来表达长度,当string进入STL后,为了与其他的数据结构保持一致,都使用size来表示长度,于是又增加了一个size。

clear&empty

在string类中,clear函数用于清空字符串内容,并将字符串的长度设置为0。

empty函数用于检查一个字符串是否为空,即字符串中是否没有任何字符。该函数返回一个bool类型的值。

reserve

 reserve是一个用来预留字符串容量的方法。

reserve方法的目的是为了避免频繁的内存分配和释放操作,提高程序的效率。当我们使用string对象时,由于字符串的长度是可变的,所以在进行增删改等操作时,可能会导致内存重新分配,这会带来一定的时间开销。

为了避免这种情况,我们可以使用reserve方法来预先分配足够的内存空间。                     

resize

resize函数用于改变字符串的大小。它可以增加或减少字符串的长度。

resize函数有两个参数,第一个参数是新的字符串长度,第二个参数是填充字符(可选)。

如果新的长度小于当前长度,则字符串会被截断。如果新的长度大于当前长度,则字符串会自动增加大小,并用指定的填充字符填充空白部分,如果没有选定字符,则默认用\0填充。

 要注意的是,就算使用resizesize缩小,capacity容量大小不会减小,而是保持原本的大小。


string的修改操作
push_back

push_back函数用于将字符添加到字符串的末尾。它接受一个字符作为参数,并将其追加到字符串的末尾。

注意:push_back函数只接受一个字符作为参数,如果传递一个字符串或其他类型的参数,将会引发编译错误。

append

string类中的append方法用于将一个字符串追加到另一个字符串的末尾。它有多个重载版本,可以接受不同类型的参数作为输入。

基本使用:

string str1 = "Hello";
string str2 = " World!";
    
// 使用append方法将str2追加到str1的末尾
str1.append(str2);
    
cout << str1 << endl;  // 输出 "Hello World!"

append方法还可以接受其他类型的参数作为输入,例如const char*charstd::stringstd::initializer_list<char>等。 

 

operator+=

operator+=是用于将一个字符串追加到另一个字符串的末尾的运算符重载。

根据其三个重载可以看出来,operator+=可以追加string对象,字符串,字符三种类型,功能全面,语法简单,比appendpush_back好用的多。

insert

insert函数可以用于在字符串中插入字符、子串或其他类型的数据。

通过函数重载可以看出,我们可以插入字符,字符串,string对象等。

插入字符串:

string str = "Hello, world!";

// 在指定位置插入字符串
str.insert(5, "!!!"); // 在位置5插入"!!!"
cout << str << endl;

输出结果为:Hello!!!, world!

 插入字符:

string str = "Hello, world!";

// 在指定位置插入字符串
str.insert(5, 3, '!'); // 在位置5插入3个'!'
cout << str << endl;

输出结果为:Hello!!!, world!

 注意:插入字符时,第二个参数是插入字符的个数,哪怕只插入一个字符,这个值也不能缺省

erase

erase函数可以用来删除字符串中的字符或子字符串。 

首先,我们来看一个简单的示例,删除字符串中的一个字符:

string str = "Hello World";
str.erase(4); // 删除第5个字符,即空格
cout << str << endl; // 输出 "HelloWorld"

删除字符串中的一个子字符串:

string str = "Hello World";
str.erase(6, 5); // 从第7个字符开始,删除5个字符,即"World"
cout << str << endl; // 输出 "Hello"

除了上述两种用法外,erase函数还可以接受迭代器作为参数,用来删除指定范围内的字符或子字符串。

string str = "Hello World";
string::iterator start = str.begin() + 6; // 第7个字符的迭代器
string::iterator end = str.begin() + 11; // 第12个字符的迭代器
str.erase(start, end); // 删除从第7个字符到第12个字符的子字符串,即"World"
cout << str << endl; // 输出 "Hello "

replace

replace函数用于在字符串中替换指定的子字符串。

string str = "Hello, World!";
    
cout << "原始字符串: " << str << endl;
    
    // 使用replace函数替换字符串
str.replace(str.find("World"), 5, "Universe");
    
cout << "替换后的字符串: " << str << endl;

输出结果应为:

原始字符串: Hello, World!
替换后的字符串: Hello, Universe!

swap

swap函数用于交换两个string对象之间的内容。

string str1 = "Hello";
string str2 = "World";
 
str1.swap(str2);
    
cout << "After swap:" << endl;
cout << "str1: " << str1 << endl;
cout << "str2: " << str2 << endl;

std中的swap()函数:

string str1 = "Hello";
string str2 = "World";
    
swap(str1, str2);
    
cout << "After swap:" << std::endl;
cout << "str1: " << str1 << endl;
cout << "str2: " << str2 << endl;

在这个例子中,我们使用了std命名空间中的swap函数,将str1str2的内容进行了交换。输出的结果与前一个例子是一样的。

但是std中的swap将两个对象完全交换了,这个过程创建了string类型的中间变量。

 而string中的swap并没有完全交换对象,只是交换了两个对象的指针,以及值,并没有创建string类型的中间变量。所以对于string对象,使用string自带的swap效率会更高。


string的查找操作
find

find函数用于在字符串中查找子字符串的第一次出现。

find函数接受两个参数:
待查找的子字符串 str 或者字符c
开始搜索的位置 pos(可选,默认值为0)                        

返回值:

  • 如果找到了指定子串,返回它在原字符串中第一次出现的位置。
  • 如果未找到指定子串,返回string::npos
string str = "Hello World";
string subStr = "World";

// 使用find函数查找子字符串的位置
size_t index = str.find(subStr);

cout << "子字符串在位置 " << index << " 处被找到" << endl;

refind

rfind用于在字符串中寻找指定子串的最后一次出现的位置,或者说是倒着查找。

rfind函数接受两个参数:
待查找的子字符串 str 或者字符c
开始搜索的位置 pos(可选,默认为string::npos

返回值:

  • 如果找到了指定子串,返回它在原字符串中最后一次出现的位置。
  • 如果未找到指定子串,返回string::npos
sub_str

substr用于提取字符串的子串。该函数可以接受两个参数,起始索引位置和子串的长度。

string str = "Hello, world!";

// 提取从索引位置3开始的子串
string sub1 = str.substr(3);

// 输出子串
cout << sub1 << endl; // 输出为 "lo, world!"

// 提取从索引位置7开始长度为5的子串
std::string sub2 = str.substr(7, 5);

// 输出子串
cout << sub2 << endl; // 输出为 "world"

 输出结果为:

lo, world!
world

可以看到,substr() 函数成功提取了指定位置和长度的子串,并将其存储在新的字符串变量中。

find_first_of & find_first_not_of

find_first_of函数用于在字符串中查找第一个与指定字符序列中的任意字符匹配的字符的位置。

 find_first_of函数有多个重载形式,其中最常用的形式如下:

size_t find_first_of (const string& str, size_t pos = 0) const;

这个函数接受一个字符串参数str,并从指定的位置pos开始搜索。find_first_of函数会在调用对象的字符串中查找第一个与str中的任意字符匹配的字符,并返回其位置。如果找不到匹配的字符,则返回string::npos

string str = "Hello World";
string chars = "aeiou";

// 在str中查找第一个出现在"aeiou"中的字符
size_t pos = str.find_first_of(chars);
 
cout << "第一个元音字母出现在位置:" << pos << endl;
cout << "字符为:" << str[pos] << endl;

输出结果为:

第一个元音字母出现在位置:1
字符为:e

 

 

 

 

 

 

 

 

 

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值