在创建对象之前确保数据的唯一性?

时间:2011-03-29 22:29:44

标签: c++

我有一个文件,里面有我需要操作的数据。该文件的每一行都包含浮点数(当然表示为字符串),如下所示:

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);

扭曲的是:

  1. 我想只创建尚未创建的对象。如果我已经使用完全相同的6个浮点数创建了Foo,而不是创建新的Foo我想要检索我已经创建的对象。

  2. 文件中的数据不可分割 - 不同数字之间可能有任意数量的空格或制表符。

  3. 在我用间距实现这个问题之前,我将从文件中读取的每一行拆分为字符串,连接代表每个foo的字符串,然后使用std::map<std::string,int>来测试唯一性,其中int地图返回表示一个std::vector<Foo*>的索引,我正在向我正在创建的每个Foo推送指针。当间距不一致时,这会失败。

    我现在能想到的就是: http://codepad.org/hLhFzhPh(例如)但这似乎完全搞砸了。我还尝试制作一个包含6个浮点值的结构,重载operator>>以从字符串流中读取,然后创建map<weirdstruct,int>,但我真的不知道如何重载operator<使这项工作。

    无论如何,这似乎应该很容易,我只是没有线索。有什么想法吗?

4 个答案:

答案 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有一些很好的实用程序可用于排序和删除重复项。

Edit1:带输入操作符的示例3D点(未测试)

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
  }

可以以非常类似的方式处理颜色值(如此相似,您可以只更改成员名称和类名称)。