Пропуск векторной позиции при pushing_back - PullRequest
3 голосов
/ 23 августа 2010

Я читаю данные из файла в вектор строк с именем data.И к этому вектору данных я отправляю новую строку через мой main с именем output_string.Output_string - это просто комбинация аргументов, передаваемых через командную строку.После всего, что я пишу обратно в мой файл (обновите файл новой строкой).Однако, когда я делаю это, все после 1-го аргумента командной строки пропускает векторную позицию всякий раз, когда встречает data.push_back(output_string);.

например, содержимое файла

bob
jack
snack

после считывания в вектор,

содержимое вектора данных

bob
jack
snack

после добавления новой строки, новая строка, являющаяся содержимым вектора данных "john", становится

bob
jack
snack
john

, но если я снова запускаю программу и использую командную строку, чтобы добавить что-то снова, она пропускает одну векторную позицию

bob
jack
snack
john

peter

и делает это для всего, что я добавлю послепервый.Почему это делается?

int main (int argc, char *argv[]){


 if (argc > 6){
  cout<<"[Error] too many inputs provided" << endl;
  return 0;
 }

 commandProcess(argc,argv);

 outputstringformat();
 //*********
 if (cominput.rem_contpos == -1){
  readData();                        //reads data from a file into vector data
  int outlen = output_string.length();
  if (outlen > 0){
   data.push_back(output_string);  //pushing what i had in argv to vector
  }

  cout<<"----------data vector------------"<<endl;
  for (int i = 0; i < data.size();i++){
   cout<<"data: " << data[i] << endl;
  }

  ofstream outfile("contactlist.dat");
  number_of_contacts = data.size();
  if(outfile.is_open()){
   for (int i =0; i < number_of_contacts; i++){
    outfile << data[i] << endl; //copying evertthing back to file, including the new argument passed to data
   }
   outfile.close();
  }
 }
 return 0;
}

РЕДАКТИРОВАТЬ: также, как я обрабатываю свои аргументы, я объединяю их в одну строку.У меня есть подозрение, что это может быть проблемой, но все еще не вижу ее ...: |

void outputstringformat(){

    if (cominput.name1.length() != 0 ){
        output_string = cominput.name1;
    }   
    if (cominput.name2.length() != 0 ){
        output_string = output_string + " " + cominput.name2;
    }
    if (cominput.name3.length() != 0 ){
        output_string = output_string + " " + cominput.name3;
    }
    if (cominput.email.length() != 0 ){
        output_string = output_string + " " + cominput.email;
    }
    if (cominput.phone.length() != 0 ){
        output_string = output_string + " " + cominput.phone;
    }
}

обновлено с reaData

void readData(){
    ifstream myfile("contactlist.dat");
    if(myfile.is_open()){
        while(!myfile.eof()){
            getline(myfile,line);
            data.push_back(line);
        }
        myfile.close();
    }
}

Ответы [ 3 ]

2 голосов
/ 23 августа 2010

Вот ваша проблема:

while(!myfile.eof()){
    getline(myfile,line);
    data.push_back(line);
}

myfile.eof() будет истинным после , которую вы пытались прочитать за концом файла;он не сообщает вам, достигнет ли следующего чтения EOF.Так что ваш последний getline ничего не будет читать (из-за EOF), но вы все равно поместите пустую строку line в вектор.

Правильный способ написать этот цикл просто:

while(getline(myfile,line)) {
    data.push_back(line);
}    

Это работает, потому что возвращаемое значение getline - это поток, который был прочитан из (в данном случае myfile), а iostreams разработаны так, чтобы при использовании в тесте, таком как if (myfile)они оцениваются как true, если и только если не было обнаружено ни ошибки, ни EOF.Написанный таким образом, когда достигается EOF, getline вернет myfile, что в тесте while будет иметь значение false, поэтому строка не будет вставлена ​​в вектор.

Этот метод также имеетПреимущество остановки чтения файла при ошибках, отличных от EOF.

1 голос
/ 23 августа 2010

Может случиться так, что изначально содержимое файла представляет собой строку:

"bob\n"
"jack\n"
"snack" // no line feed

, что строка за строкой - это "bob", "jack" и "snack". Когда вы пишете эти строки вместе с "john" endl, содержимое файла:

"bob\n"
"jack\n"
"snack\n"
"john\n" // line feed

Возможно, вы читаете это как «bob», «jack», «snack», «john» и «», потому что после прочтения «john \ n» технически конец файла не достигнут пока, но это будет достигнуто при следующей попытке прочесть.

РЕДАКТИРОВАТЬ: Этот readData, вероятно, будет работать для вас:

void readData() {
    ifstream myfile("contactlist.dat");
    if(myfile.is_open()){
        string l;
        while(myfile >> l){
            data.push_back(l);
        }
        myfile.close();
    }
}

Как показано на http://codepad.org/INgm757m,, эта версия будет работать одинаково независимо от того, является ли последний символ в contactlist.dat переводом строки.

0 голосов
/ 23 августа 2010

Здесь на самом деле недостаточно, но я подозреваю, что readData() добавляет пустую строку к вектору.Попробуйте это:

// Put this right after readData()
cout<<"----------data vector from file------------"<<endl;
for (int i = 0; i < data.size();i++){
  cout<<"data[" << i << "]: " << data[i] << endl;
}

РЕДАКТИРОВАТЬ:
Я не знаком с вашей версией getline, но похоже, что он принимает окончательный CR или LF илибез разницы.Попробуйте это:

void readData(){
    ifstream myfile("contactlist.dat");
    if(myfile.is_open()){
        while(!myfile.eof()){
            getline(myfile,line);
            if(myfile.gcount()>0){  // checking for zero-length string
                data.push_back(line);
            }
        }
        myfile.close();
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...