面向对象程序设计——Visual C++
第5章 结构体、共用体和枚举类型

思考题

1、使用结构体变量有什么好处?如何访问结构体中的成员?

使用结构体变量的好处是可以将多个相关的数据组合在一起,方便管理和操作。
访问结构体中的成员可以使用点运算符(.)或箭头运算符(->),具体取决于结构体变量是通过值传递还是通过指针传递。
例如,假设有以下结构体定义:

struct Person {
    string name;
    int age;
};

可以定义一个结构体变量并访问其成员:

Person p;
p.name = "Alice";
p.age = 25;

也可以定义一个指向结构体的指针并访问其成员:

Person* ptr = new Person;
ptr->name = "Bob";
ptr->age = 30;

2、结构体中的静态成员有什么特点?它有哪些特殊的用法?

结构体中的静态成员是所有结构体变量共享的成员,它们不属于任何一个特定的结构体变量,而是属于整个结构体。静态成员可以在结构体内部或外部进行定义和初始化,但必须在结构体外部进行访问。静态成员的特殊用法包括:

  1. 统计结构体变量的个数:可以在结构体中定义一个静态成员变量,每次创建结构体变量时,静态成员变量加1,这样就可以统计结构体变量的个数。
  2. 共享数据:可以使用静态成员变量来实现多个结构体变量之间的数据共享,这样可以节省内存空间。
  3. 实现单例模式:可以使用静态成员变量来实现单例模式,即保证一个类只有一个实例。
  4. 存储常量数据:可以使用静态成员变量来存储常量数据,这样可以避免重复定义和初始化。

3、位域和共用体分别以什么方式实现节省内存消耗的?

位域是通过将多个成员变量压缩到一个字节中来实现节省内存消耗的。
例如,如果一个结构体中有多个布尔类型的成员变量,每个成员变量占用一个字节,但实际上只需要一个比特位来存储它们的值,这时可以使用位域将它们压缩到一个字节中,从而节省内存空间。
共用体是通过共享内存空间来实现节省内存消耗的。共用体中的所有成员变量共享同一块内存空间,只有其中一个成员变量被赋值,其他成员变量的值就会被覆盖。这样可以避免为每个成员变量分配独立的内存空间,从而节省内存空间。但是需要注意的是,共用体的使用需要谨慎,因为它可能会导致数据的不确定性和安全问题。

4、哪些场合使用枚举类型比较适合,试举例说明使用枚举类型变量的优点。

枚举类型比较适合用于表示一组相关的常量,例如表示星期几、月份、颜色等。使用枚举类型变量的优点包括:

  1. 可读性好:枚举类型变量可以用有意义的名称来表示常量,使代码更加易读易懂。
  2. 安全性高:枚举类型变量只能取枚举中定义的值,不会出现非法值,从而提高了程序的安全性。
  3. 可维护性好:如果需要修改常量的值或添加新的常量,只需要修改枚举类型的定义,而不需要修改代码中的具体值,从而提高了代码的可维护性。

例如,定义一个表示星期几的枚举类型:

enum Weekday {Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday};

可以使用枚举类型变量来表示星期几:

Weekday today = Monday;
if (today == Sunday) {
    cout << "Today is Sunday." << endl;
}

习题

1、定义一个有关时间的结构体变量(成员包括小时、分、秒),并从键盘上输入数据并输出。

#include<iostream>
using namespace std;

// 时间结构体定义
struct Time {
    int hour; // 小时
    int minute; // 分钟
    int second; // 秒
};

int main() {
    Time t; // 定义时间结构体变量
    cout << "请输入小时: ";
    cin >> t.hour; // 从键盘上输入小时
    cout << "请输入分钟: ";
    cin >> t.minute; // 从键盘上输入分钟
    cout << "请输入秒: ";
    cin >> t.second; // 从键盘上输入秒
    cout << "输入的时间为:" << t.hour << ":" << t.minute << ":" << t.second << endl; // 输出时间
    return 0;
}

2、指出下面程序中的错误,并说明原因。

struct{int x,y,z}t1,t2;
struct test{int x,y,z}t3,t4;
cin>>t1>>t2;
t3=t1;
t4=t2;
cout<<t3<<t4;
enum str{“abc”,”bcd”,”dca”}

下面是程序中的错误及原因:

struct{int x,y,z}t1,t2;这行代码中结构体的定义缺少结构体名称,应该改为 struct MyStruct1 {int x, y, z;} t1, t2;

struct test{int x,y,z}t3,t4;这行代码中结构体成员的定义缺少分号,应该改为 struct test {int x, y, z;} t3, t4;

cin>>t1>>t2;输入操作符>>没有重载struct类型的输入,应该分别输入结构体的成员变量,例如cin >> t1.x >> t1.y >> t1.z >> t2.x >> t2.y >> t2.z;

t3=t1; t4=t2;结构体之间不能直接赋值,需要逐个赋值,例如t3.x = t1.x; t3.y = t1.y; t3.z = t1.z;

cout<<t3<<t4;输出操作符<<没有重载struct类型的输出,应该分别输出结构体的成员变量,例如 cout << t3.x << " " << t3.y << " " << t3.z << " " << t4.x << " " << t4.y << " " << t4.z << endl;

enum str{“abc”,”bcd”,”dca”}枚举类型中的枚举值应该是整型常量,而不是字符串常量,应该改为 enum MyEnum {ABC = 0, BCD = 1, DCA = 2};

下面是修改后的代码示例:

#include<iostream>
using namespace std;

// 定义结构体
struct MyStruct1 {
    int x, y, z;
};

struct MyStruct2 {
    int x, y, z;
} t3, t4;

int main() {
    MyStruct1 t1, t2; // 定义结构体变量
    cout << "请输入t1的x, y, z: ";
    cin >> t1.x >> t1.y >> t1.z; // 逐个输入结构体成员
    cout << "请输入t2的x, y, z: ";
    cin >> t2.x >> t2.y >> t2.z; // 逐个输入结构体成员
    t3.x = t1.x;
    t3.y = t1.y;
    t3.z = t1.z;
    t4.x = t2.x;
    t4.y = t2.y;
    t4.z = t2.z;
    cout << "t3的x, y, z为: " << t3.x << " " << t3.y << " " << t3.z << endl;
    cout << "t4的x, y, z为: " << t4.x << " " << t4.y << " " << t4.z << endl;
    enum MyEnum {ABC = 0, BCD = 1, DCA = 2};
    cout << "ABC = " << ABC << ", BCD = " <<

3、定义一个描述点三维坐标(x,y,z)的结构体变量,完成点的输入和输出,并求两点之间的距离。

#include <iostream>
#include <cmath>
using namespace std;

struct Point3D {
    double x, y, z;
};

double distance(Point3D p1, Point3D p2) {
    double dx = p1.x - p2.x;
    double dy = p1.y - p2.y;
    double dz = p1.z - p2.z;
    return sqrt(dx*dx + dy*dy + dz*dz);
}

int main() {
    Point3D p1, p2;
    cout << "Enter point 1 (x y z): ";
    cin >> p1.x >> p1.y >> p1.z;
    cout << "Enter point 2 (x y z): ";
    cin >> p2.x >> p2.y >> p2.z;
    cout << "Distance between points: " << distance(p1, p2) << endl;
    return 0;
}

4、建立50名学生信息登记表(结构体数组),每个学生的数据包括学号、姓名、性别、及三门成绩。要求:

(1)从键盘输入50名学生的数据。
(2)显示每个学生三门课的平均分。
(3)显示每门课程的全班平均分。
(4)显示名为“LiMing”的学生的三门成绩。
(5)按平均成绩由高到低将学生排名次,并按名次顺序输出这些学生的所有数据。
#include <iostream>
#include <string>
#include <algorithm>

using namespace std;

struct Student {
    string id;
    string name;
    char gender;
    double score[3];
    double avg_score;
};

const int MAX_SIZE = 50;

// 计算一个学生的平均分
double calculate_avg_score(Student& s) {
    double sum = 0.0;
    for (int i = 0; i < 3; i++) {
        sum += s.score[i];
    }
    double avg_score = sum / 3.0;
    s.avg_score = avg_score;
    return avg_score;
}

// 从键盘输入一个学生的信息
void input_student(Student& s) {
    cout << "Please enter the id, name, gender, and three scores for the student:" << endl;
    cin >> s.id >> s.name >> s.gender;
    for (int i = 0; i < 3; i++) {
        cin >> s.score[i];
    }
}

// 显示一个学生的信息
void display_student(Student& s) {
    cout << s.id << "\t" << s.name << "\t" << s.gender << "\t";
    for (int i = 0; i < 3; i++) {
        cout << s.score[i] << "\t";
    }
    cout << s.avg_score << endl;
}

// 显示一个学生的三门成绩
void display_student_scores(Student& s) {
    cout << s.id << "\t" << s.name << "\t" << s.gender << "\t";
    for (int i = 0; i < 3; i++) {
        cout << s.score[i] << "\t";
    }
    cout << endl;
}

// 显示全班每门课程的平均分
void display_class_avg_score(Student students[], int n) {
    double avg_scores[3] = {0.0};
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < 3; j++) {
            avg_scores[j] += students[i].score[j];
        }
    }
    for (int i = 0; i < 3; i++) {
        avg_scores[i] /= n;
        cout << "Average score for course " << i+1 << " is " << avg_scores[i] << endl;
    }
}

// 排序比较函数,按平均成绩从高到低排序
bool cmp(const Student& s1, const Student& s2) {
    return s1.avg_score > s2.avg_score;
}

int main() {
    Student students[MAX_SIZE];

    // 从键盘输入50名学生的数据
    for (int i = 0; i < MAX_SIZE; i++) {
        input_student(students[i]);
        calculate_avg_score(students[i]);
    }

    // 显示每个学生三门课的平均分
    cout << "Average scores for each student:" << endl;
    for (int i = 0; i < MAX_SIZE; i++) {
        display_student(students[i]);
    }

    // 显示每门课程的全班平均分
    cout << "Average scores for each course:" << endl;
    display_class_avg_score(students, MAX_SIZE);

    // 显示名为“LiMing”的学生的三门成绩
    cout << "Scores for student LiMing:" << endl;
    for (int i = 0; i < MAX_SIZE; i++) {
        if (students[i].name == "LiMing") {
            display_student_scores(students[i]);
            break;
        }
    }
    // 按平均成绩由高到低将学生排名次,并按名次顺序输出这些学生的所有数据
    sort(students, students + MAX_SIZE, cmp);
    cout << "Students ranked by average score:" << endl;
    for (int i = 0; i < MAX_SIZE; i++) {
        cout << i+1 << "\t";
        display_student(students[i]);
    }
    return 0;
}

在这个代码中,我们定义了一个结构体Student来存储每个学生的信息,包括学号、姓名、性别和三门成绩。我们还定义了一些函数来实现各种功能,比如计算一个学生的平均分,从键盘输入一个学生的信息,显示一个学生的信息等等。主函数中,我们首先从键盘输入50名学生的数据,并计算每个学生的平均分。然后,我们分别显示每个学生三门课的平均分和每门课程的全班平均分。接着,我们显示名为“LiMing”的学生的三门成绩。最后,我们按平均成绩由高到低将学生排名次,并按名次顺序输出这些学生的所有数据。

5、定义一个描述三种颜色的枚举类型(Red,Blue,Green),输出这三种颜色的全部排列组合结果。

#include <iostream>
using namespace std;
// 定义颜色枚举类型
enum Color {
    Red,
    Blue,
    Green
};
int main() {
    // 输出所有排列组合
    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 3; j++) {
            for (int k = 0; k < 3; k++) {
                if (i != j && j != k && i != k) {
                    cout << (Color)i << " " << (Color)j << " " << (Color)k << endl;
                }
            }
        }
    }
    return 0;
}

结果:

0 1 2
0 2 1
1 0 2
1 2 0
2 0 1
2 1 0