garbage value after calling a member function of a class

Viewed 264

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.

1 Answers

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