我正在从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。
有没有办法配置字符串流来执行隐式转换并舍入到最接近的整数,或者我是否需要先插入原始基本类型(浮点数)并对T执行显式转换?理想情况下,我不想告诉ReadValues有关string_with_data中数据的类型 - 它总是double,float,int,short或long之一,请求的类型也可以是这些类型中的任何一种。 / p>
感谢。
答案 0 :(得分:1)
如果您知道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;
}
这样你就可以确定:
注意:我假设您接受默认转换...
答案 1 :(得分:0)
为什么不直接从文件中提取数据作为浮点数,而不是获取第一行,然后浮点数,然后是整数?
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所说的那样,你想要一个泛型函数,你不知道“原始”类型,只有目标类型,就像迭代器一样:
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;
}