四种方法使函数返回多个值

使用多个return语句

这是最容易想到的,有多个返回值就想当然以为可以写多个return实现。下面我们来测试下:

#include <stdio.h>

int findMaxAndMin(int a, int b, int c)
{
    int temp = a>b?(temp=a):(temp=b);
    int max = temp>c?temp:c;

    int temp1 = a<b?(temp1=a):(temp1=b);
    int min = temp1<c?(temp1):c;

    return max;
    return min;
}

int main(void)
{
    int a, b, c;
    scanf("%d,%d,%d", &a, &b, &c);
    printf("The max value is: %d\n", findMaxAndMin(a, b, c));
    printf("The min value is: %d\n", findMaxAndMin(a, b, c));
    return 0;
}

我们虽然在findMaxAndMin()函数中写了两个return语句。但通过printf测出函数的返回值,是只返回了一个值。

如果我们将两个return语句颠倒下呢?

#include <stdio.h>

int findMaxAndMin(int a, int b, int c)
{
    int temp = a>b?(temp=a):(temp=b);
    int max = temp>c?temp:c;

    int temp1 = a<b?(temp1=a):(temp1=b);
    int min = temp1<c?(temp1):c;

    return min;
    return max;
}

int main(void)
{
    int a, b, c;
    scanf("%d,%d,%d", &a, &b, &c);
    printf("The max value is: %d\n", findMaxAndMin(a, b, c));
    printf("The min value is: %d\n", findMaxAndMin(a, b, c));
    return 0;
}

返回的是最小值。由此可见:

使用两个return语句是无法让函数返回两个以上的值。并且编译器只会看到第一个return并将值返回给主调函数,然后就会认为已经将函数执行完毕。不会理会第二个return语句。

方法一:使用全局变量

在findMaxAndMin()函数中,保存最大值和最小值的变量是max和min。它们默认是局部变量,只在函数中有效。

如果将其声明为全局变量,我们就可以在整个程序中利用这两个全局变量。间接的实现让函数返回两个值的操作。

#include <stdio.h>

int max, min;

void findMaxAndMin(int a, int b, int c)
{
    int temp = a>b?(temp=a):(temp=b);
    max = temp>c?temp:c;

    int temp1 = a<b?(temp1=a):(temp1=b);
    min = temp1<c?(temp1):c;
}

int main(void)
{
    int a, b, c;
    scanf("%d,%d,%d", &a, &b, &c);
    findMaxAndMin(a, b, c);
    printf("The max value is: %d\n", max);
    printf("The min value is: %d\n", min);
    return 0;
}

是可以实现需求的。但使用全局变量的缺点是,这个定义在外面的max和min是可以在这个文件中的任何地方被使用的。如果其他函数使用了全局变量,例如重新复制,那么它的值就会改变。这显然是不安全的,并且会使得代码的耦合度升高。不利于后期维护和代码调试。

方法二:使用指针变量

参考:如何让一个函数返给主函数多个返回值

方法三:利用数组

错误思想:被调函数计算出两个值max和min后,可以用一个数组保存起来,然后返回给主调函数这个数组的地址,主调函数再经过处理(指针运算,拿出里面的值)。

原因:试图让被调函数返回地址就是错误的。因为被调函数在执行完毕后,就弹栈了,所占用的空间就被释放。(即垃圾地址)。让主调函数操作那个垃圾地址是得不到正确的值的。

举例:你租了一间404房间,一天后你走了,但是你在退房前告诉你的朋友在404房间有一本书,第二天你退房后,你的朋友通过404这个地址是能找到这个房间的,但那本书可能在也可能不在,这就不一定了。

 

正确方法:在调用被调函数之前就将参数(本题是三个参数)存在一个数组中,然后将数组的地址传递给被调函数,让其通过指针来改变它们的位置(例如最小的在0号下标位置,最大的在2号下标位置)。如图:

#include <stdio.h>

void findMaxAndMin(int *pArr, int n)    //传数组给函数需要两个参数(数组名和数组长度)
{
    //排序
    for (int i = 0; i<n-1; i++)
    {
        for (int j = 0; j<n-i-1; j++)
        {
            if (pArr[j]>pArr[j+1])
            {
                int temp = pArr[j];
                pArr[j] = pArr[j+1];
                pArr[j+1] = temp;
            }
        }
    }
}

int main(void)
{
    int arr[3];
    for (int i = 0; i<3; i++)
    {
        scanf("%d", &arr[i]);
    }
    findMaxAndMin(arr, 3);
    printf("The max value is: %d\n", arr[2]);
    printf("The min value is: %d\n", arr[0]);
    return 0;
}

Ps:上述排序使用的是冒泡法,使用其他的排序算法也是可以的。

方法四:利用结构体

既然使用数组是可以的,我们可以把使用数组的方法看作把需要操作的数据打包起来,用指针来操作和改变内部的值。

下面尝试下用结构体来打包一组数据。

#include <stdio.h>

struct Arr {
    int num1, num2, num3;
    int min;
    int max;
};

void findMaxAndMin(struct Arr *pArr)    //传数组给函数需要两个参数(数组名和数组长度)
{
    int t = pArr->num1>pArr->num2?pArr->num1:pArr->num2;
    pArr->max = t>pArr->num3?t:pArr->num3;

    int t1 = pArr->num1<pArr->num2?pArr->num1:pArr->num2;
    pArr->min = t1<pArr->num3?t1:pArr->num3;
}

int main(void)
{
    struct Arr arr;
    //赋值
    arr.num1 = 2;
    arr.num2 = -4;
    arr.num3 = 8;
    findMaxAndMin(&arr);    //传地址到函数
    printf("The max value is: %d\n", arr.max);
    printf("The min value is: %d\n", arr.min);
    return 0;
}

这里强调下,第11到第15行是算法,作用是找到最大的值和最小的值。具体利用的是三目运算符(相当于两个if…else语句),如果不理解可以把这段代码改成其他的找最大最小值算法。或者用冒泡、选择等排序算法实现。

本篇文章重点不是讲解这些排序算法,往后我会抽时间专门出一篇排序算法总结。

到了这里,基本上常见的使函数返回多个值的方法就介绍完毕了。如果大家有更好的办法欢迎补充。谢谢!

作者: 高志远

高志远,24岁,男生

发表评论

邮箱地址不会被公开。