Reading from text file to structure - c++

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

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.

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

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.

Related

Reading file into array C++

I am trying to simply read a file "input.txt" into an array people[]. The txt file has 3 numbers:
10
20
30
I am getting -9.25596e+61 instead of 10 for people[0]. Here is my code:
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
class Trip {
private:
double people[3];
public:
void readFile(string file);
};
void Trip::readFile(string file) {
ifstream input;
input.open(file);
input >> people[0] >> people[1] >> people[2];
cout << people[0];
input.close();
}
int main() {
Trip trip;
trip.readFile("input.txt");
return 0;
}
Your program is correct. Working fine.
Currently, it is not getting the file. So, it is failing for you.
Provide the fully qualified path to readFile() as below example:
Path like "C:\\Users\\source\\Temp\\x64\\Debug\\input.txt"
Windows support file path with backward or forward slashes:
msdn.microsoft.com/en-us/library/aa365247(VS.85).aspx

How do I read only one type from a single-line file with multiple types?

So I have a text file with a single line that looks like this:
Steve 3 Sylvia 7 Craig 14 Lisa 14 Brian 4 Charlotte 9 Jordan 6
What I'm attempting to do is read each integer from the text file. I've tried some code which looks like this
#include <stdio.h>
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
int a;
ifstream inStream;
inStream.open("file.txt");
// case for file open failing
if ( inStream.fail() )
{
cout << "File open failed.\n";
exit(1);
}
//attempting to read each integer and print it to see if it worked right
while( inStream.good() )
{
inStream>>a;
cout<<a;
}
return 0;
}
I know this is pretty simple to do when the whole file consists of just integers, or if the entire file wasn't one line, however I'm having trouble with this case
If you know that the format will be like name number name number ... then you can do something like this:
int a;
string name;
// read name first then number
while( inStream >> name >> a )
{
cout << a << endl;
}
You can't jump over the names while reading with >>, but you can read them and do nothing with them.
A basic regex search can easly solve the problem
#include <iostream>
#include <regex>
#include <string>
int main(int argc, const char** argv) {
std::string buf = "Steve 3 Sylvya 7 Craig 14 Lisa 14 Brian 4 Charlotte 9 Jordan 6";
std::regex all_digit("\\d+");
std::smatch taken;
while(std::regex_search(buf, taken, all_digit, std::regex_constants::match_any)) {
for(auto x : taken)
std::cout << x << '\n';
buf = taken.suffix().str();
}
return 0;
}
Please adapt the above code to your needs. Switch the string with the buffer taken from the file.

Stringstream doesn't lose data when extracted

I want to create a file which stores some digits, later to be extracted into an array.
#include <vector>
#include <fstream>
#include <iostream>
#include <stringstream>
//for setw()
#include <iomanip>
std::vector<int> getData()
{
using namespace std;
//For the sake of this question simplicity
//I won't validate the data
//And the text file will contain these 10 digits:
//1234567890
ifstream in_file("altnum.txt");
//The vector which holds the results extracted from in_file
vector<int> out;
//It looks like C++ doesn't support extracting data
//from file to stringstream directly
//So i have to use a string as a middleman
stringstream ss;
string str;
//Extract digits from the file until there's no more
while (!in_file.eof())
{
/*
Here, every block of 4 digits is read
and then stored as one independent element
*/
int element;
in_file >> setw(4) >> str;
cout<<str<<"\n";
ss << str;
cout<<ss.str()<<"\n";
ss >> element;
cout<<element<<"\n";
out.push_back(element);
}
//Tell me, program, what have you got for my array?
for (auto &o : out)
cout << o << ' ';
in_file.close();
return out;
}
When i run the snippet of code above, i get the following numbers:
1234 1234 1234
while
1234 5678 90
is expected.
And then i found out (by cout-ing each variable to the screen) that the stringstream ss does not release its content when extracted to 'element'
But why is that? I thought that like cin stream, after the extraction, the stream would pop data out of it? Did i miss anything extremely important?

Challenging data file format which needs to be read into vars of array containing class objects

I have a program with 5 instances of the class Garbage, garbage has 3 variables I need to update from a data file. The first is a char array, the other two integers. All except the updating the int variables work, and I have no clue of how to achieve that, so any help is greatly appreciated. My code:
#include <iostream>
#include <cctype>
#include <cstring>
#include <fstream>
#include <iomanip>
using namespace std;
class Garbage {
public:
void writeData();
void updateFromFile( ifstream & file );
private:
char name[40];
int num1;
int num2;
};
void Garbage::writeData() {
cout << name << ", " << num1 << ", " << num2 << endl;
}
void Garbage::updateFromFile ( ifstream & file ) {
if ( !file.eof() ) {
file.getline(name, STRLEN);
/*
Int variables from Garbage class need to be updated here
*/
}
}
void readFile() {
ifstream infile("data.txt");
for(int i = 0; i < sizeof(garbages)/sizeof(garbages[0]); i++) {
garbages[i].updateFromFile(infile);
}
}
Garbage garbages[5];
int main() {
readFile();
for(int i = 0; i < sizeof(garbages)/sizeof(garbages[0]; i++) {
garbages[i].writeData();
}
return 0;
}
The data structure of "data.txt" is as follows:
lorem A
10 20
ipsum B
20 30
dolor C
30 40
sit D
40 50
amet E
50 60
lorem is the char array (may include whitespaces!), 10 is num1 and 20 is num2 and so on. Due to this being a school assignment, I cannot change the structure of the c++ code nor the data file structure. And If it's possible to achieve this without additional preprocessing directives, that would be preferable.
Any and all input is greatly appreciated!
Edit: fixed class member function naming inconsistencies and poor use of sizeof(). I also added an optional letter in name fields of the data structure showing that name may include whitespaces, and thus I can't rely on the ">>" operator alone and must use getline.
Stream operators consume whitespace. All you need is
void Letter::updateFromFile ( ifstream & file ) {
file.getline(name, STRLEN);
file >> num1 >> num2 >> ws; // eat the end of line
}
Additional:
If you have control over the parameter, I would change it to istream &, because there is nothing file stream specific going on. Strive to use the least specific type that works correctly.
C style arrays are more quirky, harder to use safely, and less featureful than std::array and std::vector. The only reason to use them today is to share definitions with C code.

Trying to store data from text file into vector of objects

I am trying to get a few lines from a text file to store into a class, Item, and using vectors. However, when I read from the file into the program, nothing is stored.
Here is my main:
#include <vector>
#include <fstream>
#include <iostream>
#include "Item.h"
using namespace std;
void readFile(vector<Item>&);
int main()
{
vector<Item> items;
readFile(items);
int size = items.size();
for (int index = 0; index < size; index++)
{
cout << items[index].getName() << endl;
}
}
This is the function in question:
void readFile(vector<Item>& vecItems, int lines)
{
ifstream inventory;
inventory.open("inventory.txt");
string itemName;
int itemDept, itemPrice, itemQuan, itemShort, itemSurplus;
string line;
if (inventory.fail())
{
cout << "ERROR NO FILE FOUND (inventory.txt)\n";
exit(1);
}
while (inventory >> itemName >> itemDept >> itemPrice >> itemQuan >> itemShort >> itemSurplus)
{
Item temp(itemName, itemDept, itemPrice, itemQuan, itemShort, itemSurplus);
vecItems.push_back(temp);
}
inventory.close();
}
I've tried calling
temp.setName(itemName)
etc etc
individually but it still does not hold in the vector. Nothing outputs in main and the debugger says size = 0. Any help is appreciated
EDIT: This is the file format
vitamins 1 15.99 1105 500 1000
shampoo 2 6.99 298 300 500
Your problem is you have a bad read. item_price is declared as an int but the price in the file is a floating point number. When you try to read in item_price it capture everything up to the . and then stops reading. On the next read operation for itemQuan it gets the . and fails as . is not a valid int. Since the read fails you never enter the while loop body which means you never create any objects.
Change item_price to a float, double or std::string to fix this.