引用文章:c语言函数可不可以返回多个值


文章目录

  • 方法一:设置全局变量
  • 例如:利用一个函数求出正方形的周长和面积。
  • 方法二:使用数组名或指针作为函数的形参
  • 实例2:编写函数求一维整形数组的最大值与最小值,并把最大值与最小值返回给主调函数。
  • 方法三:使用结构体指针作为函数的形参
  • 实例3:编写一个用户自定义函数,允许用户录入学生的基本信息(包括学号、姓名、所属班级、总评成绩),并返回这些基本信息给主调函数。
  • 结束语


C语言函数是不像python那样支持多个返回值的,那么如果需要C语言函数实现多个返回值,有什么其他的办法吗?

在C语言中,一般情况下函数的返回值是通过函数中的return语句来实现的,每调用一次return语句只能从函数中返回一个值。但在实际很多应用中,我们需要从函数中返回多个值,那我们可以用什么方法实现呢?此时我们可以用三种方法来实现。

方法一:设置全局变量

全局变量是在函数外部定义的全局变量,它不属于任何一个函数,其作用域是从变量的定义处开始,到本程序文件的结尾。在此作用域内,全局变量可为各个函数所引用。当我们需要函数返回多个值时,除了函数体中的return语句返回其中一个之外,其它的返回值我们可以通过定义全局变量来处理。因为根据全局变量的特点,在被调用函数中改变了多个全局变量和值,相当于其主调函数全局变量的值也发生了变化,也就相当于返回了多个值。

例如:利用一个函数求出正方形的周长和面积。

#include <stdio.h>

double l = 0;//定义全局变量l为正方形周长

double f(double a)//定义求面积和周长的函数
{
	double s;
	s = a * a;//求面积
	l = 4 * a;//求周长,并赋给全局变量l
	return s;//仅返回面积的值
}

void main()
{
	double a;
	double area;
	printf("请输入边长:");
	scanf_s("%lf", &a);
	area = f(a);//面积的值通过调用f函数返回值
	printf("面积为: %5.2lf\n",area);
	printf("周长为: %5.2lf\n",l);//周长即为全局变量l在f函数中改变后的值
}

运行结果:

请输入边长:7
面积为: 49.00
周长为: 28.00

上面的例子即用全局变量实现了函数中返回多值的情况,这种方式易懂。但是全局变量用多了会破坏代码的安全性,结构性,这主要是全局变量在所有函数中都可以使用,从而其值的变化不确定,所以我们要慎用。

方法二:使用数组名或指针作为函数的形参

数组名或者指针实际为地址,而数组一般都包括多个元素,指针也可以指向一组数据的着地址,把数组名或者指针作为函数形参,实际上相当于主调函数的实参与形参共用地址,所以在函数中的数组元素发生改变即是实参也随之改变。也相当于在调用函数时多个值返回给主调函数。

实例2:编写函数求一维整形数组的最大值与最小值,并把最大值与最小值返回给主调函数。

方法:以指针方式传递该一维数组A的地址,再传递一个保存最大值最小值的数组Min_Max的地址,再把数字数组的大小n传过去。然后在函数里用for循环逐个比较求出最大值最小值,存到Min_Max中:

#include "stdio.h"

void max_min(int* A, int* Min_Max, int n) /*定义求数组最大值最小值的函数,传递数组指针*/
//实参和形参同名没啥关系?
{
	Min_Max[0] = A[0];
	Min_Max[1] = A[0];

	for (int i = 1; i < n; i++) {
		if (A[i] < Min_Max[0])
		{
			Min_Max[0] = A[i];
		}
		else if (A[i] > Min_Max[1])
		{
			Min_Max[1] = A[i];
		}
	}
}


/*调用最大最小值函数*/

int main()
{
	int A[6] = {3,2,4,9,1,7};
	int Min_Max[2];
	/*for (int i = 0; i < 6; i++) {
		printf("Please input the number %d, end with enter:\n", i);
		scanf_s("%d", &A[i]);
	}*/
	max_min(A, Min_Max, sizeof(A)/sizeof(A[0]));
	printf("min=%d, max=%d\n", Min_Max[0], Min_Max[1]);
	return 0;
}

结果:

min=1, max=9

注意:该方法适用于多个返回值的数据类型一致的情况。当返回值数据类型不一致时,不适用该方法。

方法三:使用结构体指针作为函数的形参

编写返回多个值的C语言函数,可以考虑采用结构体的方式去实现。如果返回的数个数值的数据类型不一致,可以通过定义全局变量实现有多个返回值的C语言函数,也可以考虑把要求返回的数个值定义成一个结构体,然后同样以传递结构体指针方式把结构体的指针传递给形参结构体指针,那么函数中对形参结构体的修改即是对实参结构体的修改,函数被调用后获取的实参结构体成员即为函数的多个返回值,下面以实例演示该方法的应用。

实例3:编写一个用户自定义函数,允许用户录入学生的基本信息(包括学号、姓名、所属班级、总评成绩),并返回这些基本信息给主调函数。

方法:把学生基本信息定义成一个结构体,在用户自定义函数中传递该结构体的指针,则自定义函数中对结构体成员的录入操作即是对实参结构体成员的录入操作,从而实现多个返回值。参考代码如下:

// Copyright (c) 2011 rubicon IT GmbH
// Author: Dontla

#include <stdio.h>
#include <String.h>


struct student {
	//定义学生结构体,分别包含成员学号、姓名、班别、总评成绩
	char stuNo[12];
	char stuName[20];
	char classNo[15];
	int totalScore;
};

int main()
{
	struct student student1; //定义学生结构体类型变量
	printf("请输入学号,姓名,班别,总评成绩,以空格隔开:\n");
	void logInfo(struct student* ptr);//因为函数写在main函数后面,所以要声明
	logInfo(&student1);//调用函数,以学生结构体类型变量地址作为实参
	printf("\n学号:%s\n姓名:%s\n班别:%s\n总评成绩:%d\n", student1.stuNo, student1.stuName, student1.classNo, student1.totalScore);
	return 0;
}

void logInfo(struct student* ptr)//该函数实现对结构体成员数据的录入操作
{
	char stuNo[12] = { 0 }, stuName[20] = { 0 }, classNo[15] = {0};
	//如果不全初始化为零,strcpy_s函数会提示可能没有为字符串添加字符串零终止符
	int totalScore;
	scanf_s("%s %s %s %d", &stuNo, sizeof(stuNo), &stuName, sizeof(stuName), &classNo, sizeof(classNo),&totalScore);
	strcpy_s(ptr->stuNo, stuNo);
	strcpy_s(ptr->stuName, stuName);
	strcpy_s(ptr->classNo, classNo);
	ptr->totalScore = totalScore;
}

运行结果:

请输入学号,姓名,班别,总评成绩,以空格隔开:
13331333 nana 4 585

学号:13331333
姓名:nana
班别:4
总评成绩:585

D:\Dontla_small_project\20210525_address_list\vs_test\vs_test\Debug\vs_test.exe (进程 34128)已退出,代码为 0。
按任意键关闭此窗口. . .

注意:当函数要求返回的多个值是相互联系的或者返回的多个值数据类型不一致时可以采用该方法。

结束语

对于以上这三种方法,如果想要返回的数个值数据类型一致,可以考虑采用方法2;而对于不同数据类型的返回值,如果各个数值之间是相互联系的,则方法3较为合适;方法1虽然在很多情况下都可以实现多个返回值的C语言函数,但毕竟全局变量应用过程中有很多危险,要慎重使用。
  
通过对以上几种方法的分析讲解,在教学过程中,学生再遇到这样的问题时,就能根据返回值的情况选择合适的途径去实现多个返回值的C语言函数。另外,如果再遇到类似的无法用教材知识点去直接解决的问题时,他们基本都能举一反三地尝试采用间接方式去解决。
参考材料:

http://wenku.baidu.com/link?url=tJOYOInBS22mj0uJcYDEs0qZHFuCqiuhkKrrJNtoAYkffDnVIt6kiKusF491G2MVbDVzQGQgyAQ9moF3Og9v8Tt0Ny5jG05GgDmlwrhRs8K