C语言学习第六章——数组

单位换算
1KB=210B=1024B
1MB=210KB=1024KB
1GB=210MB=1024MB
内存地址
以2GB内存地址为例,2GB=231B,计算机就为这231个存储单元(字节)的位置编码:
在这里插入图片描述

#include<stdio.h>
int main(void){
	int a,b,c;
	printf("%p,%p,%p\n",&a,&b,&c); 
	
	int d[3];
	d[0]=1,d[1]=2,d[2]=3;
	printf("%d,%d,%d\n",d[0],d[1],d[2]);
	printf("%p,%p,%p\n",&d[0],&d[1],&d[2]);
	return 0;
}

一维数组

定义数组及初始化

#include<stdio.h>
int main(void){
	//1.定义数组 
	//int a[2*2];
/*
	int b = 2;
	int c[2*b];		//error
*/
	const int b=2;		//常变量 
	int c[2*b];
	//int e[3.1];		//error
	int e[(int)3.1];
	int f['A'];
	int g[true];
	//2.定义并初始化数组 
/*	完全初始化 
	//int a[4]={1,2,3,4};
	int a[]={1,2,3,4};
*/
	int a[4]={1};		//在不完全初始化中,元素如果未被初始化将会有一个默认值0 
	for(int i=0;i<4;++i)
		printf("%d\n",a[i]); 
	return 0;
}

数组的排序

#include<stdio.h>
int main(void){
	int a[5] = {89,34,-56,1,23};
	 
	int len = 5;
	/*	//冒泡排序
	for(int i=0;i<len-1;++i){
		for(int j=1;j<len-i;++j){
			if(a[i]>a[i+j]){
				int temp=a[i];
				a[i]=a[i+j];
				a[i+j]=temp;
			}
		}
	}
	*/
	//选择排序
	for(int j=0;j<len-1;++j){
		int c=0;
		for(int i=1;i<len-j;++i){
			if(a[c]<a[i])
				c=i;
		} 
		int b=a[c];
		a[c]=a[len-1-j];
		a[len-1-j]=b;
	}
	for(int k=0;k<len;++k)
		printf("%d,",a[k]); 
	putchar('\n');
	return 0;
}

指针

#include<stdio.h>
void f1(int b){
	b=10;
}
void f2(int *c){
	*c=10;
}
int main(void){
	int *p;		//p时int *类型的,用来存放int型变量的地址 	读作:定义了一个指向 int的指针变量 p 
	int a=2;
	p=&a;		//p指向 a 
	*p=3;		//*p等价于 a
	f1(a);		//printf输出3
	f2(&a); 	//printf输出10	通过函数改变main函数当中的某一个变量,就需要对这个变量取地址 
	printf("%d\n",a);
	
	int d[3];		//数组名 d是一个int *类型的常量,其值为d[0]的地址 
	p=d;
	p[0]=1;
	p[1]=2;
	p[2]=3;
	//printf("%d,%d,%d\n",d[-1]=1,d[3]=1;d[4]=1);		//error  数组下标越界 
	*p=10;
	*(p+1)=20;		//*(d+1)=20
	*(p+2)=30;		//*(p+2) ->p[2]		*(p+2)和*(2+p)等价	2[p] 
	0[p]=100;
	1[p]=200;
	2[p]=300;
	//d = &a;		//error  因为 d是一个常量 
	printf("%p,%p,%p\n",p,p+1,p+2);		// p + n 实际上是 p + sizeof(*p)*n 
	for(int i=0;i<3;++i)
		printf("%5d",d[i]);
	return 0;
}

数组的增删改查及倒置

#include<stdio.h>
#define LEN 10
//有效数个数 
int length(int *a){		//参数还可以写成 int a[LEN] 或者 int a[] 都代表a是一个int * 类型的变量 
	int j = 0;
	while(j<LEN){
		if(a[j] == 0)
			break;
		else
			++j;
	}
	 return j;
} 
void show(int a[]){
	int len=length(a);
	for(int i=0;i<len;++i)
		printf("%5d",a[i]);
	putchar('\n');
}
//删 
bool del(int *a,int index){
	int len = length(a);
	if(len==0 || index>len-1 || index<0)
		return false;
	else{
		for(int i=index+1;i<len;++i)
			a[i-1]=a[i];
		a[len-1]=0;
		return true;
	}
} 
//增 
bool insert(int *a,int index,int value){
	int len=length(a);
	if(len==LEN ||index<0 || index>len)
		return false;
	else{
		for(int i=len-1;i>=index;--i)
			a[i+1]=a[i];
		a[index]=value;
		return true;
	}
}
//倒置 
void invert(int *a){
	int len=length(a);
	/*
	int from = 0;
	int end = len-1;
	while(from<end){
		int d = a[from];
		a[from] = a[end];
		a[end]=d;
		from++;
		end--;
	}*/
	for(int from=0,end=len-1;from<end;from++,end--){
		int d = a[from];
		a[from] = a[end];
		a[end]=d;
	}
}
//查 
int find1(int *a,int value){
	int len=length(a);
	for(int i=0;i<len;++i){
		if(a[i]==value)
			return i;
	}
	return -1;
}
//二分查找
int find2(int *a,int value){
	int len=length(a);
	int from = 0;
	int end = len-1;
	while(from<=end){
		if(value==a[(from+end)/2])
			return (from+end)/2;
		else if(value > a[(from+end)/2])
			from = (from+end)/2+1;
		else
			end = (from+end)/2-1;
	}
	return -1;
}
int main(void){
	int a[LEN]={3,6,9,12,15};
	/*if(del(a,5))
		show(a);
	else
		printf("删除失败\n"); 
		*/
	//insert(a,2,8);
	//invert(a);
	//printf("%d\n",find1(a,12));		//3
	//printf("%d\n",find1(a,7));		//-1
	printf("%d\n",find2(a,15));		//4
	printf("%d\n",find2(a,7));		//-1
	show(a);
	//printf("有效元素的个数为:%d\n",length(a));
	//show(a);
	return 0;
}

二维数组

二维数组的定义及初始化
1.二维数组定义的一般形式:
类型说明符 数组名 [常量表达式][常量表达式]

2.二维数组在内存中的存储方式
例如:int a[2][3]; 这里定义了一个2行3列的数组,我们可以把它看成一个表格:
在这里插入图片描述
但实际内存是线性的,(假设此二维数组从第1000个字节处开始存放)所以实际储存方式如下::
在这里插入图片描述

#include<stdio.h>
int main(void){
//1.完全初始化 
	//int a[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};
	/*int a[3][4]={
					{1,2,3,4},
					{5,6,7,8},
					{9,10,11,12}
				};
				*/
//2.不完全初始化
	//int a[3][4] = {1}; 	//1,0,0,0,0,0,0,0,0,0,0,0
	//int a[3][4]={{1,2,3,4},{},{9,10,11,12}};	//只适合部分编译器 
	//int a[3][4] = {{1},{2,3},{4}};	//1,0,0,0,2,3,0,0,4,0,0,0
	//int a[3][4] = {{1},{2,3}};	//1,0,0,0,2,3,0,0,0,0,0,0
	int a[][4]={1,2,3,4,5,6,7,8,9,10,11};	//1,2,3,4,5,6,7,8,9,10,11,0
	
	/* 输出方式1
	for(int i=0;i<3;++i)
		for(int j=0;j<4;++j)
			printf("%d\n",a[i][j]);
			*/
	//输出方式2
	for(int i=0;i<12;++i)
		printf("%d\n",a[i/4][i%4]); 
			return 0;
}

通过指针引用多维数组
在这里插入图片描述
&a[1]:1012
a[1]+2:1020
*(a+0)+1:1004
&a[1][1]:1016
*( *(a+1)+2):6

求二维数组的鞍点
鞍点:某行最大值+某列最小值

#include<stdio.h>
#define M 5
#define N 6
bool f(int (*a)[N],int i,int j){
	for(int x=0;x<N;++x){
		if(a[x][j]<a[i][j])
			return false;
	}
	return true;
}
void show(int a[M][N]){		//int a[][N] 或者 int(*a)[N] 都是定义了一个指向含有N个整型元素的数组的指针 
	for(int i=0;i<M;++i){
		for(int j=0;j<N;++j){
			printf("%5d",a[i][j]);
		}
		putchar('\n');
	} 
}
int main(void){
	int a[M][N];
	for(int i=0;i<M*N;++i)
		a[i/N][i%N] = i;
	show(a);
	
	for(int i=0;i<N;++i){
		int k = 0;
		for(int j=1;j<N;++j){
			if(a[i][k]<a[i][j])
				k=j;
		}
		if(f(a,i,k))
			printf("a[%d][%d]是这个二维数组的鞍点\n",i,k); 
	}
	return 0;
}

字符数组

#include<stdio.h>
int main(void){
	char a[10]={'h','a',' ','h','a','\n'};		//'\0'空字符 是C语言中字符串结束的标志 
	printf("haha\0hehe");		//输出haha 
	printf("%s","ABCD");		//字符串常量末尾都有一个空字符 
	printf("%s",a);
	
	//字符型数组定义时初始化所有特有的形式 
	char b[10] = {"ha ha\n"};
	char c[10] = "ha ha\n";
	char d[]="ha";		// d 数组有3个元素 
	//c = "ha ha\n";		//error 因为c是一个char * 类型的常量 
	char *ch = "ha ha\n";	//字符串常量在计算机的内存当中是一个没有名字的数组 
	printf("AAA%s",ch);
	return 0;
}

字符串的输入和输出

#include<stdio.h>
void show(char *a,int len){
	for(int i=0;i<len;++i){
		printf("%d\n",a[i]);
	}
} 
int main(void){
	char a[30],b[30],c[30],ch;
	/* 
	scanf("%s%s%s%c",a,b,c,&ch);		//如果输入项是字符数组的数组名或者是char *类型的变量就不需要加取地址符 使用scanf输入多个字符串时,用空格,tab或者换行来分隔 
	printf("%s%s%s%c",a,b,c,ch);
	show(a,30);		//a数组当中没有被赋值的元素 是一个垃圾值 
	*/
	gets(a);//和scanf函数一样都会把字符数组当中的一个元素赋值为空字符。不同点1.gets可以把空格,tab赋给这个字符数组的元素。2.gets会丢弃换行符 
	ch = getchar();
	puts(a);
	putchar(ch);
	puts("haha"); 	//puts输出该字符串之后 在输出一个换行符 
	
	int x=2,y=3;
	printf("x=%d,y=%d\n",x,y);
	//char *p = "x=%d,y=%d\n";
	char *p = "x=%#x,y=%#x\n";
	printf(p,x,y);		//printf和scanf被称为可变格式输出输入函数 
	return 0;
}

处理字符串的函数
库函数#include<string.h>中

#include<stdio.h>
//有效长度 
int strlen(char *a){
	if(a == NULL)
		return 0;
	int len = 0;
	while(a[len] != '\0')
		len++;
	return len;
} 
//小写
char *strlwr(char *a){
	if(a == NULL)
		return NULL;
	char *a1 = a;
	while(*a != '\0'){
		if(*a <= 'Z' && *a >= 'A')
			*a += 32;
		++a;
	}
	return a1;
} 
//大写
char *strupr(char *a){
	if(a == NULL)
		return NULL;
	char *a1 = a;
	while(*a != '\0'){
		if(*a <= 'z' && *a >= 'a')
			*a -= 32;
		++a;
	}
	return a1;
} 
//复制 
char *strcpy(char *a,char *b){
	if(a == NULL||b == NULL)
		return a;
	char *a1 = a;
	/*while((*a = *b)!= '\0'){
		a++;
		b++;	
	}*/
	while((*(a++) = *(b++))!= '\0')
		;
	return a1;
}
//连接 
char *strcat(char *a,char *b){
	if(a == NULL||b == NULL)
		return a;
	char *a1 = a;
	while(*(a++) != '\0')
		;
	a--;
	while((*(a++) = *(b++))!= '\0')
		;
	return a1;
}
//覆盖 
char *strncpy(char *a,char *b,int n){
	if(a == NULL||b == NULL)
		return a;
	char *a1 = a;
	for(int i=0;i<n;++i){
		a[i]=b[i];
	}
	return a1;
}
//比较大小
 int strcmp(char *a,char *b){
 	if(a == NULL||b == NULL)
		return 2;
	do{
		if(*a=='\0' && *b=='\0')
			return 0;
		else if(*a<*b)
			return -1;
		else if(*a>*b)
			return 1;
		a++,b++;
	}while(true);
 } 
int main(void){		//以上函数注释掉也可以运行,在库函数#include<string.h>中 
	char a[] = "ABChaha";
	printf("%d\n",strlen(a));
	printf("%s\n",strlwr(a));
	printf("%s\n",strupr(a));
	printf("%s\n",strcpy(a,"lala"));
	printf("%s\n",strcat(a,"123"));
	printf("%s\n",strncpy(a,"abcdef",4));
	printf("%d\n",strcmp("abcde","abde"));
	return 0;
}

习题1
1.输出以下杨辉三角形(要求输出10行)
在这里插入图片描述
方法一:

#include<stdio.h>
#define N 10
int main(void){
	int a[N][N]={0};
	for(int i=0;i<N;++i){
		a[i][0]=1;
		a[i][i]=1;
		for(int j=0;j<i+1;++j){
			if(i>=2&&j>=1)
				a[i][j]=a[i-1][j-1]+a[i-1][j];
			printf("%5d",a[i][j]);
		} 
		putchar('\n');
	}
	return 0;
}

方法二:

#include<stdio.h>
#define N 10
void show(int a[N][N]){
	for(int i=0;i<N;++i){
		for(int j=0;j<=i;++j)
			printf("%6d",a[i][j]);
		putchar('\n');
	}
}
int main(void){
	int a[N][N]={0};
	for(int i=0;i<N;++i)
		a[i][0]=1;
	for(int i=0;i<N;++i)
		for(int j=1;j<=i;++j)
			a[i][j]=a[i-1][j-1]+a[i-1][j];
	show(a);
	return 0;
}

习题2
2.有n个整数,使前面各数顺序向后移m个位置,最后m个数变成最前面m个数,如下图:
在这里插入图片描述

#include<stdio.h>
#define N 10
void show(int a[]){
	for(int i=0;i<N;++i)
		printf("%d",a[i]);
	putchar('\n');
}
void move(int *a,int k,int index){
	for(int i=0;i<k;++i){
		int d = a[index];
		a[index] = a[index-1];
		a[index-1] = d;
		index--;
	}
}
int main(void){
	int a[N]; 
	for(int i=0;i<N;++i)
		a[i]=i;
	show(a);
	int m;
	do{
		printf("请输入m的值:");
		scanf("%d",&m);
		if(m>=0&&m<=N)
			break;
		printf("输入有误。"); 
	}while(1);
	for(int i = N-m;i<N;++i)
		move(a,N-m,i);
	show(a);
	return 0;
}

习题3
3.有n个人围城一圈,顺序排号。从第1个人开始报数(从1到3报数),凡报到3的人退出圈子,问最后留下的原来第几号的那位。

#include<stdio.h>
int main(void){
	int a[1000]={0};
	printf("请输入总人数:");
	int n;
	scanf("%d",&n);
	for(int i=0,cnt=0,sum=0;sum!=n-1;++i){
		if(a[i%n]==3)
			continue;
		if((a[i%n]=(cnt++)%3+1)==3)
			sum++;
	}
	int i;
	for(i=0;i<n;++i)
		if(a[i]!=3)
			break;
	printf("最后留下的是原来第%d个人\n",i+1);
	return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

shi_jiaye

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

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

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

打赏作者

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

抵扣说明:

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

余额充值