2019秋期计导实验十(数组,字符数组)

A. 实验8_1_矩阵转置

运行时间限制: 1000 运行内存限制: 65536
作者: scshuanghai 是否specialjudge: False
题目描述
问题描述:
任意给定一个n*m的矩阵,矩阵的行数为n,列数为m。你的任务是实现矩阵的转置,即行列互换。

输入与输出要求:
输入两个整数n、m,代表矩阵的行数与列数,n、m的范围均是1—100。然后输入n*m个整数,即此矩阵的元素。输出经过矩阵转置得到的新矩阵,新矩阵占m行,n列。每行的每个元素用空格分隔,注意最后一个数的后面为换行符。
程序运行效果:
Sample 1:
3 5↙
5 5 5 5 5↙
3 3 3 3 3↙
1 1 1 1 1↙

5 3 1
5 3 1
5 3 1
5 3 1
5 3 1
这题,不难。只是交换时遇到了问题,行数大于列数时没有交换彻底。以下是AC代码。

#include<stdio.h>
#define SIZE 101
int main()
{
	int n,m,a[SIZE][SIZE]={0},i,j,t,temp;
	scanf("%d%d",&n,&m);
	for(i=0;i<n;i++)
	for(j=0;j<m;j++)
	scanf("%d",&a[i][j]);
	t=n>m?n:m;//取行与列的最大值,以便交换的时候当行大于列的时候能完全交换,比如6行2列时。
	for(i=0;i<t;i++)
	for(j=i;j<t;j++)
	{
		temp=a[i][j];
		a[i][j]=a[j][i];
		a[j][i]=temp;
	}
	for(i=0;i<m;i++)
	for(j=0;j<n;j++)
	{
		if(j==n-1)printf("%d\n",a[i][j]);
		else printf("%d ",a[i][j]);		
	}
	return 0;
} 

B. 实验8_2_推销员的便条

运行时间限制: 1000 运行内存限制: 65536
作者: scshuanghai 是否specialjudge: False
题目描述
问题描述:
某公司有四个销售员(代号1—4),负责销售五种产品(代号1—5)。每个销售员都把当天售出的每种产品各写一张便条交上来。每张便条包含销售员的代号、产品的代号、这种产品的销售额。我们搜集到了每个月的所有便条,你的任务是根据这些便条,计算出每人、每种产品的总销售额。处理完销售信息后,以表格形式打印出结果。用列代表销售员,行代表产品。每种产品的销售总额输出到该行的最右边,每个销售员的销售总额输出到该列的最下边。

输入与输出要求:
输入一个整数n,代表便条的数量,然后是n组便条的内容,每组内容包括两个整数和一个浮点数,即销售员的代号、产品的代号、这种产品的销售额。输出信息处理后的矩阵,矩阵占6行,5列,矩阵元素保留一位小数。每行的每个元素用tab分隔,注意每行最后一个数的后面为换行符。输出格式细节见样例。
特别提醒:1、输出只包含数据,不包含列表的行和列的说明,即saler1、prod1等内容。2、存储浮点数数据的二维数组用 float类型
程序运行效果:
Sample 1:
4↙
1 1 35.6↙
1 2 23.1↙
1 1 89.3↙
4 5 22.6↙
输出:

    saler1  saler2  saler3  saler4  total

prod1 124.9 0.0 0.0 0.0 124.9
prod2 23.1 0.0 0.0 0.0 23.1
prod3 0.0 0.0 0.0 0.0 0.0
prod4 0.0 0.0 0.0 0.0 0.0
prod5 0.0 0.0 0.0 22.6 22.6
total 148.0 0.0 0.0 22.6 170.6

似乎别的博主程序是再用for循环把total加出来,我觉得那样麻烦。

#include<stdio.h>
#define SIZE 101
int main()
{
	int n,i,dh,xh,j;
	float a[5][6]={0},total[6]={0},totaldh[5]={0},pr,total1=0;
	scanf("%d",&n);
	for(i=0;i<n;i++)
	{
		/*if销售员代号==1,按产品序号放在该销售员代号下
		对应产品total+产品。
		a[i][pr1]+=pr;
		total[pr1]+=pr; */
		scanf("%d%d%f",&dh,&xh,&pr);
		a[dh][xh]+=pr;
		total[xh]+=pr;
		totaldh[dh]+=pr;//用于求销售员的总和
		total1+=pr;//用来求全部的总和
	}
	for(i=1;i<6;i++)//5个产品
	{
		for(j=1;j<5;j++) //4个销售员
		{
			printf("%.1f ",a[j][i]);
		}
		printf("%.1f\n",total[i]);输出第一种产品的总和
	}
	for(i=1;i<5;i++)
	{
		printf("%.1f ",totaldh[i]);//输出第一个销售员的总和
	}
	printf("%.1f\n",total1);//输出全部总和
	return 0;
} 

D. 实验8_5_寻找鞍点

运行时间限制: 1000 运行内存限制: 65536
作者: scshuanghai 是否specialjudge: False
题目描述
问题描述:
任意给定一个nm的矩阵,矩阵的行数为n,列数为m。你的任务是寻找该矩阵的鞍点。一个矩阵的鞍点即该位置上的元素在所在行上最大,在所在列上最小。有的矩阵也可能没有鞍点。不难证明,如果一个矩阵有鞍点,那么这个鞍点一定是唯一的。如果某个矩阵只有1行(1列),则默认该行上的所有元素满足列上最小(行上最大)的要求。
例如矩阵M:
1 2 3 4 5
2 4 6 8 10
3 6 9 12 15
4 8 12 16 20
该矩阵的鞍点为M[0][4]=5,该数在第0行最大,在第4列最小。
注:测试用例保证同行或同列内没有相等的值。
输入与输出要求:
输入两个整数n、m,代表矩阵的行数与列数,n、m的范围均是1—100。然后输入n
m个整数,即此矩阵的元素。如果找到该矩阵的鞍点则输出“The saddle point is (x,y)=v.”,x为该鞍点所在的行,y为该鞍点所在的列,v为该位置上元素的值;如果该矩阵没有鞍点,则输出“There is no saddle point in the matrix.”。
程序运行效果:
Sample 1:
4 5↙
1 2 3 4 5↙
2 4 6 8 10↙
3 6 9 12 15↙
4 8 12 16 20↙

The saddle point is (0,4)=5.

这题思路很简单:分别写两个函数找到本行最大值,与该元素所在列最小值比较,看是否在同一行。然而,这题我卡了超过一个小时,因为,数组传值调用,要传的第二个数字,即二维数组的列数,应当与定义的时候相同,不然就会发现,有些元素没传过去。。

//该位置上的元素在所在行上最大,在所在列上最小。
#include<stdio.h>
#define SIZE 101
int m,n;
int findMax(int a[][101],int);
int findMin(int a[][101],int);
int main()
{
	int a[SIZE][SIZE],i,j,flag=0,c1,c2;
	scanf("%d%d",&n,&m);
	for(i=0;i<n;i++)
	for(j=0;j<m;j++)
	scanf("%d",&a[i][j]);
	for(i=0;i<n;i++)
	{
		c1=findMax(a,i);
		//printf("%d %d\n",c1,a[i][c1]); 
		c2=findMin(a,c1);
		//printf("%d %d\n",c2,a[c2][c1]);
		if(i==c2)
		{
			flag=1;
			printf("The saddle point is (%d,%d)=%d.\n",i,c1,a[i][c1]);break;
		}
		else continue; 
	}
	if(flag==0)printf("There is no saddle point in the matrix.\n");
	return 0;
}
int findMax(int a[][101],int row)//返回列坐标
{
	int max,i,t=0,j;
	max=a[row][0];
	for(i=0;i<m;i++)
	{
		if(a[row][i]>max)max=a[row][i],t=i;
	}
	return t;
}
int findMin(int a[][101],int col)//返回行坐标
{
	int min,i,t=0;
	min=a[0][col];//除了第一个元素,其他元素都变成0了??!!//因为元素未传完 
	//printf("%d\n",col);
	//printf("%d\n",min);
	//printf("%d\n",a[1][col]);
	/*for(i=0;i<n;i++)
	{
		printf("%d\n",a[i][col]);}*/
	for(i=0;i<n;i++)
	{
		//printf("%d\n",a[i][col]);
		if(a[i][col]<min)min=a[i][col],t=i;
		//printf("%d %d\n",min,t);
	}
	//printf("%d %d\n",min,t);
	return t;
}

数组初始化及赋值的方法,memset的使用

(总结一句话,整型除了0和-1外,其他数字不能整体赋,比如,赋值1的话会输出16843009;char型可以任意赋值)

  1. 数组初始化:

即定义时即赋值:

int a[4]={0}; //每一个位置的int都为0

int b[4]={1}; //只有第一个元素为1,其他都为0

所以要想把数组初始化为其他值,则需要一个个的指定值: int b[4]={1,2,3,4};//比如指定为1,2,3,4

或者先统一初始化为0,再利用for循环改变数组的每一个元素。

  1. 数组的赋值:

在定义过后,需要给数组每一个元素赋值时,不能再像初始化那样:

         a[4] = {1,3,5,7}; //这是错误的,

         a={1,3,5,7};//这还是错的。

只能利用for循环,或者利用memcpy从其他内存拷贝一份值过来。

当使用完成后,局部数组会由函数自动释放,全局数组则需进行下清零。

这时候就要用到memset函数。

memset(a,0,sizeof(a));

或者memset(a,0,sizeof(int)4); //sizeof取的是字节。 memset是按字节进行赋值的,这里为16个字节:44

  1. memset函数:memset(void *s, int ch,size_t n); // C语言:#include <string.h> 或者 C++: #include

一般只用来清零,或者初始化局部数组为0,以免出现局部数组的每一个元素为乱值。所以第二个参数一般为0或者-1.

要注意:

3.1 memset是按字节进行赋值,

所以假设你想利用memset给a数组每一位置为1,memset(a,1,sizeof(a)); // 这时候你去打印a的每一位,值都是16843009,而非你期望的1

    原因:int为四个字节,这时候每个字节被memset置为1,而每一个元素都是一个int,即 01 01 01 01,读取十六进制为 0x01010101,十进制为 16843009

    不过 char类型的可以使用memset随意赋值为自己想要的,因为 char只占一个字节,赋多少就是多少。

e.g.:

            char a[3]={'a' , 'b', 'c'};

            memset(a, 1,sizeof(a));

for(int i=0;i<sizeof(a)/sizeof(a[0]);i++){

printf(“a[%u]=[%u]\n”,i,a[i]); //得到a[1]=1; a[2]=1; a[3]=1;

}

E. 实验8_6_矩阵变换

运行时间限制: 1000 运行内存限制: 65536
作者: scshuanghai 是否specialjudge: False
题目描述
问题描述:
任意给定一个n*n的矩阵,矩阵的行数与列数均为n。你的任务是通过行变换,使得矩阵每行元素的平均值按递增顺序排列。如果出现有的行平均值相同的情况,则按照原顺序输出。

输入与输出要求:
输入一个整数n代表矩阵的行数(列数),n的范围是1—100。然后输入n*n个整数,即此矩阵的元素。矩阵元素的绝对值不会超过1000000。输出经过行变换后的新矩阵。每行的每个元素用空格分隔,注意最后一个元素后为换行符。

程序运行效果:
Sample 1:
3↙
5 5 5↙
3 3 3↙
1 1 1↙

1 1 1
3 3 3
5 5 5

正是该题,磨难重重,理清思路:计算一行的总值(不用算平均值了,算不算没差别,并且int型能总和不溢出。),将该总值排序,使用另一个数组储存排的序号,最后按序号输出。

排序时,找最小值,用了一个数组来判断该值是否用过(该数组清0时最好清为0,清为1的下场就是,运行超时。。并且,没有得到结果。。memset用法详见上),用过,此次排序就不排它。最开始的最小值要找一个非常大的,根据数据的最大值,n取100,元素取1000000,那就是100000001.

贴上AC代码

#include<stdio.h>
#include<string.h>
#include<time.h>
#define SIZE 101
int main()
{
	int n,i,j,a[SIZE][SIZE],x[SIZE]={0},min,t,b[SIZE],temp,flag[SIZE]; 
	memset(flag,0,sizeof(flag));
	//srand(time(NULL));n=1+rand()%9;printf("%d\n",n);
	scanf("%d",&n);
	for(i=0;i<n;i++)
	for(j=0;j<n;j++)
	{
		//a[i][j]=1+rand()%9;printf("%d ",a[i][j]);
		scanf("%d",&a[i][j]);
	}
	/*for(i=0;i<n;i++)
	for(j=0;j<n;j++)
	{
		printf("%d ",a[i][j]);
	}*/
	//保存并比较平均值
	for(i=0;i<n;i++)
	for(j=0;j<n;j++)
	{
		x[i]+=a[i][j];
	}
	/*for(i=0;i<n;i++)
	{
		printf("%d ",x[i]);
	}*/
	min=100000001;
	for(j=0;j<n;j++)
	{
		for(i=0;i<n;i++)
		{
			//找出最小值的行坐标,下一次寻找时把它排除在外 
			//if(x[i]<min&&(flag[i]==1))min=x[i],t=i,flag[i]=0;//不对。这个语句,会把不是最小值的给flag=1; 
			if((x[i]<min)&&(flag[i]==0))min=x[i],t=i;
			//printf("%d %d\n",min,t);
		}
		b[j]=t;
		flag[t]=1;
		min=100000001;//不合理 ,最小值要赋成谁才合适?//已改正 
	}
	/*for(i=0;i<n;i++)
	printf("%d ",x[i]);*/
	for(i=0;i<n;i++)
	for(j=0;j<n;j++)
	{
		if(j!=n-1)
		printf("%d ",a[b[i]][j]);
		else printf("%d\n",a[b[i]][j]);
	}
	return 0;
}

F. 实验8_10_蛇形矩阵

运行时间限制: 1000 运行内存限制: 65536
作者: scshuanghai 是否specialjudge: False
题目描述
问题描述:
蛇形矩阵是一个nn的矩阵,将整数1到nn按照蛇形的顺序装入一个 n*n 的蛇形矩阵中,如样例所示分别为5阶和10阶蛇形矩阵:

输入与输出要求:
输入一个整数n,代表蛇形矩阵的阶数,n的范围是1—100。输出蛇形矩阵。每行的每个元素用空格分隔,注意最后一个数的后面为换行符。

程序运行效果:
Sample 1:
5

1 3 4 10 11
2 5 9 12 19
6 8 13 18 20
7 14 17 21 24
15 16 22 23 25
Sample 2:
10

1 3 4 10 11 21 22 36 37 55
2 5 9 12 20 23 35 38 54 56
6 8 13 19 24 34 39 53 57 72
7 14 18 25 33 40 52 58 71 73
15 17 26 32 41 51 59 70 74 85
16 27 31 42 50 60 69 75 84 86
28 30 43 49 61 68 76 83 87 94
29 44 48 62 67 77 82 88 93 95
45 47 63 66 78 81 89 92 96 99
46 64 65 79 80 90 91 97 98 100

这个题思路很简单(啊,其实我一开始也想岔了),一共有四种不同方向,向下,右上,右,左下,将其进行分类,向下之后,可能右上也可能左下,右上之后可能向右,也可能向下…列出所有情况的限制条件,再加上循环即可。(我看别的博主还有一个思路是,将n分奇数偶数讨论,看其对角线是怎么填充的,比如Lupinus_Linn的蛇形矩阵
最后,我捋了一遍代码写出来,发现和借鉴的Hush老兄长得差不多,但是,结果是这样的
在这里插入图片描述
后来才发现,不能用a[i+1][j]=a[i][j]++;它是先用后加的意思。
以下是AC代码

#include<stdio.h>
#define SIZE 101
int main()
{
	int a[SIZE][SIZE],n,i=0,j=0,path=1;
	scanf("%d",&n);
	a[0][0]=1;
	while((i!=n-1)||(j!=n-1))
	{
		if(path==1)//下
		{
			a[i+1][j]=a[i][j]+1;
			i++;
			if(j==0)path=2;
			if(j==n-1)path=4;
		}
		else if(path==2)//右上
		{
			a[i-1][j+1]=a[i][j]+1;
			i--;j++;
			if((i==0)&&(j!=n-1))path=3;
			if(j==n-1)path=1;
		}
		else if(path==3)//右
		{
			a[i][j+1]=a[i][j]+1;
			j++;
			if(i==0)path=4;
			if(i==n-1)path=2;
		}
		else if(path==4)//左下
		{
			a[i+1][j-1]=a[i][j]+1;
			i++;j--; 
			if(i!=n-1&&j==0)path=1;
			if(i==n-1)path=3;
		}
	}
	for(i=0;i<n;i++)
	for(j=0;j<n;j++)
	{
		if(j==n-1)printf("%d\n",a[i][j]);
		else printf("%d ",a[i][j]);
	}
	return 0;
} 

G. 实验9_10_统计子串

运行时间限制: 1000 运行内存限制: 65536
作者: scshuanghai 是否specialjudge: False
题目描述
问题描述:
任意给定两个字符串str1与str2, str1与str2中可以包含任意字符。你的任务是统计字符串str2在str1中出现的次数。
如字符串str1为“asasasbbbasbas”,str2为“as”,则统计结果为5。注意如果字符串str1为“aaaaa”,字符串str2为“aaa”,则统计结果为3。

输入与输出要求:
输入两个长度不超过100的字符串,以换行符结束。输出统计次数,占一行。

程序运行效果:
dhd dhdhdfg dhd dh zx67 dhd mklodhdh↙
dhd↙
6↙
这题思路简单,比较出第一个字母相等后就可以跳到函数里比较,函数设计限制条件就可。
但这题我出现了一个问题,用了全局变量num,发现,无论怎样输出的都是0.
原因在于,在主函数里之前设置的num没删,这就造成了num的值被0一直覆盖。在这里插入图片描述

#include<stdio.h>
#include<string.h>
#define SIZE 101
char str2[SIZE];
int bijiao(char [],int);
int num=0;
int main()
{
	char str1[SIZE];
	int i,len;
	gets(str1);
	gets(str2);
	
	//条件:从第一个相等字母往后str2的长度均相等 
	for(i=0;str1[i]!='\0';i++)
	{
		if(str1[i]==str2[0])
		bijiao(str1,i);
	}
	printf("%d\n",num);
	return 0;
} 
int bijiao(char str1[],int n)
{
	int len,i,j,eq=1;
	//printf("%s\n",str1);
	len=strlen(str2);
	//printf("%d\n",len);
	for(i=n+1,j=1;(str1[i]!='\0')&&(str1[i]==str2[j])&&(j<len);i++,j++)//str1不能先结束,str2只需要循环到其长度
	{
		eq++;
		//printf("%d\n",eq);
	}
	if(eq==len)num++;
}

字符数组读写输入输出

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
//gets可以读取空格
在这里插入图片描述

H. 实验9_20_字符串排序

运行时间限制: 1000 运行内存限制: 65536
作者: scshuanghai 是否specialjudge: False
题目描述
问题描述:
整数可以按照大小来排序,其实字符串也可进行排序。排序时需要比较字符串大小。字符串比较规则见Problem13中对于strcmp功能的描述。任意给定n个字符串,字符串中可以包含除换行符之外的任意字符。你的任务是将这n个字符串从小到大进行排序,然后输出。

输入与输出要求:
输入一个不超过200的整数n,代表待排序字符串的个数。然后输入n个字符串,每个字符串长度不会超过100,以换行符结束。输出排序后的n个字符串,每个字符串占一行。

程序运行效果:
Sample 1:
5↙
bbb↙
zzzzzz↙
aabbbccc↙
aaaaaa↙
abbbbb↙
aaaaaa↙
aabbbccc↙
abbbbb↙
bbb↙
zzzzzz↙

Sample 2:
3↙
abbbbbb↙
abbbbbb↙
aaaa↙
aaaa↙
abbbbbb↙
abbbbbb↙

本题要用gets输入才可,因为测试数据中字符串有空格。。
思路很简单,冒泡排序加字符数组比较和交换,使用strcmp进行比较,使用strcpy进行字符数组转移。
顺便介绍

字符数组相关其他函数

1)strcat函数

在这里插入图片描述
在这里插入图片描述
由下图程序所见,连接后字符串1后的’\0’被吃掉了
在这里插入图片描述
不管多少个’\0’都会被吃掉
在这里插入图片描述
当字符串1为空时,该函数与strcpy作用一致
在这里插入图片描述

2)strcpy函数

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3)strcmp函数

在这里插入图片描述
在这里插入图片描述

strcmp原理

在这里插入图片描述
在这里插入图片描述

/*s指向的串大于t指向的串,返回1;小于,返回-1;等于,返回0*/
int strCmp(char * s,char * t)
{
   while(*s!='\0' && *t!='\0' && *s==*t){
      s++;
      t++;
   }
       
   if(*s==*t) //若结束比较时s和t所指字符相等,则肯定都指向‘\0’
        return 0;
   else if (*s>*t)//任何一个字符均大于‘\0’(‘\0’ ASCII为0)
        return 1;
   else
        return -1;          
}

4)strlen函数

在这里插入图片描述

5)strlwr函数

在这里插入图片描述
在这里插入图片描述
好像扯得有点远(其实并没有)

#include<stdio.h>
#include<string.h>
#define SIZE 101
char str2[SIZE];
int main()
{
	int n,i,j;
	char str[201][SIZE],temp[SIZE];
	scanf("%d",&n);
	getchar();//用于吃掉输入n剩下的换行符,不然会被读入下面的字符串,从而少读入一个字符串。
	for(i=0;i<n;i++)
	gets(str[i]);
	/*for(i=0;i<n;i++)
	printf("%s\n",str[i]);*/
	for(i=0;i<n;i++)
	for(j=0;j<n-1;j++)
	if(strcmp(str[j],str[j+1])>0)
	{
		strcpy(temp,str[j]);
		strcpy(str[j],str[j+1]);
		strcpy(str[j+1],temp);
	}
	for(i=0;i<n;i++)
	puts(str[i]);
	return 0;
} 
发布了26 篇原创文章 · 获赞 18 · 访问量 1649

猜你喜欢

转载自blog.csdn.net/qq_40774136/article/details/103350818