第五章 数组

赤壁矶头千古浪,铜鞮陌上三更月。

定义一个数组

定义一个数组

long numbers[10];

方括号里面要有明确的数

数组在内存中的组织方式:

下面看一个例子:

1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>
int main(){

int data[5];
int i;
for(i = 0; i < 5; i++){
data[i] = 12 * (i + 1);
printf("data[%d] Address: %p Content: %d\n", i, &data[i], data[i] );
}

return 0;
}

首先,有一个问题,在for循环中定义i的时候会报错,例如:

for(int i = 0; i < 5; i++)

要想这么写的话要使用C99或者C11标准,得使用命令-std=c99 告诉编译器是使用的C99标准

寻址运算符

& 用于取一个变量的地址

下面的程序输出一些变量的地址:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <stdio.h>

int main(){

long a = 1L;
long b = 2L;
long c = 3L;

double d = 4.0;
double e = 5.0;
double f = 6.0;

printf("A variable of type long occupies %u bytes.", sizeof(long));
printf("\nHere are the address of some variable of type long:");
printf("\nThe address of a is: %p The address of b is: %p", &a, &b);
printf("\nThe address of c is: %p", &c);

printf("\n\nA variable of type double occupies %u bytes.", sizeof(double));
printf("\nHere are the address of some variable of type double:");
printf("\nThe address of d is: %p The address of e is: %p", &d, &e);
printf("\nThe address of f is: %p\n", &f);
return 0;
}

输出如下:

A variable of type long occupies 4 bytes.
Heere are the address of some variable of type long:
The address of a is: 000000000062FE1C The address of b is: 000000000062FE18
The address of c is: 000000000062FE14

A variable of type double occupies 8 bytes.
Here are the address of some variable of type double:
The address of d is: 000000000062FE08 The address of e is: 000000000062FE00
The address of f is: 000000000062FDF8

变量在内存中的地址如下:

在变量d和c的地址之间有一个空隙。为什么?许多编译器给变量分配内存地址的时候,其地址都是变量字节数的倍数,所以4字节变量的地址是4的倍数,8字节变量的地址是8的倍数,这就确保内存的访问是最高效的

数组的初始化

下面给出了包含5个元素的数组,并给出了初始值

double values[5] = {1.5, 2.5, 3.5, 4.5, 5.5};

如果初始化的值小于的个数小于数组中元素的数量,则初始化前面的元素:

double values[5] = {1.5, 2.5, 3.5};

数组中的前三个值为 1.5, 2.5, 3.5 其余的值为0;

如果不对数组进行初始化,那么会输出什么呢?

double values[5];

如果不进行初始化,那么编译器会把数组变量初始化为0;

在对数组进行初始化的时候也可以不指定元素的个数,编译器会自动推断出数组的个数

int primers[] = {1, 2, 3, 4, 5, 6, 7}

确定数组的大小

在有些场景下,我们需要知道一个数组的大小,那么如何确定一个数组的大小呢?

使用sizeof()方法

double values[5] = {1.5, 2.5, 3.5, 4.5, 5.5};

size_t element_count = sizeof(values)/sizeof(values[0]);

sizeof() 方法返回的是 size_t 类型的数据

size_t 是一个整数类型,类似于 int long.

多维数组

同一维数组类似

float numbers[3][5];

多维数组在内存中的组织方式:

更多维的数组也是如此,原理和定义方法都是一样的。

井字游戏

自己写的代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#include <stdio.h>
int main (){

int player = 0;
int winer = 0;

int choice = 0;
unsigned int row = 0;
unsigned int column = 0;

char board[3][3] = {{'1', '2', '3'},{'4', '5', '6'}, {'7', '8', '9'}};

unsigned int i;
for(i = 0; i < 9 && winer == 0; ++i){
printf("\n");
printf(" %c | %c | %c\n", board[0][0], board[0][1], board[0][2]);
printf("---+---+---\n");
printf(" %c | %c | %c\n", board[1][0], board[1][1], board[1][2]);
printf("---+---+---\n");
printf(" %c | %c | %c\n", board[2][0], board[2][1], board[2][2]);

player = i%2 +1; //select player

printf("请player%d选择一个下子的位置:\n", player);
scanf("%d", &choice);

//获取输之后,首先判断输入是否合理
//输入的字符应该是1-9,而且该位置不能是已经被落子了
while(choice > 9 || choice < 1 || board[(choice-1)/3][(choice-1)%3] == 'X' || board[(choice-1)/3][(choice-1)%3] == 'O'){
printf("你输入的位置不正确,请重新输入:\n");
scanf("%d", &choice);
}

//现在choice是正确的位置,只需要修改棋盘的值即可
board[(choice-1)/3][(choice-1)%3] = player == 1 ? 'X' : 'O' ;
printf("player%d落子成功!\n\n", player);

//落子后判断是否赢了,如果赢了就结束比赛
//判断当落子行和列
if(board[(choice-1)/3][0] == board[(choice-1)/3][1] && board[(choice-1)/3][0] == board[(choice-1)/3][2]){
printf("比赛结束! player%d 赢得了比赛!", player);
break;
}
if(board[0][(choice-1)%3] == board[1][(choice-1)%3] && board[0][(choice-1)%3] == board[2][(choice-1)%3]){
printf("比赛结束! player%d 赢得了比赛!", player);
break;
}
//判断斜着的行和列
if(board[0][0] == board[1][1] && board[0][0] == board[2][2]){
printf("比赛结束! player%d 赢得了比赛!", player);
break;
}
if(board[2][0] == board[1][1] && board[2][0] == board[0][2]){
printf("比赛结束! player%d 赢得了比赛!", player);
break;
}
}

printf("\n");
printf(" %c | %c | %c\n", board[0][0], board[0][1], board[0][2]);
printf("---+---+---\n");
printf(" %c | %c | %c\n", board[1][0], board[1][1], board[1][2]);
printf("---+---+---\n");
printf(" %c | %c | %c\n", board[2][0], board[2][1], board[2][2]);

if(i == 9){
printf("\n\n和局,请再来一局!");
}
return 0;
}

这个程序有一个问题就是当输入的choice为一个字母的时候,while循环会一直循环不停止

……

书上的代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#include <stdio.h>

int main(){

int player = 0;
int winner = 0;
int choice = 0;
unsigned int row = 0;
unsigned int column = 0;
char board[3][3] = {{'1', '2', '3'},{'4', '5', '6'}, {'7', '8', '9'}};

unsigned int i;
for(i = 0; i < 9 && winner ==0; ++i){
printf("\n");
printf(" %c | %c | %c\n", board[0][0], board[0][1], board[0][2]);
printf("---+---+---\n");
printf(" %c | %c | %c\n", board[1][0], board[1][1], board[1][2]);
printf("---+---+---\n");
printf(" %c | %c | %c\n", board[2][0], board[2][1], board[2][2]);

player = i%2 +1; //select player

do{
printf("Player %d, Please enter a valid square number "
"for where you want to place your %c:",
player, (player == 1) ? 'X' : 'O'
);
scanf("%d", &choice);
row = --choice/3;
column = choice % 3;
}while(choice < 0 || choice > 8 || board[row][column] > '9');

board[row][column] = (player == 1) ? 'X' : 'O';
//落子后判断是否赢了,如果赢了就结束比赛
//判断当落子行和列
if(board[row][0] == board[row][1] && board[row][0] == board[row][2]){
printf("比赛结束! player%d 赢得了比赛!", player);
break;
}
if(board[0][column] == board[1][column] && board[0][column] == board[2][column]){
printf("比赛结束! player%d 赢得了比赛!", player);
break;
}
//判断斜着的行和列
if(board[0][0] == board[1][1] && board[0][0] == board[2][2]){
printf("比赛结束! player%d 赢得了比赛!", player);
break;
}
if(board[2][0] == board[1][1] && board[2][0] == board[0][2]){
printf("比赛结束! player%d 赢得了比赛!", player);
break;
}

}

printf("\n");
printf(" %c | %c | %c\n", board[0][0], board[0][1], board[0][2]);
printf("---+---+---\n");
printf(" %c | %c | %c\n", board[1][0], board[1][1], board[1][2]);
printf("---+---+---\n");
printf(" %c | %c | %c\n", board[2][0], board[2][1], board[2][2]);

if(i == 9){
printf("\n\n和局,请再来一局!");
}

return 0;
}

书上的代码也有同样的问题,输入一个非数字就会陷入while无限循环。