Каждая вторая строка данных пропускается при чтении и сохранении данных из файла.

Я новичок в C++, и у меня возникают небольшие проблемы с чтением строк данных из текстового файла. Допустим, у меня есть неизвестное количество строк в текстовом файле, причем каждая строка имеет один и тот же формат: int string double . Единственное, что будет определенным, это пробел, который будет разделять каждый фрагмент данных в данной строке. Я использую массив структур для хранения данных. Приведенный ниже код отлично работает, за исключением того, что он пропускает строку ввода после каждого цикла. Я пробовал вставлять различные операторы ignore() и до сих пор не могу заставить его читать каждую строку, только каждую вторую строку. Если я перепишу некоторые операторы getline в конце, то после первого цикла для переменных начнут сохраняться неправильные данные.

Текстовый файл может выглядеть так:

18 JIMMY 71.5
32 TOM 68.25
27 SARAH 61.4


//code
struct PersonInfo
{
    int age;
    string name;
    double height;
};
//..... fstream inputFile; string input;

PersonInfo *people;
people = new PersonInfo[50];

int ix = 0;
getline(inputFile, input, ' ');
while(inputFile)
{
    people[ix].age = atoi(input.c_str());
    getline(inputFile, input, ' ');
    people[ix].name = input;    
    getline(inputFile, input, ' ');
    people[ix].height = atof(input.c_str());

    ix++;

    getline(inputFile, input, '\n');
    getline(inputFile, input, ' ');
}

Я уверен, что есть более продвинутые способы сделать это, но, как я уже сказал, я довольно новичок в C++, поэтому, если есть небольшие изменения в приведенном выше коде, это было бы здорово. Спасибо!


person Dawg Pwnd    schedule 11.04.2013    source источник
comment
Я бы прочитал всю строку, а затем разобрал ее на sep. поля.   -  person John3136    schedule 11.04.2013


Ответы (2)


Вы можете сделать чтение файла следующим образом:

int ix = 0;
int age = 0;
string name ="";
double height = 0.0;
ifstream inputFile.open(input.c_str()); //input is input file name

while (inputFile>> age >> name >>  height)
{
  PersonInfo p ={age, name, height};
  people[ix++] = p;
}
person taocp    schedule 11.04.2013

Вы сделали весь этот код смехотворно сложным.

struct PersonInfo
{
    int age;
    string name;
    double height;
};

std::vector<PersonInfo> people;
PersonInfo newPerson;
while(inputFile >> newPerson.age >> newPerson.name >> newPerson.height)
    people.push_back(std::move(newPerson));

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

std::string fullline;
while(std::getline(inputFile, fullline)) {
    std::stringstream linestream(fullline);
    std::getline(linestream, datawhatever);
    ....
}

Кстати, более идиоматический код может выглядеть примерно так:

std::istream& operator>>(std::istream& inputFile, PersonInfo& newPerson) 
{return inputFile >> newPerson.age >> newPerson.name >> newPerson.height;}

{ //inside a function
    std::ifstream inputFile("filename.txt");

    typedef std::istream_iterator<PersonInfo> iit;
    std::vector<PersonInfo> people{iit(inputFile), iit()}; //read in
}

Доказательство того, что это работает

person Mooing Duck    schedule 11.04.2013
comment
К сожалению, я еще не узнал о stringstream, и эта проблема решаема без него. Я уверен, что узнаю много вещей, которые могут упростить мой код до нескольких строк, но сейчас я в значительной степени застрял на том, что уже перечислил. Однако векторное решение выглядит интригующе, поэтому я собираюсь попробовать. - person Dawg Pwnd; 11.04.2013
comment
@DawgPwnd: Если вы не знакомы со строковым потоком, то первый фрагмент кода — это то, что вам нужно. - person Mooing Duck; 11.04.2013