我尝试使用fstream
虽然显然编译了,程序崩溃了。
请告诉我上面的代码有什么问题,我该怎么做才能纠正它
我想将二进制文件中的miperro5[]
的所有元素恢复为新的数组miperro6[]
。可能会解决它吗?
#include <stdio.h>
#include <iostream>
#include <Perro.hpp>
#include <fstream>
using std::cout;
using std::endl;
int main(int argc, char **argv)
{
Perro miperro5[5];
Perro miperro6[5];
miperro5[2].nombre = "lucky";
std::ofstream myfile;
myfile.open("example.bin", std::ios::out | std::ios::app | std::ios::binary);
for (int i = 0; i < 5; i++){
myfile.write(reinterpret_cast<char *>(&miperro5[i]), sizeof(Perro));
}
myfile.close();
std::ifstream myfile2;
myfile2.open("example.bin", std::ios::in | std::ios::binary);
for (int j = 0; j < 5; j++){
myfile2.read(reinterpret_cast<char *>(&miperro6[j]), sizeof(Perro));
}
myfile2.close();
for (int z = 0; z < 5; z++){
cout << miperro6[z].nombre << endl;
}
std::cin.get();
return 0;
}
这是Perro.hpp
#ifndef PERRO_HPP
#define PERRO_HPP
#include <string>
class Perro
{
public:
Perro();
~Perro();
void ladrar();
void comer();
std::string nombre;
int edad;
int arra[2];
};
#endif // PERRO_HPP
答案 0 :(得分:0)
问题可能在这里:
myfile.write(reinterpret_cast<char *>(&miperro5[i]), sizeof(Perro));
您正在为文件编写结构Perro
,但您必须确保正确编写它,因为通常会像
struct Foo
{
std::string str;
};
像你想象的那样,不会写在磁盘上。只有包含ONLY普通旧数据(POD)的结构可以像你一样编写,其余的你必须手动编写每个字段。如果您想通过对象序列化来简化生活,请寻找boost::serialization
。
答案 1 :(得分:0)
只有在课程为POD type时,您才能使用fwrite
和fread
。
Perro
不是POD类型,因为它有std::string
类型的成员变量。
让我用一个更简单的例子来说明问题。让我们说你有:
#include <iostream>
#include <fstream>
struct A
{
A(int s) : ip(new int[s]), size(s) {}
~A() { delete [] ip; }
int* ip;
int size;
};
int main()
{
A a1(10);
A a2(5);
std::cout << "a1.size: " << a1.size << ", a1.ip: " << a1.ip << std::endl;
std::ofstream myfile;
myfile.open("example.bin", std::ios::out | std::ios::binary);
myfile.write(reinterpret_cast<char *>(&a1), sizeof(A));
myfile.close();
std::ifstream myfile2;
myfile2.open("example.bin", std::ios::in | std::ios::binary);
myfile2.read(reinterpret_cast<char *>(&a2), sizeof(A));
myfile2.close();
std::cout << "a2.size: " << a2.size << ", a2.ip: " << a2.ip << std::endl;
return 0;
}
当我运行程序时,我得到以下输出:
a1.size: 10, a1.ip: 0x16b4010 a2.size: 10, a2.ip: 0x16b4010 *** Error in `./test-328': double free or corruption (fasttop): 0x00000000016b4010 *** Aborted
这里发生的是a1.ip
的二进制值被写入文件,并且相同的二进制值被读入a2.ip
。读取后,a1.ip
和a2.ip
都指向相同的内存位置。这会导致两个问题:
delete
。a2
的初始内存永远不会被取消分配。当您的某个成员变量为std::string
时会发生类似情况。
答案 2 :(得分:0)
的main.cpp
#include <stdio.h>
#include <iostream>
#include <fstream>
#include "Perro.hpp"
using std::cout;
using std::endl;
int main(int argc, char **argv)
{
Perro miperro5[5];
Perro miperro6[5];
miperro5[2].nombre = "lucky";
std::ofstream myfile;
myfile.open("example.bin", std::ios::out | std::ios::app | std::ios::binary);
for (int i = 0; i < 5; i++){
myfile << miperro5[i];
}
myfile.close();
std::ifstream myfile2;
myfile2.open("example.bin", std::ios::in | std::ios::binary);
for (int j = 0; j < 5; j++){
myfile2 >> miperro6[j];
}
myfile2.close();
for (int z = 0; z < 5; z++){
cout << miperro6[z].nombre << endl;
}
std::cin.get();
return 0;
}
Perro.hpp
#ifndef PERRO_HPP
#define PERRO_HPP
#include <string>
#include <ostream>
#include <istream>
class Perro
{
public:
Perro() {};
~Perro() {};
void ladrar();
void comer();
std::string nombre;
int edad;
int arra[2];
};
std::ostream & operator<<(std::ostream & ostrm, const Perro & src)
{
// nombre
std::string::size_type cch = src.nombre.length();
ostrm // std::string is not a primitive type, so we need to do a (sort of) deep copy.
.write(reinterpret_cast<const char *>(&cch), sizeof(std::string::size_type))
<< src.nombre.c_str() // or use unformatted output `write`
;
// edad, arra[2]
ostrm
.write(reinterpret_cast<const char *>(&src.edad), sizeof(int)) // edad
.write(reinterpret_cast<const char *>(&src.arra), sizeof(int) * 2) // arra[2]
;
return ostrm;
}
std::istream & operator>>(std::istream & istrm, Perro & dst)
{
// Read the string back.
std::string::size_type cchBuf;
istrm.read(reinterpret_cast<char *>(&cchBuf), sizeof(std::string::size_type));
char * buf = new char[cchBuf];
istrm.read(buf, cchBuf);
dst.nombre.assign(buf, cchBuf);
delete [] buf;
// Read other data members of primitive data type.
istrm
.read(reinterpret_cast<char *>(&dst.edad), sizeof(int)) // edad
.read(reinterpret_cast<char *>(&dst.arra), sizeof(int) * 2) // arra[2]
;
// Return the stream so it can be examined on its status.
return istrm;
}
#endif // PERRO_HPP