c++ save and load structures to file - c++

I am currently working on a game project and i am saving a struct with all needed values of a game-object into a file. Saving is completely fine but if i start loading them in it will only load the first 25 of them.
After that i tried with using a while (true) that loads in objects until the last object doesn't get the right type and break out of the loop. This works perfectly fine but is maybe not the most elegant solution to take.
using namespace std;
struct{
const char* type;
int sizeW;
int sizeH;
int collisionLayer;
int textureID;
int positionX;
int positionY;
} loadStruct;
ifstream fileObj;
fileObj.open("level.txt");
if (fileObj.is_open()){
while (!fileObj.eof()){
fileObj.read((char*)&loadStruct, sizeof(loadStruct));
// creating my object out of loadStruct -> working fine
}
fileObj.close();
}
I've tried to remove the check for eof() and simply put a try/catch in the while loop breaking out if error is catched but this idea was not the most elegant and didn't work 100% of the time.

Thanks for "pointing" me to the char* type ... that was seriously the problem causing it to fail. Now i reworked it and also got rid of .eof() and simply check if my type was written or not.
using namespace std;
struct {
char type[20];
int sizeW;
int sizeH;
int collisionLayer;
int textureID;
int positionX;
int positionY;
} loadStruct;
bool reading = true;
ifstream fileObj;
fileObj.open(filename);
if (fileObj.is_open()){
while (reading){
string str = "empty";
strcpy(loadStruct.type, "empty");
fileObj.read((char*)&loadStruct, sizeof(loadStruct));
if (loadStruct.type == str){
reading = false;
break;
}
}
}
fileObj.close();

Related

C++ Arrays and Vectors

I am new to C++ and this is not really part of my major so I am a little lost! If I can contact anyone personally for help please let me know :)
My program will need to read in ten integer values from a file, and store them in an array or vector. The reading of the values should be done in a separate function that takes an integer array as a parameter, and read from a file named tempInput.txt. I am unsure how to create an integer array as a parameter.
Then, from main, you will call another function, whose signature and return type is thus:
bool isDangerous(int tempArray[ ]);
If you could help me with part one or two that would be great!
namespace std;
int divison(int,int);
int main()
{
void readData(int tempArray[ ]);
int tempInput[10];
readData(tempInput);
//int size=10; //Array size
int sum =0;
//for(int i=0;i<size;i++) //Loop which inputs arrays data and
// {
//cout << myArray[i] << endl;
// }
return 0;
}
As best as I can understand the question, here's some code to get you started (Note that I haven't filled in everything exactly, I don't want to do your work for you)
#include<fstream> //So we can read from files
#include<iostream>
using namespace std;
void readData(int tempArray []) {
//Open file and read data into temp array
//If you need help reading data, see:
//http://www.cplusplus.com/doc/tutorial/files/
}
bool isDangerous(int tempArray []) {
//Do things
}
int main() {
int tempInput [10];
readData(tempInput); //Read the data into tempInput
bool result;
result = isDangerous(tempInput); //Do something with isDangerous
return 0;
}

How to initialize this array in a clean way?

I am trying to initialize this array in C++ :
C++
#include<iostream>
using namespace std;
int main(){
int arr[100];
int i = 10;
while(i){
cin >> arr[--i];
}
return 0;
}
This initializes the array perfectly, but it returns a negative status. How can I solve it?
The status code means the program didn't get to the last line of your main() function (where it should be return 0), but got killed instead. I guess you just stopped it with CTRL+C.

C++ program has stopped working

I am making a quite simple program, just a little chat bot AI kind of thing, and I have some code, c++ of course, for the program. I don't get any errors but when I run it a window comes up saying program.exe has stopped working, like it stopped responding. My code is:
#include<iostream>
#include<string.h>
#include<cmath>
#include<vector>
#include<ctime>
#include<conio.h>
#include<algorithm>
#include<cstdlib>
using namespace std;
struct strarray{
char* array[];
};
struct keyword{
string keywords;
string responses[];
};
keyword * dictionary = new keyword[2];
keyword defaultr;
keyword getMatch(string key);
string sconvert(string con);
void init();
string getResp(keyword key);
bool cont=true;
int main(int argc, char* argv[]){
string input;
while(cont){
getline(cin,input);
cout << getResp(getMatch(input));
getch();
getch();
}
}
string sconvert(string con){
con.erase(remove_if(con.begin(), con.end(), ::isspace), con.end());
con.erase(remove_if(con.begin(), con.end(), ::ispunct), con.end());
return con;
}
void init(){
srand(time(NULL));
dictionary[0].keywords="hello";
dictionary[0].responses[0]="Hello, how have you been?";
dictionary[0].responses[1]="Hello, have you missed me?";
dictionary[0].responses[2]="Hey, how's it going?";
defaultr.responses[0]="That's interesting, tell me more.";
defaultr.responses[1]="Please, tell me more.";
}
keyword getMatch(string key){
for(int i=0; i<sizeof(dictionary); i++){
if(key==dictionary[i].keywords){return dictionary[i];}
}
return defaultr;
}
string getResp(keyword key){
return key.responses[rand() % sizeof(key)];
}
When I run it, it opens up normally, but after I input something when it comes up it "stops working". Could somebody please tell me what I need to change, and why would be appreciated.
Is there some pointer problem? Or something with the rand? I'm really confused and would appreciate some advice on how to better this program so it actually works.
sizeof(dictionary) will give sizeof(keyword*), probably 4 or 8, so you will iterate over the end of the dictionary array and terminate.
Easiest fix: Define a constant to store the array length.
const dictionarySize = 2;
and use that throughout.
You also need to change struct keyword to:
struct keyword{
string keywords;
string responses[3];
};
first of all u have an infinite loop so the program should work for ever .. I took a glance at the code and using rand() % sizeof(key) is wrong, the responses is not predetermined so either you set it to a specific value for example
struct keyword {
string keywords;
string responses[2];
};
rand() % sizeof(key.responses)
or you make your structure like this
struct keyword {
string keywords;
vector<string> responses;
};
rand() % key.responses.size()
//After setting the responses by push_back for example
there are other ways but this is safer and no memory management needed ...

C++ Struct defined data passing. Simple answer im sure

I am sure this is a very simple fix and I feel dumb asking it but here it goes.
I need help with a struct and passing info from a gather function to a save or set function, and then passing it again to another function for further use.
Basically, it looks like this to start. I'll just add short snips of the code. All can be provided if you would like to see it.
I right now am just looking for the proper way to pass struct defined data from get.... to set.... functions.
struct printype
{
char dots[8][15];
int unknown15; // can have values of 0..127
string serial11_14; // 8 characters 00000000...99999999
int year8; // without century, 0..99
int month7; // 1..12
int day6; // 1..31
int hour5; // 0..23
int minute2; // 0..59
};
int getunknown15(); // prototypes
int setunknown15(int);
then we have a simple main.
int main()
{
printype pt;
pt.unknown15=getunknown15();
pt.unknown15=setunknown15(12);
pt.serial11_14=getserial11_14();
pt.serial11_14=setserial11_14("12345678");
pt.year8=getyear8();
pt.year8=setyear8(44);
pt.month7=getmonth7();
pt.month7=setmonth7(11);
pt.day6=getday6();
pt.day6=setday6(12);
pt.hour5=gethour5();
pt.hour5=sethour5(12);
pt.minute2=getminute2();
pt.minute2=setminute2(23);
cout <<"-----------------------------------------------------"<<endl;
cout <<" Let's Get Started"<<endl;
cout <<"-----------------------------------------------------"<<endl;
setup(pt.dots); // sets up the array
dpinfo(pt); // prints out the final array
ftarray(pt);
spar(pt.dots);
darray(pt.dots);
}
and finally the get and set array functions.
int getunknown15()
{
printype tem;
cout <<"-----------------------------------------------------"<<endl;
cout <<" Enter the Unkown Variable (0-127): ";
cin >>tem.unknown15;
cout <<"-----------------------------------------------------"<<endl;
return tem.unknown15;
}
next is
int setunknown15(int tem)
{
printype pp;
if (tem>127||tem<0)
{
cout << "Error" << endl;
return 0;
}
else
{
pp.unknown15 = tem;
return pp.unknown15;
}
}
I hope this isn't too much to read and understand
Anyway, I know this has a really simple answer but my brain just isn't working right now.
Edit: As StilesCrisis stated, Send struct as parameter is quiet stupid in this case. better use a const reference.
Well, I am not sure if I understand your question correctly. You can simply send struct to another function as parameter, or as a pointer.
like:
void SetStruct(const printype& var);
printype GetStruct();
Is it what you are looking for?
Please use the following access to the your fields, (by reference):
struct printype *myPtr = new printype;
myPtr->day6 = 43;
When use pointer instead of a normal variable, you should use -> instead . to access your fields.
I know this is kind of old but I thought I should give it a shot, since you are using C++ and it looks like you are trying to use some OO practices (I think), you don't need to start with a struct, even though OO principles can be applied using them as well though not as elegantly.
you can define your class header file as such.
#ifndef PRINTYPE_H
#define PRINTYPE_H
#include <string>
using namespace std;
class printype
{
private: // we always want to declare our member fields private for safety/managements reasons, no one will be able to access them outside.
char dots[8][15];
int unknown15; // can have values of 0..127
string serial11_14; // 8 characters 00000000...99999999
int year8; // without century, 0..99
int month7; // 1..12
int day6; // 1..31
int hour5; // 0..23
int minute2; // 0..59
void init(); // This is the method we use to initialize our starting state.
public: // This is our public methods, how people deal with/get/set our state.
printype(); // This is our default constructor
printype(const printype& print_type); // This our copy constructor
virtual ~printype(); // This is our destructor, its virtual, making safer for inheritance.
// This is our setters/getters
void setUnknown(int unknown);
int getUnknown();
void setYear(int year);
int getYear();
void setMonth(int mont);
int getMonth();
// and well you get the idea, you can add more methods.
};
#endif
and the accompanying class source file with your functions implementation
printype::printype()
{
this->init(); // Initialize all your vatiables, safer to just define a function to this.
}
printype::printype(const printype& orig) // copy constructor
{
this->setUknown(orig.getUnknown());
this->setDay(orig.getDay());
this->setDots(orig.getDots());
// you get the idea ...
}
printype::~printype()
{
// Have anything you need to do before destroying the object.
}
void printype::init()
{
this->setUnknwon(0);
this->setyear(0);
this->setMonth(1);
char dots[8][15] = {'\0'};
this->setDots(dots);
// you get the idea, you want to initialize all your variables since, for the most part they initially hold garbage.
}
void printype::setUnknown(int unknown)
{
if (unknown >= 0 && unknown < 127)
this->unknown15 = unknown;
else
error("Expecting unknown to be between 0 and 127"); // error should probably print the error and/or exit(-1) up to u
}
int printype::setYear(int year)
{
if (year >= 1 && year <= 99)
this->year8 = year;
else
error("Expecting year between 0 and 99"); // you may want to implement an error function!
}
int printype::getYear()
{
return this->year8;
}
void printype::setDots(char dots[8][15])
{
// you may want to do some verifications
memcpy(this->dots, dots, sizeof(dots));
}
void printype::setDots(char **dots) // this is a bit unsafe, use at your own risk.
{
if (dots)
{
unsigned int index = 0;
for (index = 0; index < 8; index++)
if (dots[index])
memcpy(this->dots[index], dots[index], 15);
else
error("dots required pointer ...");
}
else
error("dots required pointer ...");
}
char **getDots() // We will be returning a copy, we don't want the internal state to be affected, from outside, by using reference or pointers.
{
char **dots = new char*[8];
unsigned int index = 0;
for (index = 0; index < 8; index++)
{
dots[index] = new char[15];
memcpy(dots[index], this->dots[index], 15);
}
return dots;
}
// and well you get the idea ...
to use your class
printype *print_type_p = new print_type();
// or
printype pront_type_p();
// use the different public method to update the internal state.
print_type_p->setYear(3);
// or
print_type.setYear(3);
print_type_p->getYear();
// and so on.

C++ binary file with records: string at beginning

I am struggeling with reading from a binary file.
My binary file is made of records in the way like:
string - 5 x integers
The first string has differenct lengths, so I guess this may be my problem?
I try to read a record into a class which has the same type of attributes:
class Team
{
private:
string teamName;
int matchesPlayed;
int gamesWon;
int gamesLost;
int pointsWon;
int pointsLost;
public:
Team(string ="",int = 0,int = 0, int = 0, int = 0, int = 0);
~Team();
//void operator<();
void setTeamName(string);
void setMatchesPlayed(int);
void setGamesWon(int);
void setGamesLost(int);
void setPointsLost(int);
void setPointsWon(int);
void print();
};
I try to read in from another class:
Table::Table()
{
Team t1;
teams.push_back(t1);
ifstream inputFile;
inputFile.open("tabletennis.dta", ios::in | ios::binary);
if(!inputFile)
{
cout << "Datei konnte nicht geoeffnet werden!";
exit(1);
}
if(inputFile.good())
inputFile.read(reinterpret_cast<char*> (&t1), sizeof(Team));
t1.print();
}
Team::print() just prints out the content of its attributes. But the program crashes when I try to print the string.
I don't know what I may understood wrong.. but what I thought was:
Reading in to an Object with the same count and type of attributes is they way how to read a record set:
Team::Team(string teamName, int matchesPlayed, int gamesWon, int gamesLost, int pointsWon, int pointsLost)
{
setTeamName(teamName);
setMatchesPlayed(matchesPlayed);
setGamesWon(gamesWon);
setGamesLost(gamesLost);
setPointsWon(pointsWon);
setPointsLost(pointsLost);
}
Don't know for now..
Yep, if you want to do record-based I/O, then the records must really all have the same length. and record-based I/O is a rare occasion when using an array of char may be a better bet than a std::string. I would change this:
class Team
{
private:
string teamName;
int matchesPlayed;
int gamesWon;
int gamesLost;
int pointsWon;
int pointsLost;
to:
class Team
{
private:
char teamName[NAMESIZE];
int matchesPlayed;
int gamesWon;
int gamesLost;
int pointsWon;
int pointsLost;
You can then read and write:
Team t( .... ); // construct a team
os.write( (const char *) & t, sizeof( t ) );
and read:
Team t; // default construct empty team
is.read( (char *) & t, sizeof( t ) );
Nothing more to add to the answer of Neil but
I would suggest that you take a look at boost serialization.
If your file format is not fixed and you can easily change it, this will really help you to avoid a lot of traps in serialization.