警院复试C程序设计学习笔记——第六章 数组

1.单位换算及内存地址

代码如下:

#include <stdio.h>
int main(void){
	int a, b, c;
	printf("%p, %p, %p\n", &a, &b, &c);	//输出abc三个变量的地址(十六进制) 
	
	
	//定义一个数组
	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;
}

执行结果如下:

2.定义数组及初始化

代码如下:

#include <stdio.h>
int main(void){
	
	//1.定义数组 
	//int a[2*2];	//这样是可以的,相当于int a[4]; 	
	/*
	int b = 2;
	int c[2*b];	//error,因为b为整型变量 
	*/	
	const int b = 2;	//这样定义b为整型常量
	int c[2*b];			//这样就不会报错
	//int e[3.1];			//error,因为3.1不是整型
	int e[int(3.1)];	//强制类型转换,这样就不会报错
	int F['A'];			//大写A的ASCII码为65,这样就定义了一个有65个元素的数组
	int g[true];		//true为布尔型的数据,其值为1,这样就定义了一个有1个元素的数组
	
	//2.定义并初始化数组
	
	//完全初始化: 
	//int a[4] = {1, 2, 3, 4};
	//int a[] = {1, 2, 3, 4};	//这两行代码都可以对数组a进行完全初始化
	
	int a[4] = {1}; 			//不完全初始化。在不完全初始化中,元素如果未被初始化,将会有一个默认值0	 
	for(int i = 0; i < 4; ++i)
		printf("%d\n", a[i]); 
	return 0;
}

执行结果如下:

3.数组的排序

这里讲了冒泡排序和选择排序

代码如下:

#include<stdio.h>
int main(void) {
	int a[7] = {89,34,-56,1,23,100,-32};

	int len = 7;
	//冒泡排序
	/*
	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;
}

执行结果如下:

注意:要通过代码理解两种算法的思路

4.指针

#include <stdio.h>
void f1(int b){
	b = 10;
}

void f2(int *c){
	*c = 10;
}


int main(void){
	int *p;		//这是定义了一个指针变量,p是int *类型的,用来存放int型变量的地址 
	int a = 2;
	p = &a;		//p指向a 
	*p = 3;		//*p等价于a 
	printf("%d\n", a);	//结果为3 
	f1(a); 
	printf("%d\n", a);	//结果为3 
	f2(&a);				//通过函数改变main函数当中的某一个变量,就需要对这个变量取地址 
	printf("%d\n", a);	//结果为10
	
	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;
}

执行结果如下:

5.数组的增删改查及倒置

代码如下:

#include <stdio.h>
#define LEN 10

//这个函数的功能是计算数组中有效元素的个数
int length(int *a) {		//参数int a[LEN] 或者 int 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("%d\t", 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--;
	}
}

//这个函数的功能是通过值来查找位置
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");
	printf("有效元素的个数为:%d\n", length(a));
	*/
//	insert(a, 2, 8);
//	invert(a);
	printf("%d\n", find2(a, 15));
	show(a);
	return 0;
}

执行结果如下:

6.二维数组定义时的初始化

代码如下:

#include <stdio.h>
int main(void) {
	
	//完全初始化 
	//int a[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12};	//完全初始化1
	/*	完全初始化2
	int a[3][4] = {
		{1,2,3,4},
		{5,6,7,8},
		{9,10,11,12}
	};
	*/
	
	//不完全初始化 
	//int a[3][4] = {1};	//不完全初始化1
	//int a[3][4] = {{1,2,3,4},{},{9,10,11,12}};	//不完全初始化2
	//int a[3][4] = {{1},{2,3},{4}};	//不完全初始化3
	//int a[3][4] = {{1},{2,3}};		//不完全初始化4
	int a[][4] = {1,2,3,4,5,6,7,8,9,10,11};	//不完全初始化5 
	
	
	 
	/*	输出方式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;
}

执行结果如下:

7.通过指针引用多维数组

答案:

&a[1]        1012

a[1]+2        1020

*(a+0)+1        1004

&a[1][1]        1016

*(*(a+1)+2)        6

8.求二维数组的鞍点

代码如下:

#include <stdio.h>
#define M 5
#define N 6
//出具有m行n列二维数组的"鞍点",即该位置上的元素在该行上最大,在该列上最小
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');
	}

}

bool f(int (*a)[N], int i , int j){	//判断a[i][j]是不是j列上最小的元素 
	for(int x = 0; x < M; ++x){
		if(a[x][j] < a[i][j])
			return false;
	}	
	return true;
}


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 < M; ++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;
}

执行结果如下:

9.字符数组

代码如下:

#include <stdio.h>
int main(void){
	char a[10] = {'h', 'a', ' ', 'h', 'a', '\n'};	//'\0'空字符 是C语言中字符串结束的标志 
	//上面是不完全初始化,未被初始化的字符就自动赋为'\0'
	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个,因为还有一个\0 
	//c = "ha ha\n";	//error 因为c是一个char *类型的常量
	char * ch = "ha ha \n"; 	//字符串常量在计算机的内存当中是一个没有名字的数组 
	printf("AAA%s", ch);
	return 0;
}

执行结果如下:

10.字符串的输入和输出 

代码如下:

#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输入多个字符串时,用空格,tab或者换行来分隔 
	/* 
	scanf("%s%s%s%c", a, b, c, &ch);	//如果输入项是字符数组的数组名,或者是char *类型的变量,就不需要加取地址符
	printf("%s%s%s%c\n", a, b, c, &ch);
	show(a,30);		//a数组当中没有被赋值的元素 是一个垃圾值 
	*/
	
		
	/* gets函数:
	功能:将用户输入的一行文字放到数组a的元素当中 
	和scanf函数一样,都会把字符数组当中的一个元素赋值为空字符。
	不同点:1.gets可以把空格、tab赋给这个字符数组的元素 
			2.gets会丢弃换行符 
	*/
	
	/* puts函数:
	puts()函数用来向标准输出设备屏幕输出字符串并换行
	具体是把字符串输出到屏幕上,将‘\0’转换为回车换行。调用方式是:puts(str)。其中str是字符串数组名或者字符串指针。实际上,数组名就是指针。
	*/ 
	
	/*
	gets(a);
	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;
}

执行结果如下:

11.处理字符串的函数

代码如下:

#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++;
	}
	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'){
		a++;
		b++;
	}
	return a1; 
}

//这个函数的功能是将b字符串的前n个元素覆盖a字符串的前n个元素 
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){
	char a[] = "ABChaha";
	printf("%d\n", strlen(a));	//输出7
	printf("%s\n", strlwr(a));	//输出abchaha 
	printf("%s\n", strupr(a));	//输出ABCHAHA
	printf("%s\n", strcpy(a, "lala"));	//输出lala 
	//printf("%s\n", strcpy(a, "lala123456777777777"));	//error 因为字符串a长度仅为7
	printf("%s\n", strcat(a,"123")); 	//输出lala123 
	printf("%s\n", strncpy(a, "abcdef", 4));	//输出abcd123 
	printt("%d\n", strcmp("abcde", "abde"));	//输出-1 
	
	return 0;
}

执行结果如下:

实际上,这些函数在string.h中都是包含的

12.习题1 

题目要求:输出以下杨辉三角形(要求输出10行)

代码如下:

#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 = 1; 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;
}

运行结果如下:

13.习题2

题目要求:有n个整数,使前面各数顺序向后移m个位置,最后m个数变成最前面m个数,如下图

代码如下:

#include <stdio.h>
#define N 10

void show(int a[]){
	for(int i = 0; i < N; ++i)
		printf("%6d", 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("输出有误!\n");
	}while(1);
	for(int i = N-m; i < N; ++i){
		move(a, N-m, i);
	}
		
	show(a);
	return 0;
}

 执行结果如下:

14.习题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
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值