I am trying to read into a nested struct from a txt file. The output keeps repeating the same nested output. I attempted to nest two for loop but it didn't even read at all, my display was a blank screen. So I was able to get the file to read now but it repeats the same title and yearPub information for all entries.
#include<iostream>
#include<string>
#include<fstream>
#include<iomanip>
using namespace std;
struct Discography {
string title;
int yearPub;
};
struct Collection {
string name;
string genres;
int startYear;
int endYear;
Discography records;
};
void readFile(ifstream&, string, Collection [], int&);
const int DATA_FILE = 10;
int main() {
ifstream inputMusic;
Collection music[DATA_FILE];
Discography records;
const int DISPLAY_ALL = 1,
SEARCH_ARTIST_NAME = 2,
SEARCH_GENRE = 3,
SEARCH_TITLE = 4,
SEARCH_YEAR = 5,
QUIT_CHOICE = 6;
int choice;
int count = 0;
int numFile = count;
string nameArtist,results;
readFile(inputMusic, "My_Artists.txt", music, count);
void readFile(ifstream& inputMusic, string data, Collection music[], int &count)
{
inputMusic.open(data);
if (!inputMusic)
{
cout << "Error in opening file\n";
exit(1);
}
else
{
while (!inputMusic.eof())
{
inputMusic >> music[count].name
>> music[count].genres
>> music[count].startYear
>> music[count].endYear
>> music[count].records.title
>> music[count].records.yearPub;
count ;
}
inputMusic.close();
}
return;
};
InputFile:
MJ
Pop
1980
2020
BAD 1990
DRE
Rap
1970
2022
CRONIC 1995
EMINEM
Rap
1998
2022
ENCORE 2002
WHITNEY
R&B
1974
2008
SOMEBODY 1987
OUTPUT:
Name : MJ
Genre: Pop
Start Year: 1980
End Year: 2020
Title: BAD Year Published: 1990
----------------------------------------------------
Name : DRE
Genre: Rap
Start Year: 1970
End Year: 2022
Title: BAD Year Published: 1990
----------------------------------------------------
Name : EMINEM
Genre: Rap
Start Year: 1998
End Year: 2022
Title: BAD Year Published: 1990
----------------------------------------------------
Name : WHITNEY
Genre: R&B
Start Year: 1974
End Year: 2008
Title: BAD Year Published: 1990
----------------------------------------------------
CodePudding user response:
I would suggest going in a little different direction to make sure you don't write a lot of unneeded code. Here's the exact same example withe a few improvements. First improvement is the way you store your data. Instead of storing it in an array with seperate size variables and more arguments and that why not use vector. Next thing is the way you input data into your program. Not very clear. Better way would be saving it in csv file. Here's the code:
#include<iostream>
#include<string>
#include<fstream>
#include<iomanip>
#include<vector>
using namespace std;
struct Discography {
string title;
int yearPub;
Discography(string name, int publish) : title(name), yearPub(publish) {}
Discography() {}
};
struct Collection {
string name;
string genres;
int startYear;
int endYear;
Discography records;
Collection(string artistName, string genre, int start, int end, string title, int yearPublished)
: name(artistName), genres(genre), startYear(start), endYear(end), records(title, yearPublished) {}
Collection() {}
};
void readFile(vector<Collection> &music)
{
ifstream file;
file.open("myArtists.txt");
if (file.is_open())
{
string line;
while (getline(file,line))
{
int pos;
pos = line.find(';');
string name = line.substr(0, pos);
line = line.substr(pos 1);
pos = line.find(';');
string genre = line.substr(0, pos);
line = line.substr(pos 1);
pos = line.find(';');
int start = stoi(line.substr(0, pos));
line = line.substr(pos 1);
pos = line.find(';');
int end = stoi(line.substr(0, pos));
line = line.substr(pos 1);
pos = line.find(';');
string title = line.substr(0, pos);
int publish = stoi(line.substr(pos 1));
music.emplace_back(Collection(name,genre,start,end,title,publish));
}
}
else
{
cout << "Error in opening file" << endl;
}
file.close();
return;
};
void print(vector<Collection> &music)
{
for(int i = 0; i < music.size(); i )
{
cout << "Name: " << music[i].name << endl
<< "Genre: " << music[i].genres << endl
<< "Start Year: " << music[i].startYear << endl
<< "End Year: " << music[i].endYear << endl
<< "Title: " << music[i].records.title << " Year Publiszed: " << music[i].records.yearPub << endl
<< "----------------------------------------------------" << endl << endl;
}
}
int main() {
vector<Collection> music;
readFile(music);
print(music);
}
There are constructors for the structs enabling quick and easy one line creation of the objects. This coupled with vectors' dynamic size and implemented add function emplace back
makes it really easy to add to the list. Now the only thing left is to gather the data from the file. To make it more clear its always best to use a csv (comma seperated value) type file where each line is it's own object/item in your list and each variable is seperated in this instance with a colon. You go through the entire file with the while(getline(file, line))
loop seperating the values from the colons in an easy implemented string function find(character)
which returns you the position of the colons in that single line of text from your file. After you find and seperate your data, make sure your numbers are numbers and strings are string. you can switch string to number via stoi
function (String TO Integer). All your data is stored in music Collection.
The Output: