Я хочу читать данные в файлах, которые отформатированы как:
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))
}
}
…но это не работает должным образом, так как данные не были сохранены в векторе.
Кто-нибудь может помочь?
Вместо хранения ваших данных в vectors
Вы можете сохранить его в sets
, Набор содержит только уникальные значения, поэтому вам не нужно проверять уникальность вашего Points
, set
справится с этим.
Вместо определения vector<Point>
, вы должны определить set<Point>
и вместо того, чтобы использовать p.push_back
чтобы добавить точки в ваш вектор, вы должны использовать p.insert
если это set
,
Вы можете проверить set
документация Вот.
Предполагая, что вы хотите сохранить свое хранилище данных в 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 в какой-то момент и, таким образом, как установлено std::ios_base::eofbit
, Что еще более важно, вы должны проверить после операция ввода, не раньше! То есть ваш первый цикл должен начинаться примерно так:
while (std::getline(myFile, line)) {
...