Mat Mat - 3 years ago 44
C++ Question

I am trying to fill vector array with getline, what's wrong?

I would like to fill a vector array with some lines but I don't get the same back. What is the problem with my code?

using namespace std;

vector<string> calling(int n){
vector<string> file(n);
int a=0;

while(n){
getline(cin,file[a]);
cin.ignore();
a++;
n--;
}
return file;
}

int main() {
int n;
cin >> n;
vector<string> hrml = calling(n);
int a=0;
while(n){
cout << hrml[a] <<endl;
a++;
n--;
}
return 0;
}


The input:

3
aaaa aaa aa
bb b bbbb
c cc ccc


The output:

aaaa aaa aa
bb b bbbb

Answer Source

It's a combination of a few factors.

Reading the first number in the input, 3, doesn't move the "cursor" to the next line; it simply moves it past the number. When you next call getline, it returns a std::string of size 0, because it grabs the space between the end of the character and the end of the line, which is nothing.

Then, because you're using that number as an explicit number of strings to read, you're reading exactly 3 lines: "", "aaaa aaa aa", and "bb b bbbb".

Hence your output missing the line of 'c''s.

The simplest solution here is to force an extra call to getline before you call calling. (I've removed using namespace std; from your code because it's bad practice)

int main() {
    int n;
    std::cin >> n;
    std::string line;
    std::getline(std::cin, line);

Then, we can rewrite calling to not need an integer parameter:

std::vector<std::string> calling(){
    std::vector<std::string> file;
    std::string line;
    while(std::getline(std::cin, line)){
        file.push_back(std::move(line));
    }
    return file;
}

(If you're testing in your console, and you need something to mark the end of the line, use Ctrl+Z on Windows or Ctrl+D on UNIX.)

Which changes the calling line to this:

std::vector<std::string> hrml = calling();

Or this, if you're using C++11 (and don't mind the loss of explicitly visible type declaration):

auto hrml = calling();

And as long as we're here, we can write a better loop for printing the contents of our vector:

for(size_t i = 0; i < hrml.size(); i++) {
    std::cout << hrml[i] << std::endl;
}

Or, if we're using C++11:

for(std::string const& line : hrml) {
    std::cout << line << std::endl;
}

And, if you're allowed to change the format of your input file, we can ditch the reading of the number in the first place, yielding a much smaller and easier to debug program:

#include<iostream>
#include<string>
#include<vector>

std::vector<std::string> calling(){
    std::vector<std::string> file;
    std::string line;
    while(std::getline(std::cin, line)) {
        file.push_back(std::move(line));
    }
    return file;
}

int main() {
    std::vector<std::string> hrml = calling();

    for(std::string const& line : hrml) {
        std::cout << line << std::endl;
    }
    return 0;
}
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download