深究C语言-1.数组篇

学习C语言3-深究数组(上)

剩下的视频在我B站主页找!!!

目录

一,数组是什么?

数组又分为一维数组和二维数组。

分别给大家看看最基本的定义和初始化问题

现在来讲一些其他细节的东西

二,话不多说,咱来上题。

   一,基础一二维数组问题

二,数组的深入用法

三,小细节


一,数组是什么?

数组又分为一维数组和二维数组。

无论是一维数组还是二维数组,都是一组相同数据类型的有序集合,它能将一系列相同类型的数据看作一个整体,使用一个名字命名,再用下标进行分量标识,在内存中连续存放,用数组名和下标可以唯一地确定数组元素。

分别给大家看看最基本的定义和初始化问题

1.一维数组

数据类型 数组名[数组长度];
char str[100];


char str[100] = { 1,2,3 };
char str[100] = { 'a','b','c' };
char str[100] = "abc";



char str[]= { 'a','b','c' };//当把数据全部给出时,可以省略数组长度

还要提一下的:

 这是为什么?这么小的区别,为什么输出会不一样?

我把这个语句屏蔽掉也没啥用。

这就是一个基础概念的问题,在定义数组时初始化,初始化是对整个数组进行操作,而后面那种方式是对a[10]进行赋值,但是数组长度为10,最大下标为9,所以必须要加{},不然就会报错。

加了花括号我也不知道有啥用。。。。a数组中就没有第十一个元素。

那么,邪恶的事情又来了。

由上面三张图我们可以知道

1)数组未初始化,数组里面的值都是随机值。
2)数组初始化为{0},数组里面的值都是0。
3)数组初始化为{非零值},数组里面第一个值是非零值,其他的值都是0。

2.二维数组

数据类型 数组名[行下标][列下标];
char a[100][100];
char a[3][4] = { 1,2,3,4,5,6,7,8,9,0,11,12 };
char a[3][4] = { {1,2,3,4},{5,6,7,8},{9,0,11,12} };
//可以在里面加花括号也可以不加,都是一样的


二维数组省略长度时,只能省略行下标的书写,这是规定

二维数组是不是也有这种邪恶的事呢?

嘿嘿嘿,有的呢!

这样的话是不是会方便很多呢?嘿嘿嘿,不要说我为啥还有一些基础的东西不讲,我们都开始深究了,太基础的东西我只说重要一些的。 

这也是一种比较常见的初始化二维数组的方法。 

让我们接下来再看看字符串数组的初始化,因为字符串有一个专门的输入函数gets,输入一整行的字符串,所以可以只用一个for循环来完成初始化。

 每次输入一行后,输入一个回车键,跳出当前的for循环,进行下一次,可以少写,不能多写,多的部分会被舍弃。

现在来讲一些其他细节的东西

1.printf,scanf与puts,gets

scanf遇到空格或回车就结束

gets遇到回车才结束。

scanf("%d",&arr);//一般scanf后面都是要加&符号的,如果是写到数组里面,加不加&都无所谓。

sacnf("%s",str);
gets(str)//直接用数组名即可

2.“a”与‘a’的区别

“a”占两个字节,因为”“是字符串标志,系统会自动给字符串的结尾加上一个结束标识符'\0',所以这个占了两个字节

‘a’只占一个字节,因为‘’是字符标志,只有a一个字符,只占一个字节。

3.数组名是一个地址常量,存放数组内存空间的首地址,如果是&数组名,取出的就是整个数组的地址,当然,这两个的值是没有什么区别的,但是在一定的情况下就会出现区别。C语言中规定,只能引用单个的数组元素,而不能一次引用整个数组。

数组名加1的含义是往后走一个元素的大小,&数组名+1的含义就是往后走一个数组的长度。 

4.下标从0开始,下标不能越界。因为,一旦发生下标越界,就会把数据写到其他变量所占的存储单元中,甚至写入程序代码段,有可能造成不可预料的后果。

5.虽然C语言规定,只有静态存储的数组才能初始化,但一般的C语言编译系统都允许对动态存储的数组赋初值。如果静态存储的数组没有初始化,系统将自动给所有的数组元素赋值为0;

6.使用数组时,一般使用宏定义。

宏定义有宏定义的优势,修改更方便,只需要在define后面修改就好;

7.C语言支持多维数组,最常见的多维数组是二维数组。

二,话不多说,咱来上题。

   一,基础一二维数组问题

//输出大于平均值的数
#include<stdio.h>
int main(){
	int i,n;
	double ave,sum;
	int a[10];
	printf("请输入n:");
	scanf("%d",&n);
	if(n>=1&&n<=10){
		printf("请输入%d个数据:",n);
		for(i=0;i<n;i++){
			scanf("%d",&a[i]);//需要一个循环语句来输入数组的数据 
		}
		sum=0;
		for(i=0;i<n;i++){
			sum+=a[i];//同样也需要一个循环语句来累加 
		}
		 ave=sum/n;
		 printf("ave=%.2f\n",ave);
		 printf(">ave");
		 for(i=0;i<n;i++){//数组中的for循环不能用等于号哦,用等于号就需要多输出一个数据,因为数组从零开始 
		 	if(a[i]>ave)
		 	printf("%d ",a[i]);
		 }
		 printf("\n");
	}
		else
			printf("Invlid Value.\n");
	return 0; 
} 
#include<stdio.h>
#define MAXN 46//定义在最上面,需要更改时便只需改这一个地方。 数组都可以如此,更方便 
int main(){
	int i,n;
	int fib[MAXN]={1,1};//先输出前两项 
	printf("请输入n:");
	scanf("%d",&n);
	if(n>=1&&n<=46){
		for(i=2;i<n;i++){//i=2,是因为,数组从零开始,i=2时,其实是第三项 
			fib[i]=fib[i-1]+fib[i-2];//前一项等于后两项之和 
		}
		for(i=0;i<n;i++){
			printf("%6d",fib[i]);
		if((i+1)%5==0)
			printf("\n");
		}
			if(n%5!=0)
				printf("\n");
	}
	else
		printf("Invalid Value!\n");
	return 0;
} 
#include<stdio.h>
#define MAXN 8
int main(){
	int i,n,response;
	int count[MAXN+1];//实际问题是以1开头的,所以定义一个更长的,其实也可以在宏定义时定义更长的 
	printf("请输入n:");
	scanf("%d",&n);
	for(i=1;i<=MAXN;i++)
	count[i]=0;//数据的初始化,避免该存储单元之前的数据影响 !!!!!!! 
	for(i=1;i<=n;i++){
		printf("Enter your response:");
		scanf("%d",&response);
		if(response>=1&&response<=MAXN)
		count[response]++;//等价于count[response]+=1. 上面已经初始化过了,所以出现一次就会累加一次 
		else
			printf("Invalid:%d\n",response);
	}
	printf("result:\n");
	for(i=1;i<=MAXN;i++){
		if(count[i]!=0)
		printf("%4d%4d\n",i,count[i]);
	}
	return 0;
} 

这个题要看看!!!

#include<stdio.h>
#define MAXN 6
#define MAXM 6
int main(){
	int col,i,j,m,n,row;
	int a[MAXM][MAXN];
		printf("请输入m,n:");
		scanf("%d%d",&m,&n);
		printf("请输入%d个数:\n",m*n);
	for(i=0;i<m;i++){
		for(j=0;j<n;j++){
			scanf("%d",&a[i][j]);
		}
	}//二维数组的初始化方式,双重for循环 
	row=col=0;
	for(i=0;i<m;i++){//遍历数组找出最大值 
		for(j=0;j<n;j++){
			if(a[i][j]>a[row][col]){
				row=i;
				col=j;
			}
		}
	}
	printf("max=a[%d][%d]=%d\n",row,col,a[row][col]);
	return 0;
} 

把上面这几个东西搞熟,基本的一二维数组问题就都可以解决。

二,数组的深入用法

数组的作用当然不止这些,数组的优越性在于元素众多,及它的可选择性,因为元素众多,所以你可以选择多种元素。这个在后面尤为重要,(所以咱后面再讲,嘿嘿嘿)。

我们这里主要来讲一讲其他的两个主要作用,排序与查找。

上题目:

1.顺序查找法

#include<stdio.h>
#define MAXN 10
int main(){
	int i,flag,n,x;
	int a[MAXN];
	printf("please input n,x:");
	scanf("%d%d",&n,&x);
	printf("请输入%d个数:",n);
	for(i=0;i<n;i++){
		scanf("%d",&a[i]);//向数组内添加数据 
	}
	flag=0;
	for(i=0;i<n;i++){
		if(a[i]==x){
			printf("Index is %d\n",i);
			flag=1;
		}
	}
	if(flag==0)
	printf("Not found!\n");
	return 0;
} 

2.

#include<stdio.h>
#define MAXN 10
int main(){
	int i,index,n;
	int a[MAXN];
	printf("Enten n:");
	scanf("%d",&n);
	printf("请输入%d个数:",n);
	for(i=0;i<n;i++)
		scanf("%d",&a[i]);//数组输入数据,借助一个循环。 
	index=0;//假设index(首地址)为最小的项的下标 
	for(i=0;i<n;i++){
		if(a[i]<a[index])
		index=i;//如果有比他更小的,就换到首地址去 
	}
	printf("min is %d\tsub is %d\n",a[index],index);
	return 0;
} 

3.a与b中找相同(重点看题4)

#include<stdio.h>
int main(){
	int a[]={1,2,3,4,5},b[]={3,4,5,6,7,8},c[6];
	int i,j,k=0;
	for(i=0;i<5;i++){	
	    for(j=0;j<6;j++){
		    if(a[i]==b[j]){
			c[k]=a[i];
			k++;
			break;
		}
	}
}
	for(i=0;i<k;i++){
		printf("%d ",c[i]);
	}
	return 0;
} 

4.a与b中找不同

#include<stdio.h>
#define N 10
int main(){
	int m,n,i,j,k,a[N],b[N],c[2*N],flag=0;
	printf("请输入一个数:");
	scanf("%d",&m);
	printf("请输入%d个数据:",m);
	for(i=0;i<m;i++){
		scanf("%d",&a[i]);//初始化a数组 
	}
    printf("请输入一个数:");
	scanf("%d",&n);
	printf("请输入%d个数据:",n);
	for(i=0;i<n;i++){
		scanf("%d",&b[i]);//初始化b数组 
	}
	for(i=0;i<m;i++){
		for(j=0;j<n;j++){
			if(a[i]==b[j])
			break;//将a数组中的元素拿出与b数组中的元素比较 
		}
		if(j>=n){
		flag=1;
		c[k++]=a[i];//如果是正常循环结束,则表明a中的元素无与b中相同的元素 ,且flag=1 
	}
	} 
	for(j=0;j<n;j++){
		for(i=0;i<m;i++){
			if(b[j]==a[i])
			break;
		}
		if(i>=m){
		flag=1;
		c[k++]=b[j];//b也要与a比较 
		}
	}
	for(i=0;i<k;i++)
	printf("%d ",c[i]);
	if(flag==0)
	printf("No found!");//避免两数组无非公有元素而无操作 
	return 0;
}

5.最大最小值交换位置

#include<stdio.h>
#define N 10
int main(){
	int n,i,t,a[N],max,min;
	printf("请输入一个数:");
	scanf("%d",&n);
	printf("请输入%d个数:",n);
	for(i=0;i<n;i++)
	scanf("%d",&a[i]);
	max=0;
	min=0;//初始化最大最小值,使第一项为最大最小值。 
	for(i=0;i<n;i++){
		if(a[max]<a[i])
		max=i;
		if(a[min]>a[i])
		min=i;
	}
	t=a[max];
	a[max]=a[n-1];
	a[n-1]=t;
	//赋值过程一定要放在for循环外,循环结束了以后才能知道最大最小,切记切记 
	t=a[min];
	a[min]=a[0];
	a[0]=t;
	printf("%d   %d",a[0],a[n-1]);
	
	return 0;
}

6.选择法排序

#include<stdio.h>
#define MAXN 10
int main(){
	int i,index,k,n,temp;
	int a[MAXN];
		printf("请输入n:");
			scanf("%d",&n);
		printf("请输入%d个数:",n);
	for(i=0;i<n;i++)
		scanf("%d",&a[i]);
	for(k=0;k<n-1;k++){
		index=k;
		for(i=k+1;i<n;i++){
			if(a[i]<a[index])
			index=i;
		}
		temp=a[index];
		a[index]=a[k];
		a[k]=temp;
	}//k最大也只是n-2,i最大为n-1,即将a[k]与a[i]比较,在for循环结束后,下标已经交换完成,再交换数据	

		
	printf("排序为:");	
	for(i=0;i<n;i++)
		printf("%d ",a[i]);
	printf("\n");
	return 0;
} 

//第1轮在待排序记录r[1]-r[n]中选出最小的记录,将它与r[1]交换;第2轮在待排序记录r[2]-r[n]中选出最小的记录,将它与r[2]交换;以此类推,第i趟在待排序记录r[i]~r[n]中选出最小的记录,将它与r[i]交换,使有序序列不断增长直到全部排序完毕。

7.二分查找法

#include<stdio.h>
int main(){
	int low,high,mid,n=10,x;
	int a[10]={1,2,3,4,5,6,7,8,9,10};
	printf("请输入x:");
	scanf("%d",&x);
	low=0;
	high=n-1;
	while(low<=high){
		mid=(high+low)/2;
		if(x==a[mid])
		break;
		else if(x<a[mid])
		high=mid-1;
		else
		low=mid+1;
	}//这个循环就是二分查找法的主体部分。 
	if(low<=high)
	printf("Index is %d\n",mid);
	else
	printf("Noy Found");
	return 0;
} 

8.冒泡排序

#include<stdio.h>
#define MAXN 10
void swap(int *px,int *py);
void bubble(int a[],int n);

int main(){
	int n,a[MAXN],i;	
	
	printf("Enter n(n<=10):");
	scanf("%d",&n);
	printf("Enter %d integers:",n);
	
	for(i=0;i<n;i++)
	scanf("&d",&a[i]);
	
	bubble(a,n);//用数组名即可。 
	printf("After sorted:");
	for(i=0;i<n;i++)
	printf("%3d",a[i]);
	
	return 0;
}
void bubble(int a[],int n){
	int i,j,t;
	for(i=1;i<n;i++){
		for(j=0;j<n-i;j++){
			if(a[j]>a[j+1])
			swap(&a[j],&a[j+1]);
		}
	}
}
void swap(int *px,int *py){
	int t;
	t=*px;
	*px=*py;
	*py=t;
}

***9.判断回文-数组-递归-指针三种方法

1)数组

#include<stdio.h>
#define MAXLINE 80
int main(){
	int i,k;
	char line[MAXLINE];
	
	//输入字符串
	printf("Enter a string:"); 
	//输入字符串 
	k=0;
	while((line[k]=getchar())!='\n')
	k++;
	line[k]='\0';//必须要人为加上‘\0’. 
	//分别指向第一个和最后一个元素位置。 
	i=0;
	k-=1;
	
	while(i<k){
		if(line[i]!=line[k])//若对应字符不相等,则提前结束循环。 
			break;
		i++;
		k--;
	}
	//判断while循环是否正常结束,若是则说明字符串是回文。 
	if(i>=k)
		printf("是回文!");
	else
		printf("不是回文!");
	
	return 0;
}

2)递归

//递归 
#include<stdio.h>
#include<string.h>
int judge(int low,int high,char *arr,int len){
	//最终条件。
	if(len==0 || len==1) 
		return 1;
	if(arr[low]!=arr[high])
		return 0;
		
	return judge(low+1,high-1,arr,len-2);
}

int main(){
	char arr[10]="aaabbaaa";
	int len=strlen(arr);
		
	if(judge(0,len-1,arr,len))
	printf("是!");
	else
	printf("不是!"); 
	
	return 0;
} 

/*递归的作用在于把问题的规模不断缩少,直到问题缩少到简单地解决 
通过观察可以知道,一个回文字符串其中内部也是回文。所以,我们只需要以去掉两端的字符的形式一层层检查,
每一次的检查都去掉了两个字符,这样就达到了缩少问题规模的目的。
1. 字符串长度可能会奇数或偶数:

如果字符串长度是奇数,字符串会剩下最中间那位字符,但其不影响回文。当检查到长度为1的时候即代表此字符串是回文
如果字符串长度是偶数,当两端的字符串两两比较检查后不会剩下字符。即检查到长度为0的时候即代表此字符串是回文
2. 如果检查到两端两个字符不相同。则说明此字符串不是回文,直接返回0,不需要继续检查
————————————————
版权声明:本文为CSDN博主「cbsheng」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/cbs612537/article/details/8217425

3)指针与数组方法差不多。自己理解吧。

10.方阵转置

#include<stdio.h>
#define MAXN 6
int main(){
	int i,j,n,temp;
	int a[MAXN][MAXN];
	
	printf("ENTER n:");
	scanf("%d",&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=0;j<n;j++){
			if(i<=j){
				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;
} 

三,小细节

1.二维数组的每一行都可看做一个一维数组,可直接用数组名+[行号]代表该行首元素地址。

2.数组要重视长度,防止越界。

3.二维数组其实就是一种特殊的一维数组,二维数组存储方式就是类似一维数组的。

4.二维数组的数组名指的是数组的首地址,即第一行的地址。

5.数组名不能做自增自减运算,数组名是地址常量,不能做此类运算。

 请大家务必要把题目弄懂弄透!

希望大家能学到东西,也静待大家斧正和指教!!!

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

喜欢吃豆

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

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

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

打赏作者

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

抵扣说明:

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

余额充值