从 stringstream 读取具有特定字段宽度的 int
Reading int with specific field width from stringstream
我正在尝试从字符串中以十六进制表示法读取字节。字节可能会或可能不会被空格分隔,例如" 00 ffab c "
是一个有效示例,应该会导致读取 4 个字节,0x00、0xff、0xab 和 0x0c。问题是跳过空格但只读取两个相邻的数字(如果存在)。
如果输入来自文件,任务会像 while(fscanf(f, "%2d", &i) == 1) ...
一样简单,因为 sscanf
跳过空格,读取位置由底层 FILE
跟踪,并且最大字段宽度仅适用于读取的项目,而不适用于包含空格的原始输入字符。但是从字符串中读取时不可能进行位置跟踪;我需要使用 %n
格式转换说明符,它将此调用到目前为止读取的字符数存储到关联变量中,例如scanf(f, "%2d%n", &i, &readIncr)
,并通过添加相应的增量手动维护读取位置。
这有点麻烦,因此我想使用 std::istringstream
,它 确实 跟踪基础字符串中的位置。
但是在输入流上设置宽度并没有达到预期的(和预期的)效果;下面是一个最小的演示;为简单起见,我使用十进制整数。 输入 字段宽度的文档和示例很少。
我做错了什么吗?我这个用例根本不是故意的?
#include <iostream>
#include <sstream>
#include <iomanip>
#include <cstdio>
using namespace std;
int main()
{
const char *s = " 1234";
int i;
istringstream is(s);
if (is >> setw(2) >> i)
{
cout << "stringstream i: " << i << '\n';
}
if (sscanf(s, "%2d", &i) == 1)
{
cout << "scanf i: " << i << '\n';
}
}
输出是(使用 g++ 和 MSVC)
$ g++ -Wall -o fieldwidth fieldwidth.cpp && ./fieldwidth
stringstream i: 1234
scanf i: 12
遗憾的是,cpp 流远非完美。 AFAIK std::setw
仅适用于读取字符串。您可以做的是:
#include <iostream>
#include <sstream>
#include <iomanip>
#include <cstdio>
using namespace std;
int main()
{
const char *s = " 1234";
std::string i;
istringstream is(s);
if (is >> setw(2) >> i)
{
cout << "stringstream i: " << std::stoi(i) << '\n';
}
int j;
if (sscanf(s, "%2d", &j) == 1)
{
cout << "scanf i: " << j << '\n';
}
}
你得到了预期的输出:
stringstream i: 12
scanf i: 12
我正在尝试从字符串中以十六进制表示法读取字节。字节可能会或可能不会被空格分隔,例如" 00 ffab c "
是一个有效示例,应该会导致读取 4 个字节,0x00、0xff、0xab 和 0x0c。问题是跳过空格但只读取两个相邻的数字(如果存在)。
如果输入来自文件,任务会像 while(fscanf(f, "%2d", &i) == 1) ...
一样简单,因为 sscanf
跳过空格,读取位置由底层 FILE
跟踪,并且最大字段宽度仅适用于读取的项目,而不适用于包含空格的原始输入字符。但是从字符串中读取时不可能进行位置跟踪;我需要使用 %n
格式转换说明符,它将此调用到目前为止读取的字符数存储到关联变量中,例如scanf(f, "%2d%n", &i, &readIncr)
,并通过添加相应的增量手动维护读取位置。
这有点麻烦,因此我想使用 std::istringstream
,它 确实 跟踪基础字符串中的位置。
但是在输入流上设置宽度并没有达到预期的(和预期的)效果;下面是一个最小的演示;为简单起见,我使用十进制整数。 输入 字段宽度的文档和示例很少。
我做错了什么吗?我这个用例根本不是故意的?
#include <iostream>
#include <sstream>
#include <iomanip>
#include <cstdio>
using namespace std;
int main()
{
const char *s = " 1234";
int i;
istringstream is(s);
if (is >> setw(2) >> i)
{
cout << "stringstream i: " << i << '\n';
}
if (sscanf(s, "%2d", &i) == 1)
{
cout << "scanf i: " << i << '\n';
}
}
输出是(使用 g++ 和 MSVC)
$ g++ -Wall -o fieldwidth fieldwidth.cpp && ./fieldwidth
stringstream i: 1234
scanf i: 12
遗憾的是,cpp 流远非完美。 AFAIK std::setw
仅适用于读取字符串。您可以做的是:
#include <iostream>
#include <sstream>
#include <iomanip>
#include <cstdio>
using namespace std;
int main()
{
const char *s = " 1234";
std::string i;
istringstream is(s);
if (is >> setw(2) >> i)
{
cout << "stringstream i: " << std::stoi(i) << '\n';
}
int j;
if (sscanf(s, "%2d", &j) == 1)
{
cout << "scanf i: " << j << '\n';
}
}
你得到了预期的输出:
stringstream i: 12
scanf i: 12