从文件读取时获取垃圾字符

时间:2018-11-23 17:51:26

标签: c++

我有一个CS项目,我正在尝试将字符串写入/读取到大小为{10的string的{​​{1}}变量中。我是编码新手,在编写时犯了一些错误归档。请帮助我。

这是我在项目文件中定义的包含x数组的类。我很确定我在写入文件时犯了一个错误,因为它在文件中添加了垃圾字符。

string x[10]

1 个答案:

答案 0 :(得分:1)

您不能像往流中那样从流中写入/读取std::string对象 ,更不用说字符串数组了。您正在写入/读取每个字符串的内部数据,其中包括指向存储在内存中其他位置的字符数据的指针,可能是用于短字符串优化的小缓冲区等。您正在写入/读取该内部数据,而不是实际字符数据。这就是为什么您的文件中出现“垃圾”的原因。

写入时,您需要以一种字符串格式序列化,然后在读回时可以反序列化的格式,例如:

struct student
{
    string announce[10];
};

ostream& operator<<(ostream &os, const student &st)
{
    for(int x = 0; x < 10; ++x)
        os << st.announce[x] << '\n';
    return os;
}

istream& operator>>(istream &is, student &st)
{
    for(int x = 0; x < 10; ++x)
        getline(is, st.announce[x]);
    return is;
}

void write_announcement()
{
    student st;
    string line;
    int num;

    cout << "Enter number: ";
    cin >> num;
    cin.ignore(numeric_limits<streamsize>::max(), '\n');

    if ((num < 0) || (num >= 10))
    {
        cout << "Invalid number!" << endl;
        return;
    }

    cout << "Enter text: ";
    getline(cin, line);

    st.announce[num] = line;

    ofstream file("announcement.txt");
    if (!file.is_open())
    {
        cout << "Cannot create file!" << endl;
        return;
    } 

    if (!(file << st))
    {
        cout << "Cannot write to file!" << endl;
    }
}

void read_announcement()
{
    student st;
    int num;

    cout << "Enter number: ";
    cin >> num;
    cin.ignore(numeric_limits<streamsize>::max(), '\n');

    if ((num < 0) || (num >= 10))
    {
        cout << "Invalid number!" << endl;
        return;
    }

    ifstream file("announcement.txt");
    if (!file.is_open())
    {
        cout << "Cannot open file!" << endl;
        return;
    }

    if (!(file >> st))
    {
        cout << "Cannot read from file!" << endl;
        return;
    }

    cout << "Text: " << st.announce[num] << endl;
}

或者:

struct student
{
    string announce[10];
};

ostream& operator<<(ostream &os, const student &st)
{
    for(int x = 0; x < 10; ++x)
    {
        uint32_t len = st.announce[x].size();
        os.write(reinterpret_cast<char*>(&len), sizeof(len));
        os.write(st.announce[x].c_str(), len);
    }
    return os;
}

istream& operator>>(istream &is, student &st)
{
    for(int x = 0; x < 10; ++x)
        st.announce[x].clear();

    for(int x = 0; x < 10; ++x)
    {
        uint32_t len;
        if (!is.read(reinterpret_cast<char*>(&len), sizeof(len))) break;
        string s;
        if (len > 0)
        {
            s.resize(len);
            if (!is.read(&s[0], len)) break;
        }
        st.announce[x] = s;
    }

    return is;
}

void write_announcement()
{
    student st;
    string line;
    int num;

    cout << "Enter number: ";
    cin >> num;
    cin.ignore(numeric_limits<streamsize>::max(), '\n');

    if ((num < 0) || (num >= 10))
    {
        cout << "Invalid number!" << endl;
        return;
    }

    cout << "Enter text: ";
    getline(cin, line);

    st.announce[num] = line;

    ofstream file("announcement.txt", ofstream::binary);
    if (!file.is_open())
    {
        cout << "Cannot create file!" << endl;
        return;
    } 

    if (!(file << st))
    {
        cout << "Cannot write to file!" << endl;
    }
}

void read_announcement()
{
    student st;
    int num;

    cout << "Enter number: ";
    cin >> num;
    cin.ignore(numeric_limits<streamsize>::max(), '\n');

    if ((num < 0) || (num >= 10))
    {
        cout << "Invalid number!" << endl;
        return;
    }

    ifstream file("announcement.txt", ifstream::binary);
    if (!file.is_open())
    {
        cout << "Cannot open file!" << endl;
        return;
    }

    if (!(file >> st))
    {
        cout << "Cannot read from file!" << endl;
        return;
    }

    cout << "Text: " << st.announce[num] << endl;
}

话虽如此,您每次写入/读取文件时都在创建一个新的本地student,但是每次写入仅填充1个字符串,并且不会在多次写入中保留先前的字符串。因此,要么:

  1. 读取文件以加载先前的字符串,然后分配和写入新的字符串。

  2. 使student为全局变量,因此它的存在时间比任何单个写入/读取操作的时间都长,因此可以随时间缓存字符串分配。