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

发布于:2025-03-10 ⋅ 阅读:(20) ⋅ 点赞:(0)

字符数组

字符数组介绍

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

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]]