1. 一维数组总结性思维导图
前一阵子,在老师的课堂上学习了思维导图的用法,觉得很是好用,对知识点的总结以及思路都是很好的体现,所以我今天开始尝试使用思维导图的形式开始对之前的知识进行总结,争取在C语言学习完成后,能有一份完整的C语言思维导图
2. 宏函数和函数调用的区别
昨天写了宏函数,那么宏函数和函数调用的区别都有什么呢?
(1). 调用时间
宏函数是在程序预编译阶段进行宏替换,而函数调用发生在程序的运行时间
(2). 数据类型声明
宏函数在定义的时候,不需要指定参数类型,适用于多种数据类型,但这既是宏函数的优点也是他的缺点,优点在于我们不必要取管他的数据类型是什么,系统会自动匹配最优的数据类型进行计算,缺点在于,我们有可能在运算的时候出现我们不想要的计算方式以及结果
函数的参数数据类型必须严格定义,如果出现个数或者数据类型不匹配的情况,编译不会通过
(3). 运算方式
宏定义只是对文本的替换,他不会考虑运算方式,知识把相应的标识符删除掉,也不会给它分配空间,而函数调用时,则需要对形参分配空间,并把实参复制一份赋给形参分配的空间中
(4). 运算速度
函数在运行阶段需要有入栈和出栈的操作,速度相对比较慢
一个宏函数的练习:
我们先定义一个宏函数,然后再主程序中运算看看运行结果
#include<stdio.h>
#define TOTAL(x) x * x
int main()
{
int x = 7;
int y =770;
int a = TOTAL(x + y);
printf("%d", a);
}
定义一个TOTAL(x)的宏函数,再main函数调用时,入参是x + y,我们可能会想先计算x+y的值,然后再计算两个数相乘,但是宏函数的特点,他只是进行了文本替换,所以调用的时候,真正的算式是x + y * x + y,这样的到的值和我们的预期不一样,如果想先算x+以的值就得在定义宏函数的时候变成:
#define TOTAL(x) (x) * (x)
3. 数组越界
数组越界就是数组的下标变量的取值超过了初始定义的大小,导致对数组元素的访问出现在数组的范围之外
越界的结果,可能会拿到不确定的值或者会导致程序报错
#include<stdio.h>
int main()
{
int arr[6];
int i;
for(i = 0; i < 9; i++)
{
scanf("%d", &arr[i]);
}
// for(i = 0; i < 7; i++)
// {
// printf("%d ", arr[i]);
// }
printf("%d", arr[8]);
return 0;
}
我们定义了数组大小为6,但是我们赋值了9个值,在第6个数组后,输出它的值就会一个比一个怪,有的是输入的值,也有是输入+1的值,还有一个很大的数...
4. 数组的增删改查
我们在定义了一个数组后,难免相对数组进行增删改查,所以我们可以写相应的函数,对数组进行相应的操作
#include<stdio.h>
//数组的增删改查
#define N 7
int increate_arr(int a[], int length, int p, int n)
{
int i;
for(i = 0; i < p; i++)
{
a[length - 1 - i] = a[length - 2 - i];
}
a[p - 1] = n;
return 0;
}
int print_arr(int a[], int length)
{
int i;
for(i = 0; i < length; i++)
{
printf("%d ", a[i]);
}
printf("\n");
return 0;
}
int delete_arr(int a[], int length, int p)
{
int i;
a[p - 1] = 0;
for(i = p - 1; i < length; i++)
{
a[i] = a[i + 1];
}
a[length - 1] = 0;
return 0;
}
int modify_all(int a[], int length)
{
int i;
for(i = 0; i < length; i++)
{
a[i] *= 30;
}
return 0;
}
int find_arr(int a[], int length, int num)
{
int i;
int flag = 0;
for(i = 0; i < length; i++)
{
if(a[i] == num)
{
flag = 1;
break;
}
}
if(flag == 1)
{
printf("找到这个数,是第%d个元素\n", i + 1);
}
else
{
printf("没找到这个数字");
}
return 0;
}
int main()
{
int position, num;
int arr[N] = {86, 85, 4, 4396, 78, 98, 74};
print_arr(arr, N);
//数组的增加
// printf("在数组哪一位增加一个什么元素:\n");
// scanf("%d%d", &position, &num);
// increate_arr(arr, N, position, num);
// print_arr(arr, N);
// 数组的删除
// printf("请输入删除哪一个元素:\n");
// scanf("%d", &position);
// delete_arr(arr, N, position);
// print_arr(arr, N);
// 数组的的修改
// printf("对所有元素扩大30倍\n");
// modify_all(arr, N);
// print_arr(arr, N);
//查找元素
// find_arr(arr, N, 4396);
return 0;
}
我把增删改查写进一个文件里了,如果想测试功能可以自行测试,我就说说我的思路
增加一个元素,我先确定在哪个位置增加,然后将这个为之后的元素每一位向后移一位,然后将空出来的位置赋上我们增加的数
删除一个元素,我们输入我们想输入那个位置的元素,将这个数字赋0,然后将每一个数字向前移一位
修改一个元素,那我们就确定想修改的是哪个元素,然后通过下标将值替换
查询一个元素,就将这个元素和数组其他元素进行比较,如果有这个数字,就输出有这个数,没有就输出没有这个数
5. 冒泡排序
冒泡排序就是通过一次又一次的比较,将数组排序成我们想要的顺序(从大到小或者从小到大)
#include<stdio.h>
#define N 6
int pop_arr(int arr[], int length)
{
int i, j;
int temp;
for(i = 0; i < length; i++)
{
for(j = 0; j < length - 1 - i ; j++)
{
if(arr[j + 1] < arr[j])
{
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
return 0;
}
int print_arr(int arr[], int length)
{
int i;
printf("排序后的数组为:\n");
for(i = 0; i < length; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
int main()
{
int arr[6] = {43, 436, 4396, 4399, 439, 4936};
pop_arr(arr, 6);
print_arr(arr, 6);
return 0;
}
我写的是一个从小到大的冒泡排序,思路是比较相邻的元素。如果第一个比第二个大,就交换他们两个。对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。针对所有的元素重复以上的步骤,除了最后一个。持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
总结:
又一天的学习结束了,今天学到了数组的增删改查以及冒泡排序,在对数组删操作的时候,出现了一个问题,就是把想要删的值都已经赋上0了,但是运行结果删除的那个值跑到了数组最后一个值去了,怎么调试也没有结果,但是我觉得我代码逻辑应该没有问题,所以就在for循环后将最后一个值赋上了0,这样结果上是正确的,但是还是没有明白这是为什么,这是一个问题,以后发现了再做解答。