NO.25十六届蓝桥杯备战|字符数组|初始化|输入|输出|strlen|gets|fgets|strcpy|strcat(C++)

news/2025/3/10 20:42:23/

字符数组

字符数组介绍

数组的元素如果是字符类型,这种数组就是字符数组,字符数组可以是⼀维数组,可以是⼆维数组(多维数组)。
接下来主要讨论⼀维的字符数组。

char arr1[5]; //⼀维数组  
char arr2[3][5];//⼆维数组

C语⾔中使⽤双引号括起来⼀串字符表⽰字符串,这种⽅式虽然在C++中也是⽀持的,但是⼀般我们会将这种字符串称为C语⾔⻛格的字符串。如果需要将⼀个C语⾔⻛格的字符串存储起来,就可以是字符数组。

字符数组的初始化
char a[10]; //字符数组的创建

字符数组的创建同⼀维数组的创建就不再赘述,但是字符串数的初始化有2种⽅式,如下:

//⽅式1  
char ch1[10] = "abcdef";  
char ch2[] = "abcdef";//如果数组初始化的时候,数组的⼤⼩可以省略不写,数组⼤⼩会根据初始化内容来确定  //⽅式2  
char ch3[10] = {'a', 'b', 'c', 'd', 'e', 'f'};  
char ch4[] = {'a', 'b', 'c', 'd', 'e', 'f'};

如果调试看⼀下ch2 和 ch4 数组的内容,我们会明显的发现,数组 ch2 中多⼀个 ‘\0’ 字符,这是因为字符串的末尾其实隐藏⼀个 ‘\0’ 字符,这个 ‘\0’ 是字符串的结束标志,在打印字符串的时候遇到 ‘\0’ ,打印结束。
当我们把字符串存放在⼀个字符数组中的时候,这时候也可以把字符数组当做字符串看到。
![[Pasted image 20250305193310.png]]

字符串⻓度-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;  
}

![[Pasted image 20250305193517.png]]

字符数组的输⼊

输⼊没有空格字符串

使⽤scanf函数和字符数组来实现:

#include <cstdio>  int main()  
{  char arr[20] = { 0 };  //输⼊  scanf("%s", arr);  //输出  printf("%s", arr);  return 0;  
}

使⽤cin和字符数组来实现:

#include <iostream>  
using namespace std;  int main()  
{  char arr[20] = { 0 };  //输⼊  cin >> arr;  //输出  cout << arr << endl;  return 0;  
}

上⾯两个代码都是将字符串读取后从数组的起始位置开始存放的,当然也可以指定位置存放,⽐如从数组的第⼆个元素的位置开始存放,如下代码:

#include <iostream>  
using namespace std;  int main()  
{  char arr[20] = { 0 };  //输⼊  cin >> arr + 1;//arr表⽰数组的起始位置,+1意思是跳过⼀个元素,就是第⼆个元素的位置  //可以通过调试观察⼀下arr的内容  cout << arr + 1;  return 0;  
}

那么从第n个元素开始存放,就应该是 cin >> arr + n; 使⽤ scanf 函数也是⼀样的。

#include <cstdio>  int main()  
{  char arr[20] = { 0 };  //输⼊  scanf("%s", arr+2);//从arr+2的位置开始存放  //输出  printf("%s", arr+2);//从arr+2的位置开始打印  return 0;  
}
输⼊有空格的字符串
scanf的⽅式
#include <cstdio>  int main()  
{  char arr[20] = {0};  //输⼊  scanf("%s", arr);  //输出  printf("%s", arr);  return 0;  
}

当输⼊"abc def"的时候,实际上scanf只读取了abc就结束了,也就是相当于遇到空格就结束了。
![[Pasted image 20250305194120.png]]

这⾥特别说⼀下占位符%s ,它其实不能简单地等同于字符串。
它的规则是,从当前第⼀个⾮空⽩字符开始读起,直到遇到空⽩字符(即空格、换⾏符、制表符等)为⽌。
因为 %s 的读取不会包含空⽩字符,所以⽆法⽤来读取多个单词,除⾮多个 %s ⼀起使⽤。这也意味着, scanf() 不适合读取可能包含空格的字符串,⽐如书名或歌曲名。另外有⼀个细节注意⼀下, scanf() 遇到 %s 占位符,会在字符串变量末尾存储⼀个 \0 字符。

同时 scanf() 将字符串读⼊字符数组时,不会检测字符串是否超过了数组⻓度。所以,储存字符串时,很可能会超过数组的边界,导致预想不到的结果。为了防⽌这种情况,使⽤ %s 占位符时,可以指定读⼊字符串的最⻓⻓度,即写成 %[m]s ,其中的 [m] 是⼀个整数,表⽰读取字符串的最⼤⻓度,后⾯的字符将被丢弃。

#include <cstdio>  
int main()  
{  char name[11];  scanf("%10s", name); return 0;  
}

上⾯⽰例中, name 是⼀个⻓度为11的字符数组, scanf() 的占位符 %10s 表⽰最多读取⽤⼾输⼊的10个字符,后⾯的字符将被丢弃,这样就不会有数组溢出的⻛险了。

cin的⽅式
#include <iostream>  
using namespace std;  int main()  
{  char arr[20] = { 0 };//输⼊  cin >> arr;  //输出  cout << arr << endl;  return 0;  
}

![[Pasted image 20250305194831.png]]

其实cin在读取⼀个字符串的时候,在遇到空⽩字符的时候,就认为字符串结束了,不再继续往后读取剩余的字符,同时将已经读取到的字符串末尾加上\0,直接存储起来。

解决问题
gets和fgets

使⽤ gets 函数的⽅式,这种⽅式能解决问题,但是因为 gets 存在安全性问题,在C++11中取消了gets ,给出了更加安全的⽅案: fgets 。

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

gets 是从第⼀个字符开始读取,⼀直读取到 \n 停⽌,但是不会读取 \n ,也就是读取到的内容中没有包含 \n ,但是会在读取到的内容后⾃动加上 \0 。
fgets 也是从第⼀个字符开始读取,最多读取 num-1 个字符,最后⼀个位置留给 \0 ,如果num 的⻓度是远⼤于输⼊的字符串⻓度,就会⼀直读取到 \n 停⽌,并且会读取 \n ,将 \n 作为读取到内容的⼀部分,同时在读取到的内容后⾃动加上 \0 。

#include <cstdio>  
//⽅案1  
int main()
{  char arr[10] = {0};  gets(arr);  printf("%s\n", arr);  return 0;  
}  //替代⽅案-⽅法2  
#include <cstdio>  
int main()  
{  char arr[10] = {0};  fgets(arr, sizeof(arr), stdin);printf("%s\n", arr);  return 0;  
}

上述两个程序,同样在运⾏起来后,在控制台窗⼝中输⼊: abc def ,按回⻋,⽅案1和⽅案2中arr 数组的内容中差异如下:
![[Pasted image 20250305195820.png]]

有DevC++中使⽤gets函数,确实没有报错,但是在其他的IDE上,⽐如:VS2022上直接报错,不允许使⽤gets函数。
所以在代码中还是慎⽤gets函数。

scanf

当然C语⾔中使⽤ scanf 函数其实也能做到读取带有空格的字符串,只是不常⻅⽽已。⽅式就是将 “%s” 改成 "%[^\n]s" ,其中在 %s 之间加上了 [^\n] ,意思是⼀直读取,直到遇到\n ,这样即使遇到空格也就不会结束了。
这种⽅式读取,不会将 \n 读取进来,但是在读取到的字符串末尾加上 \0 。

#include <cstdio>  
int main()  
{  char arr[10] = "xxxxxxxx";  scanf("%[^\n]s", arr);  printf("%s\n", arr);  return 0;  
}
getchar

使⽤ getchar 逐个字符的读取,也是可以读取⼀个字符串的。

#include <cstdio>  int main()  
{  char arr[10] = { 0 };  int ch = 0;  int i = 0;  while ((ch = getchar()) != '\n')  {  arr[i++] = ch;  }printf("%s\n", arr);  return 0;  
}

字符数组的输出

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

strcpy和strcat

strcpy

使⽤字符数组可以存放字符串,但是字符数组能否直接赋值

char arr1[] = "abcdef";  
char arr2[20] = {0};  
arr2 = arr1;//这样这节赋值可以吗?

就整型数组中,我们说的过⼀样,这⾥也是不⾏的。
将arr1中的字符串,拷⻉到arr2中,其实C/C++中有⼀个库函数叫strcpy,可以完成。

char * strcpy ( char * destination, const char * source );  
//destination - 是⽬标空间的地址  
//source - 是源头空间的地址  
//需要的头⽂件 <cstring>
#include <cstdio>  
#include <cstring>int main()  
{  char arr1[] = "abcdef";  char arr2[20] = {0};  strcpy(arr2, arr1);  printf("%s\n", arr2);  return 0;  
}

![[Pasted image 20250305201418.png]]

strcat

有时候我们需要在⼀个字符的末尾再追加⼀个字符串,那字符数组能直接追加吗?⽐如:

char arr1[20] = "hello ";  
char arr2[] = "world";  
arr1 += arr2;//这样也是不⾏的

C/C++中有⼀个库函数叫strcat,可以完成。

char * strcat ( char * destination, const char * source );  
//destination - 是⽬标空间的地址  
//source - 是源头空间的地址  
//需要的头⽂件 <cstring>
#include <cstdio>  
#include <cstring>int main()  
{  char arr1[20] = "hello ";  char arr2[] = "world";  strcat(arr1, arr2);  printf("%s\n", arr1);  return 0;  
}

![[Pasted image 20250305203349.png]]


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

相关文章

游戏引擎学习第140天

回顾并为今天的内容做准备 目前代码的进展到了声音混音的部分。昨天我详细解释了声音的处理方式&#xff0c;声音在技术上是一个非常特别的存在&#xff0c;但在游戏中进行声音混音的需求其实相对简单明了&#xff0c;所以今天的任务应该不会太具挑战性。 今天我们会编写一个…

SDIO(Secure Digital Input Output)详解

1. SDIO的定义 SDIO&#xff08;Secure Digital Input Output&#xff09; 是基于 SD&#xff08;Secure Digital&#xff09;存储卡标准 扩展的 通用输入输出接口协议&#xff0c;允许设备通过SD卡槽连接多种外设&#xff08;如Wi-Fi模块、GPS、摄像头等&#xff09;。它不仅…

P8685 [蓝桥杯 2019 省 A] 外卖店优先级--优先队列“数组”!!!!!

P8685 [蓝桥杯 2019 省 A] 外卖店优先级 题目 解析优先队列如何判断是否使用优先队列&#xff1f;省略规则优先队列常用操作大顶堆 vs 小顶堆定义队列h队列数组 代码 题目 解析 每个外卖店会在不同的时间点收到订单&#xff0c;我们可以看见测试用例的时间顺序是不同的&#x…

VSCode 配置优化指南

Visual Studio Code&#xff08;简称 VSCode&#xff09;是一款广受欢迎的开源代码编辑器&#xff0c;以轻量、高效和高度可扩展著称。无论是初学者还是专业开发者&#xff0c;都能在它的帮助下提升开发效率。为了让 VSCode 更好地服务你的开发工作&#xff0c;以下是一份详细的…

LeetCode 572题详解 | 子树判断的递归实现

题目如下&#xff1a; 解题过程如下&#xff1a; 若根结点为空&#xff0c;return false&#xff08;为什么要写根结点为空的情况呢&#xff1f;递归中会对根结点进行解引用&#xff09; 若这两棵二叉树相同——相同的树&#xff0c;return true 递归&#xff0c;若根结点的左…

Java后端高频面经——JVM、Linux、Git、Docker

JVM内存模型是什么&#xff1f;&#xff08;B站&#xff09;JVM内存模型中的堆和栈的区别&#xff1f; &#xff08;1&#xff09;JVM的内存模型 JVM 运行时内存共分为虚拟机栈、本地方法栈、堆、元空间&#xff08;方法区&#xff09;、程序计数器五个部分。还有一部分内存叫直…

MySQL环境搭建和基本操作

前言 MySQL是现在最为流行的数据库&#xff0c;而且是开源的&#xff0c;任何人都可以在Internet下载,进行安装。 MySQL环境搭建 一、软件包安装 MySQL是目前最为流行的开放源码的数据库&#xff0c;是完全网络化的跨平台的关系型数据库系统&#xff0c;它是由瑞典MySQLAB公司…

【机器人栅格地图】基于鹭鹰算法SBOA实现机器人栅格地图路径规划(目标函数:最短距离)附Matlab代码

基于鹭鹰算法&#xff08;SBOA&#xff09;的机器人栅格地图路径规划实现 一、鹭鹰算法&#xff08;SBOA&#xff09;的基本原理 鹭鹰优化算法&#xff08;Secretary Bird Optimization Algorithm, SBOA&#xff09;是一种新型元启发式算法&#xff0c;灵感源自鹭鹰的捕猎和逃…