我在将字符串向量拆分为较小的整数vector \ array时遇到问题。我的输入矢量数据如下:
std::vector<std::string> v(2);
v[0] = "0 14 150";
v[1] = "1 2 220";
//...
我知道一个解决方案,可以制作三个数组,并使用sstream将数据转换为整数。但我想避免制作“意大利面条”代码。
谢谢你, 彼得。
答案 0 :(得分:1)
我前一段时间在stackoverflow上发现了一个split函数。不幸的是,我无法再发布链接。
void split(const std::string & str, std::vector<std::string>& cont, const std::string & delims)
{
std::size_t current, previous = 0;
current = str.find_first_of(delims);
while (current != std::string::npos)
{
cont.push_back(std::move(str.substr(previous, current - previous)));
previous = current + 1;
current = str.find_first_of(delims, previous);
}
cont.push_back(std::move(str.substr(previous, current - previous)));
}
我将需要在字符串中使用定界符(在您的情况下似乎是退格键),并在字符串向量的每个元素上调用函数:
int main()
{
std::vector<std::string> vec{ "0 14 150","1 2 220" };
std::vector<std::vector<int>> intVec(3,std::vector<int>(vec.size()));
for (int i = 0; i < vec.size(); i++)
{
std::vector<std::string> singleStr;
split(vec[i], singleStr, " ");
for (int j=0; j < singleStr.size();j++)
intVec[j][i] = (std::stoi(singleStr[j]));
}
system("pause");
}
一个更通用的解决方案可能看起来像这样。您可以将其他类型添加到BasicVariant
#include <string>
#include <vector>
class BasicVariant
{
private:
std::string str;
public:
BasicVariant(const std::string& _str) :str(_str) {}
BasicVariant(int value) :str(std::to_string(value)) {}
BasicVariant(double value) :str(std::to_string(value)) {}
inline int toInt()const { return *this; }
inline double toDouble()const { return *this; }
inline std::string toString()const { return *this; }
inline bool toBool()const { return toDouble(); }
inline operator int()const { return std::stoi(str); }
inline operator double()const { return std::stof(str); }
inline operator std::string()const { return str; }
inline operator bool()const { return toDouble(); }
};
template<typename T>
void split(const std::string& str, std::vector<T>& sink, const std::string& delims)
{
std::size_t current, previous = 0;
current = str.find_first_of(delims);
while (current != std::string::npos)
{
sink.push_back(std::move(BasicVariant(str.substr(previous, current - previous))));
previous = current + 1;
current = str.find_first_of(delims, previous);
}
sink.push_back(std::move(BasicVariant(str.substr(previous, current - previous))));
}
int main()
{
std::vector<std::string> vec{ "0 14 150","1 2 220" };
std::vector<std::vector<int>> intVec(3, std::vector<int>(vec.size()));
for (int i = 0; i < vec.size(); i++)
{
std::vector<int> row;
split(vec[i], row, " ");
for (int j = 0; j < row.size(); j++)
intVec[j][i] = row[j];
}
system("pause");
}
答案 1 :(得分:0)
编辑:我删除了详细的移调功能。
我假设您要将std::vector<std::string>
转换为2D矩阵std::vector<std::vector<int>>
。
例如,对于您的示例,假定期望的结果为arr1 = {0,1,...}
,arr2 = {14,2,...}
和arr3 = {150,220,...}
。
首先
我们可以使用std::istream_iterator
从字符串中提取整数。
我们还可以应用范围构造函数来创建与每个字符串相对应的std::vector<int>
。
因此以下功能对您有效,至少对我来说,它似乎不是意大利面条代码。
首先,此函数从传递的字符串向量{0,14,150,...}
中提取两个整数数组{1,2,220,...}
和v
作为矩阵。
由于默认构造的std::istream_iterator
是流结束迭代器,因此每个范围构造函数都会读取每个字符串,直到无法读取下一个值为止。
最后,换位的返回:
#include <vector>
#include <string>
#include <sstream>
#include <iterator>
template <typename T>
auto extractNumbers(const std::vector<std::string>& v)
{
std::vector<std::vector<T>> extracted;
extracted.reserve(v.size());
for(auto& s : v)
{
std::stringstream ss(s);
std::istream_iterator<T> begin(ss), end; //defaulted end-of-stream iterator.
extracted.emplace_back(begin, end);
}
// this also validates following access to extracted[0].
if(extracted.empty()){
return extracted;
}
decltype(extracted) transposed(extracted[0].size());
for(std::size_t i=0; i<transposed.size(); ++i){
for(std::size_t j=0; j<extracted.size(); ++j){
transposed.at(i).push_back(std::move(extracted.at(j).at(i)));
}
}
return transposed;
}
然后您可以从字符串向量中提取整数,如下所示:
std::vector<std::string> v(n);
v[0] = "0 14 150";
v[1] = "1 2 220";
...
v[n-1] = "...";
auto matrix = extractNumbers<int>(v);
其中 matrix[0]
是arr1
,matrix[1]
是arr2
,依此类推。
我们还可以通过auto arr1 = std::move(matrix[0]);
快速获取它们的内部指针。
答案 2 :(得分:0)
我们这里有些误会。
我的程序的输出应具有三个数组/向量。
输出如下:
arr1| arr1| arr3
0 | 14 | 150
1 | 2 | 220
2 | 4 | 130