C++(3):字符串、向量和数组

news2024/11/17 1:35:44

命名空间的 using 声明

using namespace::name;

1.每个名字都需要独立的 using 声明;
2.头文件不应包含 using 声明:
因为头文件的内容会拷贝到所有引用它的文件中去,如果头文件里有某个using声明,那么每个使用了该头文件的文件就都会有这个声明。(可能会引起名字冲突)

标准库类型 string

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

定义和初始化 string 对象

如何初始化类的对象是由类本身决定的。
初始化 string 对象的方式:

string sl;// 默认初始化,s1是一个空串
string s2(s1);// s2是s1的副本
string s2 = sl;// 等价于s2(s1), s2是s1的副本
string s3("value");// s3是字面值"value"的副本,除了字面值最后的那个空字符外
string s3 = "value";// 等价于s3("value"), s3是字面值"value"的副本
string s4(n, 'c');// 把s4初始化为由连续n个字符c组成的串

如果使用等号(=)初始化一个变量,实际上执行的是拷贝初始化,编译器把等号右侧的初始值拷贝到新创建的对象中去。与之相反,如果不使用等号,则执行的是直接初始化

string s5 = "hiya";//拷贝初始化
string s6("hiya");//直接初始化
string s7(10, 'c');//直接初始化,s7的内容是cccccccccc

string 对象上的操作

在这里插入图片描述

读写 string 对象

在执行读取操作时,string对象会自动忽略开头的空白(即空格符、换行符、制表符等)并从第一个真正的字符开始读起,直到遇见下一处空白为止。

string s;//空字符串
cin >>S;//将string对象读入s,遇到空白停止
cout <<s<< endl;//输出s
//如上所述,如果程序的输入是“ Hello wor1d !”(注意开头和结尾处的空格),则输出将是“Hello”,输出结果中没有任何空格。
读取未知数量的 string 对象
string word;
//反复读取,直至到达文件末尾
while (cin >> word){
	cout<< word << endl;//逐个输出单词,每个单词后面紧跟一个换行
}
使用 getline 读取一整行

用getline函数代替原来的>>运算符在最终得到的字符串中保留输入时的空白符。
getline函数的参数是一个输入流和一个string对象,函数从给定的输入流中读入内容,直到遇到换行符为止(注意换行符也被读进来了),然后把所读的内容存入到那个string对象中去(注意不存换行符)。
getline只要一遇到换行符就结束读取操作并返回结果,哪怕输入的一开始就是换行符也是如此。如果输入真的一开始就是换行符,那么所得的结果是个空string.

string line;
//每次读入一整行,直至到达文件末尾
while (getline (cin,line)){
	cout<< line<< endl;
}

getline 会将换行符也读入,但是不将换行符存入 string 对象。即触发 getline() 函数返回的那个换行符实际上被丢弃掉了。

string 的 empty 和 size 操作

empty 函数根据string对象是否为空返回一个对应的布尔值。
size函数返回string对象的长度(即string对象中字符的个数)。

if( !line.empty())//判断是否为空
if(line.size()>80)//判断长度是否超过80
string::size_type 类型

存放 string 类的 size 函数返回的是一个string::size_type 类型。string::size_type 类型是一个无符号类型的值而且能够存放下任何string对象的大小。

auto len = s.size();// len 的类型是 string::size_type

如果一条表达式中已经有了size()函数就不要再使用int,否则可能出现意想不到的问题。

比较 string 对象

1.如果两个string对象的长度不同,而且较短string对象的每个字符都与较长string对象对应位置上的字符相同,就说较短string对象小于较长string对象。
2.如果两个string对象在某些对应的位置上不一致,则string对象比较的结果其实是string对象中第一对相异字符比较的结果

两个string对象相加
string sl = "hello,",s2 ="world\n";
string s3 = s1 +s2;// s3的内容是hello, world\n
s1 += s2;//等价于sl = s1 +s2
字面值和 string 对象相加

允许把字符字面值和字符串字面值转换成string对象。
字符串字面值与string是不同的类型。

处理 string 对象中的字符

主要处理三个问题:1.如何获取字符本身;2.要知道能改变某个字符的特性;3.遇到某个条件处理停止。

cctype 头文件中定义的函数可以帮助解决这些问题
在这里插入图片描述
C++程序应该使用名为cname的头文件而不使用name.h的形式,其实两者在内容上并没有明显区别,主要区别是在名为 cname 的头文件中定义的名字从属于命名空间 std,而定义在名为 .h 的头文件则不然。

基于范围的 for 语句

范围 for (range for) 语句:遍历给定序列中的每个元素并对序列中的每个值执行某种操作。

for(declaration : expression)
	statement

其中,expression部分是一个对象,用于表示一个序列。declaration部分负责定义一个变量,该变量将被用于访问序列中的基础元素。每次迭代,declaration部分的变量会被初始化为expression部分的下一个元素值。

string str ( "some string");//每行输出str中的一个字符。
for (auto c : str)//对于str中的每个字符
	cout << c<< endl;//输出当前字符,后面紧跟一个换行符

在这里插入图片描述

使用范围for语句改变字符串中的字符

如果想要改变string对象中字符的值,必须把循环变量定义成引用类型。

string s("Hello world!!!");
//转换成大写形式。
for (auto &c : s)//1对于s中的每个字符(注意:c是引用)
	c= toupper(c);//c是一个引用,因此赋值语句将改变s中字符的值
cout<< s << endl;

使用下标可以执行随机访问string[index],注意:C++标准并不要求标准库检测下标是否合法。
对 string 的最后一个字符进行索引:string[string.size()-1]

标准库类型 vector

标准库类型vector表示对象的集合,其中所有对象的类型都相同。集合中的每个对象都有一个与之对应的索引,索引用于访问对象。
C++语言既有类模板(class template),也有函数模板,其中vector是一个类模板。

vector是模板而非类型,由vector生成的类型必须包含vector中元素的类型,例如vector<int>。

定义和初始化 vector 对象

初始化 vector 对象的方法
在这里插入图片描述
在某些情况下,初始化的真实含义依赖于传递初始值时用的是花括号还是圆括号。

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{101}; // v4有2个元素,值分别是10和1
  • 如果用的是圆括号,可以说提供的值是用来构造(construct) vector对象的。
  • 如果用的是花括号,可以表述成我们想列表初始化(list initialize)该vector对象。

如果初始化时使用了花括号的形式,但是提供的值又不能用来列表初始化,就要考虑用这样的值来构造vector对象了。

vector<string> v5{"hi"};//列表初始化:v5有一个元素
vector<string> v6("hi");//错误:不能使用字符串字面值构建vector对象
vector<string> v7 {10};//v7有10个默认初始化的元素
vector<string> v8{10,"hi"};// v8有10个值为"hi"的元素

vector 支持的操作

在这里插入图片描述
vector对象(以及string对象)的下标运算符可用于访问已存在的元素,而不能用于添加元素。

迭代器

迭代器类似于指针,也提供了对对象的间接访问。

使用迭代器

*iter;//返回迭代器iter所指元素的引用
iter->mem;//解引用iter并获取该元素的名为mem的成员,等价于(*iter).mem
++ite;//令iter指示容器中的下一个元素
--iter;//令iter指示容器中的上一个元素
//判断两个迭代器是否相等(不相等),如果两个迭代器指示的是同一个元素或者它们是同一个容器的尾后迭代器,则相等;反之,不相等
iter1 == iter2;
iter1 != iter2;

迭代器类型

拥有迭代器的标准库类型使用 iteratorconst_iterator 来表示迭代器的类型:

vector<int>::iterator it;//it能读写vector<int>的元素
string::iterator it2;//it2能读写string对象中的字符

vector<int>::const_iterator it3;//it3只能读元素,不能写元素
string::const_iterator it4;//it4只能读字符,不能写字符

const_iterator和常量指针差不多,能读取但不能修改它所指的元素值。相反,iterator的对象可读可写。

bgein 和 end 运算符

begin 和 end 返回的具体类型由对象是否是常量决定,如果对象是常量,begin和end返回const_ iterator;如果对象不是常量,返回iterator。

vector<int>v;
const vector<int> cv ;
auto itl = v.begin();// it1的类型是vector<int>::iterator
auto it2 = cv.begin (); // it2的类型是vector<int>::const_iterator

//cbegin 和 cend 都是 const_iterator 类型
auto it3 = v.cbegin();// it3的类型是vector<int>; :const_iterator

迭代器运算

string 和 vector 支持的迭代器运算:
在这里插入图片描述

数组

与vector不同的地方是,数组的大小确定不变,不能随意向数组中增加元素。因为数组的大小固定
不清楚元素的确切个数的情况下,一般使用vector 。

定义和初始化内置数组

和内置类型的变量一样,如果在函数内部定义了某种内置类型的数组,那么默认初始化会令数组含有未定义的值
数组的维度应该是已知的,也就是说维度必须是一个常量表达式。

字符串字面值的结尾处还有一个空字符,这个空字符也会被拷贝到字符数组中

char a1[] = {'C', '+', '+'};//列表初始化,没有空字符
char a2[] = {'C', '+','+','\0'};//列表初始化,含有显式的空字符
char a3[] = "C++";//自动添加表示字符串结束的空字符
const char a4[6]= "Daniel";//错误:没有空间可存放空字符!

数组不允许拷贝和赋值。但是可以一个元素一个元素进行处理。

就数组而言,是从数组的名字开始按照由内向外进行阅读:

int *ptrs [10];//ptrs是含有10个整型指针的数组
int &refs [10]=/*?*/;//错误:不存在引用的数组
int (*Parray)[10] = &arr;//Parray指向一个含有10个整数的数组
int (&arrRef)[10] = arr;//arrRef引用一个含有10个整数的数组

访问数组元素

使用 size_t 类型作为数组小标。size_t 是一种机器相关的无符号类型,它足够大能表示内存中任意对象的大小。(在 cstddef 头文件中定义)

指针和数组

对数组的元素使用取地址符就能得到指向该元素的指针。

string nums[] ={"one""two","three");//数组的元素是string对象
string *p= &nums[0];//p指向nums的第一个元素
string*p2 =nums; //等价于p2 = &nums[0]

标准库函数 begin 和 end

因为数组不是类类型,所以 begin 和 end 不是成员函数。

// pbeg指向arr的首元素,pend指向arr尾元素的下一位置
int *pbeg = begin(arr) , *pend = end(arr) ;

尾后指针不指向具体的元素,因此尾后指针不能执行解引用和递增操作。

指针运算

两个指针相减的结果是它们之间的距离。

auto n = end(arr) - begin(arr); //n 是 arr 中元素的数量

两个指针相减的结果的类型是一种名为 ptrdiff_t 的标准库类型,和 size_t一样,ptrdiff_t 也是一种定义在 cstddef 头文件中的机器相关的类型。因为差值可能为负值,所以 ptrdiff_t 是一种带符号类型

只要两个指针指向同一个数组的元素,或者指向该数组的尾元素的下一位置,就能利用关系运算符对其进行比较。如果两个指针分别指向不相关的对象,则不能比较它们。

数组内置的下标运算符所用的索引值不是无符号类型,这一点与vector和string 不一样。只要指针指向的是数组中的元素(或者数组中尾元素的下一位置),都可以执行下标运算:

int *p= &ia[2];// p指向索引为2的元素
int j=p[1];// p[1]等价于*(p+ 1),就是ia[3]表示的那个元素
int k= p[-2];// p[-2]是ia[0]表示的那个元素

C 风格字符串

c 风格字符串不是一种类型,而是一种写法,约定俗成的想法。
在这里插入图片描述

与旧代码的接口

1.允许使用字符串字面值来初始化 string 对象。

string s("Hello World");//s 的内容是 Hello world

任何出现字符串字面值的地方都可以用以空字符结束的字符数组来替代。
但不能反过来使用 string 对象初始化字符数组,要用 c_str() 函数将 string 对象转化为 c 风格字符串

char *str = s;//错误:不能用string对象初始化char*
const char *str = s.c_str();//正确

2.允许使用数组来初始化 vector 对象。
指明要拷贝区域的首元素地址和尾后地址:

int int_arr[] ={01234,5);
// ivec有6个元素,分别是int_arr中对应元素的副本
vector<int> ivec(begin(int_arr), end(int_arr));

多维数组

允许使用花括号括起来的一组值初始化多维数组:

int ia[3][4] ={//三个元素,每个元素都是大小为4的数组
	{0,123},//第1行的初始值
	{4567},//第2行的初始值
	{891011}//第3行的初始值
	};

内层嵌套的花括号不是必须的:

//没有标识每行的花括号,与之前的初始化语句是等价的
int ia[3][4] = {0,1,2,3,4,5,6,7,8,9,10,11};

显式初始化部分元素

//显式地初始化每行的首元素
int ia[3][4]= {{0 },{4 },{8}};

//显式地初始化第1行,其他元素执行值初始化
int ix[3][4] -{0,3,6,9};

多维数组的下标引用

多维数组的每个维度对应一个下标运算符。

//用arr的首元素为ia最后一行的最后一个元素赋值
ia[2][3] = arr[0][0][0];
int (&row)[4] = ia[1];//把row绑定到ia的第二个4元素数组上

使用范围 for 语句处理多维数组

for 语句中改变元素值要显示使用 & 符号声明为引用类型

size_t cnt = 0;
for (auto &row : ia)//对于外层数组的每一个元素
	for (auto &col : row){//对于内层数组的每一个元素
		col = cnt;//将下一个值赋给该元素
		++cnt;//将cnt 加 l
	}
	
for (const auto &row : ia)1/对于外层数组的每一个元素
	for (auto col : row)//对于内层数组的每一个元素
	cout << col <<endl;

要使用范围for语句处理多维数组,除了最内层的循环外,其他所有循环的控制变量都应该是引用类型。
因为如果不声明为引用类型,编译器会自动将控制变量转换为指向数组首元素的指针,在内层的循环就变得不合法了。

当程序使用多维数组的名字时,也会自动将其转换成指向数组首元素的指针(多维数组实际上是数组的数组)。

int ia [3][4];//大小为3的数组,每个元素是含有4个整数的数组
int(*p)[4]= ia;//p指向含有4个整数的数组
p = &ia[2];//p指向ia的尾元素

//声明中,圆括号必不可少:
int *ip[4];//整型指针的数组

重要术语

  1. 拷贝初始化(copy initialization) 使用赋值号(=)的初始化形式。新创建的对象是初始值的一个副本。
  2. difference_type 由string和 vector定义的一种带符号整数类型,表示两个迭代器之间的距离。
  3. 实例化(instantiation) 编译器生成一个指定的模板类或函数的过程。
  4. **以空字符结束的字符串(null-terminatedstring)**是一个字符串,它的最后一个字符后面还跟着一个空字符(‘\0’)。
  5. 尾后迭代器(off-the-end iterator) end函数返回的迭代器,指向一个并不存在的元素,该元素位于容器尾元素的下一位置。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/548836.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Apache Kafka - 重识Kafka生产者

文章目录 概述Kafka 生产者Kafka 生产者工作原理如何使用 Kafka 生产者 生产者配置项&#xff08;核心&#xff09;导图总结 概述 Kafka 生产者是 Apache Kafka 中的一个重要组件&#xff0c;它负责将数据发送到 Kafka 集群中。在实时数据处理和流式处理应用程序中&#xff0c…

如何自建个人音乐播放器Navidrome

文章目录 1. 前言2. Navidrome网站搭建2.1 Navidrome下载和安装2.1.1 安装并添加ffmpeg2.1.2下载并配置Navidrome2.1.3 添加Navidrome到系统服务 2.2. Navidrome网页测试 3. 本地网页发布3.1 cpolar的安装和注册3.2 Cpolar云端设置3.3 Cpolar本地设置 4. 公网访问测试5. 结语 转…

【总结】Nupmy1

Nupmy numpy的核心是名为ndarray的数据类型&#xff0c;它代表多维数组&#xff0c;封装了操作数据的运算和方法 1. 创建数组对象 1.1 方法1:array 通过array将list转换成数据对象 # 通过array将list转换成数据对象 array1np.array([1,2,3,4,5]) array1 # array([1, 2, 3,…

Nginx + fastCGI 实现动态网页部署

简介 本文章主要介绍下&#xff0c;如何通过Nginx fastCGI来部署动态网页。 CGI介绍 在介绍fastCGI之前先介绍下CGI是什么。CGI : Common Gateway Interface&#xff0c;公共网关接口。在物理层面上是一段程序&#xff0c;运行在服务器上&#xff0c;提供同客户端HTML页面的…

测试理论----Bug的严重程度(Severity)和优先级(Priority)的分类

【原文链接】测试理论----Bug的严重程度&#xff08;Severity&#xff09;和优先级&#xff08;Priority&#xff09;的分类 一、Bug的严重程度&#xff08;Severity&#xff09; Bug的Severity&#xff08;严重程度&#xff09;指的是一个Bug对软件系统功能影响的程度&#…

Java常用工具之Collections

目录 一、排序操作二、查找操作三、同步控制三、不可变集合四、其他五、CollectionUtils&#xff1a;Spring 和 Apache 都有提供的集合工具类六 、小结 Collections 是 JDK 提供的一个工具类&#xff0c;位于 java.util 包下&#xff0c;提供了一系列的静态方法&#xff0c;方便…

2023河海大学846软件工程学硕考研高分上岸经验分享

大家好&#xff0c;我是陪你考研每一天的大巴学长。 大巴学长为大家邀请到了2023年846软件工程学硕刚刚上岸的学长&#xff0c;为大家分享一下他的考研经验&#xff0c;经验里详细介绍了各科的复习方法&#xff0c;很有参考意义。 希望对大家有所借鉴和帮助&#xff0c;在此向…

栈实现队列(继续细起来啊)

生命不是要等待风暴过去&#xff0c;而是要学会在风暴中跳舞。 ——卡莉尔吉布朗目录 &#x1f341;一.栈实现队列 &#x1f340;二.使用两个栈实现队列的功能 &#x1f33c;1.在队列的结构体中创建两个栈 &#x1f681;2.创建一个队列的结构体指针 &#x1f309;3…

云计算中的大数据处理:尝试HDFS和MapReduce的应用

云计算中的大数据处理&#xff1a;尝试HDFS和MapReduce的应用 文章目录 云计算中的大数据处理&#xff1a;尝试HDFS和MapReduce的应用一、前言二、第一题1、命令方式2、java API方式 三、第二题1、创建CSV文件并将其上传到HDFS2、编写利用MapReduce框架的java代码3、打包java项…

【设计模式与范式:创建型】41 | 单例模式(上):为什么说支持懒加载的双重检测不比饿汉式更优?

从今天开始&#xff0c;我们正式进入到设计模式的学习。我们知道&#xff0c;经典的设计模式有 23 种。其中&#xff0c;常用的并不是很多。据我的工作经验来看&#xff0c;常用的可能都不到一半。如果随便抓一个程序员&#xff0c;让他说一说最熟悉的 3 种设计模式&#xff0c…

Kelvin和Rossby波 Part-2(浅水方程)

在前面博主有篇关于Kelvin和Rossby波的简要介绍&#xff0c;见下&#xff1a; Kelvin和Rossby波 Part-1&#xff08;简要介绍&#xff09; 开尔文波&#xff08;Kelvin Wave&#xff09;是发生在大气或海洋中的&#xff0c;迎向地形边界&#xff08;例如海岸线&#xff09;平衡…

回顾2023年计算机专业学生卑微求职 / 申博血泪史

0.前言 2023年是悲惨的一年&#xff0c;各个行业都在卷中卷。同时对于个人来说&#xff0c;2023年也是最忙碌的一年&#xff0c;不仅面临毕业&#xff0c;而且面临工作/读博&#xff0c;随便挑出一件&#xff0c;都是一件耗时耗力的事。相信大家也从网络上看到了很多的帖子或者…

文心一言 VS 讯飞星火 VS chatgpt (19)-- go语言的slice和rust语言的Vec的扩容流程是什么?

go语言的slice和rust语言的Vec的扩容流程是什么&#xff1f; 文心一言&#xff1a; 在Go语言中&#xff0c;slice&#xff08;切片&#xff09;和Rust语言中的Vec都是用于存储一组固定长度的元素的数据结构。它们的扩容流程略有不同&#xff0c;下面是它们的基本概述&#xf…

HNU数据结构与算法分析-作业3-树结构

1. (简答题) 5.1 定义满二叉树的每一个结点或者是一个分支结点&#xff0c;并恰好有两个非空子结点&#xff1b;或者是叶结点。 证明在有n个分支结点的所有二叉树中&#xff0c;满二叉树的叶结点的数目&#xff08;或者叶结点与全部结点数的比例&#xff09;是最高的。 5.6 …

Linux下安装配置maven

1.安装以及配置maven 1.1.下载maven安装包 首先需要切换到自己需要安装的目录 把配置都放到了&#xff1a;/root路径下 1.2.解压下载好的maven包 tar -zxvf apache-maven-3.6.0-bin.tar.gzcp -r apache-maven-3.6.0 /usr/local/1.3.配置maven环境变量 1.3.1.在环境变量中…

微信小程序nodejs+vue校园二手商城交易(积分兑换)38gw6

随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受用户的喜爱&#xff0c;校园二手交易被用户普遍使用&#xff0c;为方便用户能够可以随时…

chatgpt赋能Python-python3_8怎么设置字体大小

Python3.8如何设置文本字体大小 Python是一种高级编程语言&#xff0c;它在全球开发者中间得到了广泛的应用。随着Python的不断发展&#xff0c;Python 3.8版本也应运而生。在这个新版本中&#xff0c;有许多新的功能&#xff0c;其中一个是设置文本字体大小。本文将展示如何在…

redis高级篇三(分片集群)

一)进行测试Sentinel池: 集群的定义:所谓的集群&#xff0c;就是通过增加服务器的数量&#xff0c;提供相同的服务&#xff0c;从而让服务器达到一个稳定、高效的状态 之前的哨兵模式是存在着一些问题的&#xff0c;因为如果主节点挂了&#xff0c;那么sentinel集群会选举新的s…

一些题目__

好耶&#xff0c;第一次div2做出来3道题&#xff0c;虽然中间看了个题解&#xff0c;但是思路差不多&#xff0c;被复杂度困住了&#xff0c;nnd 首先是第一个题&#xff0c;emm 第一题 那么这个题的要求是&#xff0c;构造一个数组&#xff0c;满足这些条件&#xff1a; 注意…