为结构编写函数比为数组编写函数简单得多。在函数中,结构变量的行为更接近于基本的单值变量,与数组不同,结构将其数据组合成单个实体或数据对象,被视为一个整体。 可以讲一个结构赋给另一个结构,因此可以按值传递结构,此时函数将使用原始结构的副本。另外,函数也可以返回结构。 结构名只是结构的名称,要获得结构的地址,必须使用地址运算符&。 使用结构编程时,最直接的方式是像处理基本类型那样处理结构,即将结构作为参数传递,并在需要时将结构用作返回值使用。 然而,按值传递结构有一个缺点,如果结构非常大,则复制结构将增加内存要求,降低系统运行的速度。出于这些原因,许多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指针,第二个参数却不是。