1.结构体应用

登录以参加训练计划

C++ 结构体与文件操作详解 - CSP-J 核心知识点

面向10-14岁学生,结合CSP-J考纲整理的结构体与文件操作知识

目录

  1. 结构体基础
  2. 结构体数组
  3. 结构体与函数
  4. 文件基础操作
  5. 结构体与文件结合
  6. 综合应用

1. 结构体基础

结构体的概念

结构体是自定义的数据类型,可以包含多个不同类型的成员变量

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

// 定义学生结构体
struct Student {
    string name;    // 姓名
    int age;        // 年龄
    double score;   // 成绩
    char gender;    // 性别
}; // 注意分号不能少

int main() {
    // 创建结构体变量
    Student stu1;
    
    // 访问成员并赋值
    stu1.name = "Alice";
    stu1.age = 12;
    stu1.score = 95.5;
    stu1.gender = 'F';
    
    // 输出结构体信息
    cout << "姓名: " << stu1.name << endl;
    cout << "年龄: " << stu1.age << endl;
    cout << "成绩: " << stu1.score << endl;
    cout << "性别: " << stu1.gender << endl;
    
    // 初始化结构体
    Student stu2 = {"Bob", 13, 88.0, 'M'};
    
    return 0;
}

结构体嵌套

struct Date {
    int year;
    int month;
    int day;
};

struct Student {
    string name;
    Date birthday;  // 嵌套结构体
};

int main() {
    Student s;
    s.name = "Tom";
    s.birthday.year = 2010;
    s.birthday.month = 5;
    s.birthday.day = 15;
    
    cout << s.name << "的生日是: " 
         << s.birthday.year << "-" 
         << s.birthday.month << "-"
         << s.birthday.day << endl;
    
    return 0;
}

2. 结构体数组

定义与使用

#include <iostream>
using namespace std;

struct Student {
    string name;
    int score;
};

int main() {
    // 创建结构体数组
    Student class1[3] = {
        {"Alice", 90},
        {"Bob", 85},
        {"Cindy", 95}
    };
    
    // 遍历结构体数组
    for (int i = 0; i < 3; i++) {
        cout << class1[i].name << ": " << class1[i].score << endl;
    }
    
    // 修改结构体数组元素
    class1[1].score = 88;
    
    return 0;
}

应用:学生成绩排序

#include <iostream>
#include <algorithm> // sort函数
using namespace std;

struct Student {
    string name;
    int score;
};

// 比较函数,按成绩降序
bool cmp(Student a, Student b) {
    return a.score > b.score;
}

int main() {
    Student stu[5] = {
        {"Alice", 90},
        {"Bob", 85},
        {"Cindy", 95},
        {"David", 78},
        {"Eva", 92}
    };
    
    // 排序
    sort(stu, stu+5, cmp);
    
    // 输出排序结果
    cout << "成绩排名:" << endl;
    for (int i = 0; i < 5; i++) {
        cout << i+1 << ". " << stu[i].name << ": " << stu[i].score << endl;
    }
    
    return 0;
}

3. 结构体与函数

结构体作为函数参数

#include <iostream>
using namespace std;

struct Point {
    int x;
    int y;
};

// 按值传递
void printPoint(Point p) {
    cout << "(" << p.x << ", " << p.y << ")" << endl;
}

// 按引用传递(避免复制)
void movePoint(Point &p, int dx, int dy) {
    p.x += dx;
    p.y += dy;
}

int main() {
    Point p1 = {3, 4};
    printPoint(p1); // (3,4)
    
    movePoint(p1, 2, 3);
    printPoint(p1); // (5,7)
    
    return 0;
}

结构体作为函数返回值

Point createPoint(int x, int y) {
    Point p;
    p.x = x;
    p.y = y;
    return p;
}

int main() {
    Point p2 = createPoint(10, 20);
    printPoint(p2); // (10,20)
    return 0;
}

4. 文件基础操作

文件操作步骤

  1. 包含头文件:<fstream>
  2. 创建文件流对象
  3. 打开文件
  4. 读写操作
  5. 关闭文件

文件读写示例

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

int main() {
    // 写文件
    ofstream outFile("data.txt"); // 打开文件用于写
    if (!outFile) {
        cerr << "打开文件失败!" << endl;
        return 1;
    }
    
    outFile << "Hello, File!" << endl;
    outFile << 123 << " " << 3.14 << endl;
    outFile.close();
    
    // 读文件
    ifstream inFile("data.txt");
    if (!inFile) {
        cerr << "打开文件失败!" << endl;
        return 1;
    }
    
    string line;
    getline(inFile, line); // 读取一行
    cout << line << endl;
    
    int a;
    double b;
    inFile >> a >> b; // 读取整数和浮点数
    cout << a << " " << b << endl;
    
    inFile.close();
    
    return 0;
}

文件打开模式

模式标志 描述
ios::in 读取
ios::out 写入(覆盖)
ios::app 追加
ios::binary 二进制模式
// 追加写入
ofstream outFile("log.txt", ios::app);
outFile << "新的日志" << endl;
outFile.close();

5. 结构体与文件结合

结构体数据写入文件

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

struct Student {
    string name;
    int age;
    double score;
};

int main() {
    Student stu[] = {
        {"Alice", 12, 90.5},
        {"Bob", 13, 85.0},
        {"Cindy", 12, 95.5}
    };
    
    // 写入文件
    ofstream outFile("students.dat", ios::binary); // 二进制模式
    if (!outFile) {
        cerr << "打开文件失败" << endl;
        return 1;
    }
    
    // 写入结构体数组
    outFile.write((char*)stu, sizeof(stu));
    outFile.close();
    
    return 0;
}

从文件读取结构体数据

int main() {
    Student stu[3];
    
    ifstream inFile("students.dat", ios::binary);
    if (!inFile) {
        cerr << "打开文件失败" << endl;
        return 1;
    }
    
    // 读取结构体数组
    inFile.read((char*)stu, sizeof(stu));
    inFile.close();
    
    // 显示读取的数据
    for (int i = 0; i < 3; i++) {
        cout << "姓名: " << stu[i].name 
             << " 年龄: " << stu[i].age
             << " 成绩: " << stu[i].score << endl;
    }
    
    return 0;
}

文本格式读写结构体

// 写入文本格式
ofstream outText("students.txt");
for (int i = 0; i < 3; i++) {
    outText << stu[i].name << " "
            << stu[i].age << " "
            << stu[i].score << endl;
}
outText.close();

// 读取文本格式
ifstream inText("students.txt");
Student s;
while (inText >> s.name >> s.age >> s.score) {
    cout << s.name << " " << s.age << " " << s.score << endl;
}
inText.close();

6. 综合应用

学生成绩管理系统

#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
using namespace std;

struct Student {
    string name;
    int id;
    double score;
};

// 添加学生
void addStudent(vector<Student> &students) {
    Student s;
    cout << "输入姓名: ";
    cin >> s.name;
    cout << "输入学号: ";
    cin >> s.id;
    cout << "输入成绩: ";
    cin >> s.score;
    students.push_back(s);
}

// 显示所有学生
void showStudents(const vector<Student> &students) {
    for (const Student &s : students) {
        cout << s.name << "\t" 
             << s.id << "\t"
             << s.score << endl;
    }
}

// 保存到文件
void saveToFile(const vector<Student> &students, string filename) {
    ofstream outFile(filename);
    for (const Student &s : students) {
        outFile << s.name << " "
                << s.id << " "
                << s.score << endl;
    }
    outFile.close();
}

// 从文件加载
void loadFromFile(vector<Student> &students, string filename) {
    ifstream inFile(filename);
    if (!inFile) {
        cerr << "文件不存在" << endl;
        return;
    }
    
    students.clear();
    Student s;
    while (inFile >> s.name >> s.id >> s.score) {
        students.push_back(s);
    }
    inFile.close();
}

int main() {
    vector<Student> students;
    int choice;
    
    do {
        cout << "\n1. 添加学生\n"
             << "2. 显示学生\n"
             << "3. 保存到文件\n"
             << "4. 从文件加载\n"
             << "0. 退出\n"
             << "请选择: ";
        cin >> choice;
        
        switch (choice) {
            case 1: addStudent(students); break;
            case 2: showStudents(students); break;
            case 3: saveToFile(students, "students.txt"); break;
            case 4: loadFromFile(students, "students.txt"); break;
        }
    } while (choice != 0);
    
    return 0;
}

文件加密系统

#include <iostream>
#include <fstream>
#include <string>
using namespace std;

void encryptFile(string inputFile, string outputFile, int key) {
    ifstream in(inputFile, ios::binary);
    ofstream out(outputFile, ios::binary);
    
    char c;
    while (in.get(c)) {
        out.put(c ^ key); // 简单异或加密
    }
    
    in.close();
    out.close();
}

int main() {
    string source = "secret.txt";
    string encrypted = "secret_enc.dat";
    string decrypted = "secret_dec.txt";
    
    int key = 123; // 加密密钥
    
    // 加密文件
    encryptFile(source, encrypted, key);
    cout << "文件加密完成!" << endl;
    
    // 解密文件(加密的逆过程)
    encryptFile(encrypted, decrypted, key);
    cout << "文件解密完成!" << endl;
    
    return 0;
}

总结与要点

结构体要点

知识点 关键内容 注意事项
结构体定义 struct 名称 { 成员列表 }; 末尾分号不能少
结构体变量 结构体名 变量名;
成员访问 变量名.成员名 使用点运算符
结构体数组 结构体名 数组名[大小];
结构体嵌套 结构体中可以包含其他结构体

文件操作要点

知识点 关键内容 注意事项
文件流类 ifstream(输入), ofstream(输出) 需包含<fstream>
打开文件 流对象.open(文件名, 模式) 检查是否打开成功
关闭文件 流对象.close()
文本读写 <<>>运算符
二进制读写 read()write()
文件位置 seekg()tellg() 用于随机访问

结构体与文件结合要点

  1. 文本格式存储

    • 优点:人类可读
    • 缺点:占用空间大,解析复杂
  2. 二进制格式存储

    • 优点:存储紧凑,读写快速
    • 缺点:人类不可读,依赖结构体内存布局
  3. 注意事项

    • 读写结构体数组时使用sizeof计算总大小
    • 文件操作后必须检查是否成功
    • 使用二进制模式打开二进制文件
    • 不同平台可能有字节序差异

学习建议

  1. 理解结构体的本质:自定义复合数据类型
  2. 掌握点运算符:访问结构体成员
  3. 练习结构体数组:处理批量数据
  4. 熟悉文件操作流程:打开→读写→关闭
  5. 区分文本和二进制模式:根据需求选择
  6. 结合应用:实现数据持久化存储

"结构体让数据组织更清晰,文件操作让数据持久化,二者结合是编程的重要技能!"

综合练习:通讯录管理系统

#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
using namespace std;

struct Contact {
    string name;
    string phone;
    string email;
};

// 函数声明
void addContact(vector<Contact> &contacts);
void showContacts(const vector<Contact> &contacts);
void saveContacts(const vector<Contact> &contacts, string filename);
void loadContacts(vector<Contact> &contacts, string filename);

int main() {
    vector<Contact> contacts;
    loadContacts(contacts, "contacts.txt"); // 启动时加载数据
    
    int choice;
    do {
        cout << "\n===== 通讯录管理系统 =====" << endl;
        cout << "1. 添加联系人" << endl;
        cout << "2. 显示所有联系人" << endl;
        cout << "3. 保存到文件" << endl;
        cout << "0. 退出" << endl;
        cout << "请选择: ";
        cin >> choice;
        
        switch (choice) {
            case 1: addContact(contacts); break;
            case 2: showContacts(contacts); break;
            case 3: saveContacts(contacts, "contacts.txt"); break;
        }
    } while (choice != 0);
    
    return 0;
}

void addContact(vector<Contact> &contacts) {
    Contact c;
    cout << "输入姓名: ";
    cin >> c.name;
    cout << "输入电话: ";
    cin >> c.phone;
    cout << "输入邮箱: ";
    cin >> c.email;
    contacts.push_back(c);
    cout << "联系人添加成功!" << endl;
}

void showContacts(const vector<Contact> &contacts) {
    if (contacts.empty()) {
        cout << "通讯录为空!" << endl;
        return;
    }
    
    cout << "姓名\t电话\t邮箱" << endl;
    for (const Contact &c : contacts) {
        cout << c.name << "\t" 
             << c.phone << "\t"
             << c.email << endl;
    }
}

void saveContacts(const vector<Contact> &contacts, string filename) {
    ofstream outFile(filename);
    for (const Contact &c : contacts) {
        outFile << c.name << ","
                << c.phone << ","
                << c.email << endl;
    }
    outFile.close();
    cout << "数据保存成功!" << endl;
}

void loadContacts(vector<Contact> &contacts, string filename) {
    ifstream inFile(filename);
    if (!inFile) return;
    
    contacts.clear();
    string line;
    while (getline(inFile, line)) {
        // 解析CSV格式
        Contact c;
        size_t pos1 = line.find(',');
        size_t pos2 = line.find(',', pos1+1);
        
        c.name = line.substr(0, pos1);
        c.phone = line.substr(pos1+1, pos2-pos1-1);
        c.email = line.substr(pos2+1);
        
        contacts.push_back(c);
    }
    inFile.close();
    cout << "数据加载完成!" << endl;
}

章节 1. 结构体的应用

开放

题目 尝试 AC 难度
869   【基础】期末考试成绩排名 24 6 8
759   【入门】遥控飞机争夺赛 1 1 10
P724   【入门】购买贺年卡 2 2 10
963   【入门】宇宙总统2 7 1 10
822   【基础】活动选择 3 1 10
P879   【基础】新生舞会 1 1 10
776   【入门】求最大梯形的面积 1 1 10