0

I am creating a code for a sparse matrix, basically for adding two sparse matrices. And now it's not working. showing some error with return NULL. When checking for the condition that if the dimensions of the matrix are not the same, it will not execute the program as the condition will be false and it will return NULL but it's showing an error there.

#include<iostream>
using namespace std;

class Element{
public:
    int i; 
    int j; 
    int x;
};

class Sparse{
    private:
        int m;
        int n;
        int num;
        Element *ele;

    public: // constructor 
        Sparse(int n ,int m , int num){
            this->n = n;
            this->m = m;
            this->num = num;
            ele = new Element[this->num];
        }
        ~Sparse(){ // destructor
            delete []ele;
        }

//Global functions for insertion and extraction

        Sparse operator+(Sparse &s);

        friend istream & operator>>(istream &is , Sparse &s); // Insertion operator 
        friend ostream & operator<<(ostream &os , Sparse &s); // Extraction operator

}; 

Sparse Sparse::operator+(Sparse &s)
{
    int i , j , k;
    if(m!=s.m || n!=s.n)
        return NULL;
    Sparse *sum = new Sparse(m,n,num+s.num);
    i=j=k=0;
    while(i<num && j<s.num){

        if(ele[i].i < s.ele[j].i){
            sum->ele[k++] = ele[i++];
        }else if(ele[i].i > s.ele[j].i){
            sum->ele[k++] = s.ele[j++];
        }else{
             if(ele[i].j < s.ele[j].j){
                sum->ele[k++] = ele[i++];
            }else if(ele[i].j > s.ele[j].j){
                sum->ele[k++] = s.ele[j++];
            }else{
                sum->ele[k]=ele[i];
                sum->ele[k++].x = ele[i++].x +s.ele[j++].x;
            }

        }
    }
    for(;i<num;i++)sum->ele[k++] = ele[i];
    for(;j<s.num;j++)sum->ele[k++] = s.ele[j];
    sum->num = k;

    return *sum;
}

        // void read()
        istream & operator>>(istream &is , Sparse &s)
        {
            cout<<"Enter non zero elements:";
            for(int i=0;i<s.num;i++){
                cin>>s.ele[i].i>>s.ele[i].j>>s.ele[i].x;
            }
            return is;
        }

        // void Display()
        ostream & operator<<(ostream &os , Sparse &s)
        {
            int k = 0;
            for(int i= 0; i<s.m;i++){
                for(int j=0 ; j<s.n; j++){
                    if(s.ele[k].i ==i && s.ele[k].j ==j){
                        cout<<s.ele[k++].x<<" ";
                    }else{
                        cout<< "0 ";
                    }
                }
                cout<<endl;
            }
            return os;
        }



int main(){

    Sparse s1{5,5,5};
    Sparse s2{5,5,5};
    // s1.read();
    // s1.Display();

    cin>>s1;
    cin>>s2;
    
    Sparse sum=s1+s2;
    cout<<"Enter First Matrix:"<<endl<<s1;
    cout<<"Enter Second Matrix"<<endl<<s2;
    cout<<"Sum Matrix"<<endl<<sum;




    return 0; 
}

enter image description here

Marek R
  • 32,568
  • 6
  • 55
  • 140
SAR LIN
  • 9
  • 2
  • 2
    The function is supposed to return a `Sparse` object. `NULL` is not a `Sparse` object. Maybe throw an exception instead. – 001 Aug 08 '22 at 15:27
  • https://meta.stackoverflow.com/questions/285551/why-not-upload-images-of-code-errors-when-asking-a-question/285557#285557 – Marek R Aug 08 '22 at 15:30
  • If you're coming from Java, you should throw away that instinct to use `NULL` immediately. Java programmers throw null around like it's the next big thing, but in C++ it's very uncommon. First, `NULL` is literally the number 0, so if you *really* want null, you want `nullptr`, which is a null pointer object. But you don't, because [`std::optional`](https://en.cppreference.com/w/cpp/utility/optional) is the idiomatic way to do optional values in C++. And finally, as already pointed out, you can't have a scalar value be null, only pointers. – Silvio Mayolo Aug 08 '22 at 15:32
  • NULL is not a Spare object, it's an int. Basically a 0. See here https://stackoverflow.com/questions/3577580/using-null-in-c. – ZWang Aug 08 '22 at 15:34
  • 1
    BTW: https://hackernoon.com/null-the-billion-dollar-mistake-8t5z32d6 – Marek R Aug 08 '22 at 15:35
  • 1
    `Sparse operator+(Sparse &s);` -- Instantly broken due to `Sparse` having incorrect copy-semantics. You return `Sparse` by value, and your `Sparse` object lacks a user-defined copy constructor and assignment operator to handle the dynamically allocated memory. This simple program `int main() {Sparse s1(1,1,1); Sparse s2 = s1;}` -- shows the issue, where `delete []` is called twice on the same value. – PaulMcKenzie Aug 08 '22 at 15:57

1 Answers1

1

If you go and see the definition of NULL, you will notice that

#define NULL 0

The NULL is replaced by a 0, which is a long int.

In some programming languages, like Java and C#, objects are passed around as pointers, and therefore you can just assign them to null. C++, however, somehow works similar to a struct -- it is passed by value.

Sparse Sparse::operator+(Sparse &s) means that the operator will return a Sparse type. As classes are passed by value, it will return the object's data, a series of bytes. That means you can't just return a NULL to indicate that the concatenation had failed.

An alternative would be to throw an exception. You can also rewrite the operator to a method that returns a Sparse*, a pointer to a Sparse.

Sparse* addSparse(Sparse s1, Sparse s2) {
    if(s1.m != s2.m || s1.n != s2.n)
        return NULL;
    // add them together
}

That way, the caller can check if the concatenation is successful by checking the returned value.

Sparse* result = addSparse(s1, s2);
if(result != NULL) {
    // Consume the result
}
// Handle it
iLittleWizard
  • 385
  • 2
  • 12
  • 1
    `Sparse Sparse::operator+(Sparse &s)` -- This is broken for more fundamental reasons. `Sparse` is not safely copyable of assignable. – PaulMcKenzie Aug 08 '22 at 15:59