You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++链表数据写入.dat文件后丢失乱码的解决方案咨询

Fixing Data Loss & Garbage Values When Writing Linked List to .dat File

Let's break down exactly why your data is getting lost or showing up as garbage, then fix it with clear, actionable solutions.

Core Issues in Your Code

1. You're Writing an Uninitialized Object

In your write_linky function, you call fp.write((char*)&nod,sizeof(node)); — but nod is a private member of your List class that you never assign any values to. You're writing random garbage memory to the file, not the actual user data you just added to the linked list.

2. Binary-Writing std::string Is Broken

Your node struct uses std::string for fields like name and nationality. When you write the entire struct as binary data, you're only saving the pointer that std::string uses to store its characters (not the actual string content). When you read this back later, that pointer points to invalid memory, causing garbage values or crashes.


Solution 1: Text-Based Storage (Simple & Debug-Friendly)

Text format is perfect for this use case — it's human-readable, easy to debug, and avoids the pitfalls of binary serialization for complex types like std::string.

Updated write_linky Function

void List::write_linky(string name,string surName,int idNum,string nation,int number) {
    // Add the new node to your linked list first
    this->AddNode(name, surName, idNum, nation, number);
    this->printList();

    // Open file in text append mode
    fstream fp("Link.dat", ios::out | ios::app | ios::text);
    if (!fp.is_open()) {
        cout << "\nFailed to open file for writing!" << endl;
        return;
    }

    // Write each field on a new line for clarity
    fp << name << endl;
    fp << surName << endl;
    fp << idNum << endl;
    fp << nation << endl;
    fp << number << endl;

    fp.close();
    cout << "\n\nThe Data Has Been Added ";
}

Updated read_linky Function

void List::read_linky(){
    fstream fp("Link.dat", ios::in | ios::text);
    if (!fp.is_open()) {
        cout << "\nNo saved data found, or failed to open file!" << endl;
        return;
    }

    string name, surName, nation;
    int idNum, number;

    // Read each field in order until end of file
    while (getline(fp, name)) {
        getline(fp, surName);
        fp >> idNum;
        fp.ignore(); // Skip the newline left by >> operator
        getline(fp, nation);
        fp >> number;
        fp.ignore(); // Skip the newline again

        // Add the loaded data to your linked list
        this->AddNode(name, surName, idNum, nation, number);
    }

    fp.close();
    this->printList(); // Print all loaded data once
}

Solution 2: Proper Binary Serialization (If You Need Binary Format)

If you must use binary storage, you need to manually serialize std::string values by writing their length first, then the actual character data.

Updated write_linky Function

void List::write_linky(string name,string surName,int idNum,string nation,int number) {
    this->AddNode(name, surName, idNum, nation, number);
    this->printList();

    fstream fp("Link.dat", ios::out | ios::binary | ios::app);
    if (!fp.is_open()) {
        cout << "\nFailed to open file for writing!" << endl;
        return;
    }

    // Get the last node we just added
    curr = head;
    while (curr->next != nullptr) {
        curr = curr->next;
    }
    node* newNode = curr;

    // Serialize std::string: write length first, then characters
    // Write name
    size_t strLen = newNode->name.size();
    fp.write((char*)&strLen, sizeof(strLen));
    fp.write(newNode->name.c_str(), strLen);

    // Write surname
    strLen = newNode->surname.size();
    fp.write((char*)&strLen, sizeof(strLen));
    fp.write(newNode->surname.c_str(), strLen);

    // Write integer fields directly
    fp.write((char*)&newNode->idNum, sizeof(newNode->idNum));

    // Write nationality
    strLen = newNode->nationality.size();
    fp.write((char*)&strLen, sizeof(strLen));
    fp.write(newNode->nationality.c_str(), strLen);

    // Write contact number
    fp.write((char*)&newNode->number, sizeof(newNode->number));

    fp.close();
    cout << "\n\nThe Data Has Been Added ";
}

Updated read_linky Function

void List::read_linky(){
    fstream fp("Link.dat", ios::in | ios::binary);
    if (!fp.is_open()) {
        cout << "\nNo saved data found, or failed to open file!" << endl;
        return;
    }

    string name, surName, nation;
    int idNum, number;
    size_t strLen;

    while (true) {
        // Read name length and content
        if (!fp.read((char*)&strLen, sizeof(strLen))) break;
        name.resize(strLen);
        fp.read(&name[0], strLen);

        // Read surname
        if (!fp.read((char*)&strLen, sizeof(strLen))) break;
        surName.resize(strLen);
        fp.read(&surName[0], strLen);

        // Read ID number
        if (!fp.read((char*)&idNum, sizeof(idNum))) break;

        // Read nationality
        if (!fp.read((char*)&strLen, sizeof(strLen))) break;
        nation.resize(strLen);
        fp.read(&nation[0], strLen);

        // Read contact number
        if (!fp.read((char*)&number, sizeof(number))) break;

        this->AddNode(name, surName, idNum, nation, number);
    }

    fp.close();
    this->printList();
}

Additional Quick Fixes

  1. Remove the unused nod member: You have a node nod; in your List class that's never used — delete it to avoid confusion.
  2. Simplify isEmpty function: Since head is a class member, you don't need to pass it as a parameter:
    bool isEmpty(){
        return head == nullptr;
    }
    
  3. Avoid global fstream: Replace the global fstream fp with local instances inside write_linky and read_linky to prevent unexpected behavior.

内容的提问来源于stack exchange,提问作者gago

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:12:01