Chapter 4 数组
4.1 一维数组 ※
前言
在程序开发的过程中,很多场景,我们需要保存很多的数据,或者说我们需要保存一组数据,使用普通的datatype不能满足我们的需求,C++为开发者提供了数组(array)用来保存一组数据。
在C++中,数组保存的一组数据的类型必须是完全一致的,C++不支持数组保存不同的数据类型。
4.1.1 一维数组的定义和初始化
定义:
datatype array[length];------>int arr_num[5];
int arr_num[5] = {1, 2, 3, 4, 5}; //初始化4.1.2 数组名要求
1.只能由字数字和下划线组合,但不能数字开头; 2.系统关键字不能作为数组名; 3.同一作用域下不能重名; 4.见其名知其意。
4.1.3 数组下标
数组是一组具有连续内存位置的类似类型元素。
在C++中std::array是一个封装固定大小数组的容器,数组索引从0开始,可以在C++数组中只存储固定的元素集合。
4.1.4 一维数组的数据元素访问
访问数组的元素,使用中括号,即[]加上数组索引即可,要注意,下标从0开始。
因此,如果我们需要访问数组的第一个元素,其索引应该为0,要访问数组的最后一个元素,其索引是数组的长度减1.
数组名[索引/下标]a. 直接通过下标进行访问
b. 循环访问
int arr[5] = {1, 2, 3, 4, 5};
for (int i = 0; i < 5; i++){
cout << arr[i] << " ";
}
c. 使用foreach循环遍历
int arr[5] = {1, 2, 3, 4, 5};
for (int i:arr)//:之后是容器的变量名,这里指多个值的容器且连续的,int一般可以用auto让编译器自行判断变量类型
{
cout << i << " ";//这里的i不再是下标,而是数据本身
}
d. 循环赋值
int arr[5];
for (int i = 0; i < 5; i++){
cin >> arr[i];
}
4.1.5 练习1
现有五只小猪,体重分别为764,942,613,476,940。定义一个一维数组,存放五只小猪的体重,找出其中最重的小猪,并输出出来。
#include <iostream>
#include <cstdlib>
using namespace std;
int arr[5]
int m;
int main(){
for (int i = 0; i < 5; i++){
cin >> arr[i];
}
m = arr[0];
for (int i = 1; i < 5; i++){
if (m < arr[i]){
m = arr[i];
}
}
cout << m;
}
4.1.6 练习2
输入n(n <= 100)个数保存到数组中,求n个数的和以及平均值
#include <iostream>
#include <cstdlib>
using namespace std;
int arr[103];
int n, sum;
int main(){
cin >> n;
for (int i = 0; i < n; i++){
cin >> arr[i];
}
for (int i = 0; i < n; i++){
sum += arr[i];
}
cout << sum << ' ' << sum / n << endl;
}
比较两个数组是否相等,不能直接使用比较运算符 == ,需要比较数组的长度和数组中的元素是否一致。
#include <iostream>
using namespace std;
int arr1[5],arr2[5];
int main(){
for (int i = 0; i < 5; i++){
cin >> arr1[i];
}
for (int i = 0; i < 5; i++){
cin >> arr2[i];
}
//比较两个数组的元素个数是否一致,使用sizeof()函数
int arr1Count = sizeof(arr1) / sizeof(arr1[0]);//用数组的长度除去单个元素的长度,就代表数组中元素的个数
int arr2Count = sizeof(arr2) / sizeof(arr2[0]);
if (arr1Count != arr2Count)//数组内元素个数不同这两个数组绝对不相同
{
cout << "arr1 != arr2" << endl;
return 0;
}
//判断数组各元素是否一一对应一致(元素数据相同,但位置不同也不是相同的数组)
for (int i = 0; i < arr1Count; i++){
if (arr1[i] != arr2[i]){
cout << "arr1 != arr2" << endl;
return 0;
}
}
cout << "arr1 == arr2" << endl;
}
4.2 冒泡排序 ※
在上述数组是否相同的比较中,提到了元素数据相同,但位置不同也不是相同的数组;接下来只需要满足元素相同即可,不需要满足位置也一致。此时就需要使用排序先将各数组的元素先有序排序后在一一比较。
4.2.1 冒泡排序的步骤
1.比较相邻的元素。如果第一个元素比第二个元素大,就交换他们两个。
2.对每一对相邻元素做同样的工作,执行完毕后,找到第一个最大值。
3.重复以上的步骤,每次比较次数-1,直到不需要比较。
附:第一趟排序完以后,末尾必定是最大元素。
如:8、7、6、5、4进行冒泡排序,第一趟过程如下图所示

4.2.2 交换数据
现有int a = 1; int b = 2; 输出:a = 2 b = 1
A.临时变量法
int a = 1, b = 2, tmp = 0;
tmp = a;
a = b;
b = tmp;//通过一个tmp变量来保证互换时的数据不丢失
B.加减法
int a = 1, b = 2;
a = a + b;//a = 3
b = a - b;//b = 1
a = a - b;//a = 2
C.系统函数调用(swap)
swap(x,y);//将x,y两个值互换
4.2.3 冒泡排序的实现
int arr[5] = {3, 1, 2, 4, 5};
for (int i = 0; i < 5 - 1;i++){//比较趟数
for (int j = 0; j < 5 - i -1; j++){//比较次数
if (arr[i] > arr[j+1]){
swap(arr[j], arr[j + 1]);
}
}
}
for (int i = 0; i < n; i++){
cout << arr[i] << " ";
}
4.3 普通查找 ※
根据值顺序查找
比如在给定数组中查找固定的某个值,就可以从下标为0的元素开始顺序对比查找。
案例
在长度为N(N <= 100)的数组中,输入m个元素,查找k元素第一次出现的位置(位置从1开始),如果找不到k,输出-1.
input: 5 1 3 5 6 3 3
output: 2
#include <iostream>
using namespace std;
int arr[105];
int m, k;
int main(){
cin >> m;
for (int i = 1; i <= m; i++){
cin >> arr[i];
}
cin >> k;
for (int i = 1; i <= m; i++){
if (k == arr[i]){
cout << i << endl;
return 0;
}
return -1;
}
return 0;
}
4.4 二分查找 ※
二分查找也叫折半查找(Binary Search),是一种效率较高的查找方法。
- 定义两个变量l和r;//left值和right值
- 用mid(猜的数)保存l和r的中间值;
- 假如小了,则把l变成mid + 1(将左半部分排除在外);
- 假如大了,则把r变成mid - 1(将右半部分排除在外);
- 假如正确,return mid;
- 假如 l > r,则返回-1;
注:用于查找的内容逻辑上来说是需要有序的;查找的数量只能是一个,而不是多个。
过程如下图所示
案例1
在数组长度为N(N <= 100)的数组中,输入m个元素(有序),查找k元素的位置(位置从1开始),如果找不到k,输出-1.
input: 5 11 22 33 44 55 22
output: 2
#include <iostream>
using namespace std;
int arr[105], m, k;
int main(){
cin >> m;
for (int i = 1; i <= m; i++){
cin >> arr[i];
}
cin >> k;
//定义左下标、右下标、中间标号
int left = 0,right = m,mid = 0;
while (left < right){
mid = (left + right)/2;
if (arr[mid] == k){
cout << mid << endl;
break;
}
else if (arr[mid] < k){//所找数据比中间值大,必然在右边,将左标移到中间+1的位置
left = mid + 1;
}
else{//所找数据比中间值小,必然在左边,将左标移到中间-1的位置
left = mid - 1;
}
}
if (left > right)//当左标大于右标时,说明该元素无法被找到,返回-1
{
cout << -1 << endl;
}
return 0;
}
案例2
如案例1所示,一个有序数组中有多个重复的元素,输出这个元素第一次出现的位置(从1开始)
input: 10 11 22 22 22 22 22 22 33 44 55 22
output: 2
#include <iostream>
using namespace std;
int arr[105], m, k;
int main(){
cin >> m;
for (int i = 1; i <= m; i++){
cin >> arr[i];
}
cin >> k;
//定义左下标、右下标、中间标号
int left = 0,right = m,mid = 0;
while (left < right){
mid = (left + right)/2;
if (arr[mid] == k){
//往mid的左边继续查找是否一样
while(arr[mid - 1] == k && mid - 1 >= 0){
mid--;
}
cout << mid << endl;
break;
}
else if (arr[mid] < k){//所找数据比中间值大,必然在右边,将左标移到中间+1的位置
left = mid + 1;
}
else{//所找数据比中间值小,必然在左边,将左标移到中间-1的位置
left = mid - 1;
}
}
if (left > right)//当左标大于右标时,说明该元素无法被找到,返回-1
{
cout << -1 << endl;
}
return 0;
}
案例3
如案例1所示,一个有序数组中有多个重复的元素,输出这个元素最后一次出现的位置(从1开始)
input: 10 11 22 22 22 22 22 22 33 44 55 22
output: 7
#include <iostream>
using namespace std;
int arr[105], m, k;
int main(){
cin >> m;
for (int i = 1; i <= m; i++){
cin >> arr[i];
}
cin >> k;
//定义左下标、右下标、中间标号
int left = 0,right = m,mid = 0;
while (left < right){
mid = (left + right)/2;
if (arr[mid] == k){
//往mid的右边继续查找是否一样
while(arr[mid + 1] == k && mid + 1 <= m){
mid++;
}
cout << mid << endl;
break;
}
else if (arr[mid] < k){//所找数据比中间值大,必然在右边,将左标移到中间+1的位置
left = mid + 1;
}
else{//所找数据比中间值小,必然在左边,将左标移到中间-1的位置
left = mid - 1;
}
}
if (left > right)//当左标大于右标时,说明该元素无法被找到,返回-1
{
cout << -1 << endl;
}
return 0;
}
案例4
查找元素个数
在一个有序数组中,相同元素一定是挨着的,只需要找到这个元素,在左右寻找,记录个数即可。
在元素个数N(N <= 100)的数组中,输入m个元素(有序),查找k元素的个数,如果找不到,输出0.
input: 10 11 22 22 22 22 22 22 33 44 55 22
output: 6
1#include <iostream>
2
3using namespace std;
4
5int arr[105], m, k, cnt;
6int main(){
7 cin >> m;
8 for (int i = 1; i <= m; i++){
9 cin >> arr[i];
10 }
11 cin >> k;
12 //定义左下标、右下标、中间标号
13 int left = 0,right = m,mid = 0;
14 while (left < right){
15 mid = (left + right)/2;
16 if (arr[mid] == k){
17 cnt++;
18 int left_index = mid - 1;
19 int right_index = mid + 1;
20 //往mid的左边继续查找是否一样
21 while(arr[left_index] == k && left_index >= 0){
22 left_index--;
23 cnt++;
24 }
25 //往mid的右边继续查找是否一样
26 while(arr[right_index] == k && right_index <= m){
27 right_index++;
28 cnt++;
29 }
30 break;
31 }
32 else if (arr[mid] < k){//所找数据比中间值大,必然在右边,将左标移到中间+1的位置
33 left = mid + 1;
34 }
35 else{//所找数据比中间值小,必然在左边,将左标移到中间-1的位置
36 left = mid - 1;
37 }
38 }
39 cout << cnt << endl;
40
41 return 0;
42}
4.5 一维数组修改元素 ※
1.通过下标直接修改 2.先查找,再修改
案例1
蛋糕厂有两台包装称重机编号为01与02,以01号包装一块、02号包装一块、01号包装一块,以这样的方式轮流工作。经检查今日02好机器出现故障,每一块小蛋糕都少称m克,已知今日包装了n块小蛋糕,输入修正前n块小蛋糕的重量,输出修正后每块蛋糕的质量。
input:
三行,第一行一个整数n(0 < n <= 10000),第二行为n个浮点数表示修正前小蛋糕的质量,第三行为一个浮点数m表示因机器故障导致每块小蛋糕缺少的质量。 5 50.5 48.2 50.5 47.7 50.2 3.2
output: 50.5 51.4 50.5 50.9 50.2
#include <iostream>
using namespace std;
float arr[10005], m;
int n;
int main(){
cin >> n;
for (int i = 0; i < n;i++){
cin >> arr[i];
}
cin >> m;
for (int i = 0; i < n; i++){
if(i % 2 == 1){
arr[i] += m;
}
cout << arr[i] << " ";
}
return 0;
}
案例2
在一次100m百米跑比赛中,有n(5 <= n <= 10)个同学进行比赛,输入这n个同学的比赛成绩,把第一名和最后一名的同学的位置进行交换,再输出比赛成绩。
input: 5 10.3 9.8 10.6 9.9 11
output: 10.3 11 10.6 9.9 9.8
#include <iostream>
using namespace std;
float arr[12];
int n;
int max_index, min_index;
int main(){
cin >> n;
for (int i = 0; i < n; i++){
cin >> arr[i];
}
max_index = 0;
min_index = 0;
for (int i = 1; i < n; i++){
max_index = (arr[max_index] < arr[i]) ? i : max_index;
min_index = (arr[min_index] > arr[i]) ? i : min_index;
}
swap(arr[max_index],arr[min_index]);
for (int i = 0; i < n; i++){
cout << arr[i] << " ";
}
return 0;
}
4.6 数组元素的添加 ※
4.6.1 添加到数组末尾
根据现有的最大下标+1,直接插入
注意:插入的下标一定小于等于数组长度减1
案例
马路前方塞车,目前塞车数量n,输入n辆车的编号,后来又有m辆加入塞车队伍,输出现在所有塞车车辆编号,总车辆(n+m <= 100).
input: 3 12 15 9 5 10 11 8 19 6
output: 12 15 9 10 11 8 19 6
#include <iostream>
using namespace std;
int n, m, arr[102];
int main(){
cin >> n;
for (int i = 0; i < n; i++){
cin >> arr[i];
}
cin >> m;
for (int i = 0; i < m; i++){
cin >> arr[i + n];
}
for (int i = 0; i < n + m; i++){
cout << arr[i] << " ";
}
return 0;
}
4.6.2 根据要求添加到数组
案例
班里转来一位新同学,班主任老师安排这位同学坐在小张这一组,输出安排新同学座位后,小张所在小组每位同学的学号
input:
共4行,第一行为一个整数n(0 < n < 60)代表小张同学这一组的同学人数,第二行为n个整数代表小张同学所在小组每位学生的学号,第三行为一个整数k代表新来同学的学号,第四行两个整数p, m,若p = 1,则新同学坐在第m个同学的前面,若p = 0,则新同学坐在第m个同学的后面。 5 7 1 3 14 5 56 0 2
output:
一行,新同学安排好后,小张所在小组每位同学的学号 7 1 56 3 14 5
#include <iostream>
using namespace std;
int n, arr[62], k, p, m, tmp;
int main(){
cin >> n;
for (int i = 1; i <= n; i++){
cin >> arr[i];
}
cin >> k;
cin >> p >> m;
tmp = n;
if (p == 0){
for( ; n > m; n--){
arr[n+1] = arr[n];
}
arr[m+1] = k;
}
else{
for ( ; n >= m; n--){
arr[n+1] = arr[n];
}
arr[m] = k;
}
for (int i = 1; i <= tmp + 1; i++){
cout << arr[i] << " ";
}
return 0;
}
4.7 一维数组删除元素 ※
案例
小赵在录入n(2 <= n <= 100)个同学的分数,该数组中有个数据是严重错误的分数,找出该分数,删掉后,打印其余正常分数。
input: 5 90 98 87 -100 89
output: 90 98 87 89
#include <iostream>
using namespace std;
int point[105];
int n, tmp;
int main(){
cin >> n;
for(int i = 0; i < n - tmp; i++){
cin >> point[i];
if (point[i] < 0){
i--;
tmp++;
}
}
for (int i = 0; i < n - tmp;i++){
cout << point[i] << " ";
}
}
4.8 一维数组元素合并 ※
4.8.1 无序合并
案例
给定两个数组arr1和arr2,数组长度不超过100,合并成arr3
input: 4 11 2 13 41 3 100 200 300
output: 11 2 13 41 100 200 300
#include <iostream>
using namespace std;
int arr1[105], arr2[105], arr3[205];
int n1,n2;
int main(){
cin >> n1;
for(int i = 0; i < n1; i++){
cin >> arr1[i];
}
cin >> n2;
for(int i = 0; i < n2; i++){
cin >> arr2[i];
}
for(int i = 0; i < n1; i++){
arr3[i] = arr1[i];
}
for(int i = 0; i < n2; i++){
arr3[i+n1] = arr2[i];
}
for(int i = 0; i < n1+n2; i++){
cout << arr3[i] << " ";
}
return 0;
}
4.8.2 有序合并
要求合并后按降序或升序输出结果
案例
输入两个升序数组num1与num2,将num1与num2合并到num3中,并且删除重复的数,使得num3依旧为一个升序数组(不能先合并后排序)
input: 四行,第一行,先输入一个整数N1(0 < N1 < 100)代表num1数组的元素个数,再输入N1个整数代表num1中的N1个元素值,下两行同理 6 -3 2 5 7 8 12 8 0 1 2 3 10 13 18 20
input: -3 0 1 2 3 5 7 8 10 12 13 18 20
#include <iostream>
using namespace std;
int num1[105], num2[105], num3[205];
int N1, N2;
int main(){
cin >> N1;
for(int i = 0; i < N1; i++){
cin >> num1[i];
}
cin >> N2;
for(int i = 0; i < N2; i++){
cin >> num2[i];
}
int index = 0, i = 0, j = 0;
for(;i < N1 && j < N2;){
if (num1[i] < num2[j]){
num3[index++] = num1[i++];
}
else if(num1[i] > num2[j]){
num3[index++] = num2[j++];
}
else{
num3[index++] = num1[i++];
j++;
}
}
while (i < N1){
num3[index++] = num1[i++];
}
while (j < N2){
num3[index++] = num2[j++];
}
for(int i = 0; i < index; i++){
cout << num3[i] << " ";
}
return 0;
}
练习:定义一个int型的一维数组,包含10个元素,分别赋值为1~10,然后将数组中的元素都向前移一个位置,即a[0] = a[1], a[1] = a[2]...最后一个元素的值是原来第一个元素的值,然后输出这个数组
input: 1 2 3 4 5 6 7 8 9 10
output: 2 3 4 5 6 7 8 9 10 1
#include <iostream>
using namespace std;
int arr[10];
int main(){
for(int i = 0; i < 10; i++){
cin >> arr[i];
}
int temp = arr[0];
for(int i = 1; i < 10; i++){
arr[i-1] = arr[i];
}
arr[9] = temp;
for(int i = 0; i < 10; i++){
cout << arr[i] << " ";
}
return 0;
}
4.9 字符数组 ※
4.9.1 字符数组定义与声明 ▲
C++中的字符数组,是用来存放一连串字符的数组,C++的字符数组使用与其他数组基本相同,但初始化时,可以直接使用字符串进行初始化,但初始化时,可以直接使用字符串进行初始化,也就是C语言风格的字符串
语法
char arrName[count]; char arrName[count] = "abcde"; char arrName[count] = {'a','b','c','d','e'}; char arrName[count] = {"abcde"};
4.9.2 字符和字符串的区别
char是字符,也是0~127的无符号整数。通常能用一个char表示的被称为ASCII编码。
字符串是以NULL结尾的连续地址。日常生活中常用转义字符 \0 表示(如下图所示)
4.9.3 字符数组的地址 ▲
cout在遇到char数组时,会输出整个字符串,直到遇到\0,所以就算是普通的char单个字符地址,我们也需要(void*)来强制转换其类型
注:void被翻译为无类型,void*为无类型指针,一般称为通用指针或泛指针。
4.9.4 字符数组的输入和输出 ※
cin >>遇到 ' '和'\n'都会停止输入 gets(arrc) //能够直接读取到'\n' puts(arrc) //打印一串字符直到'\n'
4.9.5 字符数组的操作 ※
在使用字符数组的操作时,需添加从C语言移植的头文件#include<cstring>
#include <cstring>
strlen(p); //取字符串长度
strcpy(p, p1); //复制字符串
strncpy(p, p1, n) //复制指定长度的字符串
strcat(p, p1) //附加字符串
strncat(p, p1, n) //附加指定长度的字符串
...
4.9.5.1 strlen(p)
p代表字符数组名,通用格式写为strlen(array_name); 其作用是返回字符数组中的元素个数,且'\0'不被包含在内。
char arr[10] = 'abc';
int len = strlen(arr);
cout << len << endl; //输出为3
4.9.5.2 strcpy(p1, p2)
将p2复制到p1,再返回p1的值
char arr1[10] = "abc";
char arr2[10] = "jkl";
//arr1 = arr2; 不可取,这是一个非法的指令
strcpy(arr1, arr2); //在VS22中不能使用该函数,被认为unsafe,使用strcpy_s即可
cout << arr1 << endl; //输出为jkl
4.9.5.3 strncpy(p1, p2, n)
将p2前n个字符复制到p1,返回p1的值
char arr1[10] = "abc";
char arr2[10] = "jkl";
strncpy(arr1, arr2, 2); //在VS22中不能使用该函数,被认为unsafe,使用strncpy_s即可
cout << arr1 << endl; //输出为jk
4.9.5.4 strcmp(p1, p2)
通过ASCII码来比较p1和p2的大小,若p1 > p2 → return 1; p1 = p2 → return 0; p1 < p2 → return -1; 注:strcmp是对一个字符一个字符进行比较,而非整体进行对比,详情看下面样例中的arr5、arr6对比
char arr1[10] = "abc";
char arr2[10] = "abc";
char arr3[10] = "abb";
char arr4[10] = "abd";
int a = strcmp(arr1, arr2);
int b = strcmp(arr1, arr3);
int c = strcmp(arr1, arr4);
cout << a << endl; //输出为0
cout << b << endl; //输出为1
cout << c << endl; //输出为-1
char arr5[10] = "ab";
char arr6[10] = "ba";
int d = strcmp(arr5, arr6);
cout << d << endl; //输出为-1,从第一个字符a的ASCII值小于b的值时就已停止比较
4.9.5.5 strncmp(p1, p2, n)
通过ASCII码来比较p1、p2的大小,对前n个字符进行比较。
char arr1[10] = "abc";
char arr2[10] = "abb";
int length = 2; //设定需要比较的字符串长度
int a = strncmp(arr1, arr2, length);
cout << a << endl; //输出为0
4.9.5.6 stricmp/strcasecmp
对于不同的操作系统分成两个函数,stricmp用于Windows平台,strcasecmp则用于MacOS/Linux系统,不区分大小写比较字符串1和字符串2的大小,其结果由函数返回值带回。
但是现在对于stricmp函数为过时的,需要使用ISO C标准,可用_stricmp函数代替
char c1[10] = "ABCDE";
char c2[10] = "abcde";
int a = _stricmp(c1, c2);
cout << a << endl; //输出为0
//在不相等时,输出为差值
char c3[10] = "aBCDE";
char c4[10] = "Zbcde";
int b = _stricmp(c3, c4);
cout << b << endl; //输出为-25
4.9.5.7 strnicmp
不区分大小写比较字符串1和字符串2指定位数的大小。
char c1[10] = "abc";
char c2[10] = "abd";
int a = _strnicmp(c1, c2, 2);//函数前加下划线理由同stricmp
cout << a << endl; //输出为0
4.9.5.8 strcat(p1, p2)
将p2拼接到p1后(返回p1的值)
char c1[100] = "abcde";
char c2[100] = "fghij";
strcat_s(c1, c2);
cout << c1 << endl; //输出为abcdefghij
4.9.5.9 strncat
将字符串2的前n个字符连接到字符串1后边(返回字符串1的值)
char c1[100] = "abcde";
char c2[100] = "fghij";
strncat_s(c1, c2, 3);
cout << c1 << endl; //输出为abcdefgh
4.9.5.10 strchr/strrchr
strchr(char_array name, search for letter)在字符串中查找指定字符 strrchr(char_array name, search for letter)在字符串中反向查找指定字符
返回一个指向该字符串中第一次出现该字符的指针,如果字符串中不包含该字符则返回NULL空指针。
char c[100] = "aBCDBE";
cout << strchr(c, 'B') << endl;
//输出结果为BCDBE,具体使用返回指针详见指针部分
cout << strrchr(c, 'B') << endl;
//输出结果为BE
4.9.5.11 strlwr/strupr
strlwr(char_array name)将字符串中的大写字母换成小写字母 strupr(char_array name)将字符串中的小写字母换成大写字母
在现在使用中,此函数被认为不安全,需替换成_strlwr/strupr_s
char c[100] = "asdJKSHjd";
_strlwr_s(c);
cout << c << endl; //asdjkshjd
_strupr_s(c);
cout << c << endl; //ASDJKSHJD
4.9.5.12 memset
memset(char_array name, initial value, initial bytes)将某一块内存中的内容全部设置为指定的值
char c[10];
memset(c, 'a', sizeof(c));
for(int i = 0; i < 10; i++){
cout << c[i] << ' ';
}
//
int arr[10];
memset(arr, 12, sizeof(arr)); //将12更改为0,输出则为正确,也就相当于清空内存是被允许的。
for(int i = 0; i < 10; i++){
cout << arr[i] << ' '; //输出arr是不正确的访问,在memset里是默认一个字节处理,而整型占4个字节,无法处理
}
4.9.6 字符串到数值类型的转换 ※
atoi(p)字符串转换到int整型;atof(p)字符串转换到double浮点数;atol(p)字符串转换到long整型
char c[100] = "131.343";
int n = atoi(c);
cout << n << endl; //输出为131
double n1 = atof(c);
cout << n1 << endl; //输出为131.343
long n2 = atol(c);
cout << n2 << endl; //输出为131
4.9.7 字符检查 ※
#include<cctype> //以下函数需要包含此头文件
isalpha(); //检查是否为字母字符
isupper(); //检查是否为大写字母字符
islower(); //检查是否为小写字母字符
isdigit(); //检查是否为数字
isxdigit(); //检查是否为十六进制数字表示的有效字符
isspace(); //检查是否为空给类型字符
iscntrl(); //检查是否为控制类字符
ispunct(); //检查是否为标点符号
isalnum(); //检查是否为字母和数字
isprint(); //检查是否是可打印字符
isgraph(); //检查是否是图形字符,等效于 isalpha() || ispunct()
char c = 'A';
char a = '5';
cout << isdigit(a) << endl; //输出一个非零数即代表True
cout << isupper(c) << endl; //同上
//其余不再展示
4.9.8 练习
统计数字字符个数,输入一行字符,统计出其中数字字符的个数。 input: dream abc jlje 2022. 要求其总长度<255 output: 4 输出字符串里面数字字符的个数
#include <iostream>
#include <cstring>
using namespace std;
char c[260];
int cnt, n;
int main() {
gets_s(c);
n = strlen(c);
for (int i = 0; i < n; i++) {
//下部分使用isdigit函数
if (isdigit(c[i])) {
cnt++;
}
//下部分使用ASCII码对比
if (c[i] >= 48 && c[i] <= 57){
cnt++;
}
}
cout << cnt << endl;
return 0;
}
给定一个只包含小写字母的字符串,请你找到第一个仅出现一次的字符。如果没有,输出no input format: 一个字符串,length < 100000 output format: 输出第一个仅出现一次的字符,没有输出no input: abcabd output: c
int main() {
cin >> c;
n = strlen(c);
for (int i = 0; i < n; i++) {
a[c[i] - 97]++;
}
for (int i = 0; i < n; i++)
{
if (a[c[i] - 97] == 1) {
cout << c[i] << endl;
return 0;
}
}
cout << "no" << endl;
return 0;
}
4.10 字符串 string类
4.10.1 C++中的string类 ▲
C++标准库提供了string类类型,支持4.9 字符数组的所有操作,并且还增加了其他更多的功能。
1#include<iostream>
2#include<string>
3using namespace std;
4int main(){
5 string str1 = "Hello";
6 string str2 = "World";
7 string str3;
8
9 //复制str1到str3
10 str3 = str1;
11 cout << "str3 :" << str3 << endl;
12
13 //连接str1和str2
14 str3 = str1 + str2;
15 cout << "str1 + str2 :" << str3 << endl;
16
17 //连接后,str3的长度
18 int len = str3.size();
19 cout << str3.size() << len << endl;
20
21 return 0;
22}
4.10.2 string类几种常见的构造函数
C++中提供了专门的头文件string,来支持string类型。string类定义隐藏了字符串的数组性质,让我们可以像处理普通变量那样处理字符串。string对象和字符数组之间的主要区别是:可以将string对象声明为简单变量,而不是数组。
string(const char *s):将string对象初始化为s指向的字符串 string(size_type n, char c):创建一个包含n个元素的string对象,其中每个元素都被初始化为字符c string(const string &str):将一个string对象初始化为string对象str(复制构造函数) string():创建一个默认的string对象,长度为0(默认构造函数)
string类的设计允许程序自动处理string的大小,上述第四个代码创建了一个长度为0的对象,但是向str中写入数据时,程序会自动调整str的长度、因此,与使用数组相比,使用string对象更方便,也更安全
4.10.3 string的常见操作 ※
4.10.3.1 获取string对象的长度
在C语言中,使用strlen函数获取字符串的长度。在C++中,可以使用string.size()函数或string.length()函数来获得string对象的长度。这两个函数的实现完全一致,并没有区别,length()方法是C原因习惯保留的,而size()方法则是为了兼容STL容器而引入的。
string s = "abcde";
int len = s.size();
cout << len << endl;
4.10.3.2 复制string对象
在C语言中,使用strcpy,strncpy函数来实现字符串的复制。在C++中则方便很多,可以直接将一个string对象赋值给另一个string对象
string str1 = "Hello World!"
string str2 = str1;
cout << str1 << ' ' << str2 << endl;
无须担心长度溢出的情况,string会自行调整大小
4.10.3.3 string对象的拼接和附加
在C语言中,使用strcat、strncat函数来进行字符串拼接操作。在C++中可以使用“+”和“+=”实现拼接和附加操作。 1、使用 + 操作符拼接两个字符串
string str1("hello");
string str2("world!");
string str3 = str1 + str2;
cout << str3 << endl;
2、使用 += 操作符在字符串后面附加内容 可以使用 += 来在一个string对象后面附加一个string对象、字符以及C风格的字符串
string str1("hello");
string str2("world!\n");
str1 += str2;
str1 += "nice job\n";
str1 += 'a';
cout << str1 << endl;
3、使用string.append()函数 可以使用string.append()函数来在一个string对象后面附加一个string对象或C风格的字符串
string str1 = "hello,world!";
string str2 = "HELLO,WORLD!";
str1.append(str2);
cout << str1 <<endl;
str1.append("C string");
cout << str1 << endl;
4、使用string.push_back()函数 可以使string.push_back()函数来在一个string对象后面附加一个字符。
string str("Hello");
str.push_back("h"); //添加一个字符到str字符串后
cout << str << endl;
4.10.3.4 string对象的对比
在C语言中,使用strcmp、strncmp函数来进行字符串的比较。在C++中,由于将string对象声明为了简单变量,直接使用关系运算符(==、!=、<、<=、>、>=)即可
string str1("hello");
string str2("hello");
if (str1 == str2){
cout << "str1 = str2" << endl;
}
else if(str1 < str2){
cout << "str1 < str2" << endl;
}
else{
cout << "str1 > str2" << endl;
}
也可以使用类似strcmp的函数进行string对象的比较,string类提供的是string.compare()方法,函数原型如下(多态,详见OOP(面向对象编程)) int compare(const string& str) const; int compare(size_t pos, size_t len, const string& str) const; int compare(size_t pos, size_t len, const string& str, size_t subpos, size_t sublen) const; int compare(const char* s) const; int compare(size_t pos, size_t len, const char* s) const; int compare(size_t pos, size_t len, const char* s, size_t n) const;
compare方法的返回值如下: 1)返回0,表示相等; 2)返回结果小于0,表示比较字符串中第一个不匹配的字符比源字符串小,或者所有字符都匹配但是比较字符串比源字符串短; 3)返回结果大于0,表示比较字符串中第一个不匹配的字符比源字符串大,或者所有字符都匹配但是比较字符串比源字符串长。
string str1("aBcdef");
string str2("AbcdEf");
string str3("123456");
string str4("123dfg");
//下面是各种比较方法
int m = str1.compare(str2); //完整的1和2进行比较
int n = str1.compare(1, 5, str2); //"Bcdef"和"AbcdEf"比较
int p = str1.compare(1, 5, str2, 4, 2); //"Bcdef"和"Ef"比较
int q = str3.compare(0, 3, str4, 0, 3); //"123"和"123"比较
cout << m << ' ' << n << ' ' << p << ' ' << q << endl; //输出+ + - 0
4.3.10.5 string对象的查找操作
1、使用string.find()方法查找字符,其中npos代表-1,也就是不存在的位置
find方法的函数原型如下:
- 从字符串的pos位置开始(若找不到pos的值,则默认从索引0开始),查找子字符串str。如果找到,则返回该子字符串首次出现时其首字符的索引;否则,返回
string::npos size_type find(const string& str, size_type pos = 0) const; - 从字符串的pos位置开始(若不指定pos 的值,则默认从索引0处开始),查找子字符串s。如果找到,则返回该字符串首次出现时其首字符的索引;否则,返回
string::npos size_type find(const char *s, size_type pos = 0) const; - 从字符串的pos位置开始(若不指定pos的值,则默认从索引0处开始),查找s的前n个字符组成的子字符串。如果找到,则返回该子字符串首次出现时起首字符的索引;否则,返回
string::npos size_type find(const char *s, size_type pos, size_type n); - 从字符串的pos位置开始(若不指定pos的值,则默认从索引0处开始),查找字符ch。如果找到,则返回该字符首次出现的位置;否则,返回
string::npos size_type find(char ch, size_type pos = 0)const;
string str("cat,dog,cat,pig,little cat,hotdog,little pig,angry dog");
size_t catPos = str.find("cat",0);
if(catPos == string::npos){
printf("没有找到字符串\n");
return 0;
}
while(casPos != string::npos){
cout << "在索引" << catPos << "处找到字符串" <<endl;
catPos = str.find("cat", catPos + 1);
}
//以下为4种函数原型的用法
string s = "abc123 ghfhg";
int index = s1.find("123"); //1、2两种函数原型
cout << index << endl; //输出3
int n = s.find("123", 0, 2);
cout << n << endl; //输出3
string s1 = "abc12sda1123dfjsw";
int n1 = s1.find("123", 0, 2); //也就是寻找"12"字符串
cout << n1 <<endl; //输出3
int n2 = s1.find('c');
cout << n2 << endl; //输出2
从上述发现size_type pos参数不输入默认为0,string.rfind()只是查找顺序相反,也就是找到其出现的最后一次位置,这里就不再赘述。
2、string.find_first_of()
string.find_first_of()方法在字符串中从指定位置开始向后(默认从索引0处)查找参数中任何一个字符首次出现的位置。
string str("catlsfhiwaknf");
int pos = str.find_first_of("gat");
if(pos == string::npos){
printf("没有匹配到\n");
return 0;
}
else{
cout << "在索引" << pos << "处匹配到" << endl;
//程序输出的结果是:在索引1处匹配到
}
所查找的字符串gat中,第一次出现字符串str中的字符是'a',该字符在str中的索引是1.
3、string.find_last_of()
在字符串中查找参数中任何一个字符最后一次出现的位置(也就是从指定位置开始往前查找,第一个出现的位置)。
4、string.find_first_not_of()
在字符串中查找参数中第一个不包含在参数中的位置
5、string.find_last_not_of()
在字符串中查找参数中最后一个不包含在参数中的位置
string str = "abkd12c kdjf";
cout << str.find_first_of("jkn") << endl;
cout << str.find_last_of("jkn") << endl;
cout << str.find_first_not_of("jkn") << endl;
cout << str.find_last_not_of("jkn") << endl;
4.3.10.6 使用string.substr()函数来获取子串
string substr(size_t pos = 0, size_t len = npos)const; 其中,pos是子字符串的起始位置(索引,第一个字符的索引为0),len是子串的长度。这个函数的功能是:复制一个string对象中从pos处开始的len个字符到string对象substr中去,并返回str。
string str("Hello,World!");
string subStr = str.substr(3, 5);
cout << subStr << endl; //输出结果为:"lo,Wo".
4.3.10.7 访问string字符串的元素
可以像C语言中一样,将string对象当做一个数组,然后使用数组小标的方式来访问字符串中的元素;也可以使用string.at(index)的方式来访问元素(索引号从0开始)
string str("Hello,World!");
cout << str[1] << endl; //使用数组下标的方式访问string字符串的元素
cout << str.at(1) << endl; //使用at索引访问string字符串的元素
4.3.10.8 string对象的插入操作
使用string.insert()进行插入操作,函数原型如下 string &insert(size_t pos, const string &str); //在位置pos处插入字符串str string &insert(size_t pos, const string &str, size_t subpos, size_t sublen); //在位置pos处插入字符串str的从位置subpos处开始的sublen个字符 string &insert(size_t pos, const char* s) //在位置pos处插入字符串s; string &insert(size_t pos, const char* s, size_t n) //在位置pos处插入字符串s的前n个字符 string &insert(size_t pos, size_t n, char c); //在位置pos处插入n个字符c iterator insert(const_iterator p, size_t n, char c); //在p处插入n个字符c,并返回插入后迭代器的位置 iterator insert(const_iterator p, char c); //在p处插入字符c,并返回插入后迭代器的位置
其中const_iterator代表直接的位置,也就是用str.begin() //也就是从位置0插入
begin / end详见迭代器。
4.11 案例——点餐系统
1#include <iostream>
2
3using namespace std;
4
5int main() {
6 cout << "-----------------自助点餐系统-----------------" << endl;
7 cout << "菜单:" << endl;
8 cout << "1火锅 2回锅肉 3宫保鸡丁 4夫妻肺片 5毛血旺 6麻婆豆腐 7东坡肘子 8水煮牛肉" << endl;
9 cout << "9龙抄手 10钟水饺 11串串香 12肥肠粉 13担担面" << endl;
10 cout << "14可乐 15雪碧 16脉动 17果缤纷 18果粒橙 19营养快线" << endl;
11 cout << "套餐A(优惠10元)∶火锅 回锅肉 东坡肘子,任选其一" << endl;
12 cout << "龙抄手 钟水饺 串串香,任选其一" << endl;
13 cout << "可乐雪碧,任选其一" << endl;
14 cout << "套餐B(优惠12元)︰火锅 回锅肉 东坡肘子 水煮牛肉,任选其一" << endl;
15 cout << "肥肠粉 担担面,任选其一" << endl;
16 cout << "脉动 果缤纷 果粒橙,任选其一" << endl;
17 cout << "本店消费满100元,可加1元,换购一种饮料" << endl;
18
19 //选择单点 套餐 结账菜单变量
20 char menu;
21 int index;//接收编号
22
23 //菜名
24 string name[19] = { "火锅","回锅肉","宫保鸡丁","夫妻肺片","毛血旺","麻婆豆腐","东坡肘子","水煮牛肉","龙抄手","钟水饺","串串香","肥肠粉","担担面","可乐","雪碧","脉动","果缤纷","果粒橙","营养快线" };
25
26 //价格数组
27 int price[19] = { 30,20,15,45,21,34,22,23,31,16,18,19,11,9,13,10,9,8,6 };
28 //数量数组
29 int cnt1[19], cnt2[19];
30 memset(cnt1, 0, 19 * sizeof(int));
31 memset(cnt2, 0, 19 * sizeof(int));
32 //总价格、总优惠
33 int total = 0, offer = 0;
34
35 while (true) {
36 cout << "A单点 B套餐 C结账" << endl;
37 cin >> menu;
38 if (menu == 'A') {
39 cout << "输入编号点餐,输入0结束点餐" << endl;
40 while (1) {
41 cin >> index;
42 if (index == 0) {
43 break;
44 }
45 switch (index) {
46 case 1:
47 cnt1[0]++;
48 break;
49 case 2:
50 cnt1[1]++;
51 break;
52 case 3:
53 cnt1[2]++;
54 break;
55 case 4:
56 cnt1[3]++;
57 break;
58 case 5:
59 cnt1[4]++;
60 break;
61 case 6:
62 cnt1[5]++;
63 break;
64 case 7:
65 cnt1[6]++;
66 break;
67 case 8:
68 cnt1[7]++;
69 break;
70 case 9:
71 cnt1[8]++;
72 break;
73 case 10:
74 cnt1[9]++;
75 break;
76 case 11:
77 cnt1[10]++;
78 break;
79 case 12:
80 cnt1[11]++;
81 break;
82 case 13:
83 cnt1[12]++;
84 break;
85 case 14:
86 cnt1[13]++;
87 break;
88 case 15:
89 cnt1[14]++;
90 break;
91 case 16:
92 cnt1[15]++;
93 break;
94 case 17:
95 cnt1[16]++;
96 break;
97 case 18:
98 cnt1[17]++;
99 break;
100 case 19:
101 cnt1[18]++;
102 break;
103 }
104 }
105
106 total = 0;
107 for (int i = 0; i < 19; i++) {
108 if (cnt1[i] != 0) {
109 cout << name[i] << price[i] << "元,数量:" << cnt1[i] << " 小计:" << price[i] * cnt1[i] << "元" << endl;
110 total += price[i] * cnt1[i];
111 }
112 }
113 cout << "总计:" << total << "元,优惠:" << offer << "元" << endl;
114 }
115 else if (menu == 'B') {
116 while (true)
117 {
118 cout << "套餐A 套餐B (输入字母确定)" << endl;
119 cin >> menu;
120 if (menu == 'A') {
121 //套餐A
122 cout << "1火锅 2回锅肉 7东坡肘子" << endl;
123 cin >> index;
124 switch (index) {
125 case 1:
126 cnt2[0]++;
127 break;
128 case 2:
129 cnt2[1]++;
130 break;
131 case 7:
132 cnt2[6]++;
133 break;
134 }
135 cout << "9龙抄手 10钟水饺 11串串香" << endl;
136 cin >> index;
137 switch (index) {
138 case 9:
139 cnt2[8]++;
140 break;
141 case 10:
142 cnt2[9]++;
143 break;
144 case 11:
145 cnt2[10]++;
146 break;
147 }
148 cout << "14可乐 15雪碧" << endl;
149 cin >> index;
150 switch (index) {
151 case 14:
152 cnt2[13]++;
153 break;
154 case 15:
155 cnt2[14]++;
156 break;
157 }
158 break;
159 }
160 else if (menu == 'B') {
161 //套餐B
162 cout << "1火锅 2回锅肉 7东坡肘子 8水煮牛肉" << endl;
163 cin >> index;
164 switch (index) {
165 case 1:
166 cnt2[0]++;
167 break;
168 case 2:
169 cnt2[1]++;
170 break;
171 case 7:
172 cnt2[6]++;
173 break;
174 case 8:
175 cnt2[7]++;
176 break;
177 }
178 cout << "12肥肠粉 13担担面" << endl;
179 cin >> index;
180 switch (index) {
181 case 12:
182 cnt2[11]++;
183 break;
184 case 13:
185 cnt2[12]++;
186 break;
187 }
188 cout << "16脉动 17果缤纷 18果粒橙" << endl;
189 cin >> index;
190 switch (index) {
191 case 16:
192 cnt2[15]++;
193 break;
194 case 17:
195 cnt2[16]++;
196 break;
197 case 18:
198 cnt2[17]++;
199 break;
200 }
201 break;
202 }
203 else {
204 cout << "请输入正确的大写字母!!" << endl;
205 }
206 }
207 total = 0; // 清零是为了去掉之前点过单的值
208 for (int i = 0; i < 19; i++) {
209 if (cnt2[i] != 0) {
210 cout << name[i] << price[i] << "元,数量:" << cnt2[i] << " 小计:" << price[i] * cnt2[i] << "元" << endl;
211 total += price[i] * cnt2[i];
212 }
213 }
214 cout << "总计:" << total << "元,优惠:" << offer << "元" << endl;
215 }
216 else if (menu == 'C') {
217 //结账
218 if (total >= 100) {
219 cout << "总消费超过100元,请问是否加1元换购饮料(Y/N)" << endl;
220 cin >> menu;
221 if (menu == 'Y') {
222 total += 1;
223 cout << "14可乐 15雪碧 16脉动 17果缤纷 18果粒橙 19营养快线" << endl;
224 cin >> index;
225 switch (index)
226 {
227 case 14:
228 offer += price[13] - 1;
229 break;
230 case 15:
231 offer += price[14] - 1;
232 break;
233 case 16:
234 offer += price[15] - 1;
235 break;
236 case 17:
237 offer += price[16] - 1;
238 break;
239 case 18:
240 offer += price[17] - 1;
241 break;
242 case 19:
243 offer += price[18] - 1;
244 break;
245 }
246 }
247 }
248 cout << "您总共消费:" << total << "元,优惠了" << offer << "元" << endl;
249 break;
250 }
251 else {
252 cout << "请输入正确的大写字母!!" << endl;
253 }
254 }
255 cout << "--------------------欢迎下次光临--------------------" << endl;
256
257 return 0;
258}
4.12 二维数组 ※
4.12.1 概述
C++的数组是支持多维的,如果是二维数组,则数组中的每一个元素都是一个一维数组;如果是三维数组,那么每一个元素都是一个二维数组。
4.12.2 二维数组的声明与定义
C++的二维数组,也就是数组中的每一个元素都是一个一维数组。 type arrayName[row][col] //数据类型 数组名[行数][列数]
4.12.3 二维数组的初始化
1、可在声明之后再赋值进行初始化
2、声明时就进行初始化 int arrnum[2][2] = {{1,2},{3,4}} //推荐写法,可快速分清所表达数组
4.12.4 练习
output:{{1,0,0,0,0,1},{0,1,0,0,1,0},{0,0,1,1,0,0},{0,0,1,1,0,0},{0,1,0,0,1,0},{1,0,0,0,0,1}}
#include <iostream>
using namespace std;
int main(){
int arr[6][6];
for (int i = 0; i < 6; i++){
for(int j = 0; j < 6; j++){
if(i == j || i + j == 6){
arr[i][j] = 1;
}
else{
arr[i][j] = 0;
}
}
}
return 0;
}
4.12.5 二维字符数组
二维字符数组其实跟其他类型数组差不多,在初始化时可以被简化,可以看成多个一维字符数组组成了二位字符数组。
char arr[3][10] = {"Hello","world","C++"}; //每个字符串占一行 char arr[][10] = {"Hello","world","C++"} //同理,第二维的值不能被省略
4.12.6 练习
用1~100的随机数填充一个n行m列的整型数组(n和m均小于100),输出每行每列的和
input:(其中{1,2,3,4,5},{5,2,3,4,1},{6,7,8,1,2}为随机数生成,并非手动输入) 3 5 1 2 3 4 5 5 2 3 4 1 6 7 8 1 2
output: 15 15 24 12 11 14 9 8
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
int arr[100][100];
int row[100];
int col[100];
int main() {
int n, m, total = 0;
cin >> n >> m;
srand((unsigned)time(0));
//产生随机数
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
arr[i][j] = rand() % 100 + 1;
}
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
row[i] += arr[i][j];
col[j] += arr[i][j];
}
}
for (int i = 0; i < n; i++) {
cout << row[i] << " ";
}
cout << endl;
for (int i = 0; i < m; i++) {
cout << col[i] << " ";
}
return 0;
}
计算矩阵边缘之和:输入一个整数矩阵,计算位于矩阵边缘的元素之和。所谓矩阵边缘的元素,就是第一行和最后一行的元素以及第一列和最后一列的元素,输入第一行分别为矩阵的行数m和列数n(m < 100, n < 100),两者之间以一个空格分开。 接下来输入的m行数据中,每行包含n个整数,整数之间以一个空格分开。输出对应矩阵的边缘元素之和
input: 3 3 3 4 1 3 7 1 2 0 1
output: 15
1#include <iostream>
2using namespace std;
3int arr[100][100];
4int main() {
5 int n, m, total = 0;
6 cin >> n >> m;
7 for (int i = 0; i < n; i++) {
8 for (int j = 0; j < m; j++) {
9 cin >> arr[i][j];
10 }
11 }
12 for (int i = 0; i < n; i++) {
13 for (int j = 0; j < m; j++) {
14 if (i == 0 || j == 0 || i == n - 1 || j == m - 1) {
15 total += arr[i][j];
16 }
17 }
18 }
19 cout << total << endl;
20 return 0;
21}
对字符串中的所有单词进行倒排。构成单词的字符只有26个大写或小写英文字母,单词与单词间用空格隔开,要求倒排后的单词间隔符以一个空格表示,每个单词最长20个字母。 数据范围:字符串长度不超过100 input: this is c plus plus output:plus plus c is this
#include <iostream>
#include <cstring>
using namespace std;
char c[100][20];
int main() {
int i = 1;
while (cin >> c[i++]);
i--;
while (--i >= 1) {
cout << c[i] << " ";
}
return 0;
}
4.13 应用——迷宫
用o表示人物,通过键盘控制人物通过迷宫入口走到迷宫出口,输入wasd来进行↑←↓→操作
1#include <iostream>
2using namespace std;
3
4char map[10][21] = {
5 {"##################o#"},
6 {"# ############# #"},
7 {"# ## ########### #"},
8 {"# ## ## ###"},
9 {"# ######### #"},
10 {"# ##################"},
11 {"# ## ##########"},
12 {"# #######"},
13 {"############ ##"},
14 {"################# ##"}
15};
16
17
18void showMap();
19void showMenu();
20char direction; //存储接收到的方向字符
21void move();
22bool isSuccess();
23
24bool gameover = 0;//游戏结束的标记
25int currentpr = 0, currentpc = 18;
26int newpr = currentpr, newpc = currentpc;
27
28int main() {
29
30 while (!gameover) {
31 system("cls");//清屏
32 showMap();
33 showMenu();
34 if (isSuccess()) {
35 cout << "恭喜你,通关了!" << endl;
36 return 0;
37 }
38 cin >> direction;
39 switch (direction)
40 {
41 case 'w':
42 newpr--;
43 break;
44 case 'a':
45 newpc--;
46 break;
47 case 's':
48 newpr++;
49 break;
50 case 'd':
51 newpc++;
52 break;
53 case 'q':
54 cout << "你确定要退出吗?(Y/N)";
55 cin >> direction;
56 if (direction == 'Y') {
57 gameover = 1;
58 }
59 }
60 move();
61 }
62 return 0;
63}
64
65void showMap() {
66 for (int i = 0; i < 10; i++) {
67 cout << map[i] << endl;
68 }
69}
70
71void showMenu() {
72 cout << "↑:w ←:a ↓:s →:d exit:q" << endl;
73 cout << "请输入方向字符:" << endl;
74}
75
76void move() {
77 if (map[newpr][newpc] == ' ') {
78 map[newpr][newpc] = 'o';
79 map[currentpr][currentpc] = ' ';
80 currentpr = newpr;
81 currentpc = newpc;
82 }
83 //当撞墙时,回退到移动前的位置
84 else {
85 newpr = currentpr;
86 newpc = currentpc;
87 }
88}
89
90bool isSuccess() {
91 if (map[9][17] == 'o') {
92 return 1;
93 }
94 else {
95 return 0;
96 }
97}