1

I am trying to write an OLS regression in C++. I want the user to specify how many observations and variables goes into the X (independent variable matrix). I want to write this as a function outside the int main() function. But everytime I return the array, I get a type error. How do I specify that I want function input_x to return a matrix/array?

 /******************************************************************************   
                                  Online C++ Compiler.    
    *******************************************************************************/
    
    #include <iostream>
    
    using namespace std;
    
    
    int input_x(int num_rows, int num_cols){
        
        
       int mat[num_rows][num_cols];
       int user_input;
           
        for (int i=0; i<num_rows; i++){
            for (int j=0; j<num_cols; j++){
                    cout<<"Enter the value X:";
                    cin>>user_input;
                    mat[i][j]=user_input;
                
            }
        }
    
    
       return mat;
    }
    
    
    
    int main()
    {
        int mat[1000][1000];
        int input;
        int rows;
        int cols;
        
        cout<<"How many row?";
        cin>> rows;
        cout<<"How many columns?";
        cin>> cols;
        

        //Enter the X data
        input_x(rows,cols);
        
        
    
    
        return 0;
    }
13
  • 3
    The type of mat is int**. But you can't return a function local c-array like that. You need to use something that has proper copy semantics, like a std::vector<std::vector<int>>. Commented Jan 6, 2022 at 14:44
  • 1
    input_x is not declared to return a 2D integer array, it's declared to return an integer. And you can't actually return a native array, per se. See Return array in a function. Commented Jan 6, 2022 at 14:47
  • 1
    int man[1000][1000] -- That's C, not C++, and using this C construct in C++ is really bad practice. Check out std::vector. Or Boost.uBLAS if you want to go into matrices hardcore. But I guess before you go there, you need to understand basic data structures and function calls... Commented Jan 6, 2022 at 14:47
  • 3
    @jessica If 381 GB is not A LOT to allocate on the stack, I don't know what is. :-) Commented Jan 6, 2022 at 15:03
  • 2
    @super Replying to your very first comment. The type of mat is int [num_rows][num_cols] and not int** which you incorrectly claimed. Commented Jan 6, 2022 at 15:17

4 Answers 4

2

Mistake 1

In C++ the size of an array must be a compile time constant. So take for example,

int n = 10;
int arr[n]; //INCORRECT because n is not a compile time constant

The correct way to write the above would be

const int n = 10;
int arr[n]; //CORRECT

Similarly in your code:

int mat[num_rows][num_cols];//INCORRECT because num_rows and num_cols are not constant expressions

Mistake 2

The return type of your function input_x is int.

But the type of mat inside the function input_x is int [num_rows][num_cols] which decays to int (*)[num_cols] due to type decay.

So essentially the return type of your function(int) and what you're actually returning(int (*)[num_cols]) doesn't match and hence you get the following error:

error: invalid conversion from ‘int (*)[num_cols]’ to ‘int’

Solution

To solve these problems you should use std::vector instead of built in array as shown below:

#include <iostream>
#include <vector> 
//this function takes vector by reference and returns nothing 
void input_x(std::vector<std::vector<int>> &vec){
    
    for(auto &rows: vec)
    {
        for(auto &cols: rows)
        {
            std::cout << "Enter element: "<<std::endl;
            std::cin >> cols; 
        }
    }


   //NO NEED TO RETURN ANYTHING SINCE THE VECTOR IS PASSED BY REFERENCE SO THE CHANGE IS ALREADY REFLECTED ON THAT PASSED VECTOR
}

int main()
{
    int rows;
    int cols;
    
    std::cout<<"How many row?"<<std::endl;
    std::cin>> rows;
    std::cout<<"How many columns?"<<std::endl;
    std::cin>> cols;
    
    //create 2D vector 
    std::vector<std::vector<int>> myVec(rows, std::vector<int>(cols));
    

    //call the function and pass the vector as argument 
    input_x(myVec);

    return 0;
}
Sign up to request clarification or add additional context in comments.

Comments

1

As the comment states, your return type of the function input_x is wrong.

Your matrix mat is an array of arrays of int. This is a c-style array and you can only return it as an int** which would directly lead to a dangling reference.

Instead of using c-style arrays it's better to use standard containers, like std::vector as Fred Larson pointed out.

See the documentation here about std::vector In general https://en.cppreference.com is a good start to see if any standard library type suits your needs.

You can initialize your matrix like this:

std::vector<std::vector<int>> mat(num_rows)
for (auto & row : mat)
    row.resize(num_cols);

Don't forget to include the respective header

#include <vector>

5 Comments

std::vector<std::vector<int>> mat(num_rows, std::vector<int>(num_cols)); would be the more idiomatic approach.
@BKN So I should avoid providing a helpful comment because the information is available on other questions/answers on SO?
@super: my comment was not for you. Your comment is indeed helpful. I meant the answer by Svenja ends up duplicating...I should have used answer instead of comment to avoid confusion.
@Svenja I think your answer just ends up duplicating the already provided comments for a question that is almost a duplicate question in SO :)
@BKN Alright :) I'm new to contributing to SO. When I wrote the answer there was only the comment from Fred Larson and I thought since the person asking might not be experienced with c++ types I elaborate. Should I delete the answer?
1

One of the strengths of C++ is that many complex data types already exist in the standard library. And even more exist in common extension libraries like Boost. You would be well-advised to use those instead of "making do" with C style arrays or structs, if for no other reason than to avoid error-prone manual memory management.

Svenja showcased the "vector of vector" approach using the standard type std::vector. But there is an even better match for your use case in Boost.uBLAS' Matrix type:

#include <iostream>
#include <boost/numeric/ublas/matrix.hpp>
#include <boost/numeric/ublas/io.hpp>

// Avoid "using namespace". Keep the global namespace clean,
// and use explicit namespacing for minimal ambiguity.
namespace bu = boost::numeric::ublas;

// Use (unsigned) size_t for sizes. Use padding spaces for
// readability.
bu::matrix< int > input_x( size_t num_rows, size_t num_cols )
{
    bu::matrix< int > matrix( num_rows, num_cols );

    // Use "speaking" variable names instead of "i" and "j".
    // Use prefix "++"; while it makes no difference with POD
    // types, it does make a difference with complex ones.
    for ( size_t r = 0; r < num_rows; ++r )
    {
        for ( int c = 0; c < num_cols; ++c )
        {
            // Give all the useful information you can.
            // Don't forget to std::endl your output if
            // the next thing you do is expecting input.
            std::cout << "value " << r << ", " << c << std::endl;

            // Avoid the use of "named temporary" variables.
            // Name only what you actually need later on, and
            // if you can (like here), just work without any
            // intermediary like "user_input".
            std::cin >> matrix( r, c );
        }
    }

    return matrix;
}

int main()
{
    size_t rows;
    size_t cols;

    std::cout << "How many rows?" << std::endl;
    std::cin >> rows;
    std::cout << "How many columns?" << std::endl;
    std::cin >> cols;

    // In C++ you do not need to declare all variables at the
    // beginning of the block. Declare at the point you actually
    // need the variable.
    bu::matrix< int > matrix = input_x( rows, cols );

    return 0;
}

Comments

-1

The value returned by the function is not stored.

input_x(rows,cols); // should be stored in a variable

Also, you have to change the return type of function to a matrix.

int input_x(int num_rows, int num_cols){

To solve the problem:

  1. Create a matrix dynamically
  2. Return the matrix

Here is the code for the above approach.

/******************************************************************************
                                  Online C++ Compiler.
    *******************************************************************************/

    #include <iostream>

    using namespace std;


    int** input_x(int num_rows, int num_cols){

       int **mat = (int **)malloc(num_rows * sizeof(int *));
       int user_input;

        for (int i = 0; i < num_rows; i++) {
            mat[i] = (int *)malloc(num_cols * sizeof(int));
        }
        for (int i=0; i<num_rows; i++){
            for (int j=0; j<num_cols; j++){
                    cout<<"Enter the value X:";
                    cin>>user_input;
                    mat[i][j]=user_input;

            }
        }

       return mat;
    }



    int main()
    {
        int** mat;
        int input;
        int rows;
        int cols;

        cout<<"How many row?";
        cin>> rows;
        cout<<"How many columns?";
        cin>> cols;


        //Enter the X data
        mat = input_x(rows,cols);
/*
        for(int i=0;i<rows;i++){
            for(int j=0;j<cols;j++){
                cout<<mat[i][j]<<" ";
            }
            cout << endl;
        }
*/



        return 0;
    }

2 Comments

"To solve the problem: 1. Create a matrix dynamically." -- No. Because now your program is leaking memory. Don't use C constructs in C++.
Yeah. This approach has memory leaks. I forgot to mention

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.