c ++ stringstream read似乎没有读取整个缓冲区
c++ stringstream read doesn't seem to read the whole buffer
我有以下代码:https://godbolt.org/z/9aqqe5eYh
#include<string>
#include<sstream>
#include<iomanip>
#include<iostream>
int main() {
std::string line = "fa0834dd";
for(int i = 0; i < line.length(); i += 2) {
std::stringstream ss;
std::uint8_t byte;
ss << std::hex << line.substr(i, 2);
std::cout << ss.str() << " ";
ss >> byte;
std::cout << std::hex << std::setw(2) << byte << std::endl;
}
}
理想情况下,这会接收一串十六进制数字,将它们拆分为字节(一对十六进制数字)并将其存储为字节(出于说明目的,我在上面只使用了一个 std::uint8_t
)。
上面的代码输出这个:
Program returned: 0
Program stdout
fa f
08 0
34 3
dd d
这似乎有点奇怪。 std::uint8_t
应该足以存储 2 个十六进制字符的数据。但似乎 ss >> byte
只存储前面的十六进制字符。我的猜测是:
ss << std::hex << line.substr(i, 2);
实际上将每个十六进制字符存储为 1 个字节?
我如何修复上述代码以生成等于字符串中 2 个十六进制字符的单字节值?
stringstream
不符合将字符表示解析为字节值的条件。
您可以使用 strtol
之类的东西将字符串实际解析为值。
#include<string>
#include<sstream>
#include<iomanip>
#include<iostream>
int main() {
std::string line = "fa0834dd";
for(int i = 0; i < line.length(); i += 2) {
std::string ss = line.substr(i,2);
std::cout << ss << " ";
std::uint8_t byte = static_cast<std::uint8_t>(strtol(ss.c_str(), NULL, 16));
std::cout << std::hex << static_cast(byte) << std::endl;
}
}
Ref post
问题是std::hex
只适用于整数input/output,虽然uint8_t
在技术上是一个整数,但它只是下面的unsigned char
,iostream
将输入和输出其字符值而不是其整数值。换句话说,您的循环将两个字符放入 stringstream
,然后再次提取第一个字符。
如果要将十六进制数据转换为本机整数类型,可以使用 std::stoi 或类似的函数。例如(仅提取第一个字节):
std::string hexdata = "01020304";
size_t length;
// attempt to convert just the first two characters
uint8_t firstbyte = std::stoi(hexdata.substr(0, 2), &length, 16);
// "length" is set to the number of characters successfully parsed
// so if it is not the same number of characters that you supplied,
// then there's an issue. In this case, we are expected 2.
if (length != 2)
{
std::cerr << "was that hex??" << std::endl;
}
else
{
// you'll need to cast it to an integer type in order to see its integer value
// otherwise iostreams will just output the character value
std::cout << "value of byte is " << static_cast<int>(firstbyte) << std::end;
}
std::stoi
如果根本无法进行转换(例如,提供的字符串中的 none 个字符是可转换的),也可能会抛出异常。
我有以下代码:https://godbolt.org/z/9aqqe5eYh
#include<string>
#include<sstream>
#include<iomanip>
#include<iostream>
int main() {
std::string line = "fa0834dd";
for(int i = 0; i < line.length(); i += 2) {
std::stringstream ss;
std::uint8_t byte;
ss << std::hex << line.substr(i, 2);
std::cout << ss.str() << " ";
ss >> byte;
std::cout << std::hex << std::setw(2) << byte << std::endl;
}
}
理想情况下,这会接收一串十六进制数字,将它们拆分为字节(一对十六进制数字)并将其存储为字节(出于说明目的,我在上面只使用了一个 std::uint8_t
)。
上面的代码输出这个:
Program returned: 0
Program stdout
fa f
08 0
34 3
dd d
这似乎有点奇怪。 std::uint8_t
应该足以存储 2 个十六进制字符的数据。但似乎 ss >> byte
只存储前面的十六进制字符。我的猜测是:
ss << std::hex << line.substr(i, 2);
实际上将每个十六进制字符存储为 1 个字节?
我如何修复上述代码以生成等于字符串中 2 个十六进制字符的单字节值?
stringstream
不符合将字符表示解析为字节值的条件。
您可以使用 strtol
之类的东西将字符串实际解析为值。
#include<string>
#include<sstream>
#include<iomanip>
#include<iostream>
int main() {
std::string line = "fa0834dd";
for(int i = 0; i < line.length(); i += 2) {
std::string ss = line.substr(i,2);
std::cout << ss << " ";
std::uint8_t byte = static_cast<std::uint8_t>(strtol(ss.c_str(), NULL, 16));
std::cout << std::hex << static_cast(byte) << std::endl;
}
}
Ref post
问题是std::hex
只适用于整数input/output,虽然uint8_t
在技术上是一个整数,但它只是下面的unsigned char
,iostream
将输入和输出其字符值而不是其整数值。换句话说,您的循环将两个字符放入 stringstream
,然后再次提取第一个字符。
如果要将十六进制数据转换为本机整数类型,可以使用 std::stoi 或类似的函数。例如(仅提取第一个字节):
std::string hexdata = "01020304";
size_t length;
// attempt to convert just the first two characters
uint8_t firstbyte = std::stoi(hexdata.substr(0, 2), &length, 16);
// "length" is set to the number of characters successfully parsed
// so if it is not the same number of characters that you supplied,
// then there's an issue. In this case, we are expected 2.
if (length != 2)
{
std::cerr << "was that hex??" << std::endl;
}
else
{
// you'll need to cast it to an integer type in order to see its integer value
// otherwise iostreams will just output the character value
std::cout << "value of byte is " << static_cast<int>(firstbyte) << std::end;
}
std::stoi
如果根本无法进行转换(例如,提供的字符串中的 none 个字符是可转换的),也可能会抛出异常。