tags:

views:

62

answers:

3

Hi there, I'm reading data from a file into a vector of strings called data. And to this data vector I push_back a new string through my main called output_string. Output_string is just a combination of the arguments passed in through command line. After doing all that I write back to my file(update the file with the new string). However when I do this, everything after the 1st command line argument,it skips a vector position whenever it encounters data.push_back(output_string); again.

eg file contents

bob
jack
snack

after reading into vector,

data vector contents

bob
jack
snack

after adding new string, new string being "john" data vector contents become

bob
jack
snack
john

but if i Run the program again and use command line to add something again it skips one vector position

bob
jack
snack
john

peter

and it does this for everything that I add after the first. Why is doing this?

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;
}

EDIT: also this is how I process my arguments, I combine them into a single string. I have an inkling this could be the issue but still don't see it... :|

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;
    }
}

updated with reaData

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

There isn't really enough to go on here, but I suspect that readData() is adding an empty string to the vector. Try this:

// 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;
}

EDIT:
I'm not familiar with your version of getline, but it look as if it's picking up the final CR or LF or whatever. Try this:

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();
    }
}
Beta
you are right... could you tell me whats wrong here?void readData(){ ifstream myfile("contactlist.dat"); if(myfile.is_open()){ while(!myfile.eof()){ getline(myfile,line); data.push_back(line); } myfile.close(); }}
sil3nt
+1  A: 

What might be happening is that originally, the file contents are the string:

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

which, line-by-line, is "bob", "jack", and "snack". When you write out these lines along with "john" endl, the contents of the file are:

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

You might be reading this as "bob", "jack", "snack", "john", and "" because after "john\n" has been read, the end-of-file has technically not been reached yet, but it will be reached upon the next attempt to read.

EDIT: This readData will probably work for you:

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

As demonstrated at http://codepad.org/INgm757m, this version will have the same behavior regardless of whether the last character in contactlist.dat is a line feed.

Daniel Trebbien
thank you so much!
sil3nt
+2  A: 

Here's your problem:

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

myfile.eof() will only be true after you have attempted to read beyond the end of the file; it does not tell you whether or not the next read will reach EOF. So your last getline will not read anything (due to EOF), yet you will put the empty line string into the vector anyway.

The correct way to write this loop is simply:

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

This works because the return value of getline is the stream that was read from (myfile, in this case), and iostreams are designed so that when used in a test, such as if (myfile), they evaluate to true if and only if neither an error nor an EOF has been encountered. Written this way, when EOF is reached, getline will return myfile which will evaluate to false in the while test, and so the line will not be pushed into the vector.

This method also has the advantage of stopping the file read on errors other than EOF.

Tyler McHenry