Edvinas Sadeckas
Edvinas Sadeckas

Reputation: 33

Reading from text file to structure

Firstly, I'd like to explain what I'm trying to do. So, I have a text file with 10 names followed by their points. I'm trying to create a structure and read information from a file using a function (void). And that's my code and text file:

code:

#include <iostream>
#include <fstream>
#include <string>

using namespace std;

void read(struct laLiga t[]) {
    ifstream infile("info.txt");
    int i = 0;
    while(infile >> t.team[i] >> t.points[i]) {
        infile.get(t.team);
        infile >> t.points;
        i++;
    }
}

struct laLiga {
    char team[50];
    int points;
};

int main() {
    struct laLiga t[10];
    read(t);
    return 0;
}

text file:

Athletic Bilbao  15
Atletico Madrid  18
Barcelona  16
Alaves  10
Las Palmas  12
Real Madrid  18
Real Sociedad  10
Sevilla  17
Eibar  11
Villarreal  16

Upvotes: 1

Views: 1461

Answers (3)

Syed Ahmed Jamil
Syed Ahmed Jamil

Reputation: 2126

if you want to read or write structs in a text file then best would be to use ifstream read() function and ofstream write() function. Following is how to use them.

#include <iostream>
#include <fstream>
#include <cstring> // for strncpy()

using namespace std;

struct laLiga {
    char team[50];
    int points;
};

int main()
{
struct laLiga t;

strncpy(t.team,"Some Name",sizeof("Some Name"));
t.points = 100;

//do this for writing  a complete struct to a text file at once
ofstream output("info.txt");
output.write(reinterpret_cast<char*>(&t),sizeof(t));
output.close();

//do this for reading a complete struct from a text file at once

struct laLiga T;

ifstream input("info.txt");
input.read(reinterpret_cast<char*>(&T),sizeof(T));
input.close();

//now T will hold both the name and points fields from the text file without doing it individually

cout << "Name = " <<T.team << endl;
cout << "Points = " << T.points << endl;

return 0;
}

OUTPUT (Console)

   Name = Some Name

   Points = 100

Both read() and write() function's first parameter should be char* that is why we use reinterpret_cast to cast the complete struct to sequence of bytes and then write to file. Only drawback of doing like this is that the text file will be unreadable when opened in windows as it wont be normal text but reading and writing would be much easier.

Upvotes: 0

wally
wally

Reputation: 11002

You could use std::vector to make things easier:

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <sstream>
#include <iomanip>

using namespace std;

auto file_text = 
R"(Athletic Bilbao  15
Atletico Madrid  18
Barcelona  16
Alaves  10
Las Palmas  12
Real Madrid  18
Real Sociedad  10
Sevilla  17
Eibar  11
Villarreal  16)";

struct laLiga {
    std::string team;
    int points;
};

void read(std::vector<laLiga>& t) {
    //ifstream infile("info.txt"); // would also work
    std::stringstream infile{file_text};
    while(infile) {
        laLiga laliga{};
        std::string partial_team_name{};
        while(!(infile >> laliga.points)) { // keep going until we get the points
            infile.clear(); // we could not read points, infile stream now in error; clearing to continue
            if(infile >> partial_team_name) // maybe the next string is part of a team name
                laliga.team += (laliga.team.empty() ? "" : " ") + partial_team_name; // add to team name with space if there was something already in there
            else
                return; // no points, no team, we're done
        }
        t.push_back(laliga); // after we get the points we can add the team
    }
}

int main() {
    std::vector<laLiga> t;
    read(t);
    for(auto i : t) {
        std::cout << std::setw(30) << i.team;
        std::cout << std::setw(10) << i.points << '\n';
    }
    return 0;
}

Output:

       Athletic Bilbao        15
       Atletico Madrid        18
             Barcelona        16
                Alaves        10
            Las Palmas        12
           Real Madrid        18
         Real Sociedad        10
               Sevilla        17
                 Eibar        11
            Villarreal        16

live demo

Upvotes: 2

Some programmer dude
Some programmer dude

Reputation: 409166

First of all, you need to define the structure before you use it in the read function.

Secondly, in the read function it is the variable t that is an array, not its members. So you should be using t[i].team and t[i].points.

Thirdly, you have already read the data from the file with the >> operators in the loop condition. You should not read it again inside the loop.

Fourthly, the input file you want to read is actually harder to parse than you think. That is because you can have names both without and with spaces in them. Both the get function of input streams and the input operator >> separates on spaces. You should probably read the whole line and then split it at the last space.

Lastly, and actually a reason I should not write an answer is that you haven't actually asked a question, or told us what is wrong with your code. Please read about how to ask good questions for future questions.

Upvotes: 3

Related Questions