Read from input file

I am having trouble reading from the input file. The input file looks like this:

Lionel Messi -10 43

Fernando Torres 9 -29

Cristiano Ronaldo 7 31

Wayne Rooney 10 37

Neymar 17 29

Andres Iniesta 8 32

Robin van Persie 19 20

Lionel Messi 10 43

Xavi Hernandez 6 36

Mesut Özil 10 38

Didier Drogba 10 35

Fernando Torres 9 29

Kaka 10 17

The problem is that I cannot use the getline function because I want to save the name in one variable for storage in an array, and the first number in a variable, and the second in another. I also tried using the peek function, but I never found out about it, so I had no success. If someone knows how to read to the end of the name and store it in one variable, which would be highly appreciated.

This is what my code looks like when reading im from the input file

while(!fin.eof())
    {

     fin >> first >> last >> num >> point;

     if (num > 0 && point > 0)
     {
             list[i].firstname = first;
             list[i].lastname = last;
             list[i].number = num;
             list[i].points = point;
             i++;
     }
     else if (num < 0 || point < 0)
     {
             reject[j].firstname = first;
             reject[j].lastname = last;
             reject[j].number = num;
             reject[j].points = point;
             j++;
     }

    }

, . ,   fin → first → last → num → point;

, (, , )

+5
6

std::getline , std::vector , . , words.size() - 2 . :

std::fstream in("in.txt");
std::string line;

// Extract each line from the file
while (std::getline(in, line)) {
  std::istringstream line_stream(line);

  // Now parse line_stream into a vector of words
  std::vector<std::string> words(std::istream_iterator<std::string>(line_stream),
                                 (std::istream_iterator<std::string>()));

  int name_word_count = words.size() - 2;
  if (name_word_count > 0) {
    // Concatenate the first name_word_count words into a name string
    // and parse the last two words as integers
  }
}
+4

, getline, . , , std::istringstream, . , , - , . , :

std::string::iterator first_digit
        = std::find_if( line.begin(), line.end(), IsDigit() );
if ( first_digit == line.end() ) {
    //  format error...
} else {
    name = trim( std::string( line.begin(), first_digit ) );
    std::istringstream parser( std::string( first_digit, line.end() ) );
    parser >> firstNumber >> secondNumber >> std::ws;
    if ( !parser || parser.get() != EOF ) {
        //  format error...
    } else {
        //  Do what ya gotta do.
    }
}
+1

- :

std::string str;
while(getline(infile, str))
{
  std::string::size_type pos;
  pos = str.find_last_of(' ');
  if (pos == std::string::npos || pos < 1)
  {
      cout << "Something not right with this string: " << str << endl;
      exit(1);
  }
  int last_number = stoi(str.substr(pos));
  str = str.substr(0, pos-1);    // Remove the number and the space.
  pos = str.find_last_of(' ');
  if (pos == std::string::npos || pos < 1)
  {
      cout << "Something not right with this string: " << str << endl;
      exit(1);
  }
  int first_number = stoi(str.substr(pos));
  str = str.substr(0, pos-1); 
  // str now contains the "name" as one string. 

  // ... here you use last_number and first_number and str to do what you need to do. 
}
+1

, getline(); , '\n' .

, , , .

0

1.)

std::ifstream myFile("somewhere.txt");

2.) ,

if(myFile.is_open())

3.)

while(!myFile.eof())

4.)

myFile >> firstName[numberOfPeople];

5.)

myFile >> lastName[numberOfPeople];

6.)

myFile >> integer[numberOfPeople];

7.) Increase in the number of people

numberOfPeople++;

8.) When this is done, close the file

myFile.close();

9.) If the file does not open, report an error.

else
   std::cout << "\nFile did not open. " << std::endl;

You can use the getline function, you just need to parse the string. This can be achieved with strtok.

0
source

I implemented a solution to your problem (mainly for my own learning). It works as intended, but it feels a little long.

#include<string>
#include<fstream>
#include<sstream>
#include<iostream>
#include<vector>
#include<algorithm>
#include<iterator>

struct PlayerData {
  std::string name;
  int number;
  int points;
};

std::ostream& operator<<(std::ostream& os, const PlayerData& p) {
  os<<"Name: "<<p.name<<", Number: "<<p.number<<", Points: "<<p.points;
  return os;
}

PlayerData parse(const std::string& line) {
  PlayerData data;  
  std::stringstream ss(line);  
  std::vector<std::string> tokens;
  std::copy(std::istream_iterator<std::string>(ss),
            std::istream_iterator<std::string>(),
            std::back_inserter<std::vector<std::string>>(tokens));
  data.points = std::stoi(tokens.at(tokens.size() - 1));
  data.number = std::stoi(tokens.at(tokens.size() - 2));
  for(auto it=tokens.begin(); it!=tokens.end()-2; ++it) {
    data.name.append(" ");
    data.name.append(*it);
  }
  return data;
}

int main(int argc, char* argv[]) {
  std::string line;
  std::vector<PlayerData> players;  

  { // scope for fp                                    
    std::ifstream fp(argv[1], std::ios::in);
    while(!fp.eof()) {
      std::getline(fp, line);
      if(line.size()>0) {
        players.push_back(parse(line));
      }
    }
  } // end of scope for fp

  // print list of players, or do whatever you want with it.
  for(auto p:players) {
    std::cout<<p<<std::endl;    
  }

  return 0;
}

Compile a g ++ version that supports C ++ 11 (in my case gcc 4.7.2).

[Prompt] g++ -oparseline parseline.cpp -std=c++11 -O2
[Prompt] ./parseline players.txt
Name:  Fernando Torres, Number: 9, Points: -29
Name:  Cristiano Ronaldo, Number: 7, Points: 31
Name:  Wayne Rooney, Number: 10, Points: 37
Name:  Neymar, Number: 17, Points: 29
Name:  Andres Iniesta, Number: 8, Points: 32
Name:  Robin van Persie, Number: 19, Points: 20
Name:  Lionel Messi, Number: 10, Points: 43
Name:  Xavi Hernandez, Number: 6, Points: 36
Name:  Mesut Özil, Number: 10, Points: 38
Name:  Didier Drogba, Number: 10, Points: 35
Name:  Fernando Torres, Number: 9, Points: 29
Name:  Kaká, Number: 10, Points: 17
0
source

All Articles