10讲学会C语言之第六讲:数组


前言

大家好,我是卷卷,本节课的主题是数组,本节课的内容比较多,共有14道例题,希望大家都能坚持。本节课主要有以下几个部分:输出所有大于平均值的数,找出在矩阵中最大值所在的位置,判断回文,作业。(讨论q群号744931080,教程资源在群内)

一、输出所有大于平均值的数

例1:输入10个整数,计算这些数的平均值,再输出所有大于平均值的数。分析:本题要求输出大于平均值的数,所以需要用数组来保存这10个数。定义一个大小为10的整型数组,利用for循环,每轮循环用它保存输入的数并累加总分。再定义一个double型变量avg,保存平均分。用for循环遍历数组的每个元素,每次判断当前元素是否大于avg,若是则输出。本题的重点是数组的定义与使用,我们来看一下代码:

#include<stdio.h>
int main(){
	int i,sum=0;
	int a[10];
	printf("输入10个数:");
	for(i=0;i<10;i++){
		scanf("%d",&a[i]);
		sum+=a[i];
	}
	double avg=sum/10.0;
	printf("平均值为:%.2f\n",avg);
	printf("大于平均值的数如下:\n");
	for(i=0;i<10;i++){
		if(a[i]>avg)
			printf("%d ",a[i]);
	}
	putchar('\n');
	return 0;
}

首先定义一个规模为10的数组,数组名为 a。这样定义以后,数组的元素的值都是随机的。我们可以来试一下:在这里插入图片描述
我们可以看到,数组的元素都是随机赋值的。数组元素可以用花括号来初始化:在这里插入图片描述
我们可以看到,未被初始化的元素自动赋值为0。也就是如果不做初始化的话,元素值是随机的,如果做了初始化,未被初始化的元素就自动赋值为0。这里说一个最重要的,数组下标从0开始,也就是你只能访问a0到a9,如果你访问a[10],就是数组下标越界,编译器就会报错。我想到这里,大家应该对数组有一定的了解了。数组的元素是这样输入的:

	for(i=0;i<10;i++){
		scanf("%d",&a[i]);
		sum+=a[i];
	}

因为a[i]是一个变量,所以需要与号。然后累加每个元素。之后的代码就比较简单了,我们来试一下:在这里插入图片描述
这里注意scanf函数以空格为分隔符,也就是scanf只要遇到空格就停止输入了。所以要连续输入,几个数中间可以用空格分隔。这就是本题的讲解了。

例2:用数组计算斐波那契数列的前10个数,并按每行打印五个数的格式输出。分析:斐波那契数列的特点是第三项开始,每项都等于前两项之和,所以数组a的前两项是a0和a1,并且初值都为1。第三项开始用循环,迭代的形式计算,即a[i]=a[i-1]+a[i-2]。循环结束后,a就保存了斐波那契数列,然后遍历数组,按题目要求的格式输出即可。本题的重点是数组元素迭代,我们来看一下代码:

#include<stdio.h>
int main(){
	int i,fib[10]={1,1};
	for(i=2;i<10;i++)
		fib[i]=fib[i-1]+fib[i-2];
	for(i=0;i<10;i++){
		printf("%6d",fib[i]);
		if((i+1)%5==0)
			printf("\n");
	}
	return 0;
}

首先初始化数组,将两项赋值为1。之后每一项按照这样迭代的形式来加,这个形式非常直观,我想大家应该都理解了。然后输出即可,模5是为了每输出5个换行一次。我们来看一下结果:在这里插入图片描述
这就是斐波那契数列的前10项了。

例3:输入5个整数,将他们存入数组 a 中,再输入一个数x,然后在数组中查找x。如果找到,输出相应的最小下标,否则输出not found。分析:本题的思路很简单,首先定义整型数组a,整型变量x,然后输入5个数,将其存在a中。然后从下标0开始遍历数组,若当前元素等于x,说明找到 x,它的下标就是最小下标,输出即可。为了方便判断,可用一个整型变量flag,初值为0,找到则置为1。这样,若循环结束后,flag等于0则说明未找到,flag等于1则说明找到。代码:

#include<stdio.h>
int main(){
	int i,flag,x;
	int a[5];
	printf("输入5个整数:");
	for(i=0;i<5;i++)
		scanf("%d",&a[i]);
	printf("输入x:");
	scanf("%d",&x);
	flag=0;
	for(i=0;i<5;i++)
	if(a[i]==x){
		printf("下标是%d\n",i);
		flag=1;
		break;
	}
	if(flag==0)
		printf("x未找到!\n");
	return 0;
}

这就是例题3的代码了。for循环内,如果x和当前元素相等,就输出他的下标,将标志置为1,然后退出循环。退出循环以后,如果标志不是0,说明找到。我们试一下:在这里插入图片描述
在这里插入图片描述
这就是本题的讲解了。

例4:输入一个正整数n,再输入n个整数,将它们存入数组a 中。
(1)输出最小值,和它所对应的下标
(2)第二个是将最小值与第一个数交换,输出交换后的n个数
分析:第一个很简单,主要看第二个。将输入的数保存在数组a中,然后和寻找最大值的方法一样,寻找最小值。因为题目要求输出下标,所以有个简便的方法。即只定义一个整型变量index,表示下标,若遇到比a[index]还小的数a[i],index就更新为i。循环结束后a[index]就是最小值。两数交换需要定义临时变量temp,用temp保存a[index],然后a[index]被a[0]替换,最后a[0]被temp替换。交换完后再遍历数组,输出即可。本题的重点是交换两个元素。代码:

#include<stdio.h>
int main(){
	int i,index,n;
	int a[10];
	printf("输入n:");
	scanf("%d",&n);
	printf("输入%d个数:",n);
	for(i=0;i<n;i++)
		scanf("%d",&a[i]);
	index=0;
	for(i=1;i<n;i++)
	if(a[i]<a[index])
		index=i;
	printf("最小值:%d,对应下标%d\n",a[index],index);
	int temp=a[index];
	a[index]=a[0];
	a[0]=temp;
	printf("最小值与第一个数交换后:\n");
	for(i=0;i<n;i++)
		printf("%d ",a[i]);
	return 0;
}

输入数组元素后,就要开始判定。因为下标是从0开始的,所以设最小值元素的下标初始时为0。然后循环变量从1开始,如果当前的元素小于最小值,那么就更新最小值下标。关于交换元素,首先用一个临时变量保存a[index],为什么要保存它呢?因为接下来一行它马上就会被a[0]替换。然后因为temp中保存了a[index],所以主动替换的元素a[0]再被temp替换,这样就实现了两数的交换。当然先保存a[0]也可以,这样的话,a[0]就要被a[index]替换,然后temp再替换a[index]。所以,交换元素的模式是:首先要保存一个数,接下来一行这个数马上被替换,最后主动替换的那个数,要被temp给替换。我们来验证一下:在这里插入图片描述
这就是本题的运行结果了。

例5:选择排序法。输入一个正整数n,再输入n个整数,用选择法将他们从小到大排序后输出,选择排序算法的步骤如下:
第一步:在未排序的n个数中,找到最小数,将它与a[0]交换
第二步:在剩下未排序的n-1个数中找到最小数,将它与a[1]交换
第n-1步:在剩下未排序的,2个数中找到最小数,将它与a[n-2]交换
分析:选择排序和冒泡排序一样,都是要用到二重循环的经典算法。在用数组a保存整数以后,用for循环遍历数组,每轮循环拿当前元素的下标i作为最小值下标k。然后再用一个for循环拿a[k]去和后面的元素比大小。若a[i]小于a[k],则k就更新为 i。内层循环结束后,k就是更小元素的下标,再检查k是否已更新,即k是否等于i。若等于,说明a[i]仍是最小的元素。若不等于,则将a[i]与a[k]交换,即将最新的最小元素换到前面去。排序结束后再遍历一次数组,输出即可。本题的重点显然是选择排序,这也是一个比较重要的排序,我希望大家好好理解,而不是一味地死记。代码:

#include<stdio.h>
int main(){
	int n;
	printf("输入n:");
	scanf("%d",&n);
	int a[n],i;
	printf("输入%d个数:",n);
	for(i=0;i<n;i++)
		scanf("%d",&a[i]);
	int j,k;
	for(i=0;i<n;i++){
		k=i;
		for(j=k+1;j<n;j++)
		if(a[j]<a[k])
			k=j;
		if(k!=i){
			int temp=a[k];
			a[k]=a[i];
			a[i]=temp;
		}
	} 
	printf("排序结果:\n");
	for(i=0;i<n;i++)
		printf("%d ",a[i]);
	putchar('\n');
	return 0;
}

循环中,刚开始选取一个元素,然后拿这个元素和后面的比较,如果有元素比它更小,就更新最小元素下标。大家要注意,这个for循环是没有花括号的,那么它的执行范围只有第一个if。如果最小元素下标有更新,说明找到了最新的最小元素,然后交换两个元素即可。选择排序的核心思想就是:寻找最小元素,扔到前面。我希望大家牢记这句话,然后深刻理解。我们来看一下结果:在这里插入图片描述

例6:调查电视节目受欢迎程度。某电视台要调查观众,对该台8个栏目的受欢迎程度,共调查了1000位观众,现要求编写程序,输入每一位观众的投票情况,统计输出各栏目的得票情况。分析:这是一个分类统计的问题,输入一批整数,统计各栏目得票数后输出,这就要求累计每个栏目的得票数。本例用一个整型数组count保存各栏目的得票数,数组下标对应栏目编号。这样,count[1]到count[8]分别表示8个栏目的得票数,即count[i]代表了编号为i的栏目的得票数。当某一观众投票给栏目i时,直接使count[i]自增1即可。本题的重点显然是用数组来统计数据,这个思想是比较新颖的思想,也是比较方便和重要的思想,我希望大家能在今后的编程中灵活运用。代码:

#include<stdio.h>
int main(){
	int count[9]={0},i,option;
	for(i=1;i<=10;i++){//为方便,上限可设为10等比较小的数字 
		printf("输入你喜欢的栏目编号:");
		scanf("%d",&option);
		if(option>=1&&option<=8)
			count[option]++;//用输入的元素作为元素的索引 
		else
			printf("无效的编号!\n");
	}
	printf("各栏目投票结果如下:\n");
	for(i=1;i<=8;i++)
		printf("栏目%d:%d票\n",i,count[i]);
	printf("\n");
	return 0;
}

首先因为编号是1-8,所以定义一个规模大小为9的数组。为方便,上限可设为10等比较小的数字,这里不妨是10。首先输入栏目编号,每次判定是否在1-8之内,如果是,用编号作为下标去索引元素,然后投票数+1。用输入的数字作为元素的索引,这个是一个比较重要的思想,最后输出即可。运行一下:在这里插入图片描述
这就是本题的讲解了。

二、找出在矩阵中最大值所在的位置

例7:将一个3x2的矩阵存入一个3x2的二维数组中,找出最大值以及它的行下标和列下标,并输出该矩阵。分析:二位数组int a[m][n],表示一个m行n列的矩阵,矩阵元素为int型变量。找最大值,首先要遍历矩阵,所以用二重循环遍历二维数组。由于数组下标从0开始,所以a[i][j]表示第i+1行,第j+1列的元素。不妨设最大值的行下标为row,列下标为col,则算法和一维数组找最大值类似。比较a[row][col]与a[i][j],更新下标即可。循环结束后的最大值自然是a[row][col],再遍历一次二维数组,输出每个元素即可。本题的重点,显然是二维数组的定义与使用。代码:

#include<stdio.h>
int main(){
	int i,j,a[3][2];
	printf("输入6个整数:\n");
	for(i=0;i<3;i++)
	for(j=0;j<2;j++)
		scanf("%d",&a[i][j]);
	printf("形成的矩阵如下:\n");
	for(i=0;i<3;i++){
		for(j=0;j<2;j++)
			printf("%4d",a[i][j]);
		printf("\n");
	}
	int row=0,col=0;
	for(i=0;i<3;i++)
	for(j=0;j<2;j++)
	if(a[row][col]<a[i][j]){
		row=i;
		col=j;
	}
	printf("\nmax=a[%d][%d]=%d\n",row,col,a[row][col]);
	return 0;
}

首先定义了一个3行2列的矩阵,二维数组的初始化,需要两个花括号,比如说这样:

int a[3][2]={{1,2},{2,3},{3,1}};

我们可以看出,第一维度有3个元素,第二维有两个元素。每个第一维的元素,都是一个一维数组,第二维则是数字。其实很好理解,二维数组也是数组,只不它的元素本身也是一个数组。[3][2]就表示第一维最多有3个元素,第二维最多有2个元素,这就是二维数组的概念。输入二维数组的元素:

	for(i=0;i<3;i++)
	for(j=0;j<2;j++)
		scanf("%d",&a[i][j]);

这里其实和一维数组的输入差不多,只不过多了一层循环,多了一个变量而已。寻找最值的代码:

	int row=0,col=0;
	for(i=0;i<3;i++)
	for(j=0;j<2;j++)
	if(a[row][col]<a[i][j]){
		row=i;
		col=j;
	}

这里的算法和一维数组的算法差不多,只是多了一个循环,多了一个变量而已。我们来运行一下:在这里插入图片描述
这就是本题的结果了。

例8:定义一个3x2的二位数组a,数组元素的值由下式给出:a[i][j]=i+j;按矩阵的形式输出a。分析:问题很简单,定义二维数组,按题目给的式子赋值即可。然后再遍历一次,输出矩阵的每个元素。由于本题比较简单,这里就不做讲解了。

例9:在这里插入图片描述
大家可以发现,例子中的转置后的方阵,对角线元素没有变,但是对角线两旁的元素都发生了互换。本题前半部分很简单,按题目要求赋值即可。后半部分要理解方阵转置的特点,以对角线旁的两个元素互换。在线性代数(大学数学之一)中,矩阵对角线及以上的部分称作上三角阵,对角线及以下的部分称作下三角阵。因为只需互换行列一次,所以只需遍历上三角阵或下三角阵即可。以上三角阵为例,因为对角线元素无需遍历,所以待交换元素的列号必须大于行号。即选中第i行,而接下来的元素的列号j>i,也就是j从i+1开始遍历。下三角阵则相反,j<i,本题的重点自然是方阵转置。代码:

#include<stdio.h>
int main(){
	int i,j,n;
	printf("输入n:");
	scanf("%d",&n);
	int a[n][n];
	for(i=0;i<n;i++)
	for(j=0;j<n;j++)
		a[i][j]=i*n+j+1;
	for(i=0;i<n;i++)
	for(j=i+1;j<n;j++){ 
		int temp=a[i][j];
		a[i][j]=a[j][i];
		a[j][i]=temp;
	}
	for(i=0;i<n;i++){
		for(j=0;j<n;j++)
			printf("%4d",a[i][j]);
		printf("\n");
	}
	return 0;
}

核心是矩阵转置的代码。这里以上三角阵为例,列号j是大于i的,所以j从i+1开始,然后互换i,j处的元素即可,最后输出,我们来验证一下:在这里插入图片描述
这就是本题的结果了。

例10:在这里插入图片描述
分析:首先闰年和平年的天数是不同的,所以用一个二维数组tab来存储每月的天数,tab的第一维共两个元素,一个存放平年每月的天数,另一个存放闰年每月的天数。为了方便起见,第二维的下标从1开始,所以tab的定义形式是int tab[2][13],然后定义变量leap,接收是否为闰年的结果。用leap作为tab的第一维下标,利用循环,传入的天数。day去累加tab[leap][i],循环结束后的day就是当月的天数+之前每个月的天数,即当年过了多少天。本题的重点是二维数组的应用。这就是本题的代码:

#include<stdio.h>
int day_of_year(int year,int month,int day){
	int k,leap;
	int tab[2][13]={
		{0,31,28,31,30,31,30,31,31,30,31,30,31},
		{0,31,29,31,30,31,30,31,31,30,31,30,31}
	};
	leap=((year%4==0&&year%100!=0)||year%400==0);
	for(k=1;k<month;k++)
		day+=tab[leap][k];
	return day;
}
int main(){
	int year,month,day;
	printf("输入年,月,日:");
	scanf("%d %d %d",&year,&month,&day);
	int total=day_of_year(year,month,day);
	printf("它是该年的第%d天\n",total);
	return 0;
}

这个二维数组的第一维是平年每月的天数,第一维的第二个是闰年每月的天数。然后判定闰年还是平年,如果它是闰年,那么结果为1,它就定位到了第一维的第二个元素。如果是平年,它的结果就为0,它就定位到了第一维的第一个元素。然后传入的天数再加上每个月的天数即可。注意这里k达不到month,比如说3月15日,那么它就是15天加上1月的天数,加上2月的天数,如果加上3月的天数就错误了,我们来验证一下:在这里插入图片描述
这就是本题的讲解了。

三、判断回文

例11:输入一个以回车为结束标志的字符串,判断该字母称是否为回文,回文就是字符串,中心对称,如abcba,abccba是回文,abcdba不是回文。分析:C语言中,字符串需要用字符数组来存储,又题目最多80个字符,所以不妨定义字符数组line[80]来接收字符。判定回文很简单,只需用两个下标,从两头往中间靠拢,判定即可。字符串的输入有两种,一种是通过scanf,以%s的形式接收一整个串。还有一种是用getchar()逐个输入字符,由于本题的结束标志符是回车键,scanf又以回车符结束,所以两种方式都可以。如果标志是其他字符,则只能用getchar()。这里不妨用getchar(),用一个循环,当接收的字符为回车键就退出循环。一般用整型变量来标记字符在数组中的位置,比如k。循环结束后,k所在位置可以填结束符,也可以不填,因为题目没有要求输出一整个串。然后i从0开始,k减减,k就变为了末尾的位置。i和k从两头往中间靠,直到i和k位置的元素不相等或者i和k相遇。本题的重点显然是一维字符数组的定义与使用。代码:

#include<stdio.h>
int main(){
	int i,k;
	char line[80];
	printf("输入一个字符串:\n");
	k=0;
	while((line[k]=getchar())!='\n')
		k++; 
	i=0;
	k=k-1;
	while(i!=k){
		if(line[i]!=line[k])
			break;
		i++;
		k--;
	}
	if(i>=k)
		printf("它是回文串!\n");
	else
		printf("它不是回文串\n");
	return 0;
}

首先line是一个字符数组,它能存放79个字符加1个结束符。结束符是反斜杠0:’\0’。每定义一个字符数组,都会在末尾自动加一个结束符,在这里,line[79]是结束符,line[0] ~ line[78],即前79个位置存放结束符以外的字符。无论是在printf中还是在scanf中,字符数组的格式始终是%s。字符数组如果以%s格式输出,会以第一个结束符为标志。也就是如果数组中出现多个结束符,则输出到第一个结束符为止,后面不再输出。这就是一维字符数组的基本概念了,首先用getchar()来输入:

	k=0;
	while((line[k]=getchar())!='\n')
		k++;

如果遇到回车符,就结束循环,否则将字符存入数组line。k是下标,每存入一个字符加1。循环结束后,k就等于字符的输入个数,即字符数组的输入长度,也即输入数组的最后一个位置。由于无需用printf输出一整个字符数组,所以line[k]可以放结束符,也可以不放。由于输入了k个元素,所以元素应存放在line[0]~line[k-1],所以k要-1,指向最后一个有效元素的位置。然后是判定回文串:

	i=0;
	k=k-1;
	while(i!=k){
		if(line[i]!=line[k])
			break;
		i++;
		k--;
	}

i和k从数组两头往中间靠拢,当两个元素不等或者i和k相遇,即扫描结束时,循环结束。如果i<k,扫描未结束,即两个元素不等,说明它不是回文串。否则说明扫描结束,一切正常,没有两个字母是不相等的,是回文串。我们来验证一下:在这里插入图片描述
在这里插入图片描述
这就是本题的讲解啦。

例12:输入一个以回车符为结束标志的字符串(少于80个字符),统计其中数字字符的个数。例13:输入一个以回车符为结束标志的字符串(少于10个字符),提取其中的所有数字字符,将其转换为一个十进制整数输出。分析:这两道题的输入都一样,而且和上一题差不多,不再赘述。例12比较简单,不作讲解。这两题的区别在于遍历时的操作,例12是统计数字,例13是将数字部分转为10进制整数。统计数字很简单,主要是得到10进制数。首先定义一个整型变量num等于0,假设当前遍历的数字字符是ch,则num=num*10+ch-’0’。根据ASC码表的规律,数字字符是用十进制表示的,而且连续升序排列。所以任意一个数字字符减去字符0就是相差的十进制数,比如字符1和字符0,在ASC码表中的十进制表示相差1,所以直接相减就得到了字符1对应的整数1。例13的重点显然是数字字符串转十进制整数。代码:

#include<stdio.h>
int main(){
	int i;
	char str[10];
	printf("输入一个字符串:\n");
	i=0;
	while((str[i]=getchar())!='\n')
		i++;
	int num=0,j;
	for(j=0;j<i;j++)
	if(str[j]<='9'&&str[j]>='0')
		num=num*10+(str[j]-'0');
	printf("结果为:%d\n",num);
	return 0;
}

循环内,判定是否是数字,如果是数字,则转为十进制整数。我们来验证一下:在这里插入图片描述
这就是本题的讲解了。

最后一道例题,例14:输入一个’#’为结束标志的字符串(少于10个字符),滤去所有的非十六进制字符,组成一个新的表示十六进制数字的字符串,输出该字符串并将其转换为十六进制数后输出。分析:定义一个字符串str用于接收输入的字符,由于要形成新的字符串,不妨再定义一个字符串hex用于接收十六进制字符。算法很简单,不做赘述。需要注意本题要求输出一个字符串,最方便的做法是以%s输出。本题采用这种方法,所以在接收完字符后,要在下标处,即最后一个元素位置填充结束符。定义变量num,用于计算十六进制数,十六进制包括0-9和A-F,A-F分别对应10-15。所以如果遇到A-F中的一个字符x,根据ASC码表,x-’A’+10即相应的十六进制数。比如B,它和A相距1,但是B在十六进制中代表11,所以B-A后还得加上10。所以对于A-F的字符x,num=num16+x-’A’+10。对于小写字母,只需将大写改为小写即可。对于数字字符,和计算十进制差不多,只是num10并为num*16。本题的重点是数字字符转十六进制整数,代码:

#include<stdio.h>
int bt0_9(char ch);
int bta_z(char ch);
int btA_Z(char ch);
int main(){
	int i,k;
	char hex[80],str[80];
	printf("输入一个字符串:");
	i=0;
	while((str[i]=getchar())!='#')
		i++;
	str[i]='\0';
	i=k=0;
	while(str[i]!='\0'){
		if(bt0_9(str[i])||btA_Z(str[i])||bta_z(str[i]))
			hex[k++]=str[i];//k++ 后增符号++
			//后增:赋值后再+1,前增:+1后赋值 
		i++;
	}
	hex[k]='\0';
	printf("新字符串:");
	printf("%s",hex);
	putchar('\n');
	long num=0;//长整型:long 8bytes 
	for(i=0;hex[i]!='\0';i++){
		if(bt0_9(hex[i]))
			num=num*16+hex[i]-'0';
		else if(bta_z(hex[i]))
			num=num*16+hex[i]-'a'+10;
		else
			num=num*16+hex[i]-'A'+10;
	}
	printf("转为16进制后:%ld\n",num);
	return 0;
}
int bt0_9(char ch){
	return ch>='0'&&ch<='9';
}
int bta_z(char ch){
	return ch>='a'&&ch<='z';
}
int btA_Z(char ch){
	return ch>='A'&&ch<='Z';
}

我在这里定义了三个函数,用于判定数字,小写字母和大写字母:

int bt0_9(char ch){
	return ch>='0'&&ch<='9';
}
int bta_z(char ch){
	return ch>='a'&&ch<='z';
}
int btA_Z(char ch){
	return ch>='A'&&ch<='Z';
}

扫描输入的字符串,当字符串的元素不为结束符时,就执行循环,这样的表达方式是比较简洁的。输入未结束时,判定,如果当前字符是数字和英文字母之一,那么就把这个字符赋加入到新的字符数组hex中:

		if(bt0_9(str[i])||btA_Z(str[i])||bta_z(str[i]))
			hex[k++]=str[i];//k++ 后增符号++
			//后增:赋值后再+1,前增:+1后赋值

特别注意:这里的加加是后增符号,它的作用是赋值后再加1,如果是前增符号,它的作用就是先自增再赋值,这样就错了。循环结束后就得到了十六进制字符串,也就是只包括数字或英文字母的字符串,为了输出这部分,在末尾加上一个结束符:

	hex[k]='\0';
	printf("新字符串:");
	printf("%s",hex);
	putchar('\n');

然后是转十六进制,因为转换为十六进制的数可能比较大,所以这里用了一个长整型long,它占了8个字节。长整形的输出格式是%ld。转十六进制的式子前面已经讲过,这里就不再讲了,我们来验证一下:在这里插入图片描述
好了,这就是例题的全部讲解啦。

四、作业

我们来看一下作业,作业是14道例题加上1道练习题,总共15道题。练习1:在这里插入图片描述
这题和投票那题差不多,它们的核心思想是一样的,都是用一个count数组,只不过这里的count的规模是10。当然count数组初始化的时候,要初始化为0哦,或者你将这个数组置为全局变量数组也行,全局变量或全局变量数组,它的元素都会自动初始化为零。好了,这就是本讲的全部内容了,我们下讲见!

  • 6
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
将一个bitmap转换成C语言数组可以按照以下步骤进行: 1. 使用图片处理软件打开需要转换的bitmap文件,并将其转化为灰度图像。 2. 将灰度图像转换为黑白图像,即将所有非黑色像素点设置为白色。 3. 使用C语言编写一个程序,读取经过处理后的黑白图像文件,并将像素值转换成C语言数组的元素。 4. 将每个像素点的值存储在C语言数组。 下面是一个示例代码: ```c #include <stdio.h> #include <stdlib.h> int main() { FILE *fp; unsigned char *bitmap; unsigned char *bmp_array; int width, height; int i, j, k; fp = fopen("image.bmp", "rb"); if(fp == NULL) { printf("Cannot open file.\n"); return 1; } fseek(fp, 18, SEEK_SET); fread(&width, sizeof(int), 1, fp); fread(&height, sizeof(int), 1, fp); fseek(fp, 54, SEEK_SET); bitmap = (unsigned char*) malloc(sizeof(unsigned char) * width * height); bmp_array = (unsigned char*) malloc(sizeof(unsigned char) * width * height); fread(bitmap, sizeof(unsigned char), width * height, fp); fclose(fp); for(i = 0; i < height; i++) { for(j = 0; j < width; j++) { k = i * width + j; bmp_array[k] = bitmap[k * 3]; } } free(bitmap); free(bmp_array); return 0; } ``` 上述代码,我们首先打开了一个名为“image.bmp”的bitmap文件,并读取了该文件的宽度和高度。 然后,我们使用malloc函动态分配了两个数组——bitmap和bmp_array,分别用于存储bitmap文件的像素值和C语言数组的元素。 接着,我们从文件读取了像素值,并将每个像素点的红色、绿色、蓝色值的平均值存储在了bmp_array数组。 最后,我们释放了动态分配的内存空间,结束了程序运行。 需要注意的是,这里的代码仅适用于24位真彩色的bitmap文件。如果需要转换其他类型的bitmap文件,需要根据文件格式进行相应修改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

技术卷

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值