gpt4 book ai didi

c++ - 为什么 C++ 拒绝将结构附加到包含字符串类成员的二进制文件?

转载 作者:行者123 更新时间:2023-11-27 22:42:50 25 4
gpt4 key购买 nike

所以今天我在编程方面几乎没有取得任何进展,因为我非常缓慢地意识到 C++ 是一种对类型非常敏感的语言,如果结构的其中一个成员是类型,我就不能将结构附加到二进制文件字符串类。在我发现之前,我不知道是这种情况。我先证明我的观点。

此代码将不起作用:

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

// function Headers:
void Receive_Information(fstream& personal_data);
void Display_Information(fstream& personal_data);

struct Info
{
string name; // if this is char name[50]; ... it works perfectly.
float weight;
char grade;
};

int main()
{
fstream personal_data;
// Get two people from the stream:
Receive_Information(personal_data);
Receive_Information(personal_data);

// Now display their information from the binary file.
Display_Information(personal_data);


return 0;
}

void Receive_Information(fstream& personal_data)
{
personal_data.open("personal_data.dat", ios::out | ios::app | ios::binary); // open a binary file for appending.

Info person; // This structure variable is written to the binary file.
cout << "What is the person's name: ";
getline(cin, person.name); // change to cin.getline(person.name, 50) when defined as a character array
cout << "\nWhat is this individual's weight: ";
cin >> person.weight;
cout << "\nWhat letter grade (A, B, C, D, F) did s(he) get on the last exam: ";
cin >> person.grade;

// write the structure variable to file.
personal_data.write(reinterpret_cast<char *>(&person), sizeof(person));

cin.ignore();

personal_data.close(); // close the file after writing to it.

cout << endl;
}

void Display_Information(fstream& personal_data)
{
Info person_out; // This is the structure variable we get from opening the binary file.

personal_data.open("personal_data.dat", ios::in | ios::binary); // Open the binary file to read from.

personal_data.read(reinterpret_cast<char *>(&person_out), sizeof(person_out)); // Read the first line of the file.

while(personal_data) // While I haven't reached the end of the file keep reading in the information.
{
cout << "The weight of the person is " << person_out.weight << endl;

cout << "The person's name is " << person_out.name << endl; // This can't be printed because it's a string.

cout << "The grade this individual received on the last exam is " << person_out.grade << endl;

personal_data.read(reinterpret_cast<char *>(&person_out), sizeof(person_out));// keep pulling information from the file.

cout << endl;
}

personal_data.close();
}

如果我按预期运行程序,那么我会得到以下输出:

What is the person's name: Generic Me

What is this individual's weight: 180

What letter grade (A, B, C, D, F) did s(he) get on the last exam: A

What is the person's name: Suspicious You

What is this individual's weight: 200

What letter grade (A, B, C, D, F) did s(he) get on the last exam: C

The weight of the person is 180
The person's name is // it's no coincidence that it fails here.
Process returned 255 (0xFF) execution time : 25.193 s
Press any key to continue.

请注意,函数 Display_Information() 被特意安排为首先显示重量,然后是字符串类型的名称。我这样做是为了证明我的观点,即结构的成员可以从二进制文件中读取,但直到其中一个变量是字符串,程序才会中止。

所以我的假设是,如果其中一个成员类型为字符串,则结构不能轻易写入二进制文件。为了证明我的观点,如果我将名称更改为字符数组,那么一切正常。

所以为了摆脱困惑,我将手动删除二进制文件 personal_data.dat,然后重新运行程序,只做这两个小改动......

我会改变

struct Info
{
string name; // if this is char name[50]; ... it works perfectly.
float weight;
char grade;
};

为此:

struct Info
{
char name[50]; // A character array which can hold about 50 characters.
float weight;
char grade;
};

然后在 Receive_Information 函数中我将更改它:

getline(cin, person.name);

对此

cin.getline(person.name, 50);

一切都会神奇地起作用!!看看它是如何完美运作的!

What is the person's name: Generic Me

What is this individual's weight: 180

What letter grade (A, B, C, D, F) did s(he) get on the last exam: A

What is the person's name: Suspicious You

What is this individual's weight: 200

What letter grade (A, B, C, D, F) did s(he) get on the last exam: C

The weight of the person is 180
The person's name is Generic Me
The grade this individual received on the last exam is A

The weight of the person is 200
The person's name is Suspicious You
The grade this individual received on the last exam is C


Process returned 0 (0x0) execution time : 12.998 s
Press any key to continue.

现在我已经证明了我关于结构中的字符串的观点,是否可以做任何事情(不使用字符)来使我的原始程序在附加到二进制文件时使用结构中的字符串数据成员。顺便说一句,我还发现我的结构变量 person 可以写入一个带有字符串成员的二进制文件,然后成功读取,但是当你尝试附加多个结构时,你的程序就不太喜欢你了。很奇怪。

想法。

最佳答案

不要使用reinterpret_cast用于序列化/反序列化或字符串化。 reinterpret_cast是一种非常危险的工具,只能在非常特殊的情况下使用。处理您的问题的正确方法是提供 operator<<和一个 operator>>为你的 Info类(class)。示例:

std::ostream& operator<<(std::ostream& os, const Info& p)
{
os << name;
os << weight;
os << grade;
return os;
}

reinterpret_cast<T>从字面上要求编译器查看内存位置并将其视为 T。 .类 std::string很复杂:它们拥有资源并在其中存储指向其他内存位置的指针。如果您尝试写入 std::string 的字节out,你会得到垃圾,因为你的角色可能没有存储在 std::string 中实例本身...

关于c++ - 为什么 C++ 拒绝将结构附加到包含字符串类成员的二进制文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46949784/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com