一、一维数组的创建和初始化
1、什么是数组:
数组是一组相同类型元素的集合。
2、数组的创建方式:
type_t arr_name [const_n];
//type_t 是指数组的元素类型
//const_n 是一个常量表达式,用来指定数组的大小。
//数组创建实例:
//代码1
int arr1[10];
//代码2
int count = 10;
int arr2[count];
//代码3
char arr3[10];
float arr4[20];
double arr5[30];
?注:数组的创建,?[] 中要给一个常量才可以,不能使用变量。
3、数组的初始化:
数组的初始化是指,在创建数组的同时给数组的内容一些合理初始值(初始化)。
#include <stdio.h>
#include <string.h>
int main()
{
int arr1[10] = {1,2,3};//不完全初始化,剩下的元素默认初始化为0
char arr2[5] = {'a', 'b'};//'a','b','0','0','0'
char arr3[5] = "ab";//'a','b','\0','0','0'
char arr4[] = "abcdef";//'a','b','c','d','e','f','\0'
printf("%d\n",sizeof(arr4));
printf("%d\n",strlen(arr4));
return 0;
}
程序运行结果:
??strlen和sizeof的区别:
①strlen是求字符串的长度,它只能是针对字符串长度。strlen是库函数,使用时必须使用头文件。 ②sizeof用于计算变量,数组、类型的大小。单位是字节,sizeof是操作符。
二、一维数组的使用
对于数组的使用我们之前介绍了一个操作符: [] ,下标引用操作符。它其实就数组访问的操作符。
#include <stdio.h>
#include <string.h>
int main()
{
char arr[] = "abcdef";
int i = 0;
for(i = 0;i<strlen(arr);i++)
{
printf("%c ",arr[i]);
}
printf("\n");
int arr1[] = {1,2,3,4,5,6,7,8,9,10};
int sz =sizeof(arr1)/sizeof(arr1[0]);
int j = 0;
for(j = 0;j<sz;j++)
{
printf("%d ",arr1[j]);
}
return 0;
}
?程序运行结果:
总结: ① 数组是使用下标来访问的,下标是从0开始。 ② 数组的大小可以通过计算得到。
三、一维数组在内存中的存储
通过编写程序获得一个数组在内存中的地址。
#include <stdio.h>
int main()
{
int arr[] = {1,2,3,4,5,6,7,8,9,10};
int i;
int sz = sizeof(arr)/sizeof(arr[0]);
for(i =0;i<sz;i++)
{
printf("arr[%d] = %p\n",i,&arr[i]);
}
return 0;
}
? 程序运行结果:
仔细观察输出的结果,我们知道,随着数组下标的增长,元素的地址,也在有规律的递增。 由此可以得出结论:数组在内存中是连续存放的。
四、 二维数组的创建,初始化和使用
1、二维数组的创建:
//数组创建
int arr1[3][4];
char arr2[3][4];
double arr3[3][4];
float arr4[3][4];
?2、二维数组的初始化:
//二维数组的初始化
int arr[3][4] = {1,2,3,4};
int arr[3][4] = {{1,2},{3,4}};
int arr[][4] = {{2,3},{4,5}};
?3、二维数组的使用:
二维数组的使用也是通过下标的方式。
#include <stdio.h>
int main()
{
int arr[3][4] = {1,2,3,4,5,6,7,8};//三行四列数组
int i = 0,j = 0;
for(i = 0;i<3;i++)
{
for(j = 0;j<4;j++)
{
printf("arr[%d][%d] = %d\t",i,j,arr[i][j]);
}
printf("\n");
}
return 0;
}
?程序运行结果:
?五、二维数组在内存中的存储
打印二维数组的每个元素。
#include <stdio.h>
int main()
{
int arr[3][4] = {1,2,3,4,5,6,7,8};//三行四列数组
int i = 0,j = 0;
for(i = 0;i<3;i++)
{
for(j = 0;j<4;j++)
{
printf("arr[%d][%d] = %d\t",i,j,arr[i][j]);
}
printf("\n");
}
for(i = 0;i<3;i++)
{
for(j = 0;j<4;j++)
{
printf("arr[%d][%d] = %p\t",i,j,&arr[i][j]);
}
printf("\n");
}
return 0;
}
?程序运行结果:
?通过结果我们可以分析到,其实二维数组在内存中也是连续存储的。
?六、数组越界
数组的下标是有范围限制的。 数组的下规定是从0开始的,如果输入有n个元素,最后一个元素的下标就是n-1。 所以数组的下标如果小于0,或者大于n-1,就是数组越界访问了,超出了数组合法空间的访问。 C语言本身是不做数组下标的越界检查,编译器也不一定报错,但是编译器不报错,并不意味着程序就 是正确的,所以程序员写代码时,最好自己做越界的检查。
八、数组作为函数参数
往往我们在写代码的时候,会将数组作为参数传个函数。
比如:我要实现一个冒泡排序函数将一个整形数组排序。
//冒泡排序
#include <stdio.h>
int bubble_sort(int arr[],int sz)
{
//确定冒泡排序的趟数
int i = 0;
for(i = 0;i<sz-1;i++)
{
//每一趟冒泡排序
int j = 0;
for(j = 0;j<sz-i;j++)
{
if(arr[j] > arr[j+1])
{
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
return arr;
}
int main()
{
int arr[] = {5,7,3,9,1,4,8,2,6};
int sz = sizeof(arr)/sizeof(arr[0]);
//对数组arr进行升序排列
bubble_sort(arr,sz);//冒泡排序函数
int i = 0;
for(i = 0;i<sz;i++)
{
printf("%d ",arr[i]);
}
return 0;
}
程序运行结果:
?优化:
//冒泡排序
#include <stdio.h>
int 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-i;j++)
{
if(arr[j] > arr[j+1])
{
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
flag = 0;
}
}
if(flag == 1)
{
break;
}
}
return arr;
}
int main()
{
int arr[] = {5,7,3,9,1,4,8,2,6};
int sz = sizeof(arr)/sizeof(arr[0]);
//对数组arr进行升序排列
bubble_sort(arr,sz);//冒泡排序函数
int i = 0;
for(i = 0;i<sz;i++)
{
printf("%d ",arr[i]);
}
return 0;
}
程序运行结果:
?数组名是什么?
数组名是数组首元素的地址。(有两个例外:?sizeof(数组名),&数组名)
//数组名
#include <stdio.h>
int main()
{
int arr[10] = {1,2,3,4,5};
printf("%p\n",arr);
printf("%p\n",&arr[0]);
printf("%d\n",*arr);//对数组名解引用,看结果是否是arr的首元素
printf("%d\n",sizeof(arr));//sizeof内部单独放一个数组名,数组名表示整个数组。
printf("%p\n",&arr);//取出的是整个数组的地址。&数组名,数组名表示整个数组。
return 0;
}
程序运行结果:
1. sizeof(数组名),计算整个数组的大小,sizeof内部单独放一个数组名,数组名表示整个数组。 2. &数组名,取出的是数组的地址。&数组名,数组名表示整个数组。
arr+1表示第二个元素的地址,等效于arr[0]+1;而&arr+1表示arr最后一个元素后接着的那个地址,arr+1表示跳过整个数组,得到整个数组结束后所接着的地址。
九、数组的应用实例1:三子棋
三子棋游戏程序代码:
//三子棋游戏
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define ROW 3
#define COL 3
void menu()
{
printf("------------------------------\n");
printf("----------1.开始游戏----------\n");
printf("----------2.退 出----------\n");
printf("------------------------------\n");
return 0;
}
//初始化棋盘
void InitBoard(char board[ROW][COL],int row,int col)
{
int i = 0,j = 0;
for(i = 0;i<row;i++)
{
for(j = 0;j<col;j++)
{
board[i][j] = ' ';//将数组内的每个元素改写为空格
}
}
return 0;
}
//打印棋盘
void Display(char board[ROW][COL],int row,int col)
{
int i = 0,j = 0;
for(i = 0;i<row;i++)
{
//打印数组行数据
for(j = 0;j<col;j++)
{
if(j<col-1)
{
printf(" %c |",board[i][j]);
}
else
{
printf(" %c \n",board[i][j]);
}
}
//打印分割行
if(i<row-1)
{
int n;
for(n = 0;n<row;n++)
{
if(n<row-1)
{
printf("---|");
}
else
{
printf("---\n");
}
}
}
}
return 0;
}
void Player(char board[ROW][COL],int row,int col)
{
int x = 0,y = 0;
printf("玩家:\n");
printf("请输入棋子的坐标:");
again:
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] = '*';
}
else
{
printf("该坐标已被占用!请重新输入:");
goto again;
}
}
else
{
printf("您输入的坐标超出棋盘,请重新输入:");
goto again;
}
return 0;
}
Computer(char board[ROW][COL],int row,int col)
{
int x = 0,y = 0;
printf("电脑:\n");
while(1)
{
x = rand()%row;
y = rand()%row;
if(board[x][y] == ' ')
{
board[x][y] = '#';
break;
}
}
return 0;
}
int IsFull(char board[ROW][COL],int row,int col)
{
int i= 0,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;
//玩家赢或者电脑赢
for(i = 0;i<row;i++)
{
//横三行
if(board[i][0] == board[i][1] && board[i][0] == board[i][2] && board[i][0] != ' ')
{
return board[i][0];
}
//竖三列
else if(board[0][i] == board[1][i] && board[0][i] == board[2][i] && board[0][i] != ' ')
{
return board[0][i];
}
//对角线
else if((board[1][1] == board[0][0] && board[1][1] == board[2][2] && board[1][1] != ' ') || (board[1][1] == board[0][2] && board[1][1] == board[2][0] && board[1][1] != ' '))
{
return board[1][1];
}
}
//平局
if(1 == IsFull(board,ROW,COL))
{
return 'Q';
}
//继续
return 'C';
}
//启动游戏
void game()
{
//定义一个数组存放玩家出棋的数据
char board[ROW][COL] = {0};
//初始化棋盘
InitBoard(board,ROW,COL);
//打印棋盘
Display(board,ROW,COL);
//下棋
while(1)
{
//玩家
Player(board,ROW,COL);
//打印棋盘
Display(board,ROW,COL);
//判断谁赢了
if(IsWin(board,ROW,COL) == '*')
{
printf("恭喜你,你赢了!\n");
break;
}
else if(IsWin(board,ROW,COL) == 'Q')
{
printf("平局!\n");
break;
}
//电脑
Computer(board,ROW,COL);
//打印棋盘
Display(board,ROW,COL);
if(IsWin(board,ROW,COL) == '#')
{
printf("很遗憾,你输了!\n");
break;
}
// else if(IsWin(board,ROW,COL) == 'Q')
// {
// printf("平局!\n");
// break;
// }
}
return 0;
}
void test()
{
int input = 0;
srand((unsigned int)time(NULL));
do
{
menu();
printf("请选择;");
scanf("%d",&input);
switch(input)
{
case 1:
printf("游戏开始\n");
game();//调用game函数,启动游戏
break;
case 2:
printf("退出游戏\n");
input = 0;
break;
default:
printf("输入有误,请重新输入!\n");
break;
}
}while(input);
return 0;
}
int main()
{
test();
return 0;
}
程序运行结果:
十、数组的应用实例2:扫雷游戏
|