6 数组
请大家 及时消化 我课上讲的内容,并举一反三,模仿未讲过的例题多写程序。
如果说学习 C语言有捷径的话:那就是 多读程序,多写程序
以后会越来越难,因此一定要对前面的知识及时理解和掌握。
看懂、听懂并不等于会用。
课堂上时间有限,大家一定要及时预习和复习。
复习时注意只需要把我课上讲的几个例题理解透彻并掌握即可
写程序时注意两个关键,思路(算法) 清晰! 语法 格式正确!
2
问题:
例 1:输入全班 60个学生的 C语言成绩并统计不及格的人数。
分析:
输入 60个成绩
统计人数
输出统计结果
1.如何定义变量?
2.在数学中怎样解决这个问题?
score1,score2,……,
scorei,……,score60
3
1定义变量用于存储成绩
int score[60];
数组名
(这一组数的共同名字 )
数组 长度
含义:向系统申请 60*sizeof(int)个字节的连续空间,用于存储 60个成绩,它们共同的名字 score。将来数组中的每一个元素就分别是 score[0],score[1]、
score[2],……,score[59],此时,方括号里的数字不再表示长度,而是 下标 。
它们的名字 score表示这一串内存的起始地址。
4
……
内存地址:
1001
1002
1003
1004
1119
1120
数组的内存分配
scorescore[0]
score[1]
score[59]
score[2]
score[3]
……
注意下标从 0开始
5
涉及的语法
-数组 定义及相关概念
数组:一组具有类型相同、顺序存放的数据
什么时候定义数组?
定义格式:
数据类型 数组名 [数组长度 ];
注:数组长度必须是常数或常量。
例,int score[60];
含义:
6
2、输入 60个成绩
循环 60次输入
for (i=0;i<60;i++)
scanf("%d",&score[i]);
使用数组的每一个元素也称 数组元素的引用 。
7
3、统计不及格人数
从第一个学生起,判断每一个学生的成绩是否小于 60,是的话计数器加 1
for (i=0;i<60;i++)
if(score[I]<60)
counter++;
4、输出:
8
完整程序
#include<stdio.h>
#define N 60
void main()
{int score[N];//定义时,N不能是变量,只能是常量。
int i,counter=0;
for (i=0;i<N;i++) /*输入 */
scanf("%d",&score[i]);
for (i=0;i<N;i++) /*统计 */
if(score[i]<60)
{ counter++;}
printf("The number of unpassed students:%d",counter);
}
Q:有什么好处?
A:测试时可以只将此处改为容易测试的数目
9
例 2
求 Fibonacci数列前 40项
算法:
定义数组
求每一项
输出每一项
fib(n)= 1 ( n= 0,1)fib(n-2)+ fib(n-1) ( n>1)
int fib[40]={1,1};
/*为数组的第一、二个元素进行 初始化,
其它自动为 0*/
for(i=2;i<40;i++)
fib[i]=fib[i-2]+fib[i-1];
/*循环求剩余的 38项 */
for(i=0;i<40;i++)
{ if(i%4==0)/*每输出四个数,输出一个回车 */
printf("\n");
printf("%12d",fib[i]);
}
10
例 2:完整程序
#include <stdio.h>
void main()
{ int i,fib[40]={1,1};
for(i=2;i<40;i++)
fib [i]=fib[i-2]+fib [i-1];
for(i=0;i<40;i++)
{ if(i%5==0)
printf("\n");
printf("fib[%d]=%5d\t",i,fib[i] ) ;
}
}
11
例 3:统计总分和平均分
算法:
输入全班学生的成绩
统计总分
计算平均分
输出总分和平均分
#include <stdio.h>
#define N 60
void main()
{int a[N],i;
float sum=0,ave;
puts("please input %d score:",N);
for(i=0;i<N;i++)
{ scanf("%d",&a[i]);
sum+=a[i];
}/*输入并统计总分 */
ave=sum/N;
printf(" Sum=%.1f,Average=%.1f.\n",sum,ave);
}
将 "求一个数组所有元素之和 " 写成函数,怎样写?
12
写成多函数形式
#include <stdio.h>
#define N 60
/*函数功能:求一个长度为 n的数组中所有元素的总和 */
float Sum(int a[],int n)
{int i;
float sum=0;
for(i=0;i<n;i++)
{ sum+=a[i];
}/*统计总分 */
return sum;
}
void main()
{int score[N],i;
float sum=0,ave;
puts("please input %d score:",N);
for(i=0;i<N;i++)
{ scanf("%d",& score[i]);
}/*输入 */
sum=Sum(score,N);
/*函数调用,注意 数组名做实参 */
printf("Sum=%.1f,Average=%.1f.\n",
sum,sum/N);
}
重点:数组名做函数参数
调用过程?
13
难点:函数调用过程形参 a
Sum函数
6000
数组 score
主函数
67
78
97
79
6000
67
78

79
97
数组主函数参数传递过程:
实参是主函数中的数组名,因此,传过来的是数组首地址
形参 看似是一个数组,其实,只是一个变量,接收了传递过来的数组名(首地址)
因此形参和实参均指的是 同一个数组
只是名称和作用域各不相同,在主函数中只能使用
score,在 Sum函数中只能使用 a
14
涉及语法
-数组名作函数参数
传递整个数组到另一个函数内,只是 将数组的首地址作为参数传过去
用数组名作为函数参数
只拷贝一个地址自然比拷贝全部数据效率高
由于首地址相同,故 实参数组与形参数组占用同一段内存
这样,在该函数内,不仅可以读这个数组的元素,
还可以修改它们
普通变量 做参数,形参另占 一个 存储空间,存储由实参传递过来的 数值 。
数组 做参数,形参另占 一个 存储空间,存储由实参传递过来的 地址 。
15
小结 1
数组和数组元素的概念
数组的定义、初始化、数组元素的引用
与数组相关的程序设计
数组作函数参数
理解数组作函数参数的传递过程
理解并记住形参和实参的格式
16
作业 1
将例 2写成多函数程序,要求:
定义一个函数,求 Fibonacci数列的前 n项。
求某门课程的最高分并输出,要求:
定义一个函数,求数组中的最大值,然后在主函数中调用这个函数求课程的最高分。
17
求 Fibonacci数列的前 n项
#include<stdio.h>
#define N 100
void Fibonacci(float a[],int n);//函数声明
//函数功能:求 Fibonacci数列的前 n项,存入数组 a中
void Fibonacci(float a[],int n)
{
int i;
a[0]=a[1]=1;
for(i=2;i<n;i++)
a[i]=a[i-1]+a[i-2];
//数列已经写到 a中,其实就已经写到主函数的 fib数组中。所以不用返回 。
}
void main()
{
float fib[N];//数组长度可以定义得大一些。
int i,n;
printf("how many terms do you want to count? (0<term<=100)");
scanf("%d",&n);//由用户输入想求得的项的数目。
Fibonacci(fib,n);//调用函数求前 n项。
for(i=0;i<n;i++)
{ printf("fib[%d]=%.0f\n",i+1,fib[i]);
//输出 fib数组的元素。不能输出 a[i],因为作用域不同。
}
}
18
求 60个学生的最高分
算法:
输入 60个学生的成绩
依次比较,找出最高分(写成函数)
输出最高分。
19
方法一:
#include <stdio.h>
#define N 60
int Max_i(int a[],int n); //函数声明
void main()
{ int i,a[N],max_i;
printf("Input %d score:\n",N);
for(i=0;i<=N-1;i++)
scanf("%d",&a[i]);
max_i=Max_i(a,N); //调用函数求 a中最大值对应的下标
printf("\n The maximum score is %d,\n ",
a[max_i]);
}
/*函数功能:求一个长度为 n的数组 a中的最大值所对应的下标 */
int Max_i(int a[],int n)
{int i,max_i;
max_i=0; /*假设最大值对应的下标为 0*/
for(i=1;i<=n-1;i++)
if(a[i]>a[max_i])
{ max_i=i; } /*求最大元素对应的下标 */
return max_i;
}
20
方法二:
#include <stdio.h>
#define N 60
int Max (int a[],int n);//函数声明
void main()
{ int a[N],i,max;
printf("Input %d score:\n",N);
for(i=0;i<=N-1;i++)
scanf("%d",&a[i]);
max=Max (a,N);//调用函数求 a中最大值
printf("\n The maximum score is %d,\n ",
max);
}
/*函数功能:求一个长度为 n的数组 a中的最大值 */
int Max (int a[],int n)
{int i,max;
max=a[0]; /*假设最大值对应的下标为 0*/
for(i=1;i<=N-1;i++)
max=max>a[i]?max:a[i];
/*求最大元素对应的下标 */
return max;
}
21
例 5:在数组中查找某个数据方法一:顺序查找:按数组下标顺序查找哈,找到了!
22
方法一:顺序查找
//函数功能:用 顺序查找法 在具有 n个元素的数组 a中查找 x,返回第一次出现的下标。
//虽然在时间上要先定义函数,但往往将函数定义放在 main()之后 。
int Search(int a[],int n,int x)
{
int i;
for (i=0; i<n; i++)
{
if (a[i] == x)
{
return (i);//找到返回下标。
}
}
return (-1);//没找到返回 -1
}
23
例 5完整程序(方法一)
#include <stdio.h>
#define N 200
int Search(int a[],int n,int x);
void main()
{ int i,a[N],x,find_i;
printf("Input %d score:\n",N);
for(i=0;i<=N-1;i++)
scanf("%d",&a [i]);
printf("please input the number to search:");
scanf("%d",&x); /*输入要找的数 x*/
find_i=Search(a,N,x);//调用下边的函数查找
if(find_i==-1) /*find_i的值没变,表示没找到 */
printf("not found!");
else
printf("found!,a[%d]=%d\n",find_i,a[find_i]);
}
//函数功能:用 顺序查找法 在具有 n个元素的数组 a中查找 x,返回第一次出现的下标。
//虽然在时间上要先定义函数,但往往将函数定义放在 main()之后 。
int Search(int a[],int n,int x)
{ int i;
for (i=0; i<n; i++)
{ if (a[i] == x)
return (i); //找到返回下标。
}
return (-1);//没找到返回 -1
}
24
方法二 二分(折半查找)
我们查字典的时候怎样查找?
在 已经排好序的情况下 可以进行二分查找。
过程:先找到查找区域的中点,如果中间比要找的值小,说明要找的值在右半边,反之,在左半边,相等则表示找到。若没有找到,在新的查找区域,继续这样查找,直至所有的区域都找到。
25
二分(折半)查找数组下标 0 1 2 3 4 5 6
第一次循环,99011 99013 99015 99017 99019 ① 查找值 x=99017
low mid high x>a[mid],low=mid+1
第二次循环,99011 99013 99015 99017 99019
low=mid high x=a[mid],找到哈,找到了!
26
二分(折半)查找数组下标 0 1 2 3 4 5 6
第一次循环,99011 99013 99015 99017 99019 ② 查找值 x=99016
low mid high x>a[mid],low=mid+1
第二次循环,99011 99013 99015 99017 99019
low=mid high x<a[mid],high=mid-1
第三次循环,99011 99013 99015 99017 99019
high low 不满足 low<=high,循环结束,未找到唉,没找到!
27
二分(折半)查找
//函数功能:用 二分法 在具有 n个元素的数组 a中查找 x,返回第一次出现的下标。
//虽然在时间上要先定义函数,但往往将函数定义放在 main()之后 。
int BinSearch_(int a[],int n,int x)
{ int left=0,right=n-1,mid,find_i=-1;//标志变量
/*当还有区域没找,而且还未找到的时候循环查找 */
while (left <= right&&find_i==-1)
{ mid = (left + right) / 2; /*求区域的中点 */
if (x > a[mid]) /*重新设定右边界 */
{ left = mid + 1;}
else if (x < a[mid]) /*重新设定左边界 */
{ right = mid - 1; }
else /*找到,结束 */
{ find_i=mid; }
}
return find_i;
}
28
例 5完整程序(方法二)
#include <stdio.h>
#define N 200
int BinSearch(int a[],int n,int x);
void main()
{ int a[N],i,x,find_i;
printf("Input %d score:\n",N);
for(i=0;i<=N-1;i++)
scanf("%d",&a [i]);
printf("please input the number to search:");
scanf("%d",&x); /*输入要找的数 x*/
find_i=BinSearch(a,N,x);//调用下边的函数查找
if(find_i==-1) /*find_i的值没变,表示没找到 */
printf("not found!");
else
printf("found!,a[%d]=%d",find_i,x);
}
//函数功能:用二分法在具有 n个元素的数组 a中查找 x,返回第一次出现的下标。
//虽然在时间上要先定义函数,但往往将函数定义放在 main()之后。
int BinSearch(int a[],int n,int x)
{ int left=0,right=n-1,mid,find_i=-1;//标志变量
/*当还有区域没找,而且还未找到的时候循环查找 */
while (left <= right&&find_i==-1)
{ mid = (left + right) / 2; /*求区域的中点 */
if (x > a[mid]) /*重新设定右边界 */
{ left = mid + 1;}
else if (x < a[mid]) /*重新设定左边界 */
{ right = mid - 1; }
else /*找到,结束 */
{ find_i=mid; }
}
return find_i;
}
29
例 6 对 200个学生成绩从大到小排序
算法
输入 200个成绩
排序(写成函数)
输入排序结果
30
冒泡法 对 N个数从大到小排序:
第 0趟排序:比较 a[0]和 a[1],不满足顺序交换,
再比较 a[1]和 a[2],不满足顺序交换,依此类推,
直至 a[N-2]和 a[N-1]比较,不满足顺序交换,
通过这一趟的两两比较找到第 1个最小的数放在
a[N-1]的位置
……
第 J趟排序:比较 a[0]和 a[1],不满足顺序交换,
再比较 a[1]和 a[2],不满足顺序交换,依此类推,
直至 a[N-j-2]和 a[N-j-1]比较,不满足顺序交换,通过这一趟的两两比较找到第 j+1个最小的数放在 a[N-j-1]的位置
共 N-1趟
for(j=0;j<=N-2;j++)
{ /*第 j趟排序 */
}
/*通过依次比较 a[I]和 a[I+1],不满足顺序交换 */
for(i=0;i<=(N-2)-j;i++)
if(a[i]>a[i+1])
{t=a[i];a[i]=a[i+1];a[i+1]=t;}
31
例 6完整程序,冒泡法
//函数功能:用 冒泡法 对有 n个数组元素的数组 a进行排序
//先定义函数,但往往将函数定义放在 main()之后 。
void Sort_bubble(int a[],int n)
{int i,j,t;
for(j=0; j<=n-2; j++) /*冒泡法 排序 */
for(i=0; i<=(n-2)-j; i++)
if(a[i]<a[i+1])
{t=a[i];a[i]=a[i+1];a[i+1]=t;}
/*由于形参数组和实参数组是同一个数组,所以,对 a进行排序,
实际上就是对主函数中的 score数组进行排序。因此不需要返回。
*/
}
#include <stdio.h>
#define N 4
void Sort_bubble(int a[],int n);//函数声明
void main()
{ int score [N],i;
printf("Input %d score:\n",N);
for(i=0;i<=N-1;i++)
scanf("%d",&score [i]);
Sort_bubble(score,N);
printf(" \n The sorted score:\n");
for(i=0;i<=N-1;i++)
{ if(i%15==0) printf("\n");
printf("%4d ",score[i]);
}
}
32
选择法 对 N个数从大到小排序
第 0趟排序:从 a[0]至 a[N-1],比较找出其中最大数所在的下标 k,若 k!=0,说明 a[k]比 a[0]
大,则交换 a[0]和 a[k],通过这一趟的比较找到第 1个最大的数放在 a[0]的位置
……
第 J趟排序:从 a[j]至 a[N-1],比较找出其中最大数所在的下标 k,若 k!=j,说明 a[k]比 a[j]
大,则交换 a[j]和 a[k],通过这一趟的比较找到第 j+1个最大的数放在 a[j]的位置
共 N-1趟
for(j=0;j<=N-2;j++)
{ /*第 j趟排序,通过这一趟排序,找到第 j+1大的数存于 a[j]*/
}
/*从 a[j]至 a[N-1],比较找出其中最大数所在的下标 max_i
*/
/*若 max_i!=j,说明 a[max_i]比 a[j]大,则交换 */
max_i=j;
for(i=j+1;i<=N-1;i++)
if(a[i]>a[max_i])
{max_i=i;}
if(max_i!==j)
{t=a[max_i]; a[max_i]=a[j]; a[j]=t; }
33
例 6完整程序,选择法
//函数功能:用 选择法 对有 n个数组元素的数组 a进行排序
//先定义函数,但往往将函数定义放在 main()之后 。
void Sort_select(int a[],int n)
{int i,j,max_i,t;
for(j=0;j<=n-2;j++) /*选择法排序 */
{ max_i=j;
for(i=j+1;i<=n-1;i++)
if(a[i]>a[max_i]) /*若从小到大排序,改成 <*/
{max_i=i;}
if(max_i! =j)
{t=a[max_i]; a[max_i]=a[j]; a[j]=t; }
}
/*由于形参数组和实参数组是同一个数组,所以,对 a进行排序,实际上就是对主函数中的 score数组进行排序。
因此不需要返回。 */
}
#include <stdio.h>
#define N 200
void Sort_select int a[],int n);
void main()
{ int score [N],i;
printf("Input %d score:\n",N);
for(i=0;i<=N-1;i++)
scanf("%d",&score [i]);
Sort_select(score,N);
printf(" \n The sorted score:\n");
for(i=0;i<=N-1;i++)
{ if(i%15==0) printf("\n");
printf("%4d ",score[i]);
}
}
34
#include <stdio.h>
#define N 3
void Sort_select(int a[],int n);
int Max_i(int a[],int n);
void main()
{ int score [N],i;
printf("Input %d score:\n",N);
for(i=0;i<=N-1;i++)
scanf("%d",&score [i]);
Sort_select(score,N);
printf(" \n The sorted score:\n");
for(i=0;i<=N-1;i++)
{ if(i%15==0) printf("\n");
printf("%4d ",score[i]);
}
}
void Sort_select(int a[],int n) //函数功能:用选择法对有 n个数组元素的数组 a进行排序
{int j,max_i,t;
for(j=0;j<=n-2;j++) /*选择法排序 */
{ max_i= Max_i(&a[j],n-j); //调用函数求 a[j]以后元素的最大值对应的下标。
if((max_i+j)!=j) //如果求得的最大值的下标不是当前这个元素,则二者交换。
{t=a[max_i+j]; a[max_i+j]=a[j]; a[j]=t; }
}
/*由于形参数组和实参数组是同一个数组,所以,对 a进行排序,实际上就是对主函数中的 score数组进行排序。因此不需要返回。 */
}
int Max_i(int a[],int n) /*函数功能:求一个长度为 n的数组 a中的最大值所对应的下标 */
{int i,max_i;
max_i=0; /*假设最大值对应的下标为 0*/
for(i=1;i<=n-1;i++)
if(a[i]>a[max_i])
{ max_i=i; } /*求最大元素对应的下标 */
return max_i;
}
作业:读程序
35
小结
我们已经讲了数组的最常见的应用
计算总和、平均分
查找最大值、特定值
排序?当数组里存储的是字符串时该怎样修改前边例题的程序?
36
例 7:输入一个字符串,统计这个字符串中有多少个英文字母?
算法:
输入 string
统计英文字母的个数 number
输出 number
37
程序
#include<stdio.h>
void main()
{int i,number=0;
char a[30];
puts("please input a string:");
gets(a); /*一次性输入字符串,存入 a数组中 */
for(i=0;a[i]!='\0';i++) /*统计 */
{ if(a[i]>='a'&& a[i]<=?z')||(a[i]>='A'&& a[i]>='Z')
{number++;
}
}
printf("the string,%s has %d letter!\n",a,number);
}
gets()是 C语言库函数,gets(a)的含义是:将从键盘上 输入 的一串字符存储在数组 a中。
也可用 scanf("%s",a);实现输入,
注意 a是数组名,表示数组的起始地址,因此 不用再写&
二者的主要区别是 gets遇回车结束,
所以可以输入句子 。 Scanf()遇到空格结束,所以,只能输入单词 。另一个区别是 scanf()后遗留下表示输入结束后的空格或回车。因此,往往在用 scanf()后,还要再加一个
getchar()吸收掉那个回车或空格。
输出可以用 puts(a),也可以用
printf ("%s",a);两者的区别在于前者在输出字符串后还多输出一个回车。
/*一般字符数组中存储的字符串长度不定,所以循环条件不能用
I<30这样的语句限定,而应用
a[i]!='\0'作为循环结束条件 */
38
例 8
查找字符在字符串中出现的位置
算法
定义字符数组用来存储字符串
查找 (写成函数 )
输出查找结果
39
#include <stdio.h>
#define N 200
void Search(char a[],char x);
void main()
{
char ch,a[30]=“I am a teacher.,;
/*一般用字符串常量对字符数组 初始化,系统会自动在末尾加 ‘ \0?.也可以用 char
a[30]={?I?,,?a?,?m?,,?a?,,?t?,?e?,?a?,?c?,?h?,?e?,?r?,?.?};但不会自动加 ’ \0?,请注意体会两者的区别。 */
printf("please input a character to search:");
ch=getchar(); /*输入要找的数 x*/
Search(a,ch);//调用下边的函数查找
}
//函数功能:用 顺序查找法 在字符串 a中查找 x,输出找到的位置。
//虽然在时间上要先定义函数,但往往将函数定义放在 main()之后。
void Search(char a[],char x)
{ int i,counter=0,;
for (i=0; a[i]!='\0'; i++)
{ if (a[i] == x)
printf("found %dth!,a[%d]=%d\n",++counter,i,a[i]);; //找到输出。
}
if(counter==0)
printf("not found!");//没找到
}
Q:若想实现,在任意字符串中查找是否存在任意要找的字符,。
A,由用户输入 a,一般不直接初始化。
40
字符数组与数值型数组的区别
字符数组有两种用途
第一种是存储字符型的数据,这种应用与数值型的数组除类型没有什么区别,字符要一个一个地处理。例如:用一个字符数组存储 30个学生的性别。
第二种,而且是更多的情况下,往往用字符数组来处理字符串,这样,两者的区别比较明显,主要体现在:
字符型数组定义时长度要尽量大一些,至少要为 '\0'留出位置。
字符串经常整体处理。例如:字符串的输入输出 不用循环 实现,直接调用一次函数就能实现一串字符的输入、输出。
对字符串进行循环操作时,一般循环条件为:遇到 ‘ \0?结束。
或者也可用 i<strlen(a)作为循环条件,不能用 i<n,因为字符串的长度一定是小于所申请的数组长度的。
41
与字符串相关的库函数
在 <string.h>中定义了若干专门的字符串处理函数
strlen,
strlen(字符串 );
返回字符串的实际长度,即不包括 '\0'的实际字符个数
strcpy:
strcpy(目的字符串,源字符串 );
strcat:
strcat(目的字符串,源字符串 );
strcmp:
strcmp(字符串 1,字符串 2);
当出现第一对不相等的字符时,就由这两个字符决定所在字符串的大小
返回其 ASCII码比较的结果值
作业 1,P178
还有两个函数,
请自学。
42
例 9:求最小字符串
从键盘任意输入 5个学生的姓名,编程找出并输出按字典顺序排在最前面的学生姓名
算法:
输入字符串 str,并将其赋值给 min
循环 4次:输入一个字符串 str,比较 str和 min,若
str小,再将 str赋值给 min。
输出 min
43
#include <stdio.h>
#include <string.h>
#define ARRA_SIZE 80
void main()
{
int n,num;
char str[ARRA_SIZE],min[ARRA_SIZE];
printf("Please enter five names:\n");
gets(str);
strcpy(min,str);
for (n=1; n<5; n++)
{
gets(str);
if (strcmp(str,min) < 0)
{
strcpy(min,str);
}
}
printf("The min is:");
puts(min);
}
程序
另一种解法,用二维数组
44
错误 2,if (min > str)
最容易出现的错误
错误 1,min = str;
字符串不能直接整体复制!
strcpy(min,str); /*正确 */
也不能用关系运算符比较大小
if (strcmp(min,str) > 0) /*正确 */
写错也不会提示语法错误,为什么?
45
例 10 判断回文数
例,123454321是回文数
再例,12345321不是回文数
算法:
1 2 3 4 5 3 2 1 \0 \0 \0
i=0 j=strlen(str)-1
str
i=1 j=strlen(str)-2……
46
#include <stdio.h>
#include <string.h>
void main()
{ int i,j,equal=1;
char str[20];
printf("Input a integer,");
scanf("%s",str);
for(i=0,j=strlen(str)-1;i<j&&equal;i++,j--)
{ if(str[i]!=str[j])
{ equal=0;
}
}
if(equal)
printf("\n %s is a palindrome!\n",str);
else
printf(" %s isn't a palindrome!\n",str);
}
例 10 程序
47
小结 2
注意数值数组与字符数组的区别
几个用于字符串处理的库函数
48
作业 2:
作业 2:
读程序(例 5的选择法的第二个程序)
自己定义函数实现 strlen(),strcat(),strcmp()
三个程序的功能,当然,其中不能直接使用这三个库函数。
自己定义函数,将一个字符串的内容倒置。例如,abcde转换为 edcba.
49
写函数,计算字符串长度
算法:
输入字符串
计算其中的字符个数
从第一个字符数起,只要不到末尾,就加 1
输出
#include<stdio.h>
unsigned int My_strlen(char a[]);
/*函数功能:求一个字符串中字符个数 */
unsigned int My_strlen(char a[])
{int i,number=0;
for(i=0;a[i]!=0;i++)
{number++;
}
return number; /*直接返回 i(不用 number)即可 */
}
void main()
{
char str[50];
int n;
puts(“please input a string”);
scanf("%s",str);
n=My_strlen(str);
printf("strlen(\" %s\")=%d.\n",str,n);
}
50
写函数,比较字符串大小
算法:
输入两个字符串 a,b
比较字符串 a,b的大小
从第一对字符比起,当两个对应的字符不相等或者字符串结束时,循环结束,并计算两者之差,否则继续比较。
输出
z h a n g l i n g \0 \0
z h a n g y u \0 \0 \0 \0
#include<stdio.h>
int My_strcmp(char a[],char b[]);
/*函数功能:比较两个字符串的大小,返回它们的差 */
int My_strcmp(char a[],char b[])
{int i;
for(i=0; a[i]==b[i]&&(a[i]!=?\0?||b[i] !=?\0?);i++);
/*找第一个不相等的字符 */
return a[i]-b[i]; /*返回它们的差 */
}
void main()
{char str1[50],str2[50];
int minus;
printf(" please input two strings,");
scanf("%s%s",str1,str2);
minus=My_strcmp(str1,str2);
if(minus>0)
printf(" %s>%s.\n",str1,str2);
else if(minus<0)
printf(" %s<%s.\n",str1,str2);
else
printf(" %s=%s,n",str1,str2);
}
51
写函数,连接两个字符串
算法:
输入两个字符串 a,b
连接字符串 a,b
找到第一个字符串的末尾
将第二个字符串接入
输出
h e l l o \0
l i \0
#include<stdio.h>
void My_strcat(char a[],char b[]);
/*函数功能:将两个字符串连接后存在 a中 */
void My_strcat(char a[],char b[])
{int i;
for(i=0; a[i]!=?\0?;i++);
/*i指向 a串最后一个字符的下一个位置,这句也可直接改为
i=strlen(a);*/
for(j=0; b[j] !=?\0?;j++)
a[i+j]=b[j];
/*将 b串中的字符一个一个接入 */
a[i+j]=?\0?;
/*在 a串中写入一个结束标记 */
}
void main()
{
char str1[100],str2[50];
int n;
printf(" please input two strings,");
scanf("%s%s",str1,str2);
My_strcat(str1,str2);
printf("The result:%s.\n",str1);
}
52
写函数,求逆序字符串
算法:
输入一个字符串 string
求逆序
首尾对应字符互换
输出逆序字符串
a b c d e f g h \0 \0 \0
i=0 j=strlen(a)-1
a
i=1 j=strlen(a)-2……
#include<stdio.h>
#include<stdlib.h>
void Reverse(char a[]);
/*函数功能,求 a数组中字符串的 逆序字符串 */
void Reverse(char a[])
{int i,j,n=strlen;
char temp;
for(i=0,j=n-1; i<j;i++,j--)
{temp=a[i];a[i]=a[j];a[j]=temp;}
}
void main()
{
char str[100];
int n;
printf(" please input a string,");
scanf("%s",str);
Reverse (str);
printf(“after reverse,the string is:%s.\n",str);
}
53
数组元素的插入与删除
用数组存储数据时,当插入或删除某个数据时,是通过要插入位置之后数组元素的后移和前移来实现的。
54
插入到特定位置
将一个字符 x插入到字符串的第 pos个位置。
void Insert(char a[],char x,int pos)
{
}
int i;
if(pos>=strlen(a))
{ printf(“wrong position”);
}
else
{ 从最后一个元素开始,到 a[i],所有元素向后移;
a[i]=x;
}
for(i=strlen(a);i>=pos;i--)
a[i+1]=a[i];
55
按顺序插入
将一个字符 x按顺序插入到从小到大排好序的字符串中。
void InsertBySort(char a[],char x)
{
找到插入的位置插入 x
}
int i;
for(i=0;x<a[i]&&a[i]!=?\0?;i++);
//找到插入的位置 i
Insert(a,x,i);
//调用函数插入到 a[i]所在的位置
56
插入排序
将数组中的数据按插入排序从小到大排序
void Sort_Insert(char a[])
{
将 a中所有元素依次按顺序插入到 b中再将 b中的结果写入到 a
}
int i;
char b[100]={?\0?};
for(i=0; a[i]!=?\0?;i++)
insertbysort(b,a[i]);
b[i+1]=?\0?;
strcpy(a,b);
57
删除
删除字符串中的某一字符 x。
void Delete(char a[],char x)
{
判断 a串中每一个字符是不是 x,
是的话删除。
}
int i;
for(i=0;a[i]!=?\0?;i++)
{if(a[i]==x)
删除 a[i](从 a[i]开始的每一个字符向前挪动一个位置 );
}
{for(j=i; a[j]!=?\0?;j++)
{a[j]= a[j+1];
}
i--;
}
为什么?
因为当前的字符已经是后边挪过来的,所以要再判断一下 a[i]是不是 x
58
主函数
#include <stdio.h>
void main()
{ int i,l;
char a[20],ch;
printf("Input a string,");
scanf(“%s”,a);
getchar();
printf("Input a character to delete,");
ch=getchar();
Delete(a,ch);
printf(“after deleting:%s\n”,a);
}
为什么?
吸收掉前一次输入后的结束符,回车,。
用 gets(a)就不存在这样的问题。
59
例 11:求矩阵 a的转置 a?
a= 1 2 3 a?= 1 4
4 5 6 2 5
3 6
算法:
定义变量存储矩阵的元素
输入矩阵 a中所有元素
求矩阵 a的转置 a?
输出矩阵 a?
60
1、定义变量
/*定义一个数组用于存储 2行 3列的矩阵 */
int a[2][3];
语法,数据类型 数组名 [行数 ][列数 ]
a为 2× 3( 2行 3列)的数组,注意 下标范围
a[0]----
a[1]----
a
a[0][0] a[0][1] a[0][2]
a[1][0] a[1][1] a[1][2]
行列
61
二维数组的内存分配:
按行存放(先行后列)
a[0][0]
a[0][1]
a[0][2]
a[1][0]
a[1][1]
a[1][2]
a[0]
a[1]
a合法的初始化形式:int a[2][3]={{1,2,3},{5,6,7}}
int a[2][3]={1,2,3,5,6,7}
int a[2][3]={{1},{5}}
int a[ ][3]={1,2,3,5,6,7}
int a[ ][3]={{1},{5}}
/*列长度是必须指定出来的,
为什么? */
62
输入数组元素
/*要输入每一个 a[i][j]*/
for (i=0;i<2;i++) /*行下标从 0到 1*/
for(j=0;j<3;j++) /*列下标从 0到 2 */
scanf(“%d”,&a[i][j]);
63
求 a?
1,/*在求 a?之间,也同样要定义一个二维数组用于存储 a?,如何定义? */
int trans_a[3][2]; /*3行 2列 */
2,/*求 a?,即 trans_a[i][j] = a[j][i]*/
for (i=0; i<3; i++) /*行下标从 0到 2*/
{ for(j=0; j<2; j++) /*列下标从 0到 1 */
{ trans_a[i][j] = a[j][i];
}
}
64
输出 a?
/*要输出每一个 trans_a[i][j]*/
for (i=0;i<3;i++) /*行下标从 0到 2*/
for(j=0;j<2;j++) /*列下标从 0到 1 */
printf(“%3d”,trans_a[i][j]);
输出结果? /*按矩阵格式输出 */
for (i=0;i<3;i++)
{ for(j=0;j<2;j++)
printf(“%d”,&trans_a[i][j]);
putchar(?\n?);
}
65
#include<stdio.h>
#define M 2
#define N 3
void main()
{int a[M][N],trans_a[N][M],i,j; /*数组定义 */
for (i=0;i<M;i++) /*输入数组元素 */
for(j=0;j<N;j++)
scanf(“%d”,&a[i][j]);
for (i=0; i<N; i++) /*计算转置 */
{ for(j=0; j<M; j++)
{ trans_a[i][j] = a[j][i];
}
}
for (i=0;i<N;i++) /*输出转置结果 */
{ for(j=0;j<M;j++)
printf(“%3d”,trans_a[i][j]);
putchar(?\n?);
}
完整程序
66
将求 a?写成函数
void Trans_matrix(int a[M][N],int
trans_a[N][M])
{int i,j;
for (i=0; i<N; i++)
{ for(j=0; j<M; j++)
{ trans_a[i][j] = a[j][i];
}
}
}
为什么给参数
trans_a[M][N]?
不仅需要矩阵 a,
还需要一个空矩阵用于存储转置结果。
#include<stdio.h>
#define M 2
#define N 3
void Trans_matrix(int a[M][N],int trans_a[N][M])
void main()
{int a[M][N],trans_a[N][M],i,j; /*数组定义 */
for (i=0;i<M;i++) /*输入数组元素 */
for(j=0;j<N;j++)
scanf(“%d”,&a[i][j]);
Trans_matrix(a,trans_a);
/*调用函数计算转置,结果就保存在 trans_a里 */
for (i=0;i<N;i++) /*输出转置结果 */
{ for(j=0;j<M;j++)
printf(“%d”,trans_a[i][j]);
putchar(?\n?);
}
67
例 9求最小字符串的另一种解法
s t u d e n t \0 …
T e a c h e r \0 …
b l a c k b o a r d \0 …
c l a s s r o o m \0 …
68
#include <stdio.h>
#include <string.h>
#define N 5
#define ARRA_SIZE 80
//函数功能:在 n行的二维数组 str中求最小字符串,返回最小串所对应的下标
Int Min_string(char str[][ARRA_SIZE],int n)
{ int i,min_i=0;
for (i=1; i<n; i++)
{ if (strcmp(str[i],str[min_i]) < 0)
{ min_i= i;
}
}
return min_i;
}
main()
{ int i,min_i;
char str [N][ARRA_SIZE];
for (i=0;i<N;i++)//输入每一个数组元素
{ printf("Please enter next name:\n");
gets(str[i]);
}
min_i=Min_string(str,n);
printf("The min string is:");
puts(str[min_i]);
}
用二维数组
用一维数组
69
小结 3
注意数值数组与字符数组的区别
几个用于字符串处理的库函数
70
作业 1
1,编程实现 n行杨辉三角的计算
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1



1...2]][1[]1][1[]][[
1...01]0][[
1...01]][[
nijiajiajia
niia
niiia
71