2.string和vector容器

本文围绕C++展开,介绍了标准库类型string和vector,包括它们的初始化、操作及字符处理等内容。还阐述了迭代器,说明了使用方法和运算规则。如string可进行读写、比较等操作,vector能添加元素,迭代器可访问容器元素。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 标准库类型string

标准库类型string表示可变长的字符序列,使用 string 类型必须包含string头文件。作为标准库的一部分,string 定义在命名空间std中。

1.1 初始化string对象

如何初始化类的对象是由类本身决定的,string 的初始化方法如下:

string s1;             // 默认初始化,空字符串
string s2 = s1;        // s2是s1的副本
string s3 = "hiya";    // s3是该字符串字面值的副本;
string s4(10,'c');     // s4的内容是cccccccccc;
string s5("hiya");     // s5是该字符串字面值的副本

注意: 如果使用等号初始化一个变量,实际执行的是拷贝初始化,编译器把等号右侧的初始值拷贝到新创建的对象中去。如果不使用等号,执行的是直接初始化。

1.2 string对象上的操作

一个类除了要规定初始化其对象的方式外,还会定义对象所能执行的操作。

操作含义
os << s将 s 写到输出流 os 中,返回 os
is >> s从 is 中读取字符串赋值给 s,字符串以空白分隔,返回 is
getline(is, s)从 is 中读取一行赋给 s,返回 is
s.empty( )s 为空返回 true,否则返回 false
s.size( )返回 s 中字符的个数
s[n]返回 s 中第 n 个字符的引用,n 从 0 开始
s1 + s2返回 s1 和 s2 连接后的结果
s1 = s2用 s2 的副本代替 s1 中原来的字符
s1 == s2如果 s1 和 s2 中所含的字符完全一样则相等,该判断对字母大小写敏感
s1 != s2如果 s1 和 s2 中所含的字符存在不同则不等,该判断对字母大小写敏感
<, <=, >, >=利用字符在字典中的顺序进行比较,对字母的大小写敏感

1.读写string对象

string s;
cin >> s;
cout << s << endl;

注意: 在执行读写操作时,string 对象会自动忽略开头的空白并从第一个真正的字符开始读起,直到遇见下一处空白为止。
2.读取未知数量的string对象

string word;
while(cin >> word)
        cout << word << endl;

3.使用getline读取一整行
有时我们希望最终得到的字符串中保留输入的空白符,这时应该使用getline函数。getline 函数的参数是一个输入流和一个 string 对象,函数从给定的输入流中读取内容,直到遇到换行符为止,然后把所读的内容存到那个 string 对象中。

string line;
while(getline(cin, line))
       cout << line << endl;

4.string的成员函数
empty函数根据 string 对象是否为空返回一个对应的布尔值,只要使用点操作符指明是哪个对象执行了就可以了。
size函数返回 string 对象的长度,返回值的类型是string::size_type

string str = "Hello, world!";
// 使用 empty 函数检查字符串是否为空
if (str.empty()) {
      cout << "String is empty." << endl;
} else {
      cout << "String is not empty." << endl;
}
string::size_type len = str.size();
cout << "Length of the string: " << len << endl;

5.比较string对象
string 类定义了几种用于比较字符串的运算符:
1.相等运算符和不等运算符分别检验两个 string 对象相等或不等,string 对象相等意味着它们的长度相等且所包含字符也全相等。
2.关系运算符 <、<=、>、>= 分别检验一个 string 对象是否小于、小于等于、大于、大于等于另外一个 string 对象。
3.如果两个 string 对象在某些对应的位置上不一样,则 string 对象比较的结果其实是 string 对象中第一对相异字符比较的结果。

std::string str1 = "apple";
std::string str2 = "banana";
if (str1 == str2) {
      std::cout << "str1 and str2 are equal" << std::endl;
} else if (str1 < str2) {
      std::cout << "str1 is less than str2" << std::endl;
} else {
      std::cout << "str1 is greater than str2" << std::endl;
}

6.两个string对象相加
对 string 对象使用加法的结果是一个新的 string 对象,它所包含的字符由两部分组成,前半部分是加号左侧 string 对象所含内容,后半部分是加号右侧 string 对象所含内容。

std::string str1 = "Hello, ";
std::string str2 = "World!";
std::string result = str1 + str2; 
std::cout << result << std::endl;

7.字面值和string对象相加
标准库允许把字符字面值和字符串字面值转化成 string 对象,所以在需要 string 对象的地方就可以使用这两种字面值来替代。

string str1 = "hello,";
string result = str1 + "nihao";
cout << result << endl;

注意: 当把 string 对象和字符串字面值或字符字面值混在一条语句中时,必须确保加号两侧的运算对象至少有一个是 string。

1.3 处理string对象中的字符

下面是一些 string 的内置成员函数:

函数含义函数含义
isalnum(c )当 c 是字母或者数字时为真isprint(c )当 c 是可打印字符时为真
isalpha(c )当 c 是字母时为真isspace(c )当 c 是空白时为真
iscntrl(c )当 c 是控制字符时为真isupper(c )当 c 是大写字母时为真
isdigit(c )当 c 是数字时为真isxdigit(c )当 c 是十六进制数字时为真
isgraph(c )当 c 不是空格但可打印时为真tolower(c )当 c 是大写字母时输出小写字母
islower(c )当 c 是小写字母时为真toupper(c )当 c 是小写字母时输出大写字母
ispunct(c )当 c 是标点符号时为真

1.处理每个字符?使用基于范围的for语句
如果想对 string 对象中的每个字符做点什么操作,最好的办法是使用范围for语句。这种语句遍历给定序列中的每个元素并对序列中的每个值执行操作。

string str("some string");
for(auto c : str)
     cout << c << endl;

2.使用范围for语句改变字符串中的字符
如果想要改变 string 对象中字符的值,必须把循环变量定义成引用类型。

string s("hello world!!!");
for(auto &c : s)
      c = toupper(c);
cout << s << endl;

3.处理一部分字符
有时需要访问的只是其中一个字符或者访问多个字符但遇到某个条件就要停下来,这时建议使用下标或者迭代器。

string str2 = "some strings";
if (!str2.empty())
	str2[0] = toupper(str2[0]);
cout << str2 << endl;     // Some strings
for (auto index = 0; index != str2.size() && !isspace(str2[index]); ++index)
	 str2[index] = toupper(str2[index]);
cout << str2 << endl;    // SOME strings

2. 标准库类型vector

标准库类型vector表示对象的集合,集合中所有对象的类型相同。集合中的每个对象都有一个与之对应的索引,索引用于访问集合中的对象。使用 vector 时需要头文件vector

2.1 定义和初始化vector对象

初始化 vector 对象常用方法如下所示:

vector<T> v1;           // 空集合,T表示数据类型,如int、double或自己定义的数据类型
vector<T> v2(v1);
vector<T> v2 = v1;
vector<T> v3(n, val);  // n个val
vector<T> V4(n);       // n个重复执行了默认初始化的对象
vector<T> v5{a, b, c....};
vector<T> v5 = {a, b, c....};

1.列表初始值还是元素数量

vector<int>v1(10);    // v1有10个元素,每个值都是0
vector<int>v2{10};    // v2有1个元素,值是10
vector<int>v3(10, 1); // v3有10个元素,每个值都是1
vector<int>v4{10, 1}; // v1有2个元素,值是10, 1

2.2 向vector对象中添加元素

可以用 vector 的成员函数push_back向容器中添加元素,push_back 负责把一个值压到 vector 的尾端

vector<int> v2;
for(int i = 0; i != 100; ++i){
    v2.push_back(i);
}

注意: 不能使用范围for循环向 vector 对象添加元素,范围 for 循环会使用容器的迭代器进行遍历,当往容器中添加元素时容器可能会进行内存重新分配或者元素的移动,这会导致之前获取的迭代器失效,因此应该使用传统的for语句来添加元素。

2.3 其它的vector操作

操作含义操作含义
v.empty( )如果 v 为空返回真,否则假v1 = {a, b}用列表中的元素拷贝替换v1中的元素
v.size( )返回 v 中元素的个数v1 == v2判断是否相等
v.push_back( )向 v 的尾端添加一个值v1 != v2判断是否不等
v [n]返回 v 中第 n 个位置的元素的引用,从0开始计数<, <=, >, >=以字典顺序进行比较
v1 = v2v2 拷贝给 v1

1.关系运算符按照字典顺序进行比较
如果两个 vector 容器在相同位置的元素都一样,则元素较少的 vector 对象小于元素较多的 vector 对象,若元素的值有区别,则 vector 对象的大小关系由第一对相异的元素的大小关系来决定。

 std::vector<int> vec1 = {1, 2, 3};
 std::vector<int> vec2 = {1, 2, 4};
 // 比较大小
 if (vec1 < vec2) {
       std::cout << "vec1 小于 vec2" << std::endl;
 } else if (vec1 > vec2) {
       std::cout << "vec1 大于 vec2" << std::endl;
 } else {
       std::cout << "vec1 等于 vec2" << std::endl;
 }

2.计算vector内对象的索引
使用下标运算符能获取到指定的元素。和 string 一样,vector 对象的下标也是从 0 开始计起,其下标的类型是相应的size_type类型

std::vector<int> numbers = {10, 20, 30, 40, 50};
// 获取指定索引处的元素
std::cout << "索引为 2 的元素是: " << numbers[2] << std::endl;
// 使用 vector 的 size_type 进行迭代
for (std::vector<int>::size_type i = 0; i < numbers.size(); ++i) {
        std::cout << "索引为 " << i << " 的元素是: " << numbers[i] << std::endl;
}

3.不能用下标形式添加元素
vector 对象以及 string 对象的下标运算符可用于访问已存在的元素,而不能用于添加元素。这是因为当使用下标访问元素时,确切位置的内存可能不存在或者已经被其它数据占用。

3. 迭代器介绍

我们可以使用下标运算符来访问 string 对象的字符或 vector 对象的元素,还有一种更通用的机制也可以实现,这就是迭代器。迭代器的对象是容器中的元素或者 string 中的字符。

3.1 使用迭代器

和指针不一样的是获取迭代器不是使用取地址符,有迭代器的类型拥有返回迭代器的成员函数,这些类型都拥有名为 beginend 的成员。begin 成员负责返回指向容器中第一个元素的迭代器,end 成员负责返回指向容器尾元素的下一位置的迭代器。
1.迭代器运算符

运算符含义运算符含义
* iter返回迭代器 iter 所指元素的引用- - iter令 iter 指向容器中的上一个元素
iter. mem解引用 iter 并获取该元素名为 mem 的成员iter1 == iter2判断2个迭代器是否相等
++iter令 iter 指向容器中的下一个元素iter1 != iter2判断2个迭代器是否不等

2.迭代器的类型
实际上,迭代器的标准库类型使用iteratorconst_iterator来表示迭代器的类型。

vector<int>::iterator it;
string::iterator it2;
vector<int>::const_iterator it3;  // 只能读,不能写;
string::const_iterator it4;       // 只能读,不能写;

注意: begin( )和end( ) 返回的具体类型由对象是否是常量决定。C++新标准引入两个新函数,分别是 cbegin 和 cend,cbegin 和 cend 的返回值都是 const_iterator。
3.结合解引用和成员访问操作
解引用迭代器可获得迭代器所指的对象,如果该类型的对象恰好是类,就有希望进一步访问它的成员函数。

#include <iostream>
#include <vector>
class MyClass {
public:
    void display() {
        std::cout << "Inside MyClass display function!" << std::endl;
    }
};
int main()
{
   std::vector<MyClass> objects(3); // 创建包含3个 MyClass 对象的容器
   // 获取迭代器,并使用它来访问每个对象的成员函数
   for (auto it = objects.begin(); it != objects.end(); ++it) {
          it->display();   // 访问 MyClass 对象的 display 函数
   }
   return 0;
}

3.2 迭代器运算

可以令迭代器和一个整数值相加或相减,其返回值是向前或向后移动了若干个位置的迭代器。

// 计算得到v1中间元素最近的一个迭代器
auto mid = v1.begin() + v1.size()/2;

只要两个迭代器指向的是同一个容器中的元素或者尾元素的下一位置,就能将其相减,所得结果是两个迭代器之间的距离。所谓距离就是指右侧的迭代器向前移动多少位置就能追上左侧的迭代器,其类型是名为difference_type的有符号整型。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Litle_Pudding

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值