MST

星途 面试题库

面试题:C语言结构体文件I/O专家难度题

考虑一个复杂的结构体嵌套场景,struct Inner { int data1; char data2[15]; }; struct Outer { struct Inner inner[5]; long long extra_info; }; 现在有多个Outer结构体实例,需要将它们写入文件,并且要求在写入时对Inner结构体中的data2字段进行加密(简单替换加密,例如每个字符替换为其ASCII码值加3后的字符),读取时再解密恢复。请编写完整的文件读写及加解密处理代码,并说明如何处理文件大小变化及潜在的错误情况。
17.8万 热度难度
编程语言C

知识考点

AI 面试

面试题答案

一键面试
#include <iostream>
#include <fstream>
#include <cstring>

// 加密函数
void encrypt(char* data, int len) {
    for (int i = 0; i < len; ++i) {
        data[i] = static_cast<char>(data[i] + 3);
    }
}

// 解密函数
void decrypt(char* data, int len) {
    for (int i = 0; i < len; ++i) {
        data[i] = static_cast<char>(data[i] - 3);
    }
}

// 写入文件函数
bool writeToFile(const char* filename, const Outer* outers, int count) {
    std::ofstream file(filename, std::ios::binary);
    if (!file) {
        std::cerr << "无法打开文件进行写入" << std::endl;
        return false;
    }

    for (int i = 0; i < count; ++i) {
        Outer outer = outers[i];
        for (int j = 0; j < 5; ++j) {
            encrypt(outer.inner[j].data2, strlen(outer.inner[j].data2));
        }
        file.write(reinterpret_cast<const char*>(&outer), sizeof(Outer));
        if (file.bad()) {
            std::cerr << "写入文件时发生错误" << std::endl;
            file.close();
            return false;
        }
    }
    file.close();
    return true;
}

// 读取文件函数
bool readFromFile(const char* filename, Outer* outers, int& count) {
    std::ifstream file(filename, std::ios::binary);
    if (!file) {
        std::cerr << "无法打开文件进行读取" << std::endl;
        return false;
    }

    file.seekg(0, std::ios::end);
    std::streampos fileSize = file.tellg();
    file.seekg(0, std::ios::beg);

    if (fileSize % sizeof(Outer) != 0) {
        std::cerr << "文件大小不匹配,可能文件已损坏" << std::endl;
        file.close();
        return false;
    }

    count = static_cast<int>(fileSize / sizeof(Outer));
    for (int i = 0; i < count; ++i) {
        file.read(reinterpret_cast<char*>(&outers[i]), sizeof(Outer));
        if (file.bad()) {
            std::cerr << "读取文件时发生错误" << std::endl;
            file.close();
            return false;
        }
        for (int j = 0; j < 5; ++j) {
            decrypt(outers[i].inner[j].data2, strlen(outers[i].inner[j].data2));
        }
    }
    file.close();
    return true;
}

struct Inner { 
    int data1; 
    char data2[15]; 
}; 

struct Outer { 
    struct Inner inner[5]; 
    long long extra_info; 
}; 

int main() {
    Outer outers[2];
    // 初始化outers数据

    if (writeToFile("test.bin", outers, 2)) {
        std::cout << "写入文件成功" << std::endl;
    }

    Outer readOuters[2];
    int readCount = 0;
    if (readFromFile("test.bin", readOuters, readCount)) {
        std::cout << "读取文件成功,读取到 " << readCount << " 个实例" << std::endl;
    }

    return 0;
}

文件大小变化及潜在错误情况处理说明

  1. 文件大小变化:由于加密和解密操作只是对字符进行简单的ASCII码值调整,不会改变数据的长度,所以文件大小理论上不会因加解密操作而改变。在读取文件时,通过检查文件大小是否为Outer结构体大小的整数倍来判断文件是否完整和未损坏。
  2. 潜在错误情况处理
    • 文件打开错误:在打开文件进行读写操作时,检查文件流状态,如果无法打开文件,输出错误信息并返回false
    • 写入错误:在每次写入Outer结构体实例后,检查文件流状态,如果发生错误,输出错误信息并返回false
    • 读取错误:在每次读取Outer结构体实例后,检查文件流状态,如果发生错误,输出错误信息并返回false。同时,通过文件大小检查来处理文件可能损坏的情况。