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

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;
}

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++;
}

Input from txt file doesn't match when it is read/passed second time (C++)

So I am fairly new to coding and c++. So...sorry if this is something very obvious to some of you:
I am having a hard time getting this code to read the input stored in txt file for a second time. It works for the first time.
void readcode(ifstream& infile, int list[], int& length, bool& lenCodeOk)
{
int count;
lenCodeOk = true;
infile >> length; //get the length of the secret code
cout << "Length1 is "<<length<<endl;
if (length > MAX_CODE_SIZE)
{
lenCodeOk = false;
return;
}
//Get the secret code.
for (count = 0; count < length; count++)
{
infile >> list[count];
}
cout<<" Code recorded is: ";
for (count = 0; count < length; count++)
{
cout<<list[count]<<" "<<endl;
}
}
So the first integer in my txt file is the length of the sequence of integers. This function does everything it is supposed to. Reads the length correctly also stores everything in an array.
However when I call the below compareCode function after calling the readcode function, it comes out with a completely random/different length2 (that changes/goes one up everytime I call) and array elements.
void compareCode(ifstream& infile, ofstream& outfile, const int list[], int length)
{
int length2;
int digit;
bool codeOk;
int count;
codeOk = true;
infile >> length2;
cout<<"Length2 is "<<length<<endl;
if(length != length)
{
cout<< "The original code and its copy are not of the same length"<<endl;
return;
}
outfile << "Code Digit Code Digit Copy"<<endl;
for (count= 0; count<length; count++)
{
infile >> digit;
outfile<<setw(5)<<list[count]<<setw(17)<<digit;
if (digit != list[count])
{
outfile << " Code digits are not the same"<<endl;
codeOk = false;
}
else
{
outfile<<endl;
}
if (codeOk)
{
outfile<<"Message transmitted OK."<<endl;
}
else
{
outfile<<"Error in transmission. "<<"Retransmit!!"<<endl;
}
}
}
It seems like I am missing an important piece of information about passing fstream variables I would really appreciate if someone pointed me towards the right direction.
int main()
{
int codeArray[MAX_CODE_SIZE];//Array to store the secret code
int codeLength;// Variable to store the length of the code
int codeLength2;
bool lengthCodeOk;//Variable to indicate if the legth of the secret code is less than or equal to 250
ifstream incode;// Declare ifstream variable
ofstream outcode;//Declare ofstream variable
char inputFile[51];//Variable to store the name of the input file
char outputFile[51]; //Variable to store the name of the output file
cout<<"Enter the input file name: "<<endl;
cin>> inputFile;//makesure it is one word because ci.>>skips white space
cout<<endl;
incode.open(inputFile);
if(!incode)
{
cout<< "Cannot open the input file."<<endl;
return 1;
}
cout<< "Enter the output file name: " ;
cin>> outputFile;//Same deal, one word so cin>> can read
cout<<endl;
outcode.open(outputFile);
readcode(incode,codeArray,codeLength,lengthCodeOk);
if (lengthCodeOk)
{
compareCode(incode,outcode,codeArray,codeLength);
}
else
{
cout<<"Length of the secret code must be <= "<<MAX_CODE_SIZE<<endl;
}
incode.close();
outcode.close();
return 0;
}
this should go like this:
istream& readcode(istream& infile, std::vector<int>& list)
{
int length;
if (infile >> length) {
list.reserve(length);
for (int count = 0; count < length; count++)
{
int x;
if (infile >> x)
{
list.push_back(x);
} else {
break;
}
}
}
return infile;
}
ifstream file("somefile.txt");
if (file.good())
{
std::vector<int> a, b;
if (readcode(file, a).good())
{
file.seekg(0);
if (readcode(file, b).good())
{
cout << (a!=b? "code reading are different" : "code reading are same") << endl;
}
else
{
cerr << "failed read again code" << endl;
}
}
else
{
cerr << "failed read code" << endl;
}
}

Creating array after getting variable in other function

A text file looks like this:
3
String
String2
String3
I must create a function to read all the strings from text file, save them to array and then display it in main function. For example
void reading(int & count, string strings[]) {
ifstream fd "text.txt";
fd >> count;
for (int i=0; i<count; i++)
fd >> strings[i];
fd.close();
And main function:
int main() {
int count=0;
string strings[100];
reading(count, strings);
for (int i=0; i<count; i++)
cout << strings[i] << endl;
The number of strings is written in first line of text file. How can I create an array of exactly that number? I need it to be able to access it in main/other functions. (For example function for writing into another text file).
In case there is a super important reason to do that with an array, then use std::new, like this:
#include <iostream>
#include <string>
#include <vector>
#include <fstream>
using namespace std;
int reading(string** str_array, int& size, string filename) {
ifstream infile(filename.c_str());
if(!infile) {
cerr << "Unable to access file!\n";
return -1;
}
int n = 0;
infile >> size;
try{
*str_array = new string[size];
string str;
for (; n < size && infile; ++n) {
infile >> str;
(*str_array)[n] = str;
}
if (n != size)
cerr << "ERROR, read less than " << size << " strings!!\n\n";
} catch(bad_alloc& exc) {
return -2;
}
return 0;
}
int main() {
string* str_array = NULL;
int size;
if(reading(&str_array, size, "test.txt")) {
cerr << "Din't read file, exiting...\n";
return -1;
}
for(int i = 0; i < size; ++i)
cout << str_array[i] << endl;
delete [] str_array; // DO NOT FORGET TO FREE YOUR MEMORY
str_array = NULL;
return 0;
}
Output:
C02QT2UBFVH6-lm:~ gsamaras$ ./a.out
String
String2
String3
However, you are in c++ and you are not using an std::vector for this?
Look how simple it is with that:
#include <iostream>
#include <vector>
#include <fstream>
using namespace std;
int reading(vector<string>& v, string filename) {
ifstream infile(filename.c_str());
if(!infile) {
cerr << "Unable to access file!\n";
return -1;
}
int N = -1, n = 0;
infile >> N;
string str;
for (; n < N && infile; ++n) {
infile >> str;
v.push_back(str);
}
if (n != N)
cerr << "ERROR, read less than " << N << " strings!!\n\n";
return 0;
}
int main() {
vector<string> v;
if(reading(v, "test.txt")) {
cerr << "Din't read file, exiting...\n";
return -1;
}
for(size_t i = 0; i < v.size(); ++i)
cout << v[i] << "\n";
return 0;
}
Output:
C02QT2UBFVH6-lm:~ gsamaras$ ./a.out
String
String2
String3
Edit:
We have to pass a pointer to what we want to modify (that is, the string*), otherwise the changes we apply won't take place. Test it yourself, pass a string* as a parameter instead of string**, modify the body of the function and she what happens.
To get the idea, imagine we want to write to the pointer, the new address, which new gave us and holds the memory requested. We do write that address inside the function, but when the function terminates, we want the changes to be persistent. See my Functions in C as an example.
Allocate an array on the heap, like this:
std::string* stringArr = new std::string[(place amout of strings here)];
and don't forget to delete it at the end of main()
delete stringArr[];
Variables / arrays on the heap are dynamic so the size doesn't have to be fixed!
std::string* → This is a pointer that points to the address of the beginning of this array in your memory. (Just to let your computer know where it is)
stringArr → the name of the array
new → allocates new memory
std::string[size] → says how much to allocate
I've seen some answers that were talking about "vectors". If you wanna use them you could have a look at this page for more info! →
Vector documentation
use a vector
#include <vector>
#include<fstream>
#include <iostream>
using namespace std;
void reading(int & count, vector<string> * strings) {
ifstream fd("text.txt");
fd >> count;
string T;
for (int i=0; i<count; i++)
{
fd >> T;
strings->push_back(T);
}
fd.close();
}
int main() {
int count=0;
vector<string> strings;
reading(count, &strings);
for (int i=0; i<count; i++)
cout << strings[i] << endl;
}

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

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>{} };

C++ , read line by line and search a keyword that links to a line in a file

I've been working for days now on a machine simulator that reads instructions from a file. Just started working with C++ and im studying on vectors and parsing.
A sample file looks like this :
label0: left
right
if <1> goto label1
write 0
goto label2
label1: right
write 1
label2: halt
my code for the tape looks like this :
int main() {
int total_lines=0;
int RWH=0;
// Create a vector of strings
std::vector<string> Instruction;
// Create a string variable to hold each line read from the file.
string InstLine;
// Read through file and push onto our vector
vector<char> TapeVector; //declare tape
char temp;
cin >> noskipws;
cout << "Enter the input (end with ~):"; //initialize tape
while (cin >> temp && temp != '~') {
TapeVector.push_back(temp);
}
cout << "INPUT:";
for (int i=0;i<TapeVector.size();++i)
{
cout << TapeVector[i];
}
cout << endl;
// Open our file
ifstream InFile("input.txt",ifstream::in);
// If we can read/write great
if (InFile.good())
{
{
while(std::getline(InFile, InstLine))
Instruction.push_back(InstLine);
++total_lines;
}
}
else
cout << "Error reading file";
and here is for the parsing which I'm having problems:
while (std::getline(infile, line))
std::istringstream iss(line);
string a, b, c, d;
if (iss >> a >> b >> c >> d) //if 4 parameters
{
if (a=="if" && b==VectorTape[RWH])
{
counter=0; // counter will reset if b
}
;
}
else if (iss >> a >> b >> ) //if 2 parameters
{
if (a=="goto" //unfinished
}
else if (iss >> a >> b) //if 2 parameters
{
if (a=="goto" //unfinished
}
else if (iss >> a) //if 1 parameter
{
}
enter code here
on line 3 if label1 is detected, how do I jump and read the line with the label label1?
#include <iostream>
#include <fstream>
#include <map>
#include <string>
#include <vector>
#include <cstdlib>
#include "label.h"
using namespace std;
int main() {
int RWH=0;
std::vector<string> Instruction;
int total_lines=0;
vector<char> TapeVector; //declare tape
char temp;
cin >> noskipws;
cout << "Enter the input (end with ~):"; //initialize tape
while (cin >> temp && temp != '~')
{
TapeVector.push_back(temp);
}
cout << "INPUT:";
for (int j=0;j<TapeVector.size();++j)
{
cout << TapeVector[j];
}
cout << endl;
// Open our file
ifstream InFile("input.txt",ifstream::in);
// If we can read/write great
if (InFile.good())
{
{
string InstLine;
// Read through file and push onto our vector
while(std::getline(InFile, InstLine))
Instruction.push_back(InstLine);
++total_lines;
}
}
else
cout << "Error reading file";
vector<string> labels;
labels = lookupLabels(Instruction);
size_t i = 0;
while (i < Instruction.size())
{
istringstream iss(Instruction[i]);
// ...
string a,b,c,d;
iss >> a >> b >> c >> d;
if (a == "if")
{
if (b == TapeVector[RWH])
{
i = labels[d];
continue;
}
else
;
}
else if (a == "goto")
{
i=labels[b];
continue;
}
else if (a == "write")
{
b = TapeVector[RWH];
}
else if (a == "right")
{
++RWH;
}
else if (a == "left")
{
--RWH;
}
else if (a == "halt")
{
goto end;
}
else
{
continue;
}
++i;
} //end while
end:
for (int k=0;k<TapeVector.size();++k)
{
cout << TapeVector[k];
}
cout << endl;
InFile.close();
system("Pause");
return 0;
}
this is what i've done so far.. but there are plenty of errors i dont seem to understand.
51 C:\Users\JHONIN\Documents\THISIS\readtest 2.cpp no match for 'operator=' in 'labels = lookupLabels(const std::vector<std::string, std::allocator<std::string> >&)()'
55 C:\Users\JHONIN\Documents\THISIS\readtest 2.cpp variable `std::istringstream iss' has initializer but incomplete type
You cannot just jump forward in input file to unknown location.
You need to read entire program, store it in memory in a datastructure, at least annotated with labels, then jump within that structure, e.g.:
typedef map<string, size_t> Labels; // map label -> position in Instructions vector;
Labels lookupLabels(const vector<string>& instr) {
Labels ret;
for (size_t i = 0; i < instr.size(); ++i) {
const string& s = instr[i];
size_t colonpos = s.find(':');
if (colonpos != string::npos)
ret[s.substr(0, colonpos)] = i;
}
return ret;
}
now you can modify you "parsing with problems" in the same way - i.e. loop over lines in instructions vector, not in file. Once you hit a goto just pick another line number in labels and proceed with it, roughly like this
labels = lookupLabels(Instruction)
size_t i = 0;
while (i < Instruction.size()) {
istringstream iss(Instruction[i]);
// ...
iss >> a;
if (a == "goto") {
string label;
iss >> label;
i = labels[label];
continue;
}
++i;
}