第4章-数组
一、一维数组
1、 一维数组的创建和初始化
数组是一组相同类型元素的集合
(1)数组的创建
//语法形式 type_t arr_name[const_n]; //type_t 是指数组的元素类型 //const_n 是一个常量表达式,用来指定数组的大小
#include<stdio.h> int main() { //创建一个数组 int arr[10];//存放10个整型 char arr2[5]; int count = 10; int arr2[count];//数组不可以正常创建,存放的是变量,数组自能存放常量 char arr3[10]; float arr4[1]; double arr5[20]; return 0; }
注:数组创建,[ ]中要给一个常量才可以,不能使用变量。
(2)数组的初始化
数组的初始化是指,在创建数组的同时给数组的内容一些合理初始值(初始化)
#include<stdio.h> #include<string.h> int main() { int arr1[10] = {1,2,3}; //不完全初始化,初始化前三位,剩下元素默认初始化为0 char ch2[5] = {'a','b'};//字符初始化 ab000 char ch3[5] = "ab";//a b (无'\0'后为乱码) char arr4[] = "abcdef"; printf("%d\n", sizeof(arr4));//7 //sizeof计算arr所占空间的大小,单位是字节--操作符 printf("%d\n", strlen(arr4));//6 //strlen是求字符串的长度,即'\0'前字符个数--库函数-使用需要头文件 //sizeof和strlen没有关联 return 0; }
2、一维数组的使用
[ ]--下标引用操作符,数组访问的操作符
数组下标从0开始。
#include<stdio.h> int main() { int arr[] = { 1,2,3,4,5,6,7,8,9,0 }; int sz = sizeof(arr)/sizeof(arr[0]); int i = 0; for (i=0;i<sz;i++) { printf("%d",arr[i]); } return 0; }
#include<stdio.h> #include<string.h> int main() { char arr[] = "abcdef";//[a][b][c][d][e][f][\0] int i = 0; int len = strlen(arr); for (i = 0; i <len; i++) //for (i = 0; i < 6; i++) { printf("%c", arr[i]); } //printf("%c\n", arr[3]); return 0; }
3、一维数组在内存中的存储
数组在内存中是连续存放的
随着数组下标的增长,元素的地址由低到高变化,有规律的递增。
#include<stdio.h> int main() { int arr[] = { 1,2,3,4,5,6,7,8,9,10 }; int sz = sizeof(arr) / sizeof(arr[0]); int i = 0; for (i = 0; i < sz; i++) { printf("&arr[%d] = %p\n", i, &arr[i]); } return 0; }
#include <stdio.h> int main() { int arr[10] = { 1,2,3,4,5,6,7,8,9,10 }; int*p = arr;//数组名是数组首元素的地址 int i = 0; for (i = 0; i < 10; i++) { printf("%d ", *p); p++; } return 0; }
二、二维数组
1、二维数组的创建和初始化
(1)二维数组的创建
#include<stdio.h> int main() { int arr[3][4]; //3*4,即3行4列的二维数值 char arr[5][6]; return 0; }
(2)二维数组的初始化
初始化 ,即创建的同时给赋值
#include<stdio.h> int main() { int arr[3][4] = { 1,2,3,4 }; //初始化 - 创建的同时给赋值 int arr[3][4] = { 1,2,3,4,5,6,7}; //不完全初始化 - 后面补0 int arr[3][4] = { {1,2},{4,5} }; //{1,2}放一行,{4,5}放一行 int arr[][4] = { {2,3},{4,5} }; //二维数组有初始化,行可以省略,列不能省略 return 0; }
2、 二维数组的使用
#include<stdio.h> int main() { int arr[3][4] = { {1,2,3},{4,5} }; int i = 0; for (i = 0; i <3; i++) { int j = 0; for (j = 0; j < 4; j++) { printf("%d",arr[i][j]); } printf("\n"); } return 0; }
3、二维数组在内存中的存储
#include<stdio.h> int main() { int arr[3][4] = { {1,2,3},{4,5} }; //存储位置 //1 2 3 0 //4 5 0 0 //0 0 0 0 //下标 // 0 1 2 3 //0 //1 //2 int i = 0; for (i = 0; i < 3; i++) { int j = 0; for (j = 0; j < 4; j++) { printf("&arr[%d][%d]=%p\n", i, j, &arr[i][j]); } printf("\n"); } return 0; }
二维数组在内存中也是连续存储的
4. 数组作为函数参数
(1)冒泡排序函数
冒泡排序——升序
两两相邻进行比较,满足条件进行交换
- 一趟冒泡排序
- 9 8 7 6 5 4 3 2 1 0
- 8 9 7 6 5 4 3 2 1 0
- 8 7 9 6 5 4 3 2 1 0
- ...
- 8 7 6 5 4 3 2 1 0 9
10个元素9趟冒泡排序
一趟进行9次
//错误思路 #include <stdio.h> void bubble_sort(int arr[], int sz)//形参arr本质是指针 { //计算数组元素个数 int sz = sizeof(arr) / sizeof(arr[0]); //确定趟数 int i = 0; for (i = 0; i < sz - 1; i++) { //一趟冒泡排序的过程 int j = 0; for (j = 0; j < sz-1-i; j++) { if (arr[j] > arr[j + 1]) { //交换 int tmp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = tmp; } } } } int main() { int arr[] = { 9,8,7,6,5,4,3,2,1,0 }; bubble_sort(arr, sz);//数组传参的时候,传递的其实是数组首元素的地址 return 0; }
修改
#include<stdio.h> void bubble_sort(int arr[], int sz) { int i = 0; for (i = 0; i < sz - 1; i++) { int j = 0; for (j = 0; j < sz-1-i; j++) { if (arr[j] > arr[j + 1]) { int tmp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = tmp; } } } } int main() { int arr[] = { 9,8,7,6,5,4,3,2,1,0 }; int i = 0; int sz = sizeof(arr) / sizeof(arr[0]); //对arr数值进行传参,传递的数值arr首元素地址,即&arr[] bubble_sort(arr,sz); for (i = 0; i < sz; i++) { printf(" %d", arr[i]); } return 0; }
(2)优化
#include<stdio.h> void bubble_sort(int arr[], int sz) { int i = 0; for (i = 0; i < sz - 1; i++) { int flag = 1; //假设有序 int j = 0; for (j = 0; j < sz - 1 - i; j++) { if (arr[j] > arr[j + 1]) { int tmp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = tmp; flag = 0; //本趟排序不完全有序 } } if (flag == 1) { break; } } } int main() { int arr[] = { 9,8,7,6,5,4,3,2,1,0 }; int i = 0; int sz = sizeof(arr) / sizeof(arr[0]); bubble_sort(arr, sz); for (i = 0; i < sz; i++) { printf(" %d", arr[i]); } return 0; }
(5)数组名
1. sizeof(数组名),计算整个数组的大小,sizeof内部单独放一个数组名,数组名表示整个数组,单位是字节。
2. &数组名,取出的是数组的地址,数组名表示整个数组。
除此1,2两种情况之外,所有的数组名都表示数组首元素的地址。
#include <stdio.h> int main() { int arr[10] = { 1,2,3,4,5 }; printf("%p\n", arr);//打印第一个元素地址 printf("%p\n", &arr[0]);//首元素地址,下标为0的元素 printf("%d\n", *arr);//1 printf("%p\n", &arr);//数组的地址,指整个数组 return 0; }
三、数组的应用实例
1. 三子棋
头文件game.h
#pragma once //头文件的包含 #include <stdio.h> #include <stdlib.h> #include <time.h> //符号的定义 #define ROW 3 #define COL 3 //函数的声明 //初始化棋盘的 void InitBoard(char board[ROW][COL], int row, int col); //打印棋盘的函数 void DisplayBoard(char board[ROW][COL], int row, int col); //玩家下棋 void PlayerMove(char board[ROW][COL], int row, int col); //电脑下棋 void ComputerMove(char board[ROW][COL], int row, int col); // //1. 玩家赢了 - * //2. 电脑赢了 - # //3. 平局 - Q //4. 游戏继续 - C //判断游戏是否有输赢 char IsWin(char board[ROW][COL], int row, int col);
源文件game.c
#define _CRT_SECURE_NO_WARNINGS 1 #include "game.h" //初始化为空格 void InitBoard(char board[ROW][COL], int row, int col) { int i = 0; int j = 0; for (i = 0; i < row; i++) { for (j = 0; j < col; j++) { board[i][j] = ' '; } } } ////通过更改棋盘,行的隔数固定,只能打印3*3 //void DisplayBoard(char board[ROW][COL], int row, int col) //{ // int i = 0; // for (i = 0; i < row; i++) // { // printf(" %c | %c | %c \n", board[i][0], board[i][1], board[i][2]); // if(i<row-1)//减少一行分割 // printf("---|---|---\n"); // } //} void DisplayBoard(char board[ROW][COL], int row, int col) { int i = 0; for (i = 0; i < row; i++) { int j = 0; for (j = 0; j < col; j++) { printf(" %c ", board[i][j]); if(j<col-1) printf("|"); } printf("\n"); if (i < row - 1) { int j = 0; for (j = 0; j < col; j++) { printf("---"); if(j<col-1) printf("|"); } printf("\n"); } } } void PlayerMove(char board[][COL], int row, int col) { int x = 0; int y = 0; printf("玩家走:>\n"); while (1) { printf("请输入下棋的坐标:>"); scanf("%d %d", &x, &y); //判断坐标合法性 if (x >= 1 && x <= row && y >= 1 && y <= col) { //下棋 //坐标是否被占用 if (board[x - 1][y - 1] == ' ') { board[x - 1][y - 1] = '*'; break; } else { printf("坐标被占用, 请重新输入\n"); } } else { printf("坐标非法, 请重新输入\n"); } } } void ComputerMove(char board[ROW][COL], int row, int col) { printf("电脑走:>\n"); while (1) { int x = rand() % row; int y = rand() % col; //判断占用 if (board[x][y] == ' ') { board[x][y] = '#'; break; } } } int IsFull(char board[ROW][COL], int row, int col) { int i = 0; int j = 0; for (i = 0; i < row; i++) { for (j = 0; j < col; j++) { if (board[i][j] == ' ') { return 0;//棋盘没满 } } } return 1;//棋盘满了 } char IsWin(char board[ROW][COL], int row, int col) { int i = 0; //判断三行 for (i = 0; i < row; i++) { if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][1] != ' ') { return board[i][1];// } } //判断三列 for (i = 0; i < col; i++) { if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[1][i] != ' ') { return board[1][i]; } } //判断对角线 if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ') { return board[1][1]; } if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ') { return board[1][1]; } //判断平局 //如果棋盘满了返回1, 不满返回0 int ret = IsFull(board, row, col); if (ret == 1) { return 'Q'; } //继续 return 'C'; }
test.c
#define _CRT_SECURE_NO_WARNINGS #include "game.h" void menu() { printf("******************************\n"); printf("****** 1. play *****\n"); printf("****** 0. exit *****\n"); printf("******************************\n"); } void game() { //存储数据 - 二维数组 char board[ROW][COL]; //初始化棋盘 - 初始化空格 InitBoard(board, ROW, COL); //打印一下棋盘 - 本质是打印数组的内容 DisplayBoard(board, ROW, COL); char ret = 0;//接受游戏状态 while (1) { //玩家下棋 PlayerMove(board, ROW, COL); DisplayBoard(board, ROW, COL); //判断玩家是否赢得游戏 ret = IsWin(board, ROW, COL); if (ret != 'C') break; //电脑下棋 ComputerMove(board, ROW, COL); DisplayBoard(board, ROW, COL); //判断电脑是否赢得游戏 ret = IsWin(board, ROW, COL); if (ret != 'C') break; } if (ret == '*') { printf("玩家赢了\n"); } else if(ret == '#') { printf("电脑赢了\n"); } else { printf("平局\n"); } DisplayBoard(board, ROW, COL); } int main() { int input = 0; srand((unsigned int)time(NULL)); do { menu(); printf("请选择:>"); scanf("%d", &input); switch (input) { case 1: game(); break; case 0: printf("退出游戏\n"); break; default: printf("选择错误,重新选择\n"); break; } } while (input); //选择错误选项,跳出do while,跳转到这里,从新进入do while return 0; }

浙公网安备 33010602011771号