0

For some reason, I can't read a file that contains "string"s with C-style. If I use an array of characters, then I can do it. But I want to do strings and I would like to know how to do it. When I print the b."x attribute" it shows random characters. And yes, I know I should be using c++ files. But this is purely for an educational purpose.

Code:

struct Boleta
{
    string name;
    string surename;
    string legajo //156.455-6;
    int cod_materia;
    string date // 2022/10/26;
};
int main()
{
    Boleta boleta;
    FILE * f = fopen("DIAFINALES.DAT", "wb");
    if(!f)
    {
        cout<<"Error al abrir el archivo 'DIAFINALES.DAT'"<<endl;
        return 1;
    }
    while(true)
    {
        cout<<"Name: ", cin>>boleta.name;
        cout<<"Surname: ", cin>>boleta.surename;
        if(boleta.name == "NULO" && boleta.surename == "NULO")
            break;
        cout<<"Legajo: ", cin>>boleta.legajo;
        cout<<"Exam date: ",cin>>boleta.date;
        fwrite(&boleta, sizeof(boleta), 1, f);
    }
    fclose(f);

    FILE * f1 = fopen("DIAFINALES.DAT", "rb");
    if(!f1)
    {
        cout<<"Error al abrir el archivo 'DIAFINALES.DAT'"<<endl;
        return 1;
    }
    Boleta b;
    while(fread(&b, sizeof(b),1,f1))
    {
        cout<<"************************"<<b.legajo<<"******************************"<<endl;
        cout<<"EXAM DATE: "<<b.date<<endl;
        cout<<"Name and surname: "<<b.name<<" "<<b.surename<<endl;
        cout<<"Code of subject: "<<b.cod_materia<<endl;
    }
    fclose(f1);
    return 0;
} 
  • 2
    Related, but unfortunately none of the answers explains what is wrong with `write(std::string)`: https://stackoverflow.com/questions/10873382/write-and-read-string-to-binary-file-c – Yksisarvinen Mar 30 '22 at 21:46
  • do you intend the file to be a text file (readable and editable with a text editor) or do you intent it to be a binary file. I ask becuase you are writing the file incorrectly, – pm100 Mar 30 '22 at 21:49
  • @pm100 I get your point. But I have to do it with a binary file. Yes, with text file I guess I wouldn't have any problem. – Facundo Borrás Mar 30 '22 at 21:53
  • A `std::string` has a pointer to a buffer. `fwrite(&boleta, sizeof(boleta), 1, f);` is writing a structure that has `std::string` member variables that just writes the *pointers* to the file. That's probably not what is desired. – Eljay Mar 30 '22 at 21:53
  • no you have serious errors with either file type, text file is easier becuase you can easily see if you write the correct data. I will add an answer – pm100 Mar 30 '22 at 21:54
  • `fwrite(&boleta, sizeof(boleta), 1, f);` will basically write a series of pointers. You have to write your own serialisation methods. Google "C++ class serialization" and you'll find pages such as https://isocpp.org/wiki/faq/serialization and https://stackoverflow.com/questions/234724/is-it-possible-to-serialize-and-deserialize-a-class-in-c – Den-Jason Mar 30 '22 at 21:54
  • @Yksisarvinen for what I understand, basically, in order to avoid inconveniences in this case You should use an array of characters and forget about str. Is this correct? – Facundo Borrás Mar 30 '22 at 21:58
  • @Eljay I see, then how could I fix it? Doing fwrite of each specific attribute? Like, write of boleta.name and then fwrite of boleta.surename and so on? – Facundo Borrás Mar 30 '22 at 22:00
  • @FacundoBorrás No, the issue is that `std::string` is a class and not a `char[]`. It only stores pointers to the actual data location. By writing `std::string` directly into a binary file, you write those pointers, and obviously the pointers will be invalid when you read the file later. You need to come up with your own serialization method, so that you can find out where string starts and ends. Or yes, change to `char[]` and it should work (with all the limitations of `char[]` of course). – Yksisarvinen Mar 30 '22 at 22:01
  • 1
    How you fix it depends on if you are trying to create a *text* file, or a *binary* file. – Eljay Mar 30 '22 at 22:01
  • @Yksisarvinen Okey, I don't know what a serialization method is but I'm going to investigate rn. And also, very clear what a string is. Thanks. – Facundo Borrás Mar 30 '22 at 22:05

1 Answers1

0

You try to write 'boleta'

struct Boleta
{
    string name;
    string surename;
    string legajo //156.455-6;
    int cod_materia;
    string date // 2022/10/26;
};

to a file like this

 fwrite(&boleta, sizeof(boleta), 1, f);

this will not work. std::string is a pointer to the actual string data, the actual string is not stored in the struct.

So first you need to decide on the format of your binary file. What does each record in it look like. I suggest you have fixed size strings and the the cod_materia as 4 byte int on the end

 name........surname........legajo......dat.......cod-
 20          20             10(?)       10        4

To write this there are several ways

I would do

struct Bol_iobuf{
    char name[20];
    char surname[20];
    char legato[10];
    char date[10];
    int cod_materia;
}

now you need to marshal a belato struct into this struct

 Bolato b; // loaded with data
 Bol_iobuff buff;
 strcpy(buff.name,b.name.c_str());
 strcpy(buff.surname,b.surname.c_str());
 strcpy(buff.legato,b.lagato.c_str());
 strcpy(buff.date,b.date.c_str());
 buff.cod_materia= b.cod_materia;

now buff has all the bytes for one row and you can write it

  fwrite(&buff, sizeof(Bol_iobuff), 1, f);

reading is the same, but in revers, read into Bol_iobuff then marshall that fields by fields into a Boleta instance

NOte that I have not checked in the marshal for write code that the strings are not too large to fit in their target char arrays (20 and 10 bytes). You could use strncpy to truncate them, or you can have guard code in your input functions to ensure you never have names too long

pm100
  • 48,078
  • 23
  • 82
  • 145