Вы можете придумать элегантные решения, если используете современные элементы языка C ++.
Секрет сопоставления вещей заключается в использовании ассоциативных контейнеров, таких как std::map
. В этом вы можете сохранить ключ (например, имя) и значение (например, вес) и посмотреть его очень быстро.
И я принял проектное решение: человек может иметь только вес, если у него есть возраст. Это означает, что если файл с весами содержит больше записей, чем файл с возрастами, я буду игнорировать этих дополнительных лиц.
Чтобы добавить элементы в ваш класс Person, я добавил конструктор, который просто копирует значения переменных-членов. Вес необязательный.
И, чтобы показать хороший вывод, я переписал оператор вставки для класса Person.
Оба исходных текстовых файла содержат std::string
и integer
. Для использования более простого алгоритма чтения я создал прокси-класс для чтения std::pair<std::string, int>
.
. Для чтения файла весов мы просто определим карту и затем используем ее конструктор диапазона, чтобы прочитать все значения. через std::istream_iterator
в сочетании с определенным классом Proxy для наших пар string-int. Обратите внимание, что конечный итератор будет по умолчанию создан через {}. И мы используем функцию CAD 17 C ++ («дедукция аргументов шаблона класса»), чтобы определить std :: map без аргументов шаблона.
Для сопоставления значений мы используем std::transform
, который будет читать файл возрастов, найдите соответствующий вес и добавьте результат в наш вектор персон.
И последнее, но не менее важное, мы показываем результат на дисплее.
Пожалуйста, посмотрите полный рабочий пример :
#include <iostream>
#include <fstream>
#include <vector>
#include <map>
#include <string>
#include <utility>
#include <iterator>
#include <algorithm>
// Define a proxy class, to read a pair from a stream
struct StringIntegerPair : public std::pair<std::string, int> {
friend std::istream& operator >> (std::istream& is, StringIntegerPair& sip) {
return is >> sip.first >> sip.second;
}
};
// Our test class
class Person {
private:
std::string name{};
int age{}; // 0 means: not set
int weight{}; // 0 means: not set
public:
//setter method
// Constructor
Person(const std::string& n, const int a, const int w = 0) : name(n), age(a), weight(w) {}
// Output
friend std::ostream& operator << (std::ostream& os, const Person& p) {
return os << "Name: " << p.name << "\tAge: " << p.age << "\tWeight: " << p.weight;
}
};
int main() {
// Open file with weights and check, if it could be opened
if (std::ifstream weightStream("r:\\b.txt"); weightStream) {
// Open file with ages and check, if it could be opened
if (std::ifstream ageStream("r:\\a.txt"); ageStream) {
// Read all weights into a map
std::map namesAndWeights(std::istream_iterator<StringIntegerPair>(weightStream), {});
// Here we will store all persons
std::vector<Person> persons{};
// Now read all persons with age, check, if a weight is existing and add it to the vector
std::transform(std::istream_iterator<StringIntegerPair>(ageStream), {}, std::back_inserter(persons),
[&namesAndWeights](const std::pair<std::string, int>& na) { return Person(na.first, na.second, namesAndWeights[na.first]); });
// Show result to user
std::copy(persons.begin(), persons.end(), std::ostream_iterator<Person>(std::cout, "\n"));
}
else {
std::cerr << "\n*** Error: Could not open file with ages\n";
}
}
else {
std::cerr << "\n*** Error: Could not open file with weights\n";
}
return 0;
}