【C++】学习笔记三十四——函数和结构

函数和结构

  为结构编写函数比为数组编写函数简单得多。在函数中,结构变量的行为更接近于基本的单值变量,与数组不同,结构将其数据组合成单个实体或数据对象,被视为一个整体。
  可以讲一个结构赋给另一个结构,因此可以按值传递结构,此时函数将使用原始结构的副本。另外,函数也可以返回结构。
  结构名只是结构的名称,要获得结构的地址,必须使用地址运算符&。
  
  使用结构编程时,最直接的方式是像处理基本类型那样处理结构,即将结构作为参数传递,并在需要时将结构用作返回值使用。
  然而,按值传递结构有一个缺点,如果结构非常大,则复制结构将增加内存要求,降低系统运行的速度。出于这些原因,许多C程序员形象与传递结构的地址,然后使用指针来访问结构的内容。C++提供了第三种选择——按引用传递(将在后续介绍)。下面介绍前两种方式。


传递和返回结构

  当结构较小时,按值传递结构最合理。

程序7.11

#include<iostream>
struct travel_time
{
    int hours;
    int mins;
};
const int Mins_per_hr = 60;

travel_time sum(travel_time t1, travel_time t2);
void show_time(travel_time t);

int main()
{
    using namespace std;
    travel_time day1 = { 5, 45 };
    travel_time day2 = { 4, 55 };

    travel_time trip = sum(day1, day2);
    cout << "Two-day total: ";
    show_time(trip);

    travel_time day3 = { 4, 32 };
    cout << "Three-day total: ";
    show_time(sum(trip, day3));

    system("pause");
    return 0;
}

travel_time sum(travel_time t1, travel_time t2)
{
    travel_time total;

    total.mins = (t1.mins + t2.mins) % Mins_per_hr;
    total.hours = t1.hours + t2.hours +
        (t1.mins + t2.mins) / Mins_per_hr;
    return total;
}

void show_time(travel_time t)
{
    using namespace std;
    cout << t.hours << " hours, "
        << t.mins << " minutes\n";
}

  其中,travel_time就像一个标准的类型名,可被用来声明变量、函数的返回类型和函数的参数类型。
  


另一个处理结构的函数示例

程序7.12 直角坐标与极坐标转换

#include<iostream>
#include<cmath>

struct polar
{
    double distance;
    double angle;
};
struct rect
{
    double x;
    double y;
};

//prototype
polar rect_to_polar(rect xypos);
void show_polar(polar dapos);

int main()
{
    using namespace std;
    rect rplace;
    polar pplace;

    cout << "Enter the x and y values: ";
    while (cin >> rplace.x >> rplace.y)
    {
        pplace = rect_to_polar(rplace);
        show_polar(pplace);
        cout << "Next two numbers (q to quit): ";
    }
    cout << "Done.\n";
    system("pause");
    return 0;
}

polar rect_to_polar(rect xypos)
{
    using namespace std;
    polar answer;

    answer.distance = sqrt(xypos.x * xypos.x + xypos.y * xypos.y);
    answer.angle = atan2(xypos.y, xypos.x);
    return answer;
}

//将弧度转换为角度
void show_polar(polar dapos)
{
    using namespace std;
    const double Rad_to_deg = 57.29577951;    //180/pi
    cout << "distance = " << dapos.distance;
    cout << ", angle = " << dapos.angle * Rad_to_deg;
    cout << " degrees\n";
}

传递结构的地址

  假设要传递结构的地址而不是整个结构以节省时间和空间,则需要重新编写前面的函数,使用指向结构的指针。重新编写show_polar()函数,需要修改:

  • 调用函数时,将结构的地址(&pplace)而不是结构本身(pplace)传递给它;
  • 将形参声明为指向polar的指针,即polar *类型,由于函数不应该修改结构,因此使用const;
  • 由于形参是指针而不是结构,因此应间接成员运算符(->),而不是句点运算符。

程序7.12修改后如7.13所示。

程序7.13

#include<iostream>
#include<cmath>

struct polar
{
    double distance;
    double angle;
};
struct rect
{
    double x;
    double y;
};

//prototype
void rect_to_polar(const rect * pxy, polar *pda);
void show_polar(const polar* pda);

int main()
{
    using namespace std;
    rect rplace;
    polar pplace;

    cout << "Enter the x and y values: ";
    while (cin >> rplace.x >> rplace.y)
    {
        rect_to_polar(&rplace, &pplace);
        show_polar(&pplace);
        cout << "Next two numbers (q to quit): ";
    }
    cout << "Done.\n";
    system("pause");
    return 0;
}

void rect_to_polar(const rect *pxy, polar * pda)
{
    using namespace std;
    pda->distance = sqrt(pxy->x *pxy->x + pxy->y*pxy->y);
    pda->angle = atan2(pxy -> y, pxy->x);
}

//将弧度转换为角度
void show_polar(const polar *  pda)
{
    using namespace std;
    const double Rad_to_deg = 57.29577951;    //180/pi
    cout << "distance = " << pda->distance;
    cout << ", angle = " << pda->angle * Rad_to_deg;
    cout << " degrees\n";
}

由于原来的rect_to_polar返回一个结构,因此修改起来比较复杂。为了充分利用指针的效率,应使用指针,而不是返回值。为此,将两个指针传递给该函数,第一个指针只想要转换的结构,第二个指针指向存储转换结果的结构。函数不返回一个新的结构,而是修改调用函数中已有的结构。因此,虽然第一个参数是const指针,第二个参数却不是。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值