Конструкция try - catch. Как правильно использовать при проверке входных данных?
Всем привет, я пишу свой класс, который предназначен для действий над матрицами. В нём присутствуют методы, в которых необходимо проверять входные данные. Я написал метод insert, который вставляет строку или столбец со значениями value в исходную матрицу на позицию index (что-то типо такого же метода из библиотеки NumPy в python). Для проверки этого индекса и оси реализовал try-catch. Всё работает за исключением случая, когда index больше на единицу, чем размер по выбранной оси исходной матрицы. При таких входных данных срабатывает try-catch, однако код выполняется дальше и строка с переданным значением вставляется в самый конец матрицы. Я думал, что данную проблему можно решить, запихнув весь код метода в try-catch или разместив функцию, которая прерывает код программы, в блок catch. Сам вопрос заключается в следующем: на сколько целесообразно и этично делать так, как я хотел. И вообще нужен ли блок try-catch в таких случаях, ведь можно организовать проверку входных данных с помощью if-else и, если проверка не будет пройдена, вывести сообщение на экран и вызвать функцию, прерывающую программу. Ниже привёл часть кода класса, который необходим для работы метода и .cpp файл, в котором вызывается метод с проблемными входными данными.
matrix.h
#include <iostream>
#include <cstdlib>
using std::cout;
using std::endl;
using std::cin;
template <typename T>
class Matrix
{
public:
Matrix()
{
lines = columns = size = 0;
arr = nullptr;
shape = nullptr;
}
Matrix(const int lines, const int columns)
{
this->lines = lines;
this->columns = columns;
size = lines * columns;
shape = new int[2] {lines, columns};
arr = new T * [lines];
for (int i = 0; i < lines; i++) {
arr[i] = new T[columns];
}
}
Matrix(const Matrix& other)
{
this->lines = other.lines;
this->columns = other.columns;
this->size = other.size;
this->shape = new int[2] {other.lines, other.columns};
this->arr = new T * [other.lines];
for (int i = 0; i < other.lines; i++) {
this->arr[i] = new T[other.columns];
}
for (int i = 0; i < other.lines; i++) {
for (int j = 0; j < other.columns; j++) {
this->arr[i][j] = other.arr[i][j];
}
}
}
~Matrix()
{
clearMemory(arr, lines);
delete[] shape;
}
void fillAuto(const int a, const int b)
{
for (int i = 0; i < lines; i++) {
for (int j = 0; j < columns; j++) {
arr[i][j] = rand() % (b - a + 1) + a;
}
}
}
void printMatrix(char* name = nullptr)
{
if (name != nullptr) {
cout << name << endl;
}
for (int i = 0; i < lines; i++) {
cout << '|' << ' ';
for (int j = 0; j < columns; j++) {
if (j == columns - 1) {
if (arr[i][j] > -1) {
cout << ' ' << arr[i][j] << ' ';
}
else {
cout << arr[i][j] << ' ';
}
}
else {
if (arr[i][j] > -1) {
cout << ' ' << arr[i][j] << '\t';
}
else {
cout << arr[i][j] << '\t';
}
}
}
cout << ' ' << '|' << endl;
}
cout << endl;
}
Matrix insert(const int index, const int value, const int axis)
{
// Чтобы проверить принадлежность index допустимому диапозону,
// необходимо знать какая ось была передана.
try
{
bool isIndexRande;
if (0 == axis) {
isIndexRande = (index > -1) && (index < this->lines);
}
else if (1 == axis) {
isIndexRande = (index > -1) && (index < this->columns);
}
else {
throw std::exception("Ошибка! Переданная ось вне "
"допустимого диапозона!");
}
if (!isIndexRande) {
throw std::exception("Ошибка! Переданный индекс вне "
"допустимого диапозона!");
}
}
catch (const std::exception& ex)
{
cout << ex.what() << endl;
}
Matrix temp;
if (0 == axis) {
temp.lines = this->lines + 1;
temp.columns = this->columns;
temp.size = (this->lines + 1) * this->columns;
temp.shape = new int[2] {this->lines + 1, this->columns};
temp.arr = new T * [this->lines + 1];
for (int i = 0; i < this->lines + 1; i++) {
temp.arr[i] = new T[this->columns];
}
// Вспомогательная переменная.
// Пока цикл (i) не дошёл до переданного индекса (строки),
// каждый элемент исходной матрицы копируется в ту же позицию
// новой матрицы. Поэтому изначально a = 0.
int a = 0;
for (int i = 0; i < this->lines + 1; i++) {
for (int j = 0; j < this->columns; j++) {
if (i == index) {
temp.arr[i][j] = value;
// Т.к. цикл дошёл до переданной строки (index),
// в iую строку вставлялось новое значение на
// протяжении всей итерации. Если после этого
// использовать те же индексы, то будет пропущена
// строка в исходной матрицы. Поэтому, начиная
// со следующей строки после index, необходимо
// обращаться к исходной матрицы на одну строку ниже.
a = 1;
}
else {
temp.arr[i][j] = this->arr[i - a][j];
}
}
}
}
else if (1 == axis) {
temp.lines = this->lines;
temp.columns = this->columns + 1;
temp.size = this->lines * (this->columns + 1);
temp.shape = new int[2] {this->lines, this->columns + 1};
temp.arr = new T * [this->lines];
for (int i = 0; i < this->lines; i++) {
temp.arr[i] = new T[this->columns + 1];
}
for (int i = 0; i < this->lines; i++) {
int a = 0;
for (int j = 0; j < this->columns + 1; j++) {
if (j == index) {
temp.arr[i][j] = value;
a = 1;
}
else {
temp.arr[i][j] = this->arr[i][j - a];
}
}
}
}
return temp;
}
private:
T** arr;
int lines;
int columns
int size;
const int* shape;
template <typename T1>
void clearMemory(T1** mas, int n, bool isSquare=true)
{
if (isSquare) {
for (int i = 0; i < n; i++) {
delete[] mas[i];
}
delete[] mas;
}
else {
delete[] mas;
}
}
};
matrix.cpp
#include <iostream>
int main()
{
using std::cout;
using std::endl;
setlocale(LC_ALL, "rus");
Matrix<int> a(3, 3);
a.fillAuto(-10, 10);
a.printMatrix();
Matrix<int> c = a.insert(3, 1000, 0);
c.printMatrix();
return 0;
}