1
\$\begingroup\$

After following the suggestions you can find here, I'd like to show the result again (but I did not change the algorithm):

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

int getDimension();
void getUserInput(std::vector<std::vector<double>>& vect, int i, int dimension);
double getDeterminant(const std::vector<std::vector<double>> vect);
void printMatrix(const std::vector<std::vector<double>> vect);

int main() { 

    //First, the user has to enter the dimension of the matrix
    int dimension = getDimension();

    //Now, the user has to enter the matrix line by line, seperated by commas
    std::vector<std::vector<double>> vect(dimension, std::vector<double> (dimension));
    for(int i = 1; i <= dimension; i++) {
        getUserInput(vect, i, dimension);
    }

    //Output
    printMatrix(vect);

    std::cout << "Determinant of the matrix is : " << getDeterminant(vect) << "\n"; 
    return 0;
} 

int getDimension() {
    int dimension;
    std::cout << "Please enter dimension of Matrix: ";
    std::cin >> dimension;
    std::cout << "\n";

    if(dimension < 0 || std::cin.fail()) {
        std::cin.clear();
        std::cin.ignore();
        std::cout << "ERROR: Dimension cannot be < 0.\n";
        return getDimension();
    }

    return dimension;
}

void getUserInput(std::vector<std::vector<double>>& vect, int i, int dimension) {
    std::string str = "";
    std::cout << "Enter line " << i << " only seperated by commas: ";
    std::cin >> str;
    std::cout << "\n";
    str = str + ',';

    std::string number = "";
    int count = 0;

    for(std::size_t k = 0; k < str.length(); k++) {
        if(str[k] != ',') {
            number = number + str[k];
        }
        else if(count < dimension) {
            if(number.find_first_not_of("0123456789.-") != std::string::npos) {
                std::cout << "ERROR: Not only numbers entered.\n";
                getUserInput(vect, i, dimension);
                break;
            }
            else if(number.find_first_not_of("0123456789") == std::string::npos) {
                vect[i - 1][count] = std::stod(number);
                number = "";
                count++;
            }
            else {
                std::cout << "ERROR: Not enough numbers entered.\n";
                getUserInput(vect, i, dimension);
                break;
            }       
        }
        else {
            std::cout << "ERROR: Too many numbers entered.\n";
            getUserInput(vect, i, dimension);
            break;
        }
    }
}

double getDeterminant(const std::vector<std::vector<double>> vect) {

    int dimension = vect.size();

    if(dimension == 0) {
        return 1;
    }

    if(dimension == 1) {
        return vect[0][0];
    }

    //Formula for 2x2-matrix
    if(dimension == 2) {
        return vect[0][0] * vect[1][1] - vect[0][1] * vect[1][0];
    }

    double result = 0;
    int sign = 1;
    for(int i = 0; i < dimension; i++) {

        //Submatrix
        std::vector<std::vector<double>> subVect(dimension - 1, std::vector<double> (dimension - 1));
        for(int m = 1; m < dimension; m++) {
            int z = 0;
            for(int n = 0; n < dimension; n++) {
                if(n != i) {
                    subVect[m-1][z] = vect[m][n];
                    z++;
                }
            }
        }

        //recursive call
        result = result + sign * vect[0][i] * getDeterminant(subVect);
        sign = -sign;
    }

    return result;
}

void printMatrix(const std::vector<std::vector<double>> vect) {
    for(std::size_t i = 0; i < vect.size(); i++) {
        for(std::size_t j = 0; j < vect.size(); j++) {
            std::cout << std::setw(8) << vect[i][j] << " ";
        }
        std::cout << "\n";
    }
}

Do you have any more suggestions on improving the code?

\$\endgroup\$

2 Answers 2

2
\$\begingroup\$

You need to check for std::cin::eof() before std::cin.fail() (or simply !std::cin), because there's no point repeating the read infinitely if we've reached EOF.

To demonstrate, just run the program with closed standard input, e.g.

make 237153
./237153 <&-

The reading of the matrix's elements fails in a different way at end of stream:

./237153 <<<'2 2-,4 3,2'
Please enter dimension of Matrix: 
Enter line 1 only seperated by commas: 
ERROR: Not enough numbers entered.
Enter line 1 only seperated by commas: 
Enter line 2 only seperated by commas: 
terminate called after throwing an instance of 'std::invalid_argument'
  what():  stod
\$\endgroup\$
2
\$\begingroup\$

To add to the other answer(s):

  • The parameters to both getDeterminant and printMatrix should be const-ref instead of passed by-value.

  • int dimension = getDimension(); should be const int dimension = getDimension();

  • Note that str = str + ','; and number = number + str[k]; could be rewritten to str += ',' and number += str[k], respectively, for potentially better readability. (Same could be said more about result = result ...).

  • int dimension = vect.size(); should be const.

  • You could have a look at range-based for loops to make e.g., printMatrix easier to read. That is, you don't really need to play with the indices directly, you could just for(auto x : vect) ....

\$\endgroup\$

Your Answer

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