C语言回顾学习(数组、函数、指针应用、最大最小值查找以及删除、平均值求解)

C语言回顾学习-N1

概述

本文主要回顾C语言中的几个基础知识,你将会看到:
1.在函数体中应用指针通过改变形参同时影响到实参改变;
2.在C语言中动态分配数组元素大小;
3.数组元素的删除、打印、求平均值;
4.查询数组中的最大最小值并且打印出来,且记录下它们的索引。
我将会通过具体实例和代码分块分析讲解各个部分内容。
注:本文在VS2019编译器环境下编写

具体实例

本例子中将要解决的实际问题
编写一个程序完成以下功能:
1)从键盘输入10个百分制成绩,数据为0~100整数;
2)找出最大值和最小值并输出;
3)求出去掉最大最小值后的平均值保留两位小数输出;
4)如果在输入时输入了非0~100的成绩时,输出“输入数据有错,请重新输入”,继续=完成共10个数据输入及其功能程序。

实例分析

功能分析

1.本实例中功能1以及功能4属于同一类型,均和录入数据有关。有限定输入的个数,并且限定输入数据的大小范围,需要涉及到if判断语句结构、scanf语句、数组创建相关知识;
2.功能2以及功能3涉及到数组元素的查询和删减知识
3.本文代码中的拓展部分:
A.实现遍历数组元素,将其打印输出的功能;
B.实现查询数组中最大最小值下标功能;
C.实现由用户决定数组大小,动态定义数组大小的功能。

各功能实现方式

全局变量定义以及预编译代码
#include <stdio.h> //标准库
#include <stdlib.h> // malloc方法 动态分配数组大小
int length ; //数组长度变量,由用户输入决定
int index = -1; //索引
数据录入功能

代码演示,实现连续输入length个元素。

void my_scanf(int* a)
{
	int t;
	printf("请输入0-100之间的%d个数字组成数组:\n",length);
	for (int j = 0; j < length; j++)
	{

		scanf_s("%d", &t);//vs2019中 scanf需要使用scanf_s替代
		if (t >= 0 && t <= 100)
		{
			a[j] = t;
		}
		else  //每次输出检验是否在0-100之间 如果不是再次执行一次输入操作
		{
			j = j--;
			printf("请重新输入0-100之间的数据\n");
			continue;
		}
	}

}
数组元素的查询和删减和打印功能

1.数组元素的删除:

void my_delete(int* a, int Index)
{
	for (int j = Index; j < length; j++)
	{
		a[Index] = a[Index + 1];
	}
	length--;
}

其逻辑是知道需要删除的元素下标之后,用这个元素之后的元素覆盖它,实现替换功能,再把数组长度减1,实现数组的删减。
2.数组元素的中最大和最小数的查询打印功能:

int my_max(int* a)
{
	int max = a[0];//先取指针指向数组中的第一个数为max后再慢慢比较
	for (int j = 0; j < length; j++)
	{
		if(max <= a[j])
		{
			max = a[j];
			index = j;
		}
	}
	printf("数组中最大的数字为%d,它的数组索引是%d\n",max,index);
	return index;
}

使用中间变量max进行次次比对,max初始化时设置为和数组的第一个元素相等,以便于实现精准比对。返回所查找到的元素下标是为了更好地运用数组的查删函数进行数组元素的更改操作。
3.数组元素的遍历打印功能:

void my_print(int* a)
{
	printf("数组共有%d个元素,数组元素如下\n",length);
	for (int j = 0; j < length; j++)
	{
		printf("%d ", a[j]);
		if (j == length - 1)
		{
			printf("\n");
		}
	}
}
数组元素的平均值求取
void my_average(int* a)
{
	double sum = 0;
	for (int j = 0; j < length; j++)
	{
		sum += a[j];
	}
	printf("平均值为%.2lf\n", sum / length);
}

将格式化字符串中加入%x.y就可以设置输出的数字的位数了。
x指定数据的宽度,即在输出时可以输出的最多数字位数;y指定小数位数,即保留小数点后y位数。%.2lf表示保留到小数点后两位。

动态分配数组元素大小(malloc、free)
    printf("请输入数组的长度:(按Enter键)");
	scanf_s("%d", &length);
	array = (int*)malloc(length*sizeof(int)); 
	/*
	...
    ...
    ...
   */
	free(array); 
	array = NULL;

1.malloc( 长度*类型所占字节数)

将找到可用内存中一个大小适合的块。
返回:那块内存第一个字节的地址。因为默认返回 void * 型,所以要根据指针的类型进行强制转换.(如果找不到合适的空间,则返回空指针)。
(int*)强制转换成 int * 型的地址。

2.free(array)
使用完释放malloc申请的内存空间(一个malloc对应一个free)。
free调用后,这段内存仍然可以使用且不改变array指针的指向,只是将这段内存标记为可用内存,也就是说,当free掉这段内存之后,这段内存是可以被自由调用的,或可以被某一次malloc申请到。

3.array = NULL;
free之后array仍然是指向这段内存的地址,而且这段内存的数据也没有被覆盖,如果你某一次用指针p用malloc申请到了与array同样的地址,那么你操作了array指针后,同样也操作了p指针,出现冲突情况。所以为了避免这样的情况发生,应该在free掉array之后,将array指向NULL,这样之后就不会发生指针数据冲突的情况了。

代码源码以及实验结果

1.源码

#include <stdio.h> //标准库
#include <stdlib.h> // malloc方法 动态分配数组大小
int length ; //数组长度变量
int index = -1; //索引
void my_print(int* a)
{
	printf("数组共有%d个元素,数组元素如下\n",length);
	for (int j = 0; j < length; j++)
	{
		printf("%d ", a[j]);
		if (j == length - 1)
		{
			printf("\n");
		}
	}
}
void my_scanf(int* a)
{
	int t;
	printf("请输入0-100之间的%d个数字组成数组:\n",length);
	for (int j = 0; j < length; j++)
	{

		scanf_s("%d", &t);
		if (t >= 0 && t <= 100)
		{
			a[j] = t;
		}
		else  //每次输出检验是否在0-100之间 如果不是再次执行一次输入操作
		{
			j = j--;
			printf("请重新输入0-100之间的数据\n");
			continue;
		}
	}

}
int my_max(int* a)
{
	int max = a[0];//先取指针指向数组中的第一个数为max后再慢慢比较
	for (int j = 0; j < length; j++)
	{
		if(max <= a[j])
		{
			max = a[j];
			index = j;
		}
	}
	printf("数组中最大的数字为%d,它的数组索引是%d\n",max,index);
	return index;
}
int my_min(int* a)
{
	int min = a[0];//先取指针指向数组中的第一个数为max后再慢慢比较
	for (int j = 0; j < length; j++)
	{
		if (min >= a[j])
		{
			min = a[j];
			index = j;
		}
	}
	printf("数组中最小的数字为%d,它的数组索引是%d\n", min, index);
	return index;
}
void my_delete(int* a, int Index)
{
	for (int j = Index; j < length; j++)
	{
		a[Index] = a[Index + 1];
	}
	length--;
}
void my_average(int* a)
{
	double sum = 0;
	for (int j = 0; j < length; j++)
	{
		sum += a[j];
	}
	printf("平均值为%.2lf\n", sum / length);/*将格式化字符串中加入%x.y就可以设置输出的数字的位数了。
		x指定数据的宽度,即在输出时可以输出的最多数字位数;y指定小数位数,即保留小数点后y位数。
		*/
}
int main()
{
	int* array;
	int delete_index = -1;
	int delete_index1 = -1;
	printf("请输入数组的长度:(按Enter键)");
	scanf_s("%d", &length);
	array = (int*)malloc(length*sizeof(int)); /*
	为数组分配 length长度的内存大小   
	malloc( ) 将找到可用内存中一个大小适合的块。
    返回:那块内存第一个字节的地址。因为默认返回  void * 型,所以要根据指针的类型进行强制转换。        
   (如果找不到合适的空间,则返回空指针)(int*)强制转换成 int * 型的地址*/
	my_scanf(array);
	my_print(array);
	my_average(array);
	delete_index = my_max(array);
	delete_index1 = my_min(array);
	//printf("要删除的最大值数索引号%d\n", delete_index);
	my_delete(array, delete_index);
	//my_print(array);
	//printf("要删除的最小值数索引号%d\n", delete_index);
	my_delete(array, delete_index1);
	printf("删除最大最小值之后数组元素如下\n");
	my_print(array);
	my_average(array);
	free(array); 
	/*使用完释放malloc申请的内存空间(一个malloc对应一个free)
	free调用后,这段内存仍然可以使用且不改变array指针的指向,只是将这段内存标记为可用内存,
	也就是说,当free掉这段内存之后,这段内存是可以被自由调用的,或可以被某一次malloc申请到。*/
	array = NULL;
	/*free之后array仍然是指向这段内存的地址,而且这段内存的数据也没有被覆盖,如果你某一次用指针p
	用malloc申请到了与array同样的地址,那么你操作了array指针后,同样也操作了p指针,出现冲突情况。
    所以为了避免这样的情况发生,应该在free掉array之后,将array指向NULL,这样之后就不会发生指针
   数据冲突的情况了。  */
	return 0;
}

2.控制台功能实现:
程序执行结果

总结

重新回顾C语言学习,突发奇想写下文章记录一下学习过程,代码不足之处希望各位可以多多包涵,欢迎各位提意见和疑惑。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值