通过重载运算符<<和>>将结构转换为无符号字符(请参阅更新)



我有这个struct与2个属性(一个char和一个int,内存使用量为3字节:

struct Node {
char data;
int frequency;
}

我尝试重载操作符<<和比;比;对于这个struct,因为能够使用fstream从文件中读写这个struct。对于运算符<<我:

friend std::ostream& operator<<(std::ostream& output, const HuffmanNode& e) {
string data = string(1, e.data) + to_string(e.frequency);
output << data.data();
return output;
};

这让人想知道这将返回多少空间到输出(3字节,如预期的那样?- 1来自char类型,2来自int类型?)

当我想保存struct的文件,我得到这个:

List<Node> inOrder = toEncode.inOrder();
for(int i=1; i<=inOrder.size(); i++) {
output << inOrder.get(i)->getData();

其中列表的每个节点inOrder和树toEncode上面是前面列出的struct,iNOrder.get(i)->getData()返回它。outputfstream

现在,我如何从文件中读取?使用操作符>>,我所理解的是,它需要一个具有3个元素的unsigned char数组作为输入,并将第一个元素(1字节)转换为char,以及其他2个元素并转换为int。这是正确的吗?我可以用这个方法来做吗:

friend std::istream& operator>>(std::istream& input, HuffmanNode& e) {
...
};

或者我需要更改方法签名(和参数)?对于文件读取本身,考虑到我需要读取的字符都在文件的第一行,什么代码使程序每次从这行读取3个字符并从该数据生成struct?

我得到了什么:

写入文件,我实现了这个操作符<<:

friend std::ostream& operator<<(std::ostream& output, const HuffmanNode& e) {
union unsigned_data data;
data.c = e.data;
union unsigned_frequency frequency;
frequency.f = e.frequency;
output << data.byte << frequency.byte;
return output;
};

的用法:

List<HuffmanNode> inOrder = toEncode.inOrder();
for(int i=1; i<=inOrder.size(); i++)
output << inOrder.get(i)->getData();

这似乎工作,但我不能确定没有办法从文件中读取,我得到了这个:

operator>祝辞:

friend std::istream& operator>>(std::istream& input, HuffmanNode& e) {
union unsigned_data data;
data.c = e.data;
union unsigned_frequency frequency;
frequency.f = e.frequency;
input >> data.byte >> frequency.byte;
return input;
};

的用法:

string line;
getline(input, line);
HuffmanNode node;
stringstream ss(line);
long pos = ss.tellp();
do {
ss >> node;
toDecode.insert(node);
ss.seekp (pos+3);
} while(!ss.eof());

似乎陷入了无限循环。两个操作符都使用了这个联合:

union unsigned_data {
char c;
unsigned char byte;
};
union unsigned_frequency {
int f;
unsigned char byte[sizeof(int)];
};

这将返回多少空间到输出(如预期的3字节)?- 1来自char类型,2来自int类型?)

。您正在将值转换为std::strings,因此它们具有变量长度,具体取决于特定值(即,"123"占用与"1234567890"不同的长度)。您所描述的适用于值的二进制存储,而不适用于值的文本表示

现在,我如何从文件中读取?使用操作符>>,我所理解的是,它需要一个具有3个元素的unsigned char数组作为输入,并将第一个元素(1字节)转换为char,以及其他2个元素并转换为int。这是正确的吗?

operator<<operator>>主要用于格式化的(文本)的I/O。您的operator<<实际上正在编写格式化的输出(不过,您不需要首先将值转换为std::strings,您可以使用operator<<的相关重载按原样编写它们)。您只需要以operator>>可以反转的方式编写格式化的数据。例如:

friend std::ostream& operator<<(std::ostream& output, const HuffmanNode& e) {
output << int(e.data) << ' ' << e.frequency << ' ';
return output;
}
friend std::istream& operator>>(std::istream& input, HuffmanNode& e) {
int i;
input >> i >> e.frequency;
e.data = char(i);
input.ignore();
return input;
}

另外:

friend std::ostream& operator<<(std::ostream& output, const HuffmanNode& e) {
output << e.data << e.frequency << 'n';
return output;
}
friend std::istream& operator>>(std::istream& input, HuffmanNode& e) {
e.data = input.get();
input >> e.frequency;
input.ignore();
return input;
}

格式完全取决于你,根据你的特殊需要。

然而,操作符也可以用于读写二进制数据(只是要确保以binary模式打开流),例如:

friend std::ostream& operator<<(std::ostream& output, const HuffmanNode& e) {
output.write(&e.data, sizeof(e.data));
output.write(reinterpret_cast<const char*>(&e.frequency), sizeof(e.frequency));
return output;
}
friend std::istream& operator>>(std::istream& input, HuffmanNode& e) {
input.read(&e.data, sizeof(e.data));
input.read(reinterpret_cast<char*>(&e.frequency), sizeof(e.frequency));
return input;
}

这更符合你的想法。