数组(Array)也是一种复合数据类型,它由一系列相同类型的元素(Element)
组成。例如定义一个由4个int型元素组成的数组count
int count[4];
一个由4个结构体元素组成的数组:
struct complex_struct {
double x, y;
} a[4];
也可以定义一个包含数组成员的结构体:
struct {
double x, y;
int count[4];
} s;
8.1 定义和访问数组
#include<stdio.h>
int main(void)
{
int count[4] = {3,2,}, i;
for(i=0; i<4; i++)
printf("count[%d] = %d\n", i, count[i]);
return 0;
}
程序输出:
[root@redhat-beijing test]# gcc -Wall a.c
[root@redhat-beijing test]# ./a.out
count[0] = 3
count[1] = 2
count[2] = 0
count[3] = 0
数组也可以像结构体一样初始化,未赋初值的元素也是用 0来初始化。
数组类型做右值使用时,自动转换成指向数组首元素的指针。
1、编写一个程序,定义两个类型和长度都相同的数组,将其中一个数组的所有
元素拷贝给另一个。既然数组不能直接赋值,想想应该怎么实现。
#include<stdio.h>
int main(void)
{
int count[4] = {3,2,1,0}, i;
int count_copy[4]; //未初始化,故产生的是随即值。 若初始化,int count_copy[4] ={};则count_copy中的元素都为0
for(i=0; i<4; i++)
printf("count[%d] = %d\n", i, count[i]);
for(i=0; i<4; i++)
printf("before: count_copy[%d] = %d\n", i, count_copy[i]);
for(i=0; i<4; i++)
count_copy[i] = count[i];
for(i=0; i<4; i++)
printf("After: count_copy[%d] = %d\n", i, count_copy[i]);
return 0;
}
output:
[root@redhat-beijing test]# gcc -Wall a.c
[root@redhat-beijing test]# ./a.out
count[0] = 3
count[1] = 2
count[2] = 1
count[3] = 0
before: count_copy[0] = 14012404
before: count_copy[1] = 14004740
before: count_copy[2] = -1079859528
before: count_copy[3] = 134513833
After: count_copy[0] = 3
After: count_copy[1] = 2
After: count_copy[2] = 1
After: count_copy[3] = 0
2. 数组应用实例:统计随机数
问题是这样的:首先生成一列0~9的随机数保存在数组中,然后统计其中每个数字出现的次数并打印,检查这些数字的随机性如何。
#include <stdio.h>
#include <stdlib.h>
#define N 20
int a[N];
void gen_random(int upper_bound)
{
int i;
for (i = 0; i < N; i++)
a[i] = rand() % upper_bound;
}
void print_random()
{
int i;
for (i = 0; i < N; i++)
printf("a[%d]=%d ", i, a[i]);
printf("\n");
}
int main(void)
{
gen_random(10);
print_random();
return 0;
}
[root@redhat-beijing test]# gcc -Wall a.c
[root@redhat-beijing test]# ./a.out
a[0]=3
a[1]=6
a[2]=7
a[3]=5
a[4]=3
a[5]=5
a[6]=6
a[7]=2
a[8]=9
a[9]=1
a[10]=2
a[11]=7
a[12]=0
a[13]=9
a[14]=3
a[15]=6
a[16]=0
a[17]=6
a[18]=2
a[19]=6
编译器的工作分为两个阶段,先是预处理(Preprocess)阶段,然后才是编译阶段,用gcc的-E选
项可以看到预处理之后、编译之前的程序: gcc -E a.c
int a[20];
void gen_random(int upper_bound)
{
int i;
for (i = 0; i < 20; i++)
a[i] = rand() % upper_bound;
}
void print_random()
{
int i;
for (i = 0; i < 20; i++)
printf("a[%d]=%d\n", i, a[i]);
printf("\n");
}
int main(void)
{
gen_random(10);
print_random();
return 0;
}
[root@redhat-beijing test]#
用cpp a.c也可以达到同样的效果,只作预处理而不编译,cpp表示C preprocessor。
#include <stdio.h>
#define RECTANGULAR 1
#define POLAR 2
int main(void)
{
int RECTANGULAR;
printf("%d %d\n", RECTANGULAR, POLAR);
return 0;
}
编译报错
[root@redhat-beijing test]# gcc -Wall a.c
a.c: In function ‘main’:
a.c:642: error: expected identifier or ‘(’ before numeric constant
在整形常量前不能加 int, 例如 int 3; 在编译时会报同样的错误。
将 int RECTANGULAR; 注释掉,就能编译通过。
[root@redhat-beijing test]# gcc -Wall a.c
[root@redhat-beijing test]# ./a.out
1 2
例 8.3. 统计随机数的分布
#include <stdio.h>
#include <stdlib.h>
#define N 100000
int a[N];
void gen_random(int upper_bound)
{
int i;
for (i = 0; i < N; i++)
a[i] = rand() % upper_bound;
}
int howmany(int value)
{
int count = 0, i;
for (i = 0; i < N; i++)
if (a[i] == value)
++count;
return count;
}
int main(void)
{
int i;
gen_random(10);
printf("value\thow many\n");
for (i = 0; i < 10; i++)
printf("%d\t%d\n", i, howmany(i));
return 0;
}
程序运行结果:
[root@redhat-beijing test]# ./a.out
value how many
0 10130
1 10072
2 9990
3 9842
4 10174
5 9930
6 10059
7 9954
8 9891
9 9958
[root@redhat-beijing test]#
1、用rand函数生成[10, 20]之间的随机整数,表达式应该怎么写?
rand() % 11 + 10;
-----------------
直方图
#include <stdio.h>
#include <stdlib.h>
#define N 100000
int a[N];
void gen_random(int upper_bound)
{
int i;
for (i = 0; i < N; i++)
a[i] = rand() % upper_bound;
}
int howmany(int value)
{
int count = 0, i;
for (i = 0; i < N; i++)
if (a[i] == value)
++count;
return count;
}
int main(void)
{
int i, histogram[10];
gen_random(10);
for (i=0; i< 10; i++)
{
histogram[i] = howmany(i);
printf("histogram[%d]=%d\n", i, histogram[i]);
}
printf("value\thow many\n");
for (i = 0; i < 10; i++)
printf("%d\t%d\n", i, howmany(i));
return 0;
}
运行结果如下:
[root@redhat-beijing test]# gcc -Wall a.c -o a.out
[root@redhat-beijing test]# ./a.out
histogram[0]=10130
histogram[1]=10072
histogram[2]=9990
histogram[3]=9842
histogram[4]=10174
histogram[5]=9930
histogram[6]=10059
histogram[7]=9954
histogram[8]=9891
histogram[9]=9958
value how many
0 10130
1 10072
2 9990
3 9842
4 10174
5 9930
6 10059
7 9954
8 9891
9 9958
尽管上面的方法可以准确地得到统计结果,但是效率很低,这 100000个随机数
需要从头到尾检查十遍,每一遍检查只统计一种数字的出现次数。其实可以把
histogram中的元素当作累加器来用,这些随机数只需要从头到尾检查一遍
(Single Pass)就可以得出结果:
#include <stdio.h>
#include <stdlib.h>
#define N 100000
int a[N];
void gen_random(int upper_bound)
{
int i;
for (i = 0; i < N; i++)
a[i] = rand() % upper_bound;
}
int main(void)
{
int i, histogram[10]={0};
gen_random(10);
for(i=0; i<10; i++)
printf("histogram[%d]=%d\n",i,histogram[i]);
for(i=0; i<N; i++)
{
histogram[a[i]]++;
}
for(i=0; i<10; i++)
printf("histogram[%d]=%d\n",i,histogram[i]);
return 0;
}
输出:
[root@redhat-beijing test]# gcc -Wall a.c -o a.out
[root@redhat-beijing test]# ./a.out
histogram[0]=0
histogram[1]=0
histogram[2]=0
histogram[3]=0
histogram[4]=0
histogram[5]=0
histogram[6]=0
histogram[7]=0
histogram[8]=0
histogram[9]=0
histogram[0]=10130
histogram[1]=10072
histogram[2]=9990
histogram[3]=9842
histogram[4]=10174
histogram[5]=9930
histogram[6]=10059
histogram[7]=9954
histogram[8]=9891
histogram[9]=9958
编译运行几次,发现产生的结果一样,可知 rand()产生的是伪随机数。
在调用 rand()函数之前,先运行srand(time(NULL)); 再次编译运行,会产生不同的结果。
#include <stdio.h>
#include <stdlib.h>
#include<time.h>
#define N 100000
int a[N];
void gen_random(int upper_bound) {
int i;
for (i = 0; i < N; i++)
a[i] = rand() % upper_bound;
}
int main(void)
{
int i, histogram[10]={0};
srand(time(NULL));
gen_random(10);
for(i=0; i<N; i++)
{
histogram[a[i]]++;
}
for(i=0; i<10; i++)
printf("histogram[%d]=%d\n",i,histogram[i]);
return 0;
}
输出:
[root@redhat-beijing test]# gcc -Wall a.c -o a.out
[root@redhat-beijing test]# ./a.out
histogram[0]=10091
histogram[1]=10021
histogram[2]=10073
histogram[3]=10033
histogram[4]=10118
histogram[5]=9888
histogram[6]=10232
histogram[7]=9680
histogram[8]=9862
histogram[9]=10002
[root@redhat-beijing test]#
习题
1、补完本节直方图程序的main函数,以可视化的形式打印直方图。例如上一节统计20个随机数的结果是:
0 1 2 3 4 5 6 7 8 9
* * * * * * * *
* * * * * * *
* * *
*
*
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define N 20
int a[N];
void gen_random(int upper_bound)
{
int i;
unsigned int seed;
seed = time(NULL);
srand(seed);
for (i = 0; i < N; i++)
a[i] = rand() % upper_bound;
}
int main(void)
{
int i, j, max = 0, histogram[10] = {0};
gen_random(10);
for (i = 0; i < N; i++)
histogram[a[i]]++;
//水平方向打印
printf("水平方向:\n");
for (i = 0; i < 10; i++) {
printf("%d ", i);
for (j = 0; j < histogram[i]; j++)
printf("* ");
printf("\n");
}
//垂直打印
printf("\n\n垂直方向:\n");
for (i = 0; i < 10; i++) {
max = (max > histogram[i]) ? max : histogram[i];
printf("%d ", i);
}
printf("\n\n");
for (i = 0; i < max; i++) {
for (j = 0; j < 10; j++) {
if (histogram[j] > 0) {
printf("* ");
--histogram[j];
} else
printf(" ");
}
printf("\n");
}
printf("\n");
return 0;
}
输出:
[root@redhat-beijing test]# gcc -Wall a.c -o a.out
[root@redhat-beijing test]# ./a.out
水平方向:
0 * * *
1 * *
2 * *
3 * * *
4
5 * * *
6 * * *
7 * *
8 *
9 *
垂直方向:
0 1 2 3 4 5 6 7 8 9
* * * * * * * * *
* * * * * * *
* * * *