通过重载运算符 << 和 >> 将结构转换为无符号字符(请参阅更新)
convert struct to unsigned char through overloaded operator << and >> (see update)
我有这个 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;
};
这让人想知道这个 return 有多少 space 到输出(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()
return吧。 output
是 fstream
.
现在,我如何从文件中读取数据?使用运算符 >>,我的理解是它需要将一个包含 3 个元素的 unsigned char
数组作为输入,然后将第一个元素(1 个字节)转换为 char,将其他 2 个元素转换为一个诠释。这个对吗?我可以用这个方法做到吗:
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();
这似乎可行,但如果没有从文件中读取的方法,我无法确定,我得到了这个:
运营商>>:
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)];
};
how much space this returns to the output (3 bytes, as expected? - 1 from the char and 2 from the int?)
没有。您正在将值转换为 std::string
s,因此它们具有 可变 长度,具体取决于特定值(即 "123"
占用的长度与 "1234567890"
).您描述的内容适用于值的二进制存储,不适用于值的文本表示。
Now, how I do the reading from the file? with the operator >>, what I understand is that it need take an unsigned char
array with 3 elements as input, and take the first element (1 byte) and convert to char, and the 2 other elements and convert for an int. Is this correct?
没有。 operator<<
和 operator>>
主要用于 格式化 (文本)I/O。您的 operator<<
实际上是在编写 格式的 输出(不过,您不需要先将值转换为 std::string
,您可以将它们写成 as-is 使用 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;
}
格式完全取决于您,具体取决于您的特定需要。
然而,运算符 也可以 也用于 read/write 二进制数据(只要确保在 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;
}
这更符合你的想法。
我有这个 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;
};
这让人想知道这个 return 有多少 space 到输出(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()
return吧。 output
是 fstream
.
现在,我如何从文件中读取数据?使用运算符 >>,我的理解是它需要将一个包含 3 个元素的 unsigned char
数组作为输入,然后将第一个元素(1 个字节)转换为 char,将其他 2 个元素转换为一个诠释。这个对吗?我可以用这个方法做到吗:
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();
这似乎可行,但如果没有从文件中读取的方法,我无法确定,我得到了这个:
运营商>>:
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)];
};
how much space this returns to the output (3 bytes, as expected? - 1 from the char and 2 from the int?)
没有。您正在将值转换为 std::string
s,因此它们具有 可变 长度,具体取决于特定值(即 "123"
占用的长度与 "1234567890"
).您描述的内容适用于值的二进制存储,不适用于值的文本表示。
Now, how I do the reading from the file? with the operator >>, what I understand is that it need take an
unsigned char
array with 3 elements as input, and take the first element (1 byte) and convert to char, and the 2 other elements and convert for an int. Is this correct?
没有。 operator<<
和 operator>>
主要用于 格式化 (文本)I/O。您的 operator<<
实际上是在编写 格式的 输出(不过,您不需要先将值转换为 std::string
,您可以将它们写成 as-is 使用 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;
}
格式完全取决于您,具体取决于您的特定需要。
然而,运算符 也可以 也用于 read/write 二进制数据(只要确保在 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;
}
这更符合你的想法。