首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

C基础教程 第六章 数 组

C基础教程 第六章 数 组

为了解决比较复杂的问题,本章介绍C语言提供的一种最简单的构造类型──数组。

6.1
1维数组的定义和引用

6.1.1
1维数组的定义

6.1.2
1维数组元素的引用

6.1.3
1维数组元素的初始化

6.1.4
1维数组应用举例


6.1.1
1维数组的定义

[案例6.1]
从键盘上任意输入10个整数,要求按从小到大的顺序在屏幕上显示出来。


排序的方法有很多,本题采用冒泡法。

冒泡法的基本思想:通过相邻两个数之间的比较和交换,使排序码(数值)较小的数逐渐从底部移向顶部,排序码较大的数逐渐从顶部移向底部。就像水底的气泡一样逐渐向上冒,故而得名。

A[n]~A[1]组成的n个数据,进行冒泡排序的过程可以描述为:

1)首先将相邻的A[n]A[n-1]进行比较,如果A[n]的值小于A[n-1]的值,则交换两者的位置,使较小的上浮,较大的下沉;接着比较A[n-1]A[n-2],同样使小的上浮,大的下沉。依此类推,直到比较完A[2]A[1]后,A[1]为具有最小排序码(数值)的元素,称第一趟排序结束。


/*冒泡法排序*/


for(i=0; i<NUM-1; i++)
/*外循环:控制比较趟数*/


for(j=NUM-1; j>i; j--)
/*内循环:进行每趟比较*/


if(data[j]<data[j-1])
/*如果data[j]大于data[j-1],交换两者的位置*/


{temp=data[j];


data[j]=data[j-1];


data[j-1]=temp;


};


/*输出排序后的数据*/


printf("\nthe
result ofsort:\n");


for(i=0; i<NUM; i++)


printf("%d ",data);


getch();
/*等待键盘输入任一字符,目的使程序暂停*/

}


[程序演示]

2
然后在A[n]~A[2]区间内,进行第二趟排序,使剩余元素中排序码最小的元素上浮到A[2];重复进行n-1趟后,整个排序过程结束。

/*案例代码文件名:AL6_1.C*/

/*功能:从键盘上任意输入n个整数,用冒泡法按从小到大地排序,并在屏幕上显示出来。*/

#include "stdio.h"

#define NUM 10
/*定义符号常量(数据个数N*/

main()

{ int data[NUM];
/*定义11维整型数组data*/


int i,j,temp;
/*定义循环变量和临时变量*/


clrscr();
/*库函数clrscr():清屏*/


printf("Please input 10 numbers:\n");


for(i=0; i<NUM; i++)


scanf("%d", &data);

3


数组同变量一样,也必须先定义、后使用。

1维数组是只有1个下标的数组,定义形式如下:

数据类型
数组名[常量表达式][, 数组名2[常量表达式2]……]

1)“数据类型”是指数组元素的数据类型。

2)数组名,与变量名一样,必须遵循标识符命名规则。

3)“常量表达式”必须用方括号括起来,指的是数组的元素个数(又称数组长度),它是一个整型值,其中可以包含常数和符号常量,但不能包含变量。

注意:C语言中不允许动态定义数组。


特别说明:在数组定义时,“常量表达式”外的方括号;以及元素引用时,“下标表达式”外的方括号,都是C语言语法规则所要求的,不是本书所约定的可选项的描述符号!

4
组元素的下标,是元素相对于数组起始地址的偏移量,所以从0开始顺序编号。

5
数组名中存放的是一个地址常量,它代表整个数组的首地址。同一数组中的所有元素,按其下标的顺序占用一段连续的存储单元。


6.1.2
数组元素的引用


引用数组中的任意一个元素的形式:


数组名[下标表达式]


1.“下标表达式”可以是任何非负整型数据,取值范围是0~(元素个数-1)。


特别强调:在运行C语言程序过程中,系统并不自动检验数组元素的下标是否越界。因此在编写程序时,保证数组下标不越界是十分重要的。


21个数组元素,实质上就是1个变量,它具有和相同类型单个变量一样的属性,可以对它进行赋值和参与各种运算。


3.在C语言中,数组作为1个整体,不能参加数据运算,只能对单个的元素进行处理。

6.1.3
1维数组元素的初始化



初始化格式:

数据类型
数组名[常量表达式]{初值表}

1)如果对数组的全部元素赋以初值,定义时可以不指定数组长度(系统根据初值个数自动确定)。如果被定义数组的长度,与初值个数不同,则数组长度不能省略。

2)“初值表”中的初值个数,可以少于元素个数,即允许只给部分元素赋初值。

3)根据存储类型的不同,数组有静态数组(static)和动态数组(auto)之分;根据定义的位置不同,数组有内部数组(在函数内部定义的数组)和外部数组(在函数外部定义的数组)之分。

6.1.4
1维数组应用举例


[案例6.2] 已知某课程的平时、实习、测验和期末成绩,求该课程的总评成绩。其中平时、实习、测验和期末分别占10%、20%、20%、50%。
/*案例代码文件名:AL6_2.C*/
/*功能:从键盘上循环输入某课程的平时、实习、测验和期末成绩,按10%,20%,20%,50%的比例计算总评成绩,并在屏幕上显示出来。按空格键继续循环,其他键终止循环。*/
#include “stdio.h”
main()
{ int i=1,j;

char con_key=\x20;

/* \x20 空格键的ASCII*/

float score[5],ratio[4]={0.1,0.2,0.2,0.5};
/*定义成绩、比例系数数组*/

while(con_key=='\x20')


while(con_key=='\x20')


{clrscr();


printf("输入第%2d个学生的成绩\n", i++);


printf("平时
实习
测验
期末成绩\n");


score[4]=0;
/*score[4]:存储总评成绩*/


for(j=0; j<4; j++)


{scanf("%f",&score[j]);


score[4] += score[j] * ratio[j];


}


printf("总评成绩为:%6.1f\n",score[4]);


printf("\n按空格键继续,其它键退出");


con_key=getch();
/*getch()函数等待从键盘上输入一个字符*/


}

}

6.2
2维数组的定义和引用

6.2.1
2维数组的定义

6.2.2
2维数组元素的引用

6.2.3
2维数组元素的初始化

6.2.4
2维数组应用举例


6.2.1
2维数组的定义

[案例6.3]
给一个232维数组各元素赋值,并输出全部元素的值。


/*案例代码文件名:AL6_3.C*/

/*功能:从键盘上给23数组赋值,并在屏幕上显示出来。*/

#define Row 2

#define Col 3

#include "stdio.h"

main()


{int i, j, array[Row][Col];
/*定义123列的2维数组array*/


for(i=0; i<Row; i++)
/*外循环:控制2维数组的行*/


for(j=0; j<Col; j++)
/*内循环:控制2维数组的列*/


{printf("please input array[%2d][%2d]:",i,j);


scanf("%d",&array[j]);
/*从键盘输入a[j]的值*/


}


printf("\n");


/*输出2维数组array*/


for(i=0;i<Row;i++)


{ for(j=0;j<Col;j++)


printf("%d\t",array[j]);
/*a[j]的值显示在屏幕上*/


printf("\n");


}


getch();


}


2维数组的定义方式如下:


数据类型
数组名[行常量表达式][列常量表达式][,
数组名2[行常量表达式2][列常量表达式2]……];

1.数组元素在内存中的排列顺序为“按行存放”,即先顺序存放第一行的元素,再存放第二行,以此类推。

2. 设有一个m*n的数组x,则第i行第j列的元素x[j]在数组中的位置为:i*n+j(注意:行号、列号均从0开始计数)。


3.可以把2维数组看作是一种特殊的1维数组:它的元素又是一个1维数组。

例如,对x[3][2],可以把x看作是一个1维数组,它有3个元素:x[0]x[1]x[2],每个元素又是一个包含2个元素的1维数组,如图6-4所示。即把x[0]x[1]x[2]看作是31维数组的名字。


?6.2.2
2维数组元素的引用

引用2维数组元素的形式为:

数组名[行下标表达式][列下标表达式]

1.“行下标表达式”和“列下标表达式”,都应是整型表达式或符号常量。

2.“行下标表达式”和“列下标表达式”的值,都应在已定义数组大小的范围内。假设有数组x[3][4],则可用的行下标范围为0~2,列下标范围为0~3

3.对基本数据类型的变量所能进行的操作,也都适合于相同数据类型的2维数组元素。

6.2.3
2维数组元素的初始化

1.按行赋初值

数据类型
数组名[行常量表达式][列常量表达式]{{0行初值表}{1行初值表},……,{最后1行初值表}}

赋值规则:将“第0行初值表”中的数据,依次赋给第0行中各元素;将“第1行初值表”中的数据,依次赋给第1行各元素;以此类推。

2.按2维数组在内存中的排列顺序给各元素赋初值

数据类型
数组名[行常量表达式][列常量表达式]{初值表}

赋值规则:按2维数组在内存中的排列顺序,将初值表中的数据,依次赋给各元素。

如果对全部元素都赋初值,则“行数”可以省略。注意:只能省略“行数”。


6.2.4
2维数组应用举例


[案例6.4]
M个学生,学习N门课程,已知所有学生的各科成绩,编程:分别求每个学生的平均成绩和每门课程的平均成绩。


/*案例代码文件名:AL6_4.C*/

/*功能:计算个人平均成绩与各科平均成绩,并在屏幕上显示出来。*/

#define NUM_std
5
/*定义符号常量人数为5*/

#define NUM_course
4
/*定义符号常量课程为4*/

#include "stdio.h"

main()

{ int i,j;


static float score[NUM_std+1][NUM_course+1]={{78,85,83,65},


{88,91,89,93}, {72,65,54,75},


{86,88,75,60}, {69,60,50,72}};


for(i=0;i<NUM_std;i++)



{for(j=0;j<NUM_course;j++)


{ score[NUM_course] += score[j];/*求第i个人的总成绩*/


score[NUM_std][j] += score[j]; /*求第j门课的总成绩*/


}


score[NUM_course] /= NUM_course;/*求第i个人的平均成绩*/


}


for(j=0;j<NUM_course;j++)


score[NUM_std][j] /= NUM_std; /*求第j门课的平均成绩*/


clrscr();


/*输出表头*/


printf("学生编号
课程1
课程2
课程3
课程4
个人平均\n");


/*输出每个学生的各科成绩和平均成绩*/


for(i=0;i<NUM_std;i++)


{ printf("学生%d\t",i+1);


for(j=0;j<NUM_course+1;j++)


printf("%6.1f\t",score[j]);


printf("\n");


}


/*输出1条短划线*/


for(j=0;j<8*(NUM_course+2);j++)


printf("-");


printf("\n课程平均");


/*输出每门课程的平均成绩*/


for(j=0;j<NUM_course;j++)


printf("%6.1f\t",score[NUM_std][j]);


printf("\n");


getch();


}

6.3
字符数组与字符串

6.3.1
字符数组的逐个字符操作


6.3.2
字符数组的整体操作

6.3.3
常用的字符串处理函数

6.3.1
字符数组的逐个字符操作

[案例6.5]从键盘输入一个字符串,回车键结束,并将字符串在屏幕上输出。


/*案例代码文件名:AL6_5.C*/

main()


{int i;


static char str[80];


clrscr();


for(i=0;i<80;i++)


{ str=getch();
/*逐次给数组元素str赋值,但不回显在屏幕上*/


printf("*");
/*以星号代替输入字符的个数*/


if(str=='\x0d') break;/*若输入回车则终止循环*/


}


i=0;


while(str!='\x0d')


printf("%c",str[i++]);
/*逐次输出字符数组的各个元素*/


printf("\n");


getch();
/*程序暂停*/

}


1.字符数组的定义

1维字符数组,用于存储和处理1个字符串,其定义格式与1维数值数组一样。

2维字符数组,用于同时存储和处理多个字符串,其定义格式与2维数值数组一样。

2.字符数组的初始化

字符数组的初始化,可以通过为每个数组元素指定初值字符来实现。


3.字符数组的引用


字符数组的逐个字符引用,与引用数值数组元素类似。


1)字符数组的输入


除了可以通过初始化使字符数组各元素得到初值外,也可以使用getchar()scanf()函数输入字符。


例如:


char str[10]

……

for(i=0; i<10; i++)


{ scanf("%c", &str)


fflush(stdin);
/*清除键盘输入缓冲区*/


}

……


2)字符数组的输出


字符数组的输出,可以用putchar()printf()函数。


例如:


char
str[10]="clanguage";

……

for(i=0; i<10; i++)
printf("%c", str)

printf("\n");

……

注意:逐个字符输入、输出时,要指出元素的下标,而且使用“%c”格式符。另外,从键盘上输入字符时,无需输入字符的定界符──单引号;输出时,系统也不输出字符的定界符。

6.3.2
字符数组的整体操作

[案例6.6]
字符数组的整体输入与输出。


/*案例代码文件名:AL6_6.C*/

/*功能:将2维字符数组进行初始化,并在屏幕上输出*/

main()

{ int i;


char name[5][9]={"张三山","李四季", "王五魁", "刘六顺","赵七巧"};


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


printf("\n%s\t",name);
/*name代表该行数组元素的首地址*/


getch();

}
[程序演示]

1.字符串及其结束标志


所谓字符串,是指若干有效字符的序列。C语言中的字符串,可以包括字母、数字、专用字符、转义字符等。

C语言规定:以‘\0’作为字符串结束标志(‘\0’代表ASCII码为0的字符,表示一个“空操作”,只起一个标志作用)。因此可以对字符数组采用另一种方式进行操作了──字符数组的整体操作。

注意:由于系统在存储字符串常量时,会在串尾自动加上1个结束标志,所以无需人为地再加1个。

另外,由于结束标志也要在字符数组中占用一个元素的存储空间,因此在说明字符数组长度时,至少为字符串所需长度加1

2.字符数组的整体初始化

字符串设置了结束标志以后,对字符数组的初始化,就可以用字符串常量来初始化字符数组。

3.字符数组的整体引用

1)字符串的输入

除了可以通过初始化使字符数组各元素得到初值外,也可以使用scanf()函数输入字符串。

2)字符串的输出

printf()函数,不仅可以逐个输出字符数组元素,还可以整体输出存放在字符数组中的字符串。

6.3.3
常用的字符串处理函数

字符串标准函数的原型在头文件string.h中。

1.输入字符串──gets()函数

1)调用方式:gets(字符数组)

2)函数功能:从标准输入设备(stdin)──键盘上,读取1个字符串(可以包含空格),并将其存储到字符数组中去。

3)使用说明


1gets()读取的字符串,其长度没有限制,编程者要保证字符数组有足够大的空间,存放输入的字符串。


2)该函数输入的字符串中允许包含空格,而scanf()函数不允许。

2.输出字符串──puts()函数

1)调用方式:puts(字符数组)

2)函数功能:把字符数组中所存放的字符串,输出到标准输出设备中去,并用‘\n’取代字符串的结束标志‘\0’。所以用puts()函数输出字符串时,不要求另加换行符。

3)使用说明

1)字符串中允许包含转义字符,输出时产生一个控制操作。

2)该函数一次只能输出一个字符串,而printf()函数也能用来输出字符串,且一次能输出多个。

3.字符串比较──strcmp()函数

1)调用方式:strcmp(字符串1 ,字符串2)

其中“字符串”可以是串常量,也可以是1维字符数组。

2)函数功能:比较两个字符串的大小。

如果:字符串1=字符串2,函数返回值等于0


字符串1<字符串2,函数返回值负整数;


字符串1>字符串2,函数返回值正整数。

3)使用说明

1)如果一个字符串是另一个字符串从头开始的子串,则母串为大。

2)不能使用关系运算符“==”来比较两个字符串,只能用strcmp() 函数来处理。

[案例6.7]
gets函数和strcmp函数的应用。


/*案例代码文件名:AL6_7.C*/

/*功能:简单密码检测程序*/

#include
"stdio.h"

main()


{char pass_str[80];
/*定义字符数组passstr*/


int i=0;


/*检验密码*/


while(1)


{clrscr();


printf("请输入密码\n");


gets(pass_str);
/*输入密码*/


if(strcmp(pass_str,password)!=0)
/*口令错*/



printf("口令错误,按任意键继续");


else


break;
/*输入正确的密码,中止循环*/


getch();


i++;


if(i==3) exit(0);
/*输入三次错误的密码,退出程序*/



}


/*输入正确密码所进入的程序段*/

}

4.拷贝字符串──strcpy()函数

1)调用方式:strcpy(字符数组, 字符串)

其中“字符串”可以是串常量,也可以是字符数组。

2)函数功能:将“字符串”完整地复制到“字符数组”中,字符数组中原有内容被覆盖。

3)使用说明

1)字符数组必须定义得足够大,以便容纳复制过来的字符串。复制时,连同结束标志'\0'一起复制。

2)不能用赋值运算符“=”将一个字符串直接赋值给一个字符数组,只能用strcpy()函数来处理。

5.连接字符串──strcat()函数

1)调用方式:strcat(字符数组, 字符串)

2)函数功能:把“字符串”连接到“字符数组”中的字符串尾端,并存储于“字符数组”中。“字符数组”中原来的结束标志,被“字符串”的第一个字符覆盖,而“字符串”在操作中未被修改。

3)使用说明


1)由于没有边界检查,编程者要注意保证“字符数组”定义得足够大,以便容纳连接后的目标字符串;否则,会因长度不够而产生问题。


2)连接前两个字符串都有结束标志'\0',连接后“字符数组”中存储的字符串的结束标志'\0'被舍弃,只在目标串的最后保留一个'\0'

6.求字符串长度──strlen()函数(lenlength的缩写)

1)调用方式:strlen(字符串)

2)函数功能:求字符串(常量或字符数组)的实际长度(不包含结束标志)。

7.将字符串中大写字母转换成小写──strlwr()函数

1)调用方式:strlwr(字符串)

2)函数功能:将字符串中的大写字母转换成小写,其它字符(包括小写字母和非字母字符)不转换。

8.将字符串中小写字母转换成大写──strupr()函数

1)调用方式:strupr(字符串)

2)函数功能:将字符串中小写字母转换成大写,其它字符(包括大写字母和非字母字符)不转换。
返回列表