一个函数如何实现return好几个返回值(借鉴学习前辈的文章,链接放文章里了)
一个函数如何实现return好几个返回值—————————————壮壮的学习笔记
- 1.全局变量法(慎用)(宏定义也可以实现)
- 使用全局变量的原因
- 代码实例
- 运行结果
- 方法分析
- 2.数组指针法
- 使用数组指针法的原因
- 代码实例
- 运行结果
- 方法分析
- 3.结构体指针法
- 使用结构体指针法的原因
- 代码实例
- 运行结果
- 方法分析
- 4.返回型参数法
- 结尾
三个方法来源:https://blog.csdn.net/weixin_45863921/article/details/105220460
1.全局变量法(慎用)(宏定义也可以实现)
使用全局变量的原因
由于全局变量的作用域是从变量定义处开始直到程序结束,而对于编写有多个返回值的C语言函数,我们可以考虑把要返回的多个值定义成全局变量。当函数被调用时,全局变量被更改,我们再把更改后的全局变量值应用于主调函数中。函数被调用后被更改后的全局变量值即为函数的数个返回值
代码实例
//实例:自定义一个函数,依次分别返回两个数中较大的和较小的
#include <stdio.h>
int max = 0;
int min = 0;
void max_min(int x, int y)
{
max = x;
min = x;
max = (x > y) ? x : y;
min = (x < y) ? x : y;
}
int main()
{
int a = 0;
int b = 0;
scanf("%d %d", &a, &b);
max_min(a, b);
printf("%d %d", max, min);
return 0;
}
运行结果
方法分析
我们都知道,设计函数很重要的一点就是高内聚低耦合,函数设计出来最好是一个独立的模块,内部的程序最好与外部减少纠缠,但是这种通过全局变量来实现多个return返回值的方法就严重破坏了函数的独立性,原因很简单,你想,全局变量在整个源程序都是可以使用的,如果你在函数内部使用了这个全局变量,但是这个全局变量也很有可能在其他地方被其他代码给改掉。所以我的建议就是如果整个程序代码比较少的时候可以用用,如果程序很复杂,涉及多个函数多个文件的话,还是考虑一下下面的几种方法
2.数组指针法
使用数组指针法的原因
对于函数参数的传递,我们知道有传值和传址这两种方法。我们来复习一下这两个方法的差异,传值的话,函数参数是形参,形参是实参的一份临时拷贝,对形参的修改不会影响实参;传址的话,我们把实参的地址传过来,函数形参可以通过这个门牌号(地址)找到实参,因此也可以通过这个地址对实参进行修改。因此我们可以在主函数定义一个数组,将需要函数返回的值以变量的形式定义在这个数组里,然后把数组地址传给函数,通过数组地址找到数组并把返回值存放到数组里,这样我们就可以在数组里看到多个返回值了
代码实例
//实例:自定义一个函数,依次分别返回两个数中较大的和较小的
//
#include <stdio.h>
void max_min(int arr[])
{
if (arr[1] > arr[0])
{
int tmp = 0;
tmp = arr[1];
arr[1] = arr[0];
arr[0] = tmp;
}
}
int main()
{
int arr[2] = { 0 };
int i = 0;
printf("请输入你要比较的两个数:>\n");
for (i = 0; i < 2; i++)
{
scanf("%d", &arr[i]);
}
max_min(arr);
printf("较大的数是: %d\n", arr[0]);
printf("较小的数是: %d\n", arr[1]);
return 0;
}
运行结果
方法分析
这种方法的缺陷就是要求返回值的类型必须是一致的,如果不一致可以看看第三种方法(第一个方法也可以实现多个返回值类型不一致的函数,但是就是太危险了)
3.结构体指针法
使用结构体指针法的原因
我们能够知道,结构体里能够定义多种类型的数据,但是存值方法却类似数组,所以利用结构体简直就是集上面两种方法之大成(存值形式类似数组的话,也就可以传址给函数,避免出现全局变量的尴尬情况,而结构体内多种数据类型又避免了数组只能存放一种数据类型的尴尬,真的棒!!!)。。但是初学者难以理解结构体这个知识点
代码实例
//实例:自定义一个函数,用户能输入学生的姓名,班级,总成绩和排名,并将这些数据返回给主函数进行调用
#include<stdio.h>
#include<string.h>
struct stu
{
char name[20];
int class;
float score;
int rank;
};
void scanf1(struct stu* ps1)
{
char name1[20] = { 0 };
int class1 = 0;
float score1 = 0.0f;
int rank1 = 0;
scanf("%s%d%f%d", name1, &class1, &score1, &rank1);
strcpy(ps1->name, name1);
ps1->class = class1;
ps1->score = score1;
ps1->rank = rank1;
}
int main()
{
struct stu s1;
scanf1(&s1);
printf("口腔医学210%d班的%s同学,你的总成绩是%f,在该专业排名第%d", s1.class, s1.name, s1.score, s1.rank);
return 0;
}
运行结果
方法分析
这个代码是集1.2两种方法的大成,但是这里难点特别多,比如结构体的定义,结构体的赋值,结构体的引用等等
4.返回型参数法
该方法是练习的时候发现的,我也将那道题和这个方法做了结合,想要详细了解可以去看那篇文章
杨氏矩阵、返回型参数
这个方法的思想就是,在函数参数中多传入两个变量的地址,然后在函数中解引用访问这两个变量,可以把需要返回的值放入这两个变量,因为是传址,因此可以成功接收到。
但是,如果这两个参数是毫无意义的,那我觉得不如就用我之前介绍的三种方式。
这里的px,py就是返回型参数
参入的参数是极其有意义的。一、row、col代表矩阵的行列长度,这正是矩阵需要的。二、row、col都有代表下标的属性(意思是行列和下标都是代表位置的变量,用来接收目标下标也是情理之中)
#include<stdio.h>
void Young_matrix(int arr[3][3], int key, int *px, int *py)
{
int x = 0;
int y = *py-1;//(x,y)是初始矩阵右上角元素的下标
while (x <= *px-1 && y >= 0)
{
if (arr[x][y] > key)
{
y--;//去掉一列
}
else if (arr[x][y] < key)
{
x++;//去掉一行
}
else
{
*px = x;
*py = y;
return;
}
}
*px = -1;
*py = -1;
}
int main()
{
int arr[3][3] = { 1,2,3,4,5,6,5,7,8 };
int key = 0;//要寻找的值
scanf("%d", &key);
int row = 3;
int col = 3;
Young_matrix(arr, key, &row, &col);
if(-1 == row && -1 == col)
{
printf("找不到\n");
}
else
{
printf("找到了,下标是:(%d,%d)\n", row, col);
}
return 0;
}
结尾
这里是壮壮的学习之路,感谢大家的浏览与支持
2401_83052026: %e的输出不应该是小数点前一位,小数点后六位,e 后四位包括符号位嘛? 1.123456e+004
壮壮: 是的,你可以单独弄个测试用例试试看
zyl_718: 也就是说即使srand在循环外,它的值也是持续变化的吗
跳动的bit: 排序介绍的很详细,支持大佬
壮壮: 不会的,因为种子是time,而time是不断在变的呀