Search code examples
c++operator-overloadingostreamistream

Tests failing, when reading and writing a custom object from and to a stringstream


There are no syntax errors and this is not the full code for Pixel_test.cpp and Pixel.cpp.

I only have the full header file.

The test that is failing, is the assert(actual == correct);.

I was thinking, that the problem is stemming from the Pixel.cpp file in the std::ostream& and std::istream&.

I have spent hours, trying to see why this test is not working, so I came here to get some help.

Pixel_test.cpp:

   stringstream in, out;
   string correct;
   Pixel pix;
   pix.set(5,3,2);
   correct = 5,3,2;
   out << pix;
   string actual = out.str();
   assert(actual == correct);
   in << (6,4,6);
   in >> pix;
   assert(pix.getRed() == 6);
   assert(pix.getBlue() == 6);
   assert(pix.getGreen() == 4);

Pixel.cpp:

std::ostream& operator<<(std::ostream& out, const Pixel& pix)
{
     int r, g, b;
     r = pix.getRed();
     g = pix.getGreen();
     b = pix.getBlue();
     out << r << g << b;
     return(out);
}
std::istream& operator>>(std::istream& out, Pixel& pix)
{
     int r, g, b;
     pix.setRed(r);
     pix.setGreen(g);
     pix.setBlue(b);
     out >> r >> g >> b;
     return out;
}

Pixel.h:

#ifndef PIXEL_H
#define PIXEL_H

namespace imagelab
{
    class Pixel
    {
     public:
        Pixel( int r=0, int g=0, int b=0 );     
        void set( int r, int g, int b );
        void setRed( int r );
        void setGreen( int g );
        void setBlue( int b );
        int getRed( ) const;
        int getGreen( ) const;
        int getBlue( ) const;

     private:
        int rval;   // red 0-255
        int gval;   // green 0-255
        int bval;   // blue 0-255
    };

    bool operator== (const Pixel& pix1, const Pixel& pix2);
    bool operator!= (const Pixel& pix1, const Pixel& pix2);
    std::ostream& operator<< (std::ostream& out, const Pixel& pix);
    std::istream& operator>> (std::istream& in, Pixel& pix);
}

#endif

Solution

  • For assert(actual == correct); to work, both strings should be exactly the same, which is not true in your case.

    So, replace:

    correct = 5,3,2;
    

    in Pixel_test.cpp with:

    correct = "5,3,2";
    

    and also replace:

    out << r << g << b;
    

    in std::ostream& operator<<(std::ostream& out, Pixel& pix) with:

    out << r << ',' << g << ',' << b;
    

    to render the same output for out << pix;.

    By making the above changes your assert(actual == correct); would stop failing.

    But, the assertss after that may fail because, when you call in>>pix; this function gets called:

    std::istream& operator>>(std::istream& out, Pixel& pix)
    {
     int r, g, b;
     pix.setRed(r);
     pix.setGreen(g);
     pix.setBlue(b);
     out >> r >> g >> b;
     return out;
    }
    

    And we can clearly see that r g and b are not assigned any values, before calling their respective set methods.

    Hence, only garbage values get stored in rval bval and gval of pix.

    This is why the asserts:

    assert(pix.getRed() == 6);
    assert(pix.getBlue() == 6);
    assert(pix.getGreen() == 4);
    

    are bound to fail.

    EDIT:

    To correct this, you need to read the input, that you just put into the stream, into the variables r g and b.

    So, change your std::istream& operator>>(std::istream& out, Pixel& pix) function like this:

    std::istream& operator>>(std::istream& out, Pixel& pix)
    {
     int r, g, b;
     out >> r >> g >> b;
     pix.setRed(r);
     pix.setGreen(g);
     pix.setBlue(b);
     return out;
    }
    

    Also replace:

    in << (6,4,6);
    

    in your Pixel_test.cpp file with:

    in << "6 4 6";
    

    because stringstream stores data as a string.