C++:字符数组

news/2025/1/12 20:58:39/

一、字符数组介绍

数组的元素如果是字符类型,这种数组就是字符数组,字符数组可以是一维数组,可以是二维数组
(多维数组)。我们接下来主要讨论的是一维的字符数组。
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;
}

http://www.ppmy.cn/news/1562598.html

相关文章

(长期更新)《零基础入门 ArcGIS(ArcMap) 》实验六----流域综合处理(超超超详细!!!)

流域综合处理 流域综合治理是根据流域自然和社会经济状况及区域国民经济发展的要求,以流域水流失治理为中心,以提高生态经济效益和社会经济持续发展为目标,以基本农田优化结构和高效利用及植被建设为重点,建立具有水土保持兼高效生态经济功能的半山区流域综合治理模式。数字高程…

Python AI教程之十五:监督学习之决策树(6)高级算法C5.0决策树算法介绍

C5.0决策树算法 C5 算法由 J. Ross Quinlan 创建,是 ID3 决策树方法的扩展。它通过根据信息增益(衡量通过按特定属性进行划分而实现的熵减少量)递归地划分数据来构建决策树。 对于分类问题,C5.0 方法是一种决策树算法。它构建规则集或决策树,这是对 C4.5 方法的改进。根…

【Linux】Linux开发:GDB调试器与Git版本控制工具指南

Linux相关知识点可以通过点击以下链接进行学习一起加油&#xff01;初识指令指令进阶权限管理yum包管理与vim编辑器GCC/G编译器make与Makefile自动化构建 在 Linux 开发中&#xff0c;GDB 调试器和 Git 版本控制工具是开发者必备的利器。GDB 帮助快速定位代码问题&#xff0c;G…

linux下shell中使用上下键翻出历史命名时出现^[[A^[[A^[[A^[[B^[[B的问题解决

前言 今天在使用linux的时候&#xff0c;使用上下键想翻出历史命令时&#xff0c;却出现[[A[[A[[A[[B^[[B这种东东&#xff0c;而tab键补全命令的功能也无法使用。最终发现是由于当前用户使用的shell是/bin/sh的原因。 解决方法 运行以下命令&#xff0c;将默认 shell 设置为…

计算机网络之---ICMP协议与Ping命令

ICMP 协议 ICMP (Internet Control Message Protocol) 是一种网络层协议&#xff0c;主要用于在 IP 网络中传递控制消息。ICMP 主要用于网络设备之间的故障报告和诊断&#xff0c;帮助设备检测网络连接问题。它是 IP 协议的核心部分之一&#xff0c;用于发送错误消息和操作信息…

深入解析 Flink 与 Spark 的性能差异

&#x1f496; 欢迎来到我的博客&#xff01; 非常高兴能在这里与您相遇。在这里&#xff0c;您不仅能获得有趣的技术分享&#xff0c;还能感受到轻松愉快的氛围。无论您是编程新手&#xff0c;还是资深开发者&#xff0c;都能在这里找到属于您的知识宝藏&#xff0c;学习和成长…

从excel提取和过滤数据到echarts中绘制图

主页面 介绍 echarts的事例页面,导入数据比较麻烦,此项目从excel中提取数据(含过滤数据),以注入页面. 代码说明 所有的需要从excel中读取的参数,从代码中替换.需以{{data}} 包含在内使用绘制参数的解析代码参数可以解析出来所有参数数据配置上传文件后,可以选择列数据过滤条…

可视化重塑汽车展示平台新体验

汽车展示平台利用图扑可视化技术&#xff0c;实现全方位、互动式车型展示&#xff0c;提供沉浸式用户体验&#xff0c;助力消费者深入了解车辆特性&#xff0c;优化销售沟通效率&#xff0c;推动汽车行业的数字化创新。