Sir Ryan
Sir Ryan

Reputation: 37

C++ Save a Struct String into A Text File

In my program, I save high scores along with a time in minutes and seconds. In my code, I currently store this as two ints in a struct called highscore. However, this is a little tedious when it comes to formatting when I display the output. I want to display the times as 12:02 not 12:2. I have a variable already made called string clock throughout my game, it is already formatted with the colon, all I want to do is add that inside my text file.

How can I refactor my code to have a single variable for the timestamp, which will be correctly formatted? I want to be able to write my data into the file by directly calling the structure.

// Used for Highscores
struct highscore
{
    char name[10]; 
    int zombiesKilled; 

    // I would like these to be a single variable        
    int clockMin;
    int clockSec;

    char Date[10];
}; 

// I write the data like this:
highscore data;
// ...
data[playerScore].clockMin = clockData.minutes;
data[playerScore].clockSec = clockData.seconds;

streaming = fopen( "Highscores.dat", "wb" );
fwrite( data, sizeof(data), 1 , streaming); 
// ...

Upvotes: 1

Views: 4033

Answers (2)

Barmak Shemirani
Barmak Shemirani

Reputation: 31599

You can experiment with time functions. And reading/writing structures.

The right way however is to use c++ basic file storage instead of dumping binar data.

struct highscore
{
    char name[10];
    int n;
    std::time_t dateTime;
};

int main()
{
    int total_seconds = 61;
    char buf[50];
    sprintf(buf, "minutes:seconds=> %02d:%02d", total_seconds / 60, total_seconds % 60);
    cout << buf << endl;

    std::time_t timeNow = std::time(NULL);
    std::tm timeFormat = *std::localtime(&timeNow);
    cout << "Current date/time " << std::put_time(&timeFormat, "%c %Z") << endl;

    highscore data;

    //write data:
    {
        FILE *streaming = fopen("Highscores.dat", "wb");

        strcpy(data.name, "name1");
        data.n = 1;
        data.dateTime = std::time(NULL);
        fwrite(&data, sizeof(data), 1, streaming);

        strcpy(data.name, "name2");
        data.n = 2;
        data.dateTime = std::time(NULL);
        fwrite(&data, sizeof(data), 1, streaming);

        fclose(streaming);
    }

    //read data:
    {
        FILE *streaming = fopen("Highscores.dat", "rb");

        fread(&data, sizeof(data), 1, streaming);
        cout << "reading:\n";
        cout << data.name << endl;
        cout << data.n << endl;
        timeFormat = *std::localtime(&data.dateTime);
        cout << std::put_time(&timeFormat, "%c %Z") << endl;
        cout << endl;

        fread(&data, sizeof(data), 1, streaming);
        cout << "reading:\n";
        cout << data.name << endl;
        cout << data.n << endl;
        timeFormat = *std::localtime(&data.dateTime);
        cout << std::put_time(&timeFormat, "%c %Z") << endl;
        cout << endl;

        fclose(streaming);
    }

    return 0;
}

Upvotes: 1

CinchBlue
CinchBlue

Reputation: 6190

It seems that you want to simply just write a C-string or std::string to a file using C's fwrite() function.

This should be quite easy, given that your C-string is in ASCII-conforming format (no Unicode funny business):

//It appears you want to use C-style file I/O
FILE* file = NULL;
fopen("Highscores.dat", "wb");

//std::string has an internal C-string that you can access
std::string str = "01:00";
fwrite(str.c_str(), sizeof(char), sizeof(str.c_str()), file);
//You can also do this with regular C strings if you know the size.

We can also choose to try and use C++-style file I/O for cleaner interfaces.

#include <iostream>
#include <string>
#include <iomanip>
#include <fstream>

int main() {
    std::string str = "00:11";

    std::ofstream file("example.txt");

    if (file.good()) {
        file << str;
        std::cout << "Wrote line to file example.txt.\n";
    }
    file.close();

    //Let's check if we actually wrote the file.
    std::ifstream read("example.txt");
    std::string buffer;

    if (read.good())
        std::cout << "Opened example.txt.\n";
    while(std::getline(read, buffer)) {
        std::cout << buffer;
    }

    return 0;
}

Additionally, there are data types in <chrono> that can prove quite helpful for times like there.

If you want to be able to do this:

file << data_struct;

then it would make sense for you to create an operator overload for std::ostream.

Upvotes: 2

Related Questions