2015-09-16 2 views
1

Прежде всего позвольте мне сказать спасибо тем людям, которые публикуют здесь часто, я приобрел массу знаний, изучая этот сайт за последние несколько лет.C++ Создание объекта из текстового файла

Хорошо, этот вопрос был задан раньше, но у меня есть небольшой поворот, который я не могу получить.

Вот моя структура.

struct person 
{ 
    string Sex; 
    string Name; 
    string Match; 
    int phoneNumber; 
    int numInterests; 
    vector<string> interests; 
}; 

Задача разработана как «Программа знакомств», которая соответствует людям противоположного пола с аналогичными интересами.

Вот пример текстового файла после этого формата:

«Секс» «Имя» «Номер телефона» «Количество интересов» «Список интересов» «Match (если совпадение найдено)»

M Tyler 1234567890 3 soccer football tv Jess 
F Lyns 1234567890 3 hockey sex movies 
F Jess 1234567890 3 soccer football tv Tyler 
M Taylor 1234567890 3 hockey sex movies 

В этом примере файл соответствует Jess и Tyler. Вот моя функция до сих пор ...

void LoadClients(std::ifstream &file,vector<person>& peps) 
{ 
    string sex,name,interests,line, match; 
    double phone,ni; 
    person p; 
    for(int i=0;i<maxPeople("Clients.mf"); i++){ 
     file>>sex>>name>>phone>>ni; 
     p.Sex = sex; 
     p.Name = name; 
     p.phoneNumber = phone; 
     p.numInterests = ni; 
     for (int i=0; i<ni; i++){ 
      file >> line; 
      p.interests.push_back(line); 
     } 
     file >> match; 
     p.Match = match; 
     peps.push_back(p); 

     // person p; 
     //istringstream iss(line); 
    } 

}; 

Функция компилирует, но не правильно читать вообще. Вот остальная часть моей работы, в случае, если вы хотите увидеть его ...

int maxPeople(const char* file)///Just returns the number of lines in the file 
{ 
    ifstream inFile(file); 
    int c = count(istreambuf_iterator<char>(inFile), 
      istreambuf_iterator<char>(), '\n'); 
    return c; 
} 
int main() 
{ 
    int numberOfClients=maxPeople("Clients.mf"); 
    ifstream file("Clients.mf"); 

    vector<person> peps; 
    LoadClients(file,peps); 

    return 0; 
} 

Моей функцию LoadClients был смоделирован после элегантного ответа я нашел здесь: Reading a string and integers

Все, что я прошу это как получить эту функцию, чтобы создать вектор или массив людей из текстового файла.

Заключительная программа будет иметь дополнительные функции «NewClient», «UnMatch», «PrintMatched» и «PrintSingles», но я думаю, что смогу их обработать. Любые советы приветствуются :)

Спасибо за чтение!

EDIT1: Использование этого формата.

void LoadClients(std::ifstream &file,vector<person>& peps) 
{ 
    person p; 
    string line; 
    while(getline(file, line)) 
    { 
     istringstream iss(line); 
     iss >> p.Sex >> p.Name >> p.phoneNumber >> p.numInterests; 
     for(int i=0;i<p.numInterests;i++){ 
      string interest; 
      iss >> interest; 
      p.interests.push_back(interest); 
     } 

    } 
}; 

Я решил пропустить «матч» пока. Я получаю ошибку сегментации, когда я обращаюсь к объектам из основного.

ifstream file("Clients.mf"); 

vector<person> peps; 
LoadClients(file,peps); 
for(int i=0; i<numberOfClients;i++){ 
    cout << peps[0].Name; 
} 
+0

Спасибо всем, кто помог! – user5340194

ответ

1

BTW, это не хорошая идея для sex быть string, если you'ld не нравится ваша программа для обработки инопланетян ... И вы, возможно, проблемы с вашим int phoneNumber s. И numInterests является избыточным, если у вас есть interests.size(). Так вы можете сделать ...

struct Person { 
    enum class Gender { 
     Unknown, 
     Male, 
     Female, 
    }; 

    Gender gender; 
    std::string name; 
    std::string match; 
    std::string phoneNumber; 
    std::vector<std::string> interests; 
}; 

Теперь, к проблеме. Функция должна выглядеть (без проверки и C++ 11!) ...

static Person::Gender readGender(std::ifstream &input) { 
    char ch; 
    input >> ch; 
    switch(ch) { 
     case 'M': 
      return Person::Gender::Male; 

     case 'F': 
      return Person::Gender::Female; 

     default: 
      return Person::Gender::Unknown; 
    } 
} 

void LoadClients(std::ifstream &file, std::vector<person> &out) { 
    for(int i = 0; i < maxPeople("Clients.mf"); i++) { 
     Person p; 
     unsigned numInterests; 

     p.gender = readGender(file); 
     file >> p.name; 
     file >> p.phoneNumber; 
     file >> numInterests; 
     for(unsigned i = 0; i < numInterests; i++){ 
      std::string interest; 
      file >> interest; 

      p.interests.push_back(interest); 
     } 

     file >> p.match; 
     out.push_back(p); 
    } 
} 

Edit: Вы должны иметь средства для программы различать, есть ли match или нет, в противном случае неопределенной фрустрации будет искать вас!

Редактировать: Недопустимый предыдущий комментарий из-за комментариев от OP.

Редактировать: Исправлены некоторые подводные камни в соответствии с комментариями.

+0

Я не оставлял ключевую информацию в системе соответствия. Программа будет автоматически соответствовать двум людям, если у них есть 3 или более совпадающих интересов. Это займет немного времени для реализации, но оно выглядит достаточно прямо. – user5340194

+0

Для любых других новичков, читающих это, мне пришлось добавить флаг -std = C++ 11 в компилятор GCU GCC для работы вышеописанного метода. Все еще работаю над проектом, но спасибо вам. Я вернусь, когда это закончится. – user5340194

+0

Мне пришлось переключать input.get() внутри коммутатора на 'char g; input >> g; switch (g) 'get() не« продвигал »файл на следующую строку, а собирал невидимый символ в конце каждой строки. – user5340194

1

Телефон и ni (я предполагаю, что это количество интересов) не должны быть двойными. Я бы сделал «Телефон» строкой и ni int (некоторые могли бы утверждать, что они неподписанные, но достаточно близко).

Двойные и Float являются «потерянными» типами данных, не подходят для подсчета или номера телефона.

Вы фактически не говорите, что такое поведение и что вы ожидаете от него. Я предполагаю, что ваш груз будет наперекосяк, и это из-за этой линии:

file >> match; 

Вы не знаете, есть ли линия или нет, так что он может забрать первую работу на следующий линия.

Я бы переключился на использование getLine и потокового потока и проверить, пуста ли строка (поток строк IE в конце или нет) перед извлечением соответствия.

3

Поскольку ваши входы записи основаны на линиях, используйте линейный считыватель. Проблема с программой прямо сейчас предполагает, что всегда есть совпадение. Но на второй строке входного файла нет совпадения. Поэтому будет прочитан следующий текст с разделителями-разделителями.

Мне нравится этот подход к разбору строки из файлов, так как это просто:

string line; 
while(getline(file, line)) 
{ 
    istringstream iss(line); 

    // Now, parse out of 'iss' instead of 'file'. 
    person p; 
    bool ok = false; 
    if(iss >> p.Sex >> p.Name >> p.phoneNumber >> p.numInterests) 
    { 
     p.interests.reserve(p.numInterests); 
     for(int i = 0; i < p.numInterests; i++) 
     { 
      string interest; 
      if(iss >> interest) p.interests.emplace_back(interest); 
     } 

     ok = !iss.error(); 

     iss >> p.Match; // optional 
    } 

    if(ok) peps.push_back(p); 
} 

Вы могли бы пойти на один шаг дальше и определить оператор ввода потока для Person структуры. Затем, основной цикл чтения будет выглядеть следующим образом:

person p; 
iss >> p; 
+0

Использование этого формата. 'void LoadClients (std :: ifstream & file, vector & peps) { человек p; строка строки; while (getline (файл, строка)) { istringstream iss (строка); iss >> p.Sex >> p.Name >> p.phoneNumber >> p.numInterests; для (int i = 0; i > интерес; p.interests.push_back (процент); } } }; ' Я решил пропустить« матч »на данный момент. Я получаю ошибку сегментации, когда я обращаюсь к объектам из основного. 'cout << peps [0] .Name; ' – user5340194

+0

В этом коде, который вы поставили выше, вы никогда не подталкивали запись на свой вектор. Не обращайтесь к индексу 0, если не знаете, что размер вектора равен не менее 1. – paddy