将文件中的数据提取到矢量中,但避免重复

时间:2012-11-11 11:36:03

标签: c++ vector file-read

我想读取格式为:

的文件中的数据
Point1, [3, 4]

我正在使用分隔符“['']'和','并用''(空格)替换它们。我的代码现在很好并且正常工作。但问题是,如果Point1, [3, 4]出现一次,我希望它是唯一的,如果文本文件中存在相同的数据则不再出现。

这就是我所拥有的:

string line, name;
char filename[50];
int x,y;

cout << "Please enter filename : ";
cin >> filename;

ifstream myfile(filename);
if (myfile.is_open()) {
    while ( myfile.good() ) {
        getline(myfile, line);

        for (unsigned int i = 0; i < line.size(); ++i) {
            if (line[i] == '[' || line[i] == ']' || line[i] == ',') {
                line[i] = ' ';
            }
            istringstream in(line);
            in >> name >> x >> y;                                  
        }
        cout <<name <<endl;

        if (name=="Point") {
            p.push_back(Point(x,y));         
        }                          
        count++;
    }    
    myfile.close();
    cout << count;
}
else cout<< "Unable to open file";

我该怎么做?我尝试在if(name=="Point")

之后添加此内容
for (int j=0; j<p.size(); j++) {
    if(p.getX != x && p.getY) != y) {
        p.push_back(Point(x,y))
    }
}

...但由于数据未存储到矢量中,因此无法正常工作。

任何人都可以提供帮助吗?

2 个答案:

答案 0 :(得分:4)

您可以将数据存储到vectors,而不是将数据存储到sets。集合仅包含唯一值,因此您无需检查Points的唯一性,set将对其进行管理。

您必须定义vector<Point>,而不是使用set<Point>来向您的向量中添加点,而不是定义p.push_back,如果是p.insert,则必须使用set set

您可以查看{{1}}文档here

答案 1 :(得分:0)

假设您希望将数据存储保存在std::vector<Point>中,您可以检查是否已存在相应的点。假设定义了相等运算符,它就像这样简单:

if (p.end() == std::find(p.begin(), p.end(), Point(x, y))) {
    p.push_back(Point(x, y));
}

如果Point类型没有相等运算符且不应该使用等号运算符,则可以将函数对象与find_if()一起使用,例如:

if (p.end() == std::find_if(p.begin(), p.end(),
                      [=](Point const& v) { return x == v.x && y == v.y; })) {
    ...

你应该将循环与其他操作分开:你建议检查点是否已经存在的循环基本上是std::find()所做的循环,除了你在每次迭代中插入一个新点!您首先要查看所有现有点并查看它是否存在于任何位置。只有在没有的情况下,才会插入一个新点。

请注意,在替换字符串中的字符时出现了类似的错误:在检查每个字符后尝试解码字符串。这不是一个语义问题,但它是一个主要的性能问题。你应该在循环中替换字符,然后在循环之后,你应该只解码一次字符串。当然,在解码字符串时,您需要检查格式是否正常,因为确定输入操作是否成功需要始终。也就是说,在你的循环替换你想要的字符之后:

std::istringstream in(line);
if (in >> name >> x >> y) {
    // now process the data
}

...或者,如果你像我一样,并且不喜欢命名只是临时的东西:

if (std::istringstream(line) >> std::ws >> name >> x >> y) {

另外注意:检查good()的流通常是错误的,因为流可以处于非常好的条件,除了它在某个时刻看到了EOF,因此设置为{{ 1}}。更重要的是,您需要检查之后输入操作,而不是之前!也就是说,你的第一个循环应该从这样开始:

std::ios_base::eofbit