2

I was trying to call a member of class a from class b but was unsuccessful it works but always gives garbage value for the vector in class a and yes the exception is thrown on the third time while the read loop is only supposed to run only 2 times.

b.h

 #pragma once
#include <iostream>
#include <fstream>
#include <vector>
#include <string> 
#include <iomanip>
#include "a.h"

using namespace std;

class b {
    fstream fio;
    string s;
    a aio;
public:
    b(string);
    b( b& );
    void all(string);
    void out();
    void reset();
    ~b();
};

b.cpp

#include "b.h"

b::b(string in)
    :fio{ "see.bin",ios::in | ios::out | ios::binary | ios::app }, s{ in }
{
}

b::b( b& bi ) 
    : fio{ "see.bin",ios::in | ios::out | ios::binary | ios::app }, s{ bi.s }
{   
}

void b::all(string in) {
    s = in;
    reset();
    aio.set_n( s );             //n is a string in a class
    aio.set_s( 11 );             // s is a size_t object in a class
    aio.set_v( 114 );            // v is the vector in a class
    fio.write( ( char* )&aio, sizeof( aio ) );
    reset();
}

void b::out() {
    reset();
        while (fio.read( ( char* )&aio, sizeof( aio )  //read function gone rouge 
            aio.print();
}

void b::reset() {
    fio.clear();
    fio.seekg( 0, ios_base::beg );
}

b::~b() {
    fio.close();
}

main.cpp

#include "b.h"


int main() {
    b obj_1( "" );
    obj_1.all( "xyz" );
    obj_1.out();

}

a.cpp

#include "a.h"

a::a()
    :s{ 0 }
{
}

a::a( a& ai )
    : s{ ai.s }, n{ ai.n }
{
    for (auto c : ai.v)
        v.push_back( c );
}

a::a( a&& ai ) noexcept
    :s{ ai.s }, n{ ai.n }
{
    for (auto c : ai.v)
        v.push_back( c );
    ai.v.clear();
}

void a::set_v( int i ) {v.push_back( i );}

void a::set_s( size_t si ) {    s = si;}

void a::set_n( string na ) {n = na;}


void a::print(){
    cout << s << " " << n << " ";
    for (int &p : v)
        cout << " " << p;
}

a::~a() {v.clear();}

for reference a is a class having a copy constructor, move constructor ,normal constructor ,all the setters for each object and an destructor. Thank you for helping me and reading my badly written code.

Amit kh
  • 59
  • 1
  • 9
  • 3
    Where is the definition of `a`? Please make a [minimal reproducible example](https://stackoverflow.com/help/minimal-reproducible-example). – cigien May 16 '20 at 15:26
  • i'll try my best to keep it as short as possible i added definition of a if necessary and please tell me if you need .h file as well – Amit kh May 16 '20 at 17:59

1 Answers1

1

Non-POD types cannot be directly written or read. For example, the std::string class. The string class has some member data, but commonly, the string content is elsewhere (like in dynamic memory).

I would suggest define the << and >> operator for your class to serialize and un-serialize.

The Boost::serialization library handles this rather elegantly. I've used it in several projects. There's an example program, showing how to use it, here.

The only native way to do it is to use streams. That's essentially all the Boost::serialization library does, it extends the stream method by setting up a framework to write objects to a text-like format and read them from the same format.

For built-in types, or your own types with operator<< and operator>> properly defined, that's fairly simple; see the C++ FAQ for more information.

See also Qt serialization and protobuf

**EDIT: **

Try this but this is not portable and it doesn't handle all of the corner cases.

#include <iostream>
#include <string>
#include <vector>

#include <fstream>

class Bin {

public:
    void set_size(size_t s)                 { size_ = s; }
    void set_str(const std::string& s)      { str_ = s; }
    void append_int(int s)                  { vec_.emplace_back(s); }

public:
    size_t get_size(void) const             { return size_; }
    std::string get_str(void) const         { return str_; }
    std::vector<int> get_vec(void) const    { return vec_; }

public:
    void print(void) const
    {
        std::cout << "---- A ----" << std::endl;
        std::cout << "Size: " << size_ << std::endl;
        std::cout << "Str: " << str_ << std::endl;
        std::cout << "Vec: ";
        for (const auto& i: vec_)
            std::cout << i << " ";
        std::cout << std::endl;
        std::cout << "-----------" << std::endl;
    }

public:
    friend std::ofstream& operator<<(std::ofstream& fstream, const Bin& obj)
    {
        size_t str_size = obj.str_.length();
        size_t vec_size = obj.vec_.size();
        fstream.write(reinterpret_cast<const char *>(&obj.size_), sizeof(obj.size_));
        fstream.write(reinterpret_cast<const char *>(&str_size), sizeof(str_size));
        for (const auto& i: obj.str_)
            fstream.write(reinterpret_cast<const char *>(&i), sizeof(i));
        fstream.write(reinterpret_cast<const char *>(&vec_size), sizeof(vec_size));
        for (const auto& i: obj.vec_)
            fstream.write(reinterpret_cast<const char *>(&i), sizeof(i));
        return fstream;
    }

public:
    friend std::ifstream& operator>>(std::ifstream& fstream, Bin& obj)
    {
        obj.str_.clear();
        obj.vec_.clear();
        size_t size = 0;

        fstream.read(reinterpret_cast<char *>(&obj.size_), sizeof(obj.size_));
        fstream.read(reinterpret_cast<char *>(&size), sizeof(size));
        for (size_t i = 0; i < size; i++)
        {
            char c;
            fstream.read(&c, sizeof(c));
            obj.str_.push_back(c);
        }
        fstream.read(reinterpret_cast<char *>(&size), sizeof(size));
        for (size_t i = 0; i < size; i++)
        {
            int j;
            fstream.read(reinterpret_cast<char *>(&j), sizeof(j));
            obj.vec_.emplace_back(j);
        }
        return fstream;
    }

private:
    size_t size_;
    std::string str_;
    std::vector<int> vec_;
};

int main(void)
{
    Bin a, b;
    a.set_size(100);
    a.set_str("stackoverflow");
    for (int i = 0; i < 10; i++)
        a.append_int(i + 1);
    a.print();
    {
        std::ofstream ostream("see.bin", std::ios::out | std::ios::binary);
        ostream << a;
    }

    std::ifstream istream("see.bin", std::ios::in | std::ios::binary);
    istream >> b;
    b.print();
    return 0;
}
abhiarora
  • 9,743
  • 5
  • 32
  • 57
  • thank you for helping, since I am using binary file should I use operator overloading or just the read and write function? – Amit kh May 16 '20 at 18:33
  • hey I tried using the read method in the overloaded operator and it worked but the only issue with that was it gave an error whenever the destructor of a was called. Can you please tell why because I don't want to use serialization yet, anyways thanks for the help.(edit: it is probably due to the deletion of the string in a)(void _Container_base12::_Orphan_all() // this function gives an exception in xmemory) – Amit kh May 17 '20 at 06:33
  • See an example in my answer. – abhiarora May 17 '20 at 08:10
  • 1
    thanks a lot to all it worked. i used operator overloading on >> and << operator with custom input i was able to input the vector and string in file then get it back thanks a lot for helping me. – Amit kh May 17 '20 at 12:47