使用隐式转换从字符串流插入
Insert from stringstream with implict conversion
我正在从 ASCII 文件中以科学记数法读取以空格分隔的单精度值。每行有多个值。我通过 streamstream 填充一个向量;向量的原始类型可能与数据的类型不同:
// Illustrates typical string from file
std::string string_with_floats("-2.750000e+001 2.750000e+001 3.450000e+001");
// Template parameter is the desired return type
vector<int> data = ReadValues<int>(string_with_floats);
template <class T>
vector<T>& ReadValues(std::string& string_with_data)
{
std::stringstream ss(string_with_data);
std::vector<T> values;
T val;
while(stream >> val)
{
values.push_back(val);
}
return values;
}
上面的示例导致只用第一个值填充向量,截断为 -2,大概是因为循环在遇到非数字字符时立即终止。当传入的字符串包含 int 值时,它会按预期工作,即使模板参数是 float。
有没有办法将字符串流配置为执行隐式转换并舍入到最接近的整数,或者我是否需要先插入原始原始类型(float)并执行显式转换为 T?理想情况下,我不想告诉 ReadValues string_with_data 中的数据类型——它总是 double、float、int、short 或 long 之一,请求的类型也可以是以下任何一种这些类型。
谢谢。
如果您知道 string_with_data 中数据的类型,那就更简单了:只需读取该类型的一个值,然后将其转换为所需的类型,然后再将其推入向量:
template <class T>
vector<T>& ReadValues(std::string& string_with_data)
{
std::stringstream ss(string_with_data);
std::vector<T> values;
float val; // use original type not required one
while(stream >> val)
{
values.push_back((T) val);
}
return values;
}
如果你不知道原始类型,它会有点困难,因为在 C++ 和标准库中都没有大到可以接受所有其他类型的单一类型。因此,您必须将每个数据作为字符串读取,然后使用辅助字符串流将其解码为所需的类型:
template <class T>
std::vector<T> ReadValues(std::string& string_with_data)
{
std::stringstream ss(string_with_data);
std::vector<T> values;
std::string str;
T val;
while(ss >> str) // first store the value into a string whatever it is
{
std::stringstream(str) >> val; // then read it as the required type
values.push_back(val);
}
return values;
}
这样你就可以确定:
- 读取 int 时没有在流中留下 float 的尾部部分
- 你在读取原始字符串时使用了所需类型允许的最大精度
注意:我假定您接受默认转换...
为什么不直接从文件中提取数据作为浮点数,而是先获取第一行,然后是浮点数,然后是整数?
double f;
std::vector<int> out;
std::ifstream file("numbers.txt");
file >> std::scientific;
while (file >> f)
out.push_back(out);
或者如果你想让它对迭代器更友好:
std::vector<int> out;
std::ifstream file("numbers.txt");
file >> std::scientific;
std::copy(std::istream_iterator<double>(file),
std::istream_iterator<double>(),
std::back_inserter(out)));
如果像@SergeBallesta 所说的那样,您想创建一个不知道 "original" 类型,只知道目标类型的通用函数,以类似迭代器的方式:
template <class T>
std::vector<T> ReadValues(std::string& string_with_data)
{
std::istringstream ss(string_with_data);
std::vector<T> values;
using iss_it = std::istream_iterator<std::string>;
std::transform(iss_it(string_with_data), iss_it(), std::back_inserter(values),
[](const std::string& x) { return boost::lexical_cast<T>(x) });
return values;
}
我正在从 ASCII 文件中以科学记数法读取以空格分隔的单精度值。每行有多个值。我通过 streamstream 填充一个向量;向量的原始类型可能与数据的类型不同:
// Illustrates typical string from file
std::string string_with_floats("-2.750000e+001 2.750000e+001 3.450000e+001");
// Template parameter is the desired return type
vector<int> data = ReadValues<int>(string_with_floats);
template <class T>
vector<T>& ReadValues(std::string& string_with_data)
{
std::stringstream ss(string_with_data);
std::vector<T> values;
T val;
while(stream >> val)
{
values.push_back(val);
}
return values;
}
上面的示例导致只用第一个值填充向量,截断为 -2,大概是因为循环在遇到非数字字符时立即终止。当传入的字符串包含 int 值时,它会按预期工作,即使模板参数是 float。
有没有办法将字符串流配置为执行隐式转换并舍入到最接近的整数,或者我是否需要先插入原始原始类型(float)并执行显式转换为 T?理想情况下,我不想告诉 ReadValues string_with_data 中的数据类型——它总是 double、float、int、short 或 long 之一,请求的类型也可以是以下任何一种这些类型。
谢谢。
如果您知道 string_with_data 中数据的类型,那就更简单了:只需读取该类型的一个值,然后将其转换为所需的类型,然后再将其推入向量:
template <class T>
vector<T>& ReadValues(std::string& string_with_data)
{
std::stringstream ss(string_with_data);
std::vector<T> values;
float val; // use original type not required one
while(stream >> val)
{
values.push_back((T) val);
}
return values;
}
如果你不知道原始类型,它会有点困难,因为在 C++ 和标准库中都没有大到可以接受所有其他类型的单一类型。因此,您必须将每个数据作为字符串读取,然后使用辅助字符串流将其解码为所需的类型:
template <class T>
std::vector<T> ReadValues(std::string& string_with_data)
{
std::stringstream ss(string_with_data);
std::vector<T> values;
std::string str;
T val;
while(ss >> str) // first store the value into a string whatever it is
{
std::stringstream(str) >> val; // then read it as the required type
values.push_back(val);
}
return values;
}
这样你就可以确定:
- 读取 int 时没有在流中留下 float 的尾部部分
- 你在读取原始字符串时使用了所需类型允许的最大精度
注意:我假定您接受默认转换...
为什么不直接从文件中提取数据作为浮点数,而是先获取第一行,然后是浮点数,然后是整数?
double f;
std::vector<int> out;
std::ifstream file("numbers.txt");
file >> std::scientific;
while (file >> f)
out.push_back(out);
或者如果你想让它对迭代器更友好:
std::vector<int> out;
std::ifstream file("numbers.txt");
file >> std::scientific;
std::copy(std::istream_iterator<double>(file),
std::istream_iterator<double>(),
std::back_inserter(out)));
如果像@SergeBallesta 所说的那样,您想创建一个不知道 "original" 类型,只知道目标类型的通用函数,以类似迭代器的方式:
template <class T>
std::vector<T> ReadValues(std::string& string_with_data)
{
std::istringstream ss(string_with_data);
std::vector<T> values;
using iss_it = std::istream_iterator<std::string>;
std::transform(iss_it(string_with_data), iss_it(), std::back_inserter(values),
[](const std::string& x) { return boost::lexical_cast<T>(x) });
return values;
}