我有一个文件,里面有我需要操作的数据。该文件的每一行都包含浮点数(当然表示为字符串),如下所示:
x1 y1 z1 x2 y2 z2 x3 y3 z3 r1 g1 b1 r2 g2 b2 r3 g3 b3
每一行代表我需要创建的3个不同的对象,例如:
Foo foo1(x1,y1,z1,r1,g1,b1);
Foo foo2(x2,y2,z2,r2,g2,b2);
Foo foo3(x3,y3,z3,r3,g3,b3);
我想只创建尚未创建的对象。如果我已经使用完全相同的6个浮点数创建了Foo
,而不是创建新的Foo
我想要检索我已经创建的对象。
文件中的数据不可分割 - 不同数字之间可能有任意数量的空格或制表符。
在我用间距实现这个问题之前,我将从文件中读取的每一行拆分为字符串,连接代表每个foo的字符串,然后使用std::map<std::string,int>
来测试唯一性,其中int地图返回表示一个std::vector<Foo*>
的索引,我正在向我正在创建的每个Foo
推送指针。当间距不一致时,这会失败。
我现在能想到的就是:
http://codepad.org/hLhFzhPh(例如)但这似乎完全搞砸了。我还尝试制作一个包含6个浮点值的结构,重载operator>>
以从字符串流中读取,然后创建map<weirdstruct,int>
,但我真的不知道如何重载operator<
使这项工作。
无论如何,这似乎应该很容易,我只是没有线索。有什么想法吗?
答案 0 :(得分:4)
1:使用std::set<Foo>
记录您已构建的内容。 std::map
+ std::vector
解决方案既不可靠,修复后也会出现问题。
2:以下内容跳过输入中的任何前导空格:
double x;
std::cin >> x;
和任何std::istream
类似。
答案 1 :(得分:1)
我想在比较之前我会将输入转换为实际浮点数。对于浮点数,字符串表示中的差异不一定表示实际值的差异。例如,12345
等于1.2345e4
。
答案 2 :(得分:0)
如果您只是想要快速解决方案,可以这样。
std::stringstream sIn(theline);
std::stringstream sOut;
std::string temp;
while (sIn >> temp) sOut << temp << " ";
std::string fixedline = sOut.str();
答案 3 :(得分:0)
我看到的问题是找到完全匹配,因为您使用的是浮点数。
我建议将operator==(x,y,z,r,g,b)
添加到Foo
。将所有Foo
个对象放入容器中,并使用operator==()
进行比较,以查看是否已创建Foo
个对象。
另一种方法是将<x,y,z,r,g,b>
分解为父结构。创建这些容器。创建Foo
对象时,将实例放入容器中。您可以在创建 next Foo
实例之前搜索容器。
我还建议转置数据文件,使每行只包含一个x,y,z,r,g,b的向量。对文件进行排序。在将其复制到程序之前删除重复项。使用程序之外的应用程序执行此操作(首选)。 Cygwin和Linux有一些很好的实用程序可用于排序和删除重复项。
ifndef POINT3D_HPP
#include <iostream>
#include <cmath>
class Point3d
{
public:
Point3d(double x = 0.0, double y = 0.0, double z = 0.0)
: m_x(x), m_y(y), m_z(z)
{ ; }
Point3d(const Point3d& p3d)
: m_x(p3d.m_x), m_y(p3d.m_y), m_z(p3d.m_z)
{ ; }
friend std::istream& operator>>(std::istream& inp, Point3d& p3d);
bool operator==(const Point3d& p) const
{
return (std::fabs(m_x - p.m_x) < 5.0E-5)
&& (std::fabs(m_y - p.m_y) < 5.0E-5)
&& (std::fabs(m_z - p.m_z) < 5.0E-5);
}
private:
double m_x;
double m_y;
double m_z;
};
inline std::istream&
operator>>(std::istream& inp, Point3d& p)
{
inp >> p.m_x;
inp >> p.m_y;
inp >> p.m_z;
return inp;
}
#endif // POINT3D_HPP
class Foo
: public Point3d
{
public:
Foo(double x, double y, double z,
double r, double g, double b)
: Point3d(x, y, z),
m_r(r), m_g(g), m_b(b)
{ ; }
Foo(const Point3d& p3d,
double r, double g, double b)
: Point3d(p3d),
m_r(r), m_g(g), m_b(b)
{ ; }
double m_r, m_g, m_b;
};
读取数据文件就像这样:
std::ifstream data_file("data.bin");
Point3d p1;
Point3d p2;
Point3d p3;
// Input the first 3 points on the line.
data_file >> p1;
data_file >> p2;
data_file >> p3;
// Or: data_file >> p1 >> p2 >> p3
// Before creating a Foo:
std::vector<Point3d> existing_points;
std::vector<Point3d>::const_iterator iter;
bool is_duplicate = false;
for (iter = existing_points.begin();
iter != existing_points.end();
++iter)
{
if (*iter == p1)
{
is_duplicate = true;
break;
}
}
if (! is_duplicate)
{
existing_points.push_back(p1);
// Create a new Foo
}
可以以非常类似的方式处理颜色值(如此相似,您可以只更改成员名称和类名称)。