Parse (split) a txt file with a string and int in c++ - c++

im a Student and new to this site. I want to split my txt file with my highscore data back to my Highscore List.
The txt file stores my Highscore like name:score
My parsing is not working and i dont know why?
I just want to split it to name and score again and then put it in my HighscoreList.
If you have any question about the code just ask :)
#include "highscore.h"
highscore::highscore(){
}
struct highscore::Player{
string spielerName;
int score;
};
void highscore::writeHighscore(string name, int score ,int playerNumberx){
Player HighscoreListe[100];
for(int i=0;i<=99;i++){
HighscoreListe[i].score = {0};
}
for(int i=0;i<=99;i++){
HighscoreListe[i].spielerName = "leer";
}
HighscoreListe[playerNumberx].spielerName = name;
HighscoreListe[playerNumberx].score = score;
int i, j,temp;
string temp1;
ifstream myfile("scores.txt");
string line;
//heres the point where i need help!!
if (myfile.is_open()){
int z=0;
while(getline(myfile, line)){
string name1;
string score1;
int d = 20;
while(line[z] != ':'){
name1 += line[z];
z++;
}
z = z+2;
while(line[z] != '\0'){
score1 += line[z];
z++;
}
HighscoreListe[d].spielerName = name;
HighscoreListe[d].score = score;
d++;
}
myfile.close();
}else cout << "Unable to open file" << endl;
for(i = 0; i<100; i++) {
for(j = i+1; j<100; j++)
{
if(HighscoreListe[j].score < HighscoreListe[i].score) {
temp = HighscoreListe[i].score;
temp1 = HighscoreListe[i].spielerName;
HighscoreListe[i].score = HighscoreListe[j].score;
HighscoreListe[i].spielerName = HighscoreListe[j].spielerName;
HighscoreListe[j].score = temp;
HighscoreListe[j].spielerName = temp1;
}
}
}
ofstream myfilex("scores.txt");
if (myfilex.is_open()){
for(int i = 99;i>89;i--){
myfilex << HighscoreListe[i].spielerName << ":" << HighscoreListe[i].score<<endl;
}
myfilex.close();
}
else cout << "Unable to open file" << endl;
}
void highscore::readHighscore(){
string line;
ifstream myfile("scores.txt");
if (myfile.is_open()){
while(getline(myfile, line)){
cout << line << endl;
}
}
else cout << "Unable to open file" << endl;
}

Make a >> overload for highscore::Player.
In the >> overload
Use std::getline to read a line from the input stream.
Create a std::istringstream out of the line.
Use std::getline to read up to the : from the istringstream into a local string name;.
Use another std::getline to read the rest of the line into a string.
Convert the string into an int with std::stoi and store into a local int score;. Make sure you provide a pos argument.
Ensure that the entire string was converted by comparting the pos argument with the string's length.
If nothing went wrong, store name and score into the highscore::Player passed by the caller. Otherwise, set the failbit on the input stream with setstate
return the input stream.
Now the reading code should be something simple like
int scorecount = 0;
while (myfile >> HighscoreListe[scorecount])
{
scorecount++;
}

Related

How to read a file line by line and separate the lines components?

I am new to C++ (I usually use Java) and am trying to make a k-ary heap. I want to insert values from a file into the heap; however, I am at a loss with the code for the things I want to do.
I wanted to use .nextLine and .hasNextLine like I would in Java with a scanner, but I am not sure those are applicable to C++. Also, in the file the items are listed as such: "IN 890", "IN 9228", "EX", "IN 847", etc. The "IN" portion tells me to insert and the "EX" portion is for my extract_min. I don't know how to separate the string and integer in C++ so I can insert just the number though.
int main(){
BinaryMinHeap h;
string str ("IN");
string str ("EX");
int sum = 0;
int x;
ifstream inFile;
inFile.open("test.txt");
if (!inFile) {
cout << "Unable to open file";
exit(1); // terminate with error
}
while (inFile >> x) {
sum = sum + x;
if(str.find(nextLin) == true //if "IN" is in line)
{
h.insertKey(nextLin); //insert the number
}
else //if "EX" is in line perform extract min
}
inFile.close();
cout << "Sum = " << sum << endl;
}
The result should just add the number into the heap or extract the min.
Look at the various std::istream implementations - std::ifstream, std::istringstream, etc. You can call std::getline() in a loop to read a std::ifstream line by line, using std::istringstream to parse each line. For example:
int main() {
BinaryMinHeap h;
string line, item;
int x sum = 0;
ifstream inFile;
inFile.open("test.txt");
if (!inFile) {
cout << "Unable to open file";
return 1; // terminate with error
}
while (getline(inFile, line)) {
istringstream iss(line);
iss >> item;
if (item == "IN") {
iss >> x;
sum += x;
h.insertKey(x);
}
else if (item == "EX") {
// perform extract min
}
}
inFile.close();
cout << "Sum = " << sum << endl;
return 0;
}

Trouble with pointers and reading information into an array

I'm having some issues when trying to read in some values to a dynamically allocated array. Everything looks okay to me, but when the code is run, only the last entry into the array is shown. The code is below. If you could give me some recommendations I would appreciate it.
ifstream infile;
infile.open("MovieStatistics.txt");
int numOfStudents = 0;
string first, last, line;
int movies;
int *numMovies = nullptr;
string *names = nullptr;
if (!infile) {
cout << "Error opening file";
} else {
while (getline(infile, line)) {
numOfStudents++;
stringstream ss(line);
ss >> first >> last >> movies;
}
numMovies = new int[numOfStudents];
names = new string[numOfStudents];
}
for (int i = 0; i < numOfStudents; i++) {
names[i] = first + " " + last;
numMovies[i] = movies;
}
Your problem is you assign first and last inside the read loop but you don't store the values in an array or vector so they contain the last values.
To get it to work you could edit the code to:
ifstream infile;
infile.open("data.txt");
int numOfStudents = 0;
string first, last, line;
int movies;
int *numMovies = nullptr;
string *names = nullptr;
// get the number of students
while (getline(infile, line))
numOfStudents++;
numMovies = new int[numOfStudents];
names = new string[numOfStudents];
// clear the buffer
infile.clear();
infile.seekg(0, ios::beg);
int i = 0;
while(getline(infile, line)){
stringstream ss(line);
ss >> first >> last >> movies;
names[i] = first + " " + last;
numMovies[i] = movies;
++i;
}
for(int i = 0; i < numOfStudents; i++)
cout << names[i] << endl;
// don't forget to free memory:
delete[] movies;
delete[] names;
infile.close();
What I recommend is to use class vector:
std::ifstream infile("data.txt");
std::string sLine;
std::vector<std::string> vecNames;
while(getline(infile, sLine))
vecNames.push_back(sLine);
auto size = vecNames.size();
//for(auto x : vecNames)
// std::cout << x << std::endl;
for(int i(0); i != size; ++i)
std::cout << vecNames[i] << std::endl;
infile.close();
So you loop over the file, repeatedly reading data into first, last and movies — overwriting the previous values each time.
Much later, you take the current value of those variables, and write it to your dynamic arrays numOfStudents times.
You probably want to rewind the stream and loop over the file again so that you can pull out all the data; you never actually stored each sample the first time around.

C++ filling array of structure from file

Hi I need to read a file and get data from file to array of structure.
Structure
struct Activity {
string ID;
string Name;
string quantity; };
I have this function for reading from file
int* fillStructure(ifstream &fileActivity){
int i=0;
int numberOfElements = numberOfLines(fileActivity);
Activity* myActivity = new Activity[numberOfElements];
while (i < numberOfElements)
{
getline(fileActivity, myAktivity[i].ID, ',');
getline(fileActivity, myActivity[i].Name, ',');
getline(fileActivity, myActivity[i].quantity, '\n');
i++;
}
fileActivity.close();
return myActivity; }
And when i try in main function to print members of structures It doesnt work
int main(){
if (!(fileActivity.is_open())){
cout << "Error when reading file" << endl;
return 0;
}
fillStructure(fileActivity);
cout << myActivity[1].ID << endl; return 0; }
I am beginner, can you guys help me what I am doing wrong ?
You declared myActivity in void fillStructure(ifstream &fileActivity), but trying to access from int main().
You have to declare your return value in the main function.
struct Activity {
string ID;
string Name;
string quantitiy;
};
Activity* fillStructure(ifstream &fileActivity) {
int i = 0;
int numberOfElements = numberOfLines(fileActivity);
Activity* myActivity = new Activity[numberOfElements];
while (i < numberOfElements)
{
getline(fileActivity, myActivity[i].ID, ',');
getline(fileActivity, myActivity[i].Name, ',');
getline(fileActivity, myActivity[i].quantitiy, '\n');
i++;
}
fileActivity.close();
return myActivity;
}
int main(){
ifstream fileActivity ("test.txt", ifstream::in);
Activity* retFile;
retFile = fillStructure(fileActivity);
cout << retFile[1].ID << endl;
return 0;
}
Declare the return Type of the fillStructure function in the main function like this:
Activity* retFile;
This codesnippet works for me

std::ifstream data type?

The variable "read" in this program needs to be passed through a function and i don't know what data type it is. I have used http://www.cplusplus.com/reference/fstream/ifstream/ifstream/
and http://www.cplusplus.com/reference/fstream/ifstream/ but I'm struggling to find anything, is this just not possible?
int main()
{
string line = " ", ans = " ", ans2 = " ", data = " ";
int i = 0, j = 0;
cout << "What file do you want to read? : ";
cin >> ans;
cout << "What do you want the new file to be called? : ";
cin >> ans2;
ifstream read(ans.c_str());
for (i = 0; !read.eof(); i++)
{
read_function(line, read);
write_function(line, ans2);
}
return 0;
}
string read_function(string line, string read)
{
getline(read, line, ' ');
cout << line;
}
void write_function(string line, string ans2)
{
ofstream write(ans2.c_str(), ios::app);
write << line;
write.close();
}
You have ifstream read but a function
string read_function(string line, string read)
// ^------
If you change the function to
string read_function(string line, ifstream & read)
// ^------
the read_function then expects a stream as the second parameter, not a string.
You will have a similar problem with the next function.
The comments point out other problems.
If you get an error about types, sit back and look at what you are passing to functions and what they expect.

incorrect stof() declaration

I'm reading in values from a text file and printing the to screen as strings. The idea is to read in each individual string and print them to screen along with the running average of strings read in printed next to it.
i have this for my string to float declaration
int main()
{
string inputfile, intstring;
float counter;
counter = 0;
float average;
average = 0;
float stringconv = stof(intstring);
cout << "Enter the name of a file to open\n";
cin >> inputfile;
ifstream inFile;
inFile.open(inputfile.c_str());
and later on to calculate the average
while (!inFile.eof())
{
getline(inFile, intstring, ' ');
cout << intstring <<","<<average<< endl;
//increments counter to keep average output correct
counter = counter +1;
//goes to next line at each space encountered in text file
average = (counter + stringconv) /2;
}
I've included this just in case my issue lies there. Can anyone tell me how to properly declare my conversion?
and here is a full version which compiles
#include <math.h>
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
int main()
{
string inputfile, intstring;
float counter;
counter = 0;
float average;
average = 0;
float dividor;
dividor = 1;
cout << "Enter the name of a file to open\n";
cin >> inputfile;
ifstream inFile;
inFile.open(inputfile.c_str());
if (!inFile)
{
cout << "Error opening file " << inputfile << endl;
char stopchar;
cin >> stopchar;
return -1;
}
while (!inFile.eof())
{
//goes to next line at each space encountered in text file
getline(inFile, intstring, ' ');
cout << intstring <<","<<average<< endl;
float stringconv;
stringconv = stof(intstring);
average = (counter + stringconv)/dividor ;
dividor = dividor +1;
//increments counter to keep average output correct
}
inFile.close();
char stopchar;
cin >> stopchar;
}
Here:
string inputfile, intstring;
...
float stringconv = stof(intstring);
You can't do that. I mean, you can, but it doesn't do what you think it does. You think you're creating a macro or function or something, so that you can change intstring and then stringconv will automatically change. But what you're actually doing is converting the uninitialized string into an integer once, and never changing it again. You must do the conversion inside the read loop.
EDIT: If you're not required to use stof(), then you can save yourself a lot of headaches by using the stream input operator:
float number;
inFile >> number; // this is the basic form
while(inFile >> number) // this is how to do it as a loop
...
In C++, float stringconv = stof(intstring); won't meen automatic conversion like assign in Verilog.
Call stof() each time you need to convert.
Try this:
while (!inFile.eof())
{
getline(inFile, intstring, ' ');
cout << intstring <<","<<average<< endl;
//increments counter to keep average output correct
counter = counter +1;
//goes to next line at each space encountered in text file
stringconv = stof(intstring); // add this here
average = (counter + stringconv) /2;
}