C++:字符数组

一、字符数组介绍

数组的元素如果是字符类型,这种数组就是字符数组,字符数组可以是一维数组,可以是二维数组
(多维数组)。我们接下来主要讨论的是一维的字符数组。
char arr1[5]; //⼀维字符数组
char arr2[3][5];//⼆维字符数组
C 语言中使用双引号括起来一串字符表示字符串,这种方式虽然在 C++ 中也是支持的,但是一般我们会将这种字符串称为C语言风格的字符串。如果需要将一个C语言风格的字符串存储起来,就可以是字符数组。
1. 字符数组的初始化
char a[10]; //字符数组的创建
字符数组的创建同一维数组的创建我就不再赘述了,但是字符串数的初始化有2种方式,如下:
//方式1
char ch1[10] = "abcdef";
char ch2[] = "abcdef";//如果数组初始化的时候,数组的大小可以省略不写,数组大小会根据初
始化内容来确定
//方式2
char ch3[10] = {'a', 'b', 'c', 'd', 'e', 'f'};//对数组中的元素逐个初始化,但是最后不会有'\0'
char ch4[] = {'a', 'b', 'c', 'd', 'e', 'f'};
如果调试看⼀下 ch2 ch4 数组的内容,我们会明显的发现,数组 ch2 中多一个 '\0' 字符,这
是因为字符串的末尾其实隐藏一个 '\0' 字符,这个 '\0' 是字符串的结束标志,在打印字符串的时
候遇到 '\0' ,打印结束。当我们把字符串存放在一个字符数组中的时候,这时候也可以把字符数组当做字符串看待。
2. 字符串长度-strlen
字符数组中存放的着字符串,这个字符数组有自己的长度,也就是数组的元素个数,这个可以使用
sizeof计算,那数组中存放的字符串的长度是多少?其实C/C++中有一个库函数叫:strlen,可以求字符串的长度,其实统计的就是字符串中 \0之前的字符个数。strlen需要的头文件是<cstring> 。
size_t strlen ( const char * str );
//str - 指针,存放的是字符串的起始地址,从这个地址开始计算字符串的⻓度

那我们应该怎么使用这个函数呢?下面给出代码演示:

#include <iostream>
#include <cstring>
using namespace std;
int main()
{
 char arr[20] = "abcdef";
 cout << "数组的⻓度:" << sizeof(arr)/sizeof(arr[0]) << endl;
 cout << "字符串的⻓度:" << strlen(arr) << endl;
 return 0;
}

二、字符数组的输入

1.输入没有空格字符串

使用scanf函数和字符数组来实现:
#include <iostream>
#include <cstdio>
using namespace std;
int main()
{
	char arr[20] = { 0 };
	//输入
	scanf("%s", arr);
	//输出
	printf("%s", arr);
	return 0;
}
使用cin和字符数组来实现:
#include <iostream>
#include <cstdio>
using namespace std;
int main()
{
	char arr[20] = { 0 };
	//输入
	cin >> arr;
	//输出
	printf("%s", arr);
	return 0;
}
上面两个代码都是将字符串读取后从数组的起始位置开始存放的,当然我们也可以指定位置位置存放,比如从数组的第二个元素的位置开始存放,如下代码:
#include <iostream>
using namespace std;
int main()
{
	char arr[20] = { 0 };
	//输入
	cin >> arr + 1;//arr表示数组的起始位置,+1意思是跳过一个元素,就是第二个元素的位置
	//可以通过调试观察一下arr的内容
	cout << arr + 1;
	return 0;
}

当我们输入hello时,通过调试可以发现是从数组的第二个位置开始存放的。

2.输入有空格的字符串

scanf的方式:
当输入"hello world"的时候,实际上scanf只读取了hello就结束了,也就是遇到空格就结束了。我们在使用占位符%s输入字符串时需要注意 它其实不能简单地等同于字符串。它的规则是,从当前第一个非 空白字符开始读起,直到遇到空白字符(即空格、换行符、制表符等)为止。 因为 %s 的读取不会包含空白字符,所以无法用来读取多个单词,除非多个 %s一 起使用。 这也意味着, scanf() 不适合读取可能包含空格的字符串,比如书名或歌曲名。另外有一 个细节注意⼀下, scanf() 遇到 %s 占位符,会在字符串变量末尾存储一个 \0 字符。
同时 scanf() 将字符串读入字符数组时,不会检测字符串是否超过了数组长度。所以,储存字符串
时,很可能会超过数组的边界,导致预想不到的结果。为了防止这种情况,使用 %s 占位符时,可以指定读入字符串的最长长度,即写成 %[m]s ,其中的 [m] 是一个整数,表示读取字符串的最大长度,后面的字符将被丢弃,这样就不会有数组溢出的风险了。
cin的方式:
我们可以发现 结果也是一样,没有任何区别。 其实cin在读取一个字符串的时候,在遇到空白字符的时候,就认为字符串结束了,不再继续 往后读取剩余的字符,同时将已经读取到的字符串末尾加上\0,直接存储起来。
那我们应该使用什么方式来解决这种情况的问题呢?
(1) gets 和 fgets
使用  gets 函数的方式,这种方式能解决问题,但是因为 gets 存在安全性问题,在C++11中取消了
gets ,给出了更加安全的方案: fgets。
gets 是从第一个字符开始读取,一直读取到 \n 停止,但是不会读取 \n ,也就是读取到的内容中没有包含 \n ,但是会在读取到的内容后自动加上 \0 。gets 虽然在一些编译器中能够运行成功,但也会存在警告以及潜在的问题。

scanf("%d",&n);读取一个整数后,它不会消耗输入缓冲区中的换行符(即用户按下的Enter键)。这个换行符会被gets(arr);视为有效的输入,因此gets()实际上可能不会等待用户进一步输入。当然gets()还有除此之外的不足之处,这里就不赘述了。所以在代码中还是慎用gets函数。

fgets 也是从第一个字符开始读取,最多读取 num-1 个字符,最后⼀个位置留给 \0 ,如果 num 的长度是远大于输⼊的字符串长度,就会一直读取到 \n 停止,并且会读取 \n ,将 \n 作为读取到内容的一部分,同时在读取到的内容后自动加上 \0
#include <iostream>
using namespace std;
int main()
{
	char arr[20] = { 0 };
	//输入
	fgets(arr, sizeof(arr), stdin);
	//输出
	printf("%s", arr);
	return 0;
}

在这里说明一下它的三个参数,第一个是我们输入的数组的地址,第二个是要输入到数组中的最大字符数(包括终止符'\0'),第三个是输入流的来源,因为我们是使用键盘输入的,所以可以使用stdin用作从标准输入中读取的参数。

char * fgets ( char * str, int num, FILE * stream );

(2)scanf

当然C语言中使用  scanf 函数其实也能做到读取带有空格的字符串,只是不常见而已。方式就是
"%s" 改成 "%[^\n]s" ,其中在 % s 之间加上了 [^\n] ,意思是一直读取,直到遇到\n ,这样即使遇到空格也就不会结束了。这种方式读取,不会将 \n 读取进来,但会在读取到的字符串末尾加上 \0。
#include <cstdio>
int main()
{
	char arr[20];
	scanf("%[^\n]s", arr);
	printf("%s\n", arr);
	return 0;
}

(3)getchar

使用  getchar 逐个字符的读取,也是可以读取一个字符串的。
#include <cstdio>
int main()
{
	char arr[20] = { 0 };
	char ch = 0;
	int i = 0;
	while ((ch = getchar()) != '\n')
	{
		arr[i++] = ch;
	}
	arr[i] = '\0';
	printf("%s\n", arr);
	return 0;
}

三、字符数组的输出

1. C 语言中可以在 printf 函数中使用 %s 占位符的方式,打印字符数组中的字符串。
2. C++ 中使用 cout ,可以直接打印字符数组中的字符串内容。
3. 也可以采用循环的方式逐个字符打印字符串的内容。
以下三个演示中的cout都可以使用scanf来实现相同的效果。
//方法1
#include <iostream>
#include <cstdio>
using namespace std;
int main()
{
	char a[] = "hello world";
	cout << a << endl;
	printf("%s\n", a);
	return 0;
}
#include <iostream>
#include <cstdio>
using namespace std;
//方法2
//单个字符的打印,直到\0字符,\0不打印
int main()
{
	char a[] = "hello world";
	int i = 0;
	while (a[i] != '\0')
	{
		cout << a[i];
		i++;
	}
	cout << endl;
	return 0;
}
#include <iostream>
#include <cstdio>
using namespace std;
//方法3
//单个字符打印,根据字符串长度来逐个打印,
// strlen可以求出字符串的长度,不包含\0
int main()
{
	char a[] = "hello world";
	int i = 0;
	for (i = 0; i < strlen(a); i++)
	{
		cout << a[i];
	}
	cout << endl;
	return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于SpringBoot实现的保障性住房管理系统

&#x1f942;(❁◡❁)您的点赞&#x1f44d;➕评论&#x1f4dd;➕收藏⭐是作者创作的最大动力&#x1f91e; &#x1f496;&#x1f4d5;&#x1f389;&#x1f525; 支持我&#xff1a;点赞&#x1f44d;收藏⭐️留言&#x1f4dd;欢迎留言讨论 &#x1f525;&#x1f525;&…

分享3个国内使用正版GPT的网站【亲测有效!2025最新】

1. molica 传送入口&#xff1a;https://ai-to.cn/url/?umolica 2. 多帮AI 传送入口&#xff1a;https://aigc.openaicloud.cn?inVitecodeMYAAGGKXVK 3. 厉害猫 传送入口&#xff1a;https://ai-to.cn/url/?ulihaimao

LabVIEW瞬变电磁接收系统

利用LabVIEW软件与USB4432采集卡开发瞬变电磁接收系统。系统通过改进硬件配置与软件编程&#xff0c;解决了传统仪器在信噪比低和抗干扰能力差的问题&#xff0c;实现了高精度的数据采集和处理&#xff0c;特别适用于地质勘探等领域。 ​ 项目背景&#xff1a; 瞬变电磁法是探…

CM3/4启动流程

CM3/4启动流程 1. 启动模式2. 启动流程 1. 启动模式 复位方式有三种&#xff1a;上电复位&#xff0c;硬件复位和软件复位。 当产生复位&#xff0c;并且离开复位状态后&#xff0c;CM3/4 内核做的第一件事就是读取下列两个 32 位整数的值&#xff1a; 从地址 0x0000 0000 处取…

快手短剧播放器uniapp如何引入与对接?

uniApp前端微短剧项目开源分享 开源地址&#xff1a;git开源下载地址 文章目录 快手短剧播放器uniapp如何引入与对接&#xff1f;1.引入短剧播放器2.创建文件kscomponents组件3.local-stream.js文件说明4.用户行为事件4.local-stream.ksml文件参考如下 快手短剧播放器uniapp如何…

.NET AI 开发人员库 --AI Dev Gallery简单示例--问答机器人

资源及介绍接上篇 nuget引用以下组件 效果展示&#xff1a; 内存和cpu占有&#xff1a; 代码如下&#xff1a;路径换成自己的模型路径 模型请从上篇文尾下载 internal class Program{private static CancellationTokenSource? cts;private static IChatClient? model;privat…

如何构建多层决策树

构建一颗多层的决策树时&#xff0c;通过递归选择最佳划分特征&#xff08;依据 信息增益 或 基尼系数&#xff09;对数据集进行划分&#xff0c;直到满足停止条件&#xff08;例如叶节点纯度达到要求或树的深度限制&#xff09;。以下是基于 信息增益 和 基尼系数 的递推公式和…

VSCode 使用鼠标滚轮控制字体

一、 文件 | 首选项 | 设置 二、单击在 settings.json中编辑 "editor.mouseWheelZoom": true 注注注意&#xff1a;保存哦&#xff01;ctrlS 三、测试 按住ctrl鼠标滚轮&#xff0c;控制字体大小

十年后LabVIEW编程知识是否会过时?

在考虑LabVIEW编程知识在未来十年内的有效性时&#xff0c;我们可以从几个角度进行分析&#xff1a; ​ 1. 技术发展与软件更新 随着技术的快速发展&#xff0c;许多编程工具和平台不断更新和改进&#xff0c;LabVIEW也不例外。十年后&#xff0c;可能会有新的编程语言或平台…

注册中心如何选型?Eureka、Zookeeper、Nacos怎么选

这是小卷对分布式系统架构学习的第9篇文章&#xff0c;第8篇时只回答了注册中心的工作原理的内容&#xff0c;面试官的第二个问题还没回答&#xff0c;今天再来讲讲各个注册中心的原理&#xff0c;以及区别&#xff0c;最后如何进行选型 上一篇文章&#xff1a;如何设计一个注册…

C++ 复习总结记录三

C 复习总结记录三 主要内容 1、类的六个默认成员函数 2、构造函数 3、析构函数 4、拷贝构造函数 5、赋值运算符重载 6、const 成员函数 7、取地址及 const 取地址操作符重载 一 类的六个默认成员函数 如果一个类中什么成员都没有&#xff0c;简称为空类。空类中并不是…

【简博士统计学习方法】第1章:4. 模型的评估与选择

4. 模型的评估与选择 4.1 训练误差与测试误差 假如存在样本容量为 N N N的训练集&#xff0c;将训练集送入学习系统可以训练学习得到一个模型&#xff0c;我们将这么模型用决策函数的形式表达&#xff0c;也就是 y f ^ ( x ) y\hat{f}(x) yf^​(x)&#xff0c;关于模型的拟合…

计算机网络 (30)多协议标签交换MPLS

前言 多协议标签交换&#xff08;Multi-Protocol Label Switching&#xff0c;MPLS&#xff09;是一种在开放的通信网上利用标签引导数据高速、高效传输的新技术。 一、基本概念 MPLS是一种第三代网络架构技术&#xff0c;旨在提供高速、可靠的IP骨干网络交换。它通过将IP地址映…

【Java】JVM内存相关笔记

Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域。这些区域有各自的用途&#xff0c;以及创建和销毁的时间&#xff0c;有的区域随着虚拟机进程的启动而一直存在&#xff0c;有些区域则是依赖用户线程的启动和结束而建立和销毁。 程序计数器&am…

鸿蒙 ArkUI实现地图找房效果

常用的地图找房功能&#xff0c;是在地图上添加区域、商圈、房源等一些自定义 marker&#xff0c;然后配上自己应用的一些筛选逻辑构成&#xff0c;在这里使用鸿蒙 ArkUI 简单实现下怎么添加区域/商圈、房源等 Marker. 1、开启地图服务 在华为开发者官网&#xff0c;注册应用&…

STM32-WWDG/IWDG看门狗

WWDG/IWDG一旦开启不能关闭&#xff0c;可通过选项字节在上电时启动硬件看门狗&#xff0c;看门狗计数只能写入不能读取。看门狗启用时&#xff0c;T6bit必须置1&#xff0c;防止立即重置。 一、原理 独立看门狗-超时复位 窗口看门狗-喂狗&#xff08;重置计数器&#xff0c;…

基于JAVA+SSM的车辆运输管理

基于JAVASSM的车辆运输管理 前言 ✌全网粉丝20W,csdn特邀作者、博客专家、CSDN[新星计划]导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末附源码下载链接&#x1f345; 哈喽兄弟们&#…

【Linux系列】Vim 编辑器中的高效文本编辑技巧:删除操作

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

win10 VS2019上libtorch库配置过程

win10 VS2019上libtorch库配置过程 0 引言1 获取libtorch2 在VS上配置使用libtorch库3 结语 0 引言 &#x1f4bb;&#x1f4bb;AI一下&#x1f4bb;&#x1f4bb;   libtorch库是一个用于深度学习的C库&#xff0c;是PyTorch的官方C前端。它提供了用于构建和训练深度学习模…

通过gradle发布aar或jar携带sources-jar到maven nexus

找了很久&#xff0c;没有找到满意的。终于找到一个好的办法。 gradle7.x适用。比以前的写法简洁。 发布传统的jar工程 比如okhttp&#xff0c;fastjson等项目&#xff0c;纯java工程。 直接创建新文件publish.gradle: apply plugin: maven-publishProperties properties …