为了解决比较复杂的问题,本章介绍 C语言提供的一种最简单的构造类型 ──数组 。
7.1 1维数组的定义和引用
7.2 2维数组的定义和引用
7.3 字符数组与字符串
[Return]
第 7章 数 组
7.1 1维数组的定义和引用
7.1.1 1维数组的定义
7.1.2 1维数组元素的引用
7.1.3 1维数组元素的初始化
7.1.4 1维数组应用举例
[Return]
7.1.1 一维数组的定义
[案例 7.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]为具有最小排序码 ( 数值 ) 的元素,称第一趟排序结束 。
( 2) 然后在 A[n]~A[2]区间内,进行第二趟排序,使剩余元素中排序码最小的元素上浮到 A[2];重复进行 n-1趟后,整个排序过程结束 。
/*案例代码文件名,AL7_1.C*/
/*功能:从键盘上任意输入 n个整数,用冒泡法按从小到大地排序,
并在屏幕上显示出来 。 */
#include "stdio.h"
#define N 11 /*定义符号常量 ( 数据个数 N) */
main()
{ int data[N]; /*定义 1个 1维整型数组 data*/
int i,j,t; /*定义循环变量和临时变量 */
clrscr(); /*库函数 clrscr():清屏 */
printf("Please input 10 numbers:\n");
for(i=1; i<N; i++)
scanf("%d",&data[i]);
/*冒泡法排序 */
for(i=1; i<=N-1; i++) /*外循环:控制比较趟数 */
for(j=1; j<=N-i; j++) /*内循环:进行每趟比较 */
if(data[j]<data[j-1]) /*如果 data[j]大于 data[j-1],交换两者的位置 */
{t=data[j];
data[j]=data[j-1];
data[j-1]=t; }
/*输出排序后的数据 */
printf("\nthe result of sort:\n");
for(i=0; i<N; i++)
printf("%d ",data[i]);
}
[程序演示 ]
数组同变量一样,也必须先定义,后使用 。
一维数组是只有 1个下标的数组,定义形式如下:
数据类型 数组名 [常量表达式 ][,数组名 2[常量表达式 2]…… ];
( 1),数据类型,是指数组元素的数据类型 。
( 2) 数组名,与变量名一样,必须遵循标识符命名规则 。
( 3),常量表达式,必须用方括号括起来,指的是数组的元素个数 ( 又称数组长度 ),它是一个整型值,其中可以包含常数和符号常量,但不能包含变量 。
注意,C语言中不允许动态定义数组 。
( 4) 数组元素的下标,是元素相对于数组起始地址的偏移量,
所以 从 0开始顺序编号 。
( 5) 数组名中存放的是一个地址常量,它代表整个数组的首地址 。 同一数组中的所有元素,按其下标的顺序占用一段连续的存储单元 。 [Return]
7.1.2 数组元素的引用引用数组中的任意一个元素的形式:
数组名 [下标表达式 ]
1.,下标表达式,可以是任何非负整型数据,取值范围是 0~( 元素个数 -1) 。
特别强调,在运行 C语言程序过程中,系统并不自动检验数组元素的下标是否越界 。 因此在编写程序时,保证数组下标不越界是十分重要的 。
2,1个数组元素,实质上就是 1个变量,它具有和相同类型单个变量一样的属性,可以对它进行赋值和参与各种运算 。
3,在 C语言中,数组作为 1个整体,不能参加数据运算,只能对单个的元素进行处理 。
[Return]
7.1.3 1维数组元素的初始化初始化格式,
数据类型 数组名 [常量表达式 ]= {初值表 };
( 1) 如果对数组的全部元素赋以初值,定义时可以不指定数组长度 ( 系统根据初值个数自动确定 ) 。 如果被定义数组的长度,与初值个数不同,则数组长度不能省略 。 如,int a[]={1,2,4,8}; int a[5]={0};int a[10]={1,4,8};
( 2),初值表,中的初值个数,可以少于元素个数,
即允许只给部分元素赋初值 。 int a[10]={1,4,8};
( 3) 根据存储类型的不同,数组有静态数组 ( static)
和动态数组 ( auto) 之分;根据定义的位置不同,数组有内部数组 ( 在函数内部定义的数组 ) 和外部数组 ( 在函数外部定义的数组 ) 之分 。
[Return]
7.1.4 一 维数组应用举例
[案例 7.2] 已知某课程的平时、实习、测验和期末成绩,求该课程的总评成绩。其中平时、实习、测验和期末分别占 10%,20%、
20%,50%。
/*案例代码文件名,AL7_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')
{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()函数等待从键盘上输入一个字符 */
}
}
[程序演示 ]
[Return]
7.2 2维数组的定义和引用
7.2.1 2维数组的定义
7.2.2 2维数组元素的引用
7.2.3 2维数组元素的初始化
7.2.4 2维数组应用举例
[Return]
二维数组的定义方式如下:
数据类型 数组名 [行常量表达式 ][列常量表达式 ][,数组名
2[行常量表达式 2][列常量表达式 2]……];
1.数组元素在内存中的排列顺序为“按行存放”,即先顺序存放第一行的元素,再存放第二行,以此类推。
2,设有一个 m*n的数组 x,则第 i行第 j列的元素 x[i][j]在数组中的位置为,i*m+j( 注意,行号、列号均从 0开始计数)。
3.可以把 2维数组看作是一种特殊的 1维数组:它的元素又是一个 1维数组。
例如,对 x[3][2],可以把 x看作是一个 1维数组,它有 3个元素,x[0]、
x[1],x[2],每个元素又是一个包含 2个元素的 1维数组,如图 7-4所示 。
即把 x[0],x[1],x[2]看作是 3个 1维数组的名字 。
X[0]-------------x00 x01
X[1]-------------x10 x11
X[2]-------------x20 x21 [Return]
7.2.1 二维数组的定义
7.2.2 2维数组元素的引用引用 2维数组元素的形式为:
数组名 [行下标表达式 ][列下标表达式 ]
1.,行下标表达式,和,列下标表达式,,都应是整型表达式或符号常量 。
2.,行下标表达式,和,列下标表达式,的值,都应在已定义数组大小的范围内 。 假设有数组 x[3][4],则可用的行下标范围为 0~2,列下标范围为 0~3。
3,对基本数据类型的变量所能进行的操作,也都适合于相同数据类型的二维数组元素 。
[Return]
7.2.3 二 维数组元素的初始化
1,按行赋初值数据类型 数组名 [行常量表达式 ][列常量表达式 ]= {{第 0行初值表 },{第 1行初值表 },……,{最后 1行初值表 }};
赋值规则:将,第 0行初值表,中的数据,依次赋给第 0行中各元素;将,第 1行初值表,中的数据,依次赋给第 1行各元素;以此类推 。
A[2][3]={{0,1,2},{3,4,5}}
2,按 2维数组在内存中的排列顺序给各元素赋初值数据类型 数组名 [行常量表达式 ][列常量表达式 ]= {初值表 };
赋值规则:按 2维数组在内存中的排列顺序,将初值表中的数据,
依次赋给各元素 。
如果对全部元素都赋初值,则“行数”可以省略。 注意,只能省略“行数”。
Int a[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};
3.可以对部分元素赋初值 int a[3][4]={{1},{3},{6}}
[Return]
[案例 7.3] 给一个 2* 3的 2维数组各元素赋值,并输出全部元素的值 。
/*案例代码文件名,AL7_3.C*/
/*功能:从键盘上给 2* 3数组赋值,并在屏幕上显示出来 。 */
#define Row 2
#define Col 3
#include "stdio.h"
main()
{ int i,j,array[Row][Col]; /*定义 1个 2行 3列的 2维数组 array*/
for(i=0; i<Row; i++) /*外循环:控制 2维数组的行 */
for(j=0; j<Col; j++) /*内循环:控制 2维数组的列 */
{printf("please inputarray[%2d][%2d]:",i,j);
scanf("%d",&array[i][j]); /*从键盘输入 a[i][j]的值 */
}
printf("\n");
/*输出 2维数组 array*/
for(i=0;i<Row;i++)
{ for(j=0;j<Col;j++)
printf("%d\t",array[i][j]); /*将 a[i][j]的值显示在屏幕上 */
printf("\n"); }
}
7.2.4 2维数组应用举例例 7.4有一个 3× 4的矩阵,要求编程序求出其中最大的那个元素的值,以及其所在的行号和列号 。
main()
{int I,j,col=0,row=0,max;
int a[3][4]={{1,2,3,4},{45,14,-21,21},{9,15,13,-78}};
max=a{0][0];
for (I=0;I<=2;I++)
for(j=0;j<=3;j++)
if (a[I][j]>max)
{max=a[I][j];
I=row;
j=col;}
printf("max=%d,row=%d,col=%d\n",max,row,col);
}
[案例 7.5] 有 M个学生,学习 N门课程,已知所有学生的各科成绩,
编程:分别求每个学生的平均成绩和每门课程的平均成绩。
/*案例代码文件名,AL7_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[i][NUM_course] += score[i][j];/*求第 i个人的总成绩 */
score[NUM_std][j]+= score[i][j];/*求第 j门课的总成绩 */
}
score[i][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("%7.1f\t",score[i][j]);
printf("\n"); }
/*输出 1条短划线 */
for(j=0;j<8*(NUM_course+2);j++)
printf("-");
printf("\n课程平均 ");
for(j=0;j<NUM_course;j++) /*输出每门课程的平均成绩 */
printf("%7.1f\t",score[NUM_std][j]);
printf("\n");
getch(); } [程序演示 ] [Return]
7.3 字符数组与字符串
7.3.1 字符数组的逐个字符操作
7.3.2 字符数组的整体操作
7.3.3 常用的字符串处理函数
[Return]
7.3.1 字符数组的逐个字符操作
[案例 7.5]从键盘输入一个字符串,回车键结束,并将字符串在屏幕上输出 。
/*案例代码文件名,AL7_5.C*/
main()
{int i;
static char str[80];
clrscr();
for(i=0;i<80;i++)
{ str[i]=getch(); /*逐次给数组元素 str[i]赋值,但不回显在屏幕上 */
printf("*"); /*以星号代替输入字符的个数 */
if(str[i]=='\x0d') break;/*若输入回车则终止循环 */
}
i=0;
while(str[i]!='\x0d')
printf("%c",str[i++]); /*逐次输出字符数组的各个元素 */
printf("\n");
getch(); /*程序暂停 */
} [程序演示 ]
1,字符数组的定义字符数组,用于存储和处理字符串,其定义格式与数值数组一样 。
Char ch[4];
Ch[0]='I';ch[1]=' ';ch[2]='a';ch[3]='m';
2,字符数组的初始化字符数组的初始化,可以通过为每个数组元素指定初值字符来实现 。
3,字符数组的引用字符数组的逐个字符引用,与引用数值数组元素类似 。
( 1) 字符数组的输入除了可以通过初始化使字符数组各元素得到初值外,
也可以使用 getchar()或 scanf()函数输入字符 。
例如:
char str[10];
……
for(i=0; i<10; i++) /*或 scanf("%s",str)*/
{ scanf("%c",&str[i]);
fflush(stdin); /*清除键盘输入缓冲区 */
}
……
( 2) 字符数组的输出字符数组的输出,可以用 putchar()或 printf()函数 。
例如:
char str[10]="c language";
……
for(i=0; i<10; i++) printf("%c",str[i]); /*或 printf("%s",str);*/
printf("\n");
……
注意,逐个字符输入,输出时,要指出元素的下标,而且使用,%c”格式符 。 另外,从键盘上输入字符时,无需输入字符的定界符 ──单引号;输出时,系统也不输出字符的定界符 。
[Return]
7.3.2 字符数组的整体操作
[案例 7.7] 字符数组的整体输入与输出 。
/*案例代码文件名,AL7_7.C*/
/*功能:将 2维字符数组进行初始化,并在屏幕上输出 */
main()
{ int i;
char name[5][9]={"张三山 ","李四季 ","王五魁 ","刘六顺 ","赵七巧 "};
for(i=0;i<5;i++)
printf("\n%c\t",name[i]); /*name[i]代表该行数组元素的首地址 */
getch();
} [程序演示 ]
1.字符串及其结束标志所谓字符串,是指若干有效字符的序列。 C语言中的字符串,可以包括字母、数字、专用字符、转义字符等。
C语言规定:以‘ \0?作为字符串结束标志(‘ \0?代表 ASCII码为 0的字符,表示一个“空操作”,只起一个标志作用)。因此可以对字符数组采用另一种方式进行操作了 ──字符数组的整体操作 。
注意,由于系统在存储字符串常量时,会在串尾自动加上 1个结束标志,所以无需人为地再加 1个 。
另外,由于结束标志也要在字符数组中占用一个元素的存储空间,
因此在说明字符数组长度时,至少为字符串所需长度加 1。
2,字符数组的整体初始化字符串设置了结束标志以后,对字符数组的初始化,就可以用字符串常量来初始化字符数组 。
3,字符数组的整体引用
( 1) 字符串的输入除了可以通过初始化使字符数组各元素得到初值外,也可以使用
scanf()函数输入字符串 。
( 2) 字符串的输出
printf()函数,不仅可以逐个输出字符数组元素,还可以整体输出存放在字符数组中的字符串 。
[Return]
7.3.3 常用的字符串处理函数字符串标准函数的原型在头文件 string.h中 。
1,输入字符串 ──gets()函数
( 1) 调用方式,gets(字符数组 )
( 2) 函数功能:从标准输入设备 (stdin)──键盘上,读取
1个字符串 ( 可以包含空格 ),并将其存储到字符数组中去 。
( 3) 使用说明
1) gets()读取的字符串,其长度没有限制,编程者要保证字符数组有足够大的空间,存放输入的字符串 。
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()函数来处理 。
[案例 7.7] gets函数和 strcmp函数的应用 。
/*案例代码文件名,AL7_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'。
7,求字符串长度 ──strlen()函数 ( len是 length的缩写 )
( 1) 调用方式,strlen(字符串 )
( 2) 函数功能:求字符串 ( 常量或字符数组 ) 的实际长度
( 不包含结束标志 ) 。
7,将字符串中大写字母转换成小写 ──strlwr()函数
( 1) 调用方式,strlwr(字符串 )
( 2) 函数功能:将字符串中的大写字母转换成小写,其它字符 ( 包括小写字母和非字母字符 ) 不转换 。
8,将字符串中小写字母转换成大写 ──strupr()函数
( 1) 调用方式,strupr(字符串 )
( 2) 函数功能:将字符串中小写字母转换成大写,其它字符
( 包括大写字母和非字母字符 ) 不转换 。
[Return]
7.3.4字符数组应用举例例 7.6输入一行字符,统计其中有多少个单词,单词之间用空格分隔开。
#include <stdio.h>
main()
{char str[81]
int I,num=0,word=0;
char c;
gets(str);
for(I=0;(c=str[i])!='\0';I++)
if(c=='')word=0;
else if(word==0)
{word=1;
num++;
}
printf("there are %d words in the line.\n",num);
}
例 7.7 有 3个字符串,要求找出最大者。
#include<stdio.h>
#include<string.h>
Main()
Char string[20];
Char str[3][20];
Int I;
For (I=0;I<3;I++)
Gets(str[i]);
If(strcmp(str[0],str[1])>0) strcpy(string,str[0]);
Else strcpy(string,str[1]);
If(strcmp(str[2],string)>0) strcpy(string,str[2]);
Printf("\nthe largest string is,\n%s\n",string);
}
作业:
P141
7.2,7.3,7.5,7.10,7.11
下列程序的运行结果是
#include<stdio.h>
main()
{int i,j=4;
for(I=j;I<=2*j;I++)
swith(I/j)
{case 0:
case 1:printf("*");break;
case 2:printf("#");
}
}
下列程序的运行结果是
#include<stdio.h>
main()
{int m,n;
printf(""enter m,n:");
scanf("%d%d",&m,&n);
while(m!=n)
{while(m>n )m- =n;
while(n>m)n- =m;
}
printf("m=%d\n",m);
}
从键盘输入的 10个整数中,找出第一个能被 7整除的数。若找到,打印此数后退出循环;
若未找到,打印,no exist”.
#include<stdio.h>
Main()
{int I,a;
for (I=1;I<=10;I++)
{scanf("%d",&a);
if(a%7==0)
{printf("%d",a);
__________;}
}
if ( ___) printf("no exist\n");
}
打印 100以内个位数为 6,且能被
3整除的所有数。
#include<stdio.h>
Main()
{int I,j;
for (I=0;____;I++)
{j=I*10+6;
if (___) continue;
Printf("%d",j);
}
}
7.1 1维数组的定义和引用
7.2 2维数组的定义和引用
7.3 字符数组与字符串
[Return]
第 7章 数 组
7.1 1维数组的定义和引用
7.1.1 1维数组的定义
7.1.2 1维数组元素的引用
7.1.3 1维数组元素的初始化
7.1.4 1维数组应用举例
[Return]
7.1.1 一维数组的定义
[案例 7.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]为具有最小排序码 ( 数值 ) 的元素,称第一趟排序结束 。
( 2) 然后在 A[n]~A[2]区间内,进行第二趟排序,使剩余元素中排序码最小的元素上浮到 A[2];重复进行 n-1趟后,整个排序过程结束 。
/*案例代码文件名,AL7_1.C*/
/*功能:从键盘上任意输入 n个整数,用冒泡法按从小到大地排序,
并在屏幕上显示出来 。 */
#include "stdio.h"
#define N 11 /*定义符号常量 ( 数据个数 N) */
main()
{ int data[N]; /*定义 1个 1维整型数组 data*/
int i,j,t; /*定义循环变量和临时变量 */
clrscr(); /*库函数 clrscr():清屏 */
printf("Please input 10 numbers:\n");
for(i=1; i<N; i++)
scanf("%d",&data[i]);
/*冒泡法排序 */
for(i=1; i<=N-1; i++) /*外循环:控制比较趟数 */
for(j=1; j<=N-i; j++) /*内循环:进行每趟比较 */
if(data[j]<data[j-1]) /*如果 data[j]大于 data[j-1],交换两者的位置 */
{t=data[j];
data[j]=data[j-1];
data[j-1]=t; }
/*输出排序后的数据 */
printf("\nthe result of sort:\n");
for(i=0; i<N; i++)
printf("%d ",data[i]);
}
[程序演示 ]
数组同变量一样,也必须先定义,后使用 。
一维数组是只有 1个下标的数组,定义形式如下:
数据类型 数组名 [常量表达式 ][,数组名 2[常量表达式 2]…… ];
( 1),数据类型,是指数组元素的数据类型 。
( 2) 数组名,与变量名一样,必须遵循标识符命名规则 。
( 3),常量表达式,必须用方括号括起来,指的是数组的元素个数 ( 又称数组长度 ),它是一个整型值,其中可以包含常数和符号常量,但不能包含变量 。
注意,C语言中不允许动态定义数组 。
( 4) 数组元素的下标,是元素相对于数组起始地址的偏移量,
所以 从 0开始顺序编号 。
( 5) 数组名中存放的是一个地址常量,它代表整个数组的首地址 。 同一数组中的所有元素,按其下标的顺序占用一段连续的存储单元 。 [Return]
7.1.2 数组元素的引用引用数组中的任意一个元素的形式:
数组名 [下标表达式 ]
1.,下标表达式,可以是任何非负整型数据,取值范围是 0~( 元素个数 -1) 。
特别强调,在运行 C语言程序过程中,系统并不自动检验数组元素的下标是否越界 。 因此在编写程序时,保证数组下标不越界是十分重要的 。
2,1个数组元素,实质上就是 1个变量,它具有和相同类型单个变量一样的属性,可以对它进行赋值和参与各种运算 。
3,在 C语言中,数组作为 1个整体,不能参加数据运算,只能对单个的元素进行处理 。
[Return]
7.1.3 1维数组元素的初始化初始化格式,
数据类型 数组名 [常量表达式 ]= {初值表 };
( 1) 如果对数组的全部元素赋以初值,定义时可以不指定数组长度 ( 系统根据初值个数自动确定 ) 。 如果被定义数组的长度,与初值个数不同,则数组长度不能省略 。 如,int a[]={1,2,4,8}; int a[5]={0};int a[10]={1,4,8};
( 2),初值表,中的初值个数,可以少于元素个数,
即允许只给部分元素赋初值 。 int a[10]={1,4,8};
( 3) 根据存储类型的不同,数组有静态数组 ( static)
和动态数组 ( auto) 之分;根据定义的位置不同,数组有内部数组 ( 在函数内部定义的数组 ) 和外部数组 ( 在函数外部定义的数组 ) 之分 。
[Return]
7.1.4 一 维数组应用举例
[案例 7.2] 已知某课程的平时、实习、测验和期末成绩,求该课程的总评成绩。其中平时、实习、测验和期末分别占 10%,20%、
20%,50%。
/*案例代码文件名,AL7_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')
{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()函数等待从键盘上输入一个字符 */
}
}
[程序演示 ]
[Return]
7.2 2维数组的定义和引用
7.2.1 2维数组的定义
7.2.2 2维数组元素的引用
7.2.3 2维数组元素的初始化
7.2.4 2维数组应用举例
[Return]
二维数组的定义方式如下:
数据类型 数组名 [行常量表达式 ][列常量表达式 ][,数组名
2[行常量表达式 2][列常量表达式 2]……];
1.数组元素在内存中的排列顺序为“按行存放”,即先顺序存放第一行的元素,再存放第二行,以此类推。
2,设有一个 m*n的数组 x,则第 i行第 j列的元素 x[i][j]在数组中的位置为,i*m+j( 注意,行号、列号均从 0开始计数)。
3.可以把 2维数组看作是一种特殊的 1维数组:它的元素又是一个 1维数组。
例如,对 x[3][2],可以把 x看作是一个 1维数组,它有 3个元素,x[0]、
x[1],x[2],每个元素又是一个包含 2个元素的 1维数组,如图 7-4所示 。
即把 x[0],x[1],x[2]看作是 3个 1维数组的名字 。
X[0]-------------x00 x01
X[1]-------------x10 x11
X[2]-------------x20 x21 [Return]
7.2.1 二维数组的定义
7.2.2 2维数组元素的引用引用 2维数组元素的形式为:
数组名 [行下标表达式 ][列下标表达式 ]
1.,行下标表达式,和,列下标表达式,,都应是整型表达式或符号常量 。
2.,行下标表达式,和,列下标表达式,的值,都应在已定义数组大小的范围内 。 假设有数组 x[3][4],则可用的行下标范围为 0~2,列下标范围为 0~3。
3,对基本数据类型的变量所能进行的操作,也都适合于相同数据类型的二维数组元素 。
[Return]
7.2.3 二 维数组元素的初始化
1,按行赋初值数据类型 数组名 [行常量表达式 ][列常量表达式 ]= {{第 0行初值表 },{第 1行初值表 },……,{最后 1行初值表 }};
赋值规则:将,第 0行初值表,中的数据,依次赋给第 0行中各元素;将,第 1行初值表,中的数据,依次赋给第 1行各元素;以此类推 。
A[2][3]={{0,1,2},{3,4,5}}
2,按 2维数组在内存中的排列顺序给各元素赋初值数据类型 数组名 [行常量表达式 ][列常量表达式 ]= {初值表 };
赋值规则:按 2维数组在内存中的排列顺序,将初值表中的数据,
依次赋给各元素 。
如果对全部元素都赋初值,则“行数”可以省略。 注意,只能省略“行数”。
Int a[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};
3.可以对部分元素赋初值 int a[3][4]={{1},{3},{6}}
[Return]
[案例 7.3] 给一个 2* 3的 2维数组各元素赋值,并输出全部元素的值 。
/*案例代码文件名,AL7_3.C*/
/*功能:从键盘上给 2* 3数组赋值,并在屏幕上显示出来 。 */
#define Row 2
#define Col 3
#include "stdio.h"
main()
{ int i,j,array[Row][Col]; /*定义 1个 2行 3列的 2维数组 array*/
for(i=0; i<Row; i++) /*外循环:控制 2维数组的行 */
for(j=0; j<Col; j++) /*内循环:控制 2维数组的列 */
{printf("please inputarray[%2d][%2d]:",i,j);
scanf("%d",&array[i][j]); /*从键盘输入 a[i][j]的值 */
}
printf("\n");
/*输出 2维数组 array*/
for(i=0;i<Row;i++)
{ for(j=0;j<Col;j++)
printf("%d\t",array[i][j]); /*将 a[i][j]的值显示在屏幕上 */
printf("\n"); }
}
7.2.4 2维数组应用举例例 7.4有一个 3× 4的矩阵,要求编程序求出其中最大的那个元素的值,以及其所在的行号和列号 。
main()
{int I,j,col=0,row=0,max;
int a[3][4]={{1,2,3,4},{45,14,-21,21},{9,15,13,-78}};
max=a{0][0];
for (I=0;I<=2;I++)
for(j=0;j<=3;j++)
if (a[I][j]>max)
{max=a[I][j];
I=row;
j=col;}
printf("max=%d,row=%d,col=%d\n",max,row,col);
}
[案例 7.5] 有 M个学生,学习 N门课程,已知所有学生的各科成绩,
编程:分别求每个学生的平均成绩和每门课程的平均成绩。
/*案例代码文件名,AL7_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[i][NUM_course] += score[i][j];/*求第 i个人的总成绩 */
score[NUM_std][j]+= score[i][j];/*求第 j门课的总成绩 */
}
score[i][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("%7.1f\t",score[i][j]);
printf("\n"); }
/*输出 1条短划线 */
for(j=0;j<8*(NUM_course+2);j++)
printf("-");
printf("\n课程平均 ");
for(j=0;j<NUM_course;j++) /*输出每门课程的平均成绩 */
printf("%7.1f\t",score[NUM_std][j]);
printf("\n");
getch(); } [程序演示 ] [Return]
7.3 字符数组与字符串
7.3.1 字符数组的逐个字符操作
7.3.2 字符数组的整体操作
7.3.3 常用的字符串处理函数
[Return]
7.3.1 字符数组的逐个字符操作
[案例 7.5]从键盘输入一个字符串,回车键结束,并将字符串在屏幕上输出 。
/*案例代码文件名,AL7_5.C*/
main()
{int i;
static char str[80];
clrscr();
for(i=0;i<80;i++)
{ str[i]=getch(); /*逐次给数组元素 str[i]赋值,但不回显在屏幕上 */
printf("*"); /*以星号代替输入字符的个数 */
if(str[i]=='\x0d') break;/*若输入回车则终止循环 */
}
i=0;
while(str[i]!='\x0d')
printf("%c",str[i++]); /*逐次输出字符数组的各个元素 */
printf("\n");
getch(); /*程序暂停 */
} [程序演示 ]
1,字符数组的定义字符数组,用于存储和处理字符串,其定义格式与数值数组一样 。
Char ch[4];
Ch[0]='I';ch[1]=' ';ch[2]='a';ch[3]='m';
2,字符数组的初始化字符数组的初始化,可以通过为每个数组元素指定初值字符来实现 。
3,字符数组的引用字符数组的逐个字符引用,与引用数值数组元素类似 。
( 1) 字符数组的输入除了可以通过初始化使字符数组各元素得到初值外,
也可以使用 getchar()或 scanf()函数输入字符 。
例如:
char str[10];
……
for(i=0; i<10; i++) /*或 scanf("%s",str)*/
{ scanf("%c",&str[i]);
fflush(stdin); /*清除键盘输入缓冲区 */
}
……
( 2) 字符数组的输出字符数组的输出,可以用 putchar()或 printf()函数 。
例如:
char str[10]="c language";
……
for(i=0; i<10; i++) printf("%c",str[i]); /*或 printf("%s",str);*/
printf("\n");
……
注意,逐个字符输入,输出时,要指出元素的下标,而且使用,%c”格式符 。 另外,从键盘上输入字符时,无需输入字符的定界符 ──单引号;输出时,系统也不输出字符的定界符 。
[Return]
7.3.2 字符数组的整体操作
[案例 7.7] 字符数组的整体输入与输出 。
/*案例代码文件名,AL7_7.C*/
/*功能:将 2维字符数组进行初始化,并在屏幕上输出 */
main()
{ int i;
char name[5][9]={"张三山 ","李四季 ","王五魁 ","刘六顺 ","赵七巧 "};
for(i=0;i<5;i++)
printf("\n%c\t",name[i]); /*name[i]代表该行数组元素的首地址 */
getch();
} [程序演示 ]
1.字符串及其结束标志所谓字符串,是指若干有效字符的序列。 C语言中的字符串,可以包括字母、数字、专用字符、转义字符等。
C语言规定:以‘ \0?作为字符串结束标志(‘ \0?代表 ASCII码为 0的字符,表示一个“空操作”,只起一个标志作用)。因此可以对字符数组采用另一种方式进行操作了 ──字符数组的整体操作 。
注意,由于系统在存储字符串常量时,会在串尾自动加上 1个结束标志,所以无需人为地再加 1个 。
另外,由于结束标志也要在字符数组中占用一个元素的存储空间,
因此在说明字符数组长度时,至少为字符串所需长度加 1。
2,字符数组的整体初始化字符串设置了结束标志以后,对字符数组的初始化,就可以用字符串常量来初始化字符数组 。
3,字符数组的整体引用
( 1) 字符串的输入除了可以通过初始化使字符数组各元素得到初值外,也可以使用
scanf()函数输入字符串 。
( 2) 字符串的输出
printf()函数,不仅可以逐个输出字符数组元素,还可以整体输出存放在字符数组中的字符串 。
[Return]
7.3.3 常用的字符串处理函数字符串标准函数的原型在头文件 string.h中 。
1,输入字符串 ──gets()函数
( 1) 调用方式,gets(字符数组 )
( 2) 函数功能:从标准输入设备 (stdin)──键盘上,读取
1个字符串 ( 可以包含空格 ),并将其存储到字符数组中去 。
( 3) 使用说明
1) gets()读取的字符串,其长度没有限制,编程者要保证字符数组有足够大的空间,存放输入的字符串 。
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()函数来处理 。
[案例 7.7] gets函数和 strcmp函数的应用 。
/*案例代码文件名,AL7_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'。
7,求字符串长度 ──strlen()函数 ( len是 length的缩写 )
( 1) 调用方式,strlen(字符串 )
( 2) 函数功能:求字符串 ( 常量或字符数组 ) 的实际长度
( 不包含结束标志 ) 。
7,将字符串中大写字母转换成小写 ──strlwr()函数
( 1) 调用方式,strlwr(字符串 )
( 2) 函数功能:将字符串中的大写字母转换成小写,其它字符 ( 包括小写字母和非字母字符 ) 不转换 。
8,将字符串中小写字母转换成大写 ──strupr()函数
( 1) 调用方式,strupr(字符串 )
( 2) 函数功能:将字符串中小写字母转换成大写,其它字符
( 包括大写字母和非字母字符 ) 不转换 。
[Return]
7.3.4字符数组应用举例例 7.6输入一行字符,统计其中有多少个单词,单词之间用空格分隔开。
#include <stdio.h>
main()
{char str[81]
int I,num=0,word=0;
char c;
gets(str);
for(I=0;(c=str[i])!='\0';I++)
if(c=='')word=0;
else if(word==0)
{word=1;
num++;
}
printf("there are %d words in the line.\n",num);
}
例 7.7 有 3个字符串,要求找出最大者。
#include<stdio.h>
#include<string.h>
Main()
Char string[20];
Char str[3][20];
Int I;
For (I=0;I<3;I++)
Gets(str[i]);
If(strcmp(str[0],str[1])>0) strcpy(string,str[0]);
Else strcpy(string,str[1]);
If(strcmp(str[2],string)>0) strcpy(string,str[2]);
Printf("\nthe largest string is,\n%s\n",string);
}
作业:
P141
7.2,7.3,7.5,7.10,7.11
下列程序的运行结果是
#include<stdio.h>
main()
{int i,j=4;
for(I=j;I<=2*j;I++)
swith(I/j)
{case 0:
case 1:printf("*");break;
case 2:printf("#");
}
}
下列程序的运行结果是
#include<stdio.h>
main()
{int m,n;
printf(""enter m,n:");
scanf("%d%d",&m,&n);
while(m!=n)
{while(m>n )m- =n;
while(n>m)n- =m;
}
printf("m=%d\n",m);
}
从键盘输入的 10个整数中,找出第一个能被 7整除的数。若找到,打印此数后退出循环;
若未找到,打印,no exist”.
#include<stdio.h>
Main()
{int I,a;
for (I=1;I<=10;I++)
{scanf("%d",&a);
if(a%7==0)
{printf("%d",a);
__________;}
}
if ( ___) printf("no exist\n");
}
打印 100以内个位数为 6,且能被
3整除的所有数。
#include<stdio.h>
Main()
{int I,j;
for (I=0;____;I++)
{j=I*10+6;
if (___) continue;
Printf("%d",j);
}
}