issue with text file reading and emty space passing in dynamic array - c++

I need help in c++ with reading text from file into dynamic array.
File
Regbis
Vardenis Paverdenis
Jonas Puikuolis
Gediminas Jonaitis
Futbolas
Tadas Pilkius
Justas Julis
Tenisas
Ricerdas Berankis
I tried like this and another way with while and getline s.empty but it didn't work for me.
using namespace std;
struct struktura{
char team;
char lastname;
char firstname;
} sarasas[999];
int main()
{
char x [200];
int kiek;
ifstream duomenys;
duomenys.open("duom.txt");
int row, col;
while (!duomenys.eof())
{
cout << "How many teams" << endl;
cin >> row;
int **a = new int *[row];
for (int i = 0; i < row; i++)
{
cin >> col;
a[i] = new int[col];
}
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
duomenys >> a[i][j];
cout << a[i][j] << " ";
}
cout << endl;
}
}
system("Pause");
return 0;
}

Okay, this has quite a few problems. I'd start with using std::string for the strings, and std::vector for the dynamic array.
Then I'd work at defining the data structures at least halfway reasonably. I think the general idea is something like this:
struct team {
std::string name;
std::vector<std::string> players;
};
Then I'd define an operator>> for a team, something like this:
std::istream &operator>>(std::istream &is, team &t) {
std::vector<std::string> players;
std::string temp;
// If we can't read a team name, return signaling failure:
if (!std::getline(is, temp))
return is;
// save the team name
t.name = temp;
// and read the player's names:
while (std::getline(is, temp)) {
if (temp.empty()) // empty line--end of this team's players
break;
players.push_back(temp);
}
t.players = players; // Write the player's names into the destination
is.clear(); // and signal success, since we read a team's data
return is;
}
From there, we can read all the teams in a file:
std::ifstream in("teams.txt");
std::vector<team> teams { std::istream_iterator<team>{in},
std::istream_iterator<team>{} };

Related

Parse (split) a txt file with a string and int in 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++;
}

Issues moving between files (&syntax), comparing structs, and c-strings

Prompt part 1
prompt part 2
The requirements of this program are in the photos. Please note I can only use the libraries i already have implemented in my code.
I have been trying all day and I know this is very messy and not the best way but I cannot think of any other ways to get what I want. (Please don't be too harsh on me, I am very well aware im not very smart. That's why im asking you)
Here is what I have
#include <iostream>
#include<fstream>
#include <cstring>
using namespace std;
struct Move{
char name[50];
int damage;
};
struct Character{
char name[50];
char char_class[50];
int hitPoints;
int armorClass;
bool isAlive;
char moveName[50];
};
struct Sesh{
char char1[50];
char moveName[50];
char target[50];
int roll;
};
void session( Character c, ofstream& out);
int main() {
Character c;
int M, N, K; //# of moves, # of characters
Character *character;
Move *moves;
Sesh *sesh;
/* To open an input file, that is, a file that contains data we need to
* read into our program, a la cin, we need a variable of type ifstream
*/
ifstream in1, in2;
// The next step is to open the input file using the ifstream variable
in1("character".c_str());
// If, for some reason, we cannot open the file, print an error message
if (!in1) {
cout << "Error opening character.txt" << endl;
} else {
// file was opened successfully.
// We can now use the ifstream variable just like cin, to read from the file
//Read in number of moves
in1 >> M;
//declare the dynamic Move array of size 'M'
moves = new Move[M];
in1.ignore();// to get rid of preceding newline
for (int i = 0; i < M; i++) {
char tab; // a char to read the separator character
getline(in1, moves[i].name, '\t');
in1 >> moves[i].damage; //do i need a \n here
in1 >> '\n';
}
in1 >> N;
character = new Character[N];
in1.ignore();
for (int i = 0; i < N; i++) {
char tab; // a char to read the separator character
getline(in1, character[i].name, '\t');
getline(in1, character[i].char_class, '\t');
in1 >> character[i].hitPoints;
in1 >> tab;
in1 >> character[i].armorClass;
in1 >> tab;
getline(in1, character[i].moveName, '\n');
// isAlive=true;
}
cout << "Inputs read in successfully" << endl;
}
in2("session".c_str());
if (!in2) {
cout << "Error opening session.txt" << endl;
} else {
in2 >> K; //numAttacks
sesh = new Sesh[K];
in2.ignore();
for (k = 0; k < 15; k++) { // k<K keep getting error for infinity loop?
char tab; // a char to read the separator character
getline(in2, character[k].name, '\t');
getline(in2, sesh[k].moveName, '\t');
getline(in2, sesh[k].target, '\t');
in2 >> sesh[k].roll;
in2 >> '\n';
}
for (i = 0; i < 9; i++) {
for (k = 0; k < 15; k++) {
if ((sesh[k].char1 == character[i].name) && (sesh[k].moveName == character[i].moveName)) {
for (int j = 0; j < N; j++) {
if (character[j].name == sesh[k].target) {
if (character[j].armorClass <= sesh[k].roll) {
for (int x = 0; x < M; x++) {
if (moves[x].name == character[i].moveName) {
character[j].hitPoints = character[j].hitPoints - moves[x].damage;
if (character[j].hitPoints < 0) {
character[j].isAlive = false;
}
}
}
}
}
}
}
}
}
ofstream out;
out(alive.c_string);
if (!out)
cout << "error opening MovieOutputs.txt" << endl;
else {
//output file was opened successfully
// We can use the ofstream variable just like cout, to print to the file
for (int i = 0; i < N; i++)
if (character[i].isAlive == 0) { //0 is true?
print(character[i], out); // Use the print function to print
cout << "Wrote to output file";
}
}
// once we are done with the file, we close it.
in1.close();
in2.close();
}
// We're done with the output file. Close it.
out.close();
//delete the dynamic array
delete[] character;
delete[] moves;
delete[] sesh;
// To run programs with files, we need to run using debugging.
// The cin.get() makes the program wait for us to press a key before it terminates.
cin.get();
}
void print(Character c, ofstream &out)
{
// Just use the oftstream variable like cout.
out << c.name << c.hitPoints << endl;
}

Read access violation, error code 0xFFFFFFFFFFFFFFFF

I'm sorry this is a repeat question, but no solutions seem to work for my code.
This is for an assignment in school on reading from a file and copying the data to an array. An exception is thrown every time I try to edit the array "arr" in main.
Here's my code:
#include <iostream>
#include <fstream>
using namespace std;
struct Student {
string name;
float gpa;
int id;
};
void PrintStudents(Student arr[], int nstudents) {
for (int i = 0; i < nstudents; i++) {
cout << "Student name: " << arr[i].name << endl;
cout << "Student GPA: " << arr[i].gpa << endl;
cout << "Student ID: " << arr[i].id << endl;
}
}
int ReadStudents(string fname, Student arr[]) {
ifstream file;
file.open(fname);
int counter = 0;
string name_local;
float gpa_local;
int id_local;
int index = 0;
while (!file.eof()) {
if (counter == 0) {
file >> name_local;
}
else if (counter == 1) {
file >> gpa_local;
}
else if (counter == 2) {
file >> id_local;
}
counter++;
if (counter == 3) {
counter = 0;
Student newStudent = { name_local, gpa_local, id_local };
arr[index] = newStudent;
index++;
}
}
file.close();
return index;
}
void fillStudentArray(Student array[], int array_size) {
Student temp = { "", 0, 0 };
for (int i = 0; i < array_size; i++) {
array[i] = temp;
}
return;
}
int main() {
Student arr[128];
fillStudentArray(arr, 128); // exception thrown here??
cout << "Array filled." << endl;
cout << "Reading students" << endl;
int nstudents = ReadStudents("csci10.hw8.students.txt", arr);
PrintStudents(arr, nstudents);
return 0;
}
Thanks for any help! I'm totally stumped.
Edit: Woah, I left for a 30 minute coffee break and came back to a ton of answers! I'll try to respond to all of them.
Edit 2: Just got a solution! I was working in VS 2019, switched to old school terminal G++ and it worked! Thanks everyone for all the answers :)
You do not check the file was successfully opened. Try this:
ifstream file( fname );
if ( !file )
return -1;
You do not need local variables for reading. Read directly in your array elements:
file >> arr[index].name
ReadStudents ignores the size of the passed array: you might get in trouble if you read more than the allocated size (read this again). You might use std::vector, if allowed. Alternatively, pass the size, too – the same way you did for fill.
The way you are trying to read from file is overly complicated. Try a more c++ approach:
Define an extraction operator for Student:
std::istream& operator>>( std::istream& is, Student& s )
{
return is >> s.name >> s.gpa >> s.id;
}
Use it like you would use it for reading an integer:
file >> arr[ index ]
Alternatively you could use:
is >> arr[ index ].name >> arr[ index ].gpa >> arr[ index ].id
You will get something like this:
int ReadStudents( string fname, Student arr[]/*how large is the array?*/ )
{
ifstream file( fname );
if ( !file )
return -1;
int index = 0;
while ( file >> arr[ index ].name >> arr[ index ].gpa >> arr[ index ].id )
index++;
return index;
}
Explanation
If the stream does not get opened successfull, you get an endless loop. You never check if the reading operations are successfull. If they are not you never reach eof but keep incrementing index and write to array indices out of bounds. Also the counter is superfluos here.
Furthermore I would suggest to use a std::vector instead of an array and use push_back(). This makes sure, you don't write out of bounds.
(Possible) solution
This loop:
while (!file.eof()) {
if (counter == 0) {
file >> name_local;
}
else if (counter == 1) {
file >> gpa_local;
}
else if (counter == 2) {
file >> id_local;
}
counter++;
if (counter == 3) {
counter = 0;
Student newStudent = { name_local, gpa_local, id_local };
arr[index] = newStudent;
index++;
}
}
should be changed (with the function definition) to:
int ReadStudents(string fname, std::vector<Student> &vec)
{
// open stream, etc.
while (file >> name_local >> gpa_local >> id_local) {
Student newStudent = { name_local, gpa_local, id_local };
vec.push_back(newStudent);
}
// cleanup
}
To explain a bit further what the while (file >> name_local >> gpa_local >> id_local) does:
Since std::ifstream::operator>> returns a reference to the stream itself, you can chain those statements together.
The last reference gets implicitly converted to bool (or void* in c++11 or earlier) as seen here. This evaluates true if the last reading operations where successfull (so name_local, gpa_local and id_local now have valid values) and the stream is ready for IO-operations (so it didn't reach eof while reading). This implies that it's also checking if the stream was opened at all.
Once those conditions are met you can create a new element and push it into the vector.

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