1

Тема: Клас "слід матриці"

допоможіть переробити код з урахуванням класу

#include <iostream>
#include <ctime>
using namespace std;

int main()
{
    setlocale(LC_ALL, "ukraine");
    cout << "\t\tСлід матриці\n";

    srand(time(NULL));
    int X = 0;
    int n = 0;
    cout << "введіть кількість стовпців і рядків: ";
    cin >> n; 
    int** a = new int* [n];
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n; j++)
        {
            a[i] = new int[n];
        }
    }
    
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n; j++)
        {
            a[i][j] = rand() % 100;
            cout << a[i][j] << " ";
            if (a[i] == a[j])
            {
                X += a[i][j];
            }
        }
        cout << endl;
    }
    cout << "слід матриці: " << X << endl;
    // Удаление массива
    for (int i = 0; i < n; i++)
    {
        delete[]a[i];
    }
    delete[] a;
    return 0;
}

2

Re: Клас "слід матриці"

MMORPG написав:

допоможіть переробити код з урахуванням класу або дайте хоть приклад на с++

#include <iostream>
#include <ctime>
using namespace std;

int main()
{
    setlocale(LC_ALL, "ukraine");
    cout << "\t\tСлід матриці\n";

    srand(time(NULL));
    int X = 0;
    int n = 0;
    cout << "введіть кількість стовпців і рядків: ";
    cin >> n; 
    int** a = new int* [n];
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n; j++)
        {
            a[i] = new int[n];
        }
    }
    
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n; j++)
        {
            a[i][j] = rand() % 100;
            cout << a[i][j] << " ";
            if (a[i] == a[j])
            {
                X += a[i][j];
            }
        }
        cout << endl;
    }
    cout << "слід матриці: " << X << endl;
    // Удаление массива
    for (int i = 0; i < n; i++)
    {
        delete[]a[i];
    }
    delete[] a;
    return 0;
}

дякую

3

Re: Клас "слід матриці"

В ідеалі класом має бути сама матриця (Matrix), а "слід матриці" має бути методом (GetTrace) цього класу, який не приймає параметрів (крім this) і повертає одне число (результат обчислення).

Для цього вам потрібно :

  1. створити файли { "Matrix.h", "Matrix.cpp" }

  2. в Matrix.h описати клас і оголосити його методи (приклад)

  3. в Matrix.cpp описати (implement) { конструктори, деструктор, методи } класу

Подякували: MMORPG, koala2

4 Востаннє редагувалося MMORPG (27.10.2019 19:47:11)

Re: Клас "слід матриці"

я зараз застряг на цьому моменті

#include <iostream>
#include <ctime> 
using namespace std;


class Matrix
{
private:
    int n,m;
    int ????????;
public:
    Matrix(int n, int m);
    void showMatrix();
    ~Matrix();
    double* operator [](int i)
    {
        return A[i];
    }
};
Matrix::Matrix(int n, int m) : n(n), m(m)
{
    
    A = new double* [n];
    for (int i = 0; i < n; ++i)
    {
        A[i] = new double[m];
        for (int j = 0; j < m; j++)
            A[i][j] = 0;
    }
}
void obchislinya (?????????)
        {
            ????????????????????????????????
        };

void Matrix::showMatrix()
{
    ????????
}
Matrix::~Matrix()
{
    for (int i = 0; i < n; i++)
    {
        delete[]A[i];
    }
    delete[] A;
}
int main()
{
    setlocale(LC_ALL, "ukraine");
    cout << "\t\tслід матриці\n";
    srand(time(NULL));

    ??????????????

    system("pause");
    return 0;
}

і не можу здвинутись далі

5

Re: Клас "слід матриці"

Ви просто не з того боку підійшли. От уявіть собі, що у вас є власний ідеальний тип Matrix, який робить усе, що вам треба. Як би ви хотіли з ним працювати? Ну, можливо, якось так:

cin>>size;
Matrix matrix(size);
matrix.print();
cout<<matrix.get_trace();

А може, так:

Matrix matrix;//запитує розмір сам конструктор
cout<<matrix; //якщо не знаєте, як таке робити, використовуйте matrix.print()
cout<<matrix.trace; //public змінна trace, обчислена конструктором. Не дуже правильно, але ж ви навчаєтеся, правда?

А далі від цього відштовхуйтеся.

Подякували: leofun01, MMORPG2

6

Re: Клас "слід матриці"

Так я навчаюсь.
Тільки почали вчити ООП і класи.
(і бац таке завдання)
і до кінця ще не розумію, як з ним взаємодіяти

7

Re: Клас "слід матриці"

Це ще не ООП. Це процедурне програмування і АТД.
Ви можете розкласти код, який маєте, по функціях, щоб main виглядала якось так:

int **a;
int n;
cin>>n;
matrix_create(a,n);
matrix_show(a,n);
cout << matrix_trace(a,n)<<endl;
matrix_destroy(a,n);
return 0;

Можете вільно перекидати частину дій туди чи сюди, але щоб main не працювала з a не напряму, а лише викликала інші функції? Просто якщо у вас так не виходить, то до АТД (навіть не ООП) вам ще треба кілька концепцій вивчити.

Подякували: MMORPG1

8 Востаннє редагувалося wander (28.10.2019 00:03:31)

Re: Клас "слід матриці"

MMORPG написав:

Так

Що так?)
Ви, згідно з попереднім повідомленням прикинули собі, як ви хочете взаємодіяти з вашою матрицею?
Поки у вас не буде цього загального бачення продовжувати буде важко.

MMORPG написав:

Тільки почали вчити ООП і класи.
(і бац таке завдання)
і до кінця ще не розумію, як з ним взаємодіяти

Ну, зробіть як розумієте, не сподобається перепишіть, рано чи пізно щось та й вийде.
Перш за все проясніть для себе, що має вміти робити ваш клас.
(Наприклад: він повинен створювати матрицю (яким чином?) задаючи розмірність, як параметри конструктора і заповнюючи її руками користувача і т.д.)

Наступна ваша помилка в тому, що ви почали писати код одразу.
Почніть з простого, наприклад, зі створення вашого ще неіснуючого класу.

int main() {
    Matrix mtx;
}

Ваш код не скопліюється, тоді ви створюєте ваш клас Matrix і робите все, щоб код скомпілювався і запустився.
Потім передайте параметри в конструктор (якого теж немає), код знову не скомпілюється, додайте необхідний конструктор, щоб все збілдилось, і так далі повторюєте (крок за кроком, згідно з вашим "ТЗ", що має вміти робити ваш клас), і з методами класу, так само. Подумайте спочатку, а що має робити метод print, яку поведінку я від нього очікую? Просто, щоб він вивів у консоль матрицю? Якщо так, лиш тоді пишіть код.
Спочатку взаємодія, потім код. Причому думати тре максимально тупо, не намагайтеся написати "розумний код" наперед, який буде мати конструктори, методи і тд, ні - пишіть тупий і простий код, починайте з простого, якщо щось не виходить поверніться на крок назад і спробуйте знову.

Таким чином у вас вималюється інтерфейс )
Загалом за майже таким принципом працює TDD.

Подякували: MMORPG1

9

Re: Клас "слід матриці"

MMORPG, ось готовий код з використанням шаблону (template) :

// Matrix.h

#ifndef MATRIX_H
#define MATRIX_H

#include <exception>
#include <iostream>

template<typename T>
class Matrix {
    private:
        int n, m;
        T **a;
    public:
        Matrix(int n, int m) : n(n), m(m), a(nullptr) {
            a = new T*[n];
            if(!a) throw std::bad_alloc();
            for(int i(0); i < n; ++i) {
                T *ai(a[i] = new T[m]);
                if(!ai) {
                    for(--i; i >= 0; --i)
                        delete[] a[i];
                    delete[] a;
                    a = nullptr;
                    throw std::bad_alloc();
                }
                for(int j(0); j < m; j++)
                    ai[j] = 0;
            }
        }
        ~Matrix() {
            if(!a) return;
            for(int i(0); i < n; ++i)
                delete[] a[i];
            delete[] a;
            a = nullptr;
        }
        T *operator [](int i) {
            return (i >= 0 && i < n && a) ? a[i] : nullptr;
        }
        T const *operator [](int i) const {
            return (i >= 0 && i < n && a) ? a[i] : nullptr;
        }
        T get_trace() const {
            T trace(0);
            if(!a) return trace;
            int c = n < m ? n : m;
            for(int i(0); i < c; ++i)
                trace += a[i][i];
            return trace;
        }
        int get_n() const { return n; }
        int get_m() const { return m; }
        void init(T (*generator)()) {
            for(int i(0); i < n; ++i)
                for(int j (0); j < m; ++j)
                    a[i][j] = generator();
        }
};

using namespace std;

template<typename T>
ostream &operator <<(ostream &out, Matrix<T> const &matrix) {
    int n(matrix.get_n()), m(matrix.get_m()), i(0), j(0);
    T const *row(matrix[i]);
    out << "[\r\n  [ " << row[j];
    for(++j; j < m; ++j)
        out << ", " << row[j];
    out << " ]";
    for(++i; i < n; ++i) {
        row = matrix[i];
        out << ",\r\n  [ " << row[j = 0];
        for(++j; j < m; ++j)
            out << ", " << row[j];
        out << " ]";
    }
    out << "\r\n]";
    return out;
}

#endif
// Main.cpp

#include <ctime>
#include <iostream>
#include "Matrix.h"

int main(int argc, char const *argv[]) {
    Matrix<int> matrix(3, 5);
    srand(time(nullptr));
    matrix.init([]() -> int { return rand() % 10; });
    /*//
    matrix[0][0] = 2;
    matrix[1][1] = 3;
    matrix[2][2] = 4;
    //*/
    std::cout << "Matrix : " << matrix << "\r\n";
    std::cout << "Trace : " << matrix.get_trace() << endl;
    return 0;
}

А Matrix.cpp можна видалити.

Подякували: MMORPG1

10 Востаннє редагувалося wander (28.10.2019 09:13:27)

Re: Клас "слід матриці"

leofun01 написав:

MMORPG, ось готовий код з використанням шаблону (template) :

// Matrix.h

#ifndef MATRIX_H
#define MATRIX_H

#include <exception>
#include <iostream>

template<typename T>
class Matrix {
    private:
        int n, m;
        T **a;
    public:
        Matrix(int n, int m) : n(n), m(m), a(nullptr) {
            a = new T*[n];
            if(!a) throw std::bad_alloc();
            for(int i(0); i < n; ++i) {
                T *ai(a[i] = new T[m]);
                if(!ai) {
                    for(--i; i >= 0; --i)
                        delete[] a[i];
                    delete[] a;
                    a = nullptr;
                    throw std::bad_alloc();
                }
                for(int j(0); j < m; j++)
                    ai[j] = 0;
            }
        }
        ~Matrix() {
            if(!a) return;
            for(int i(0); i < n; ++i)
                delete[] a[i];
            delete[] a;
            a = nullptr;
        }
        T *operator [](int i) {
            return (i >= 0 && i < n && a) ? a[i] : nullptr;
        }
        T const *operator [](int i) const {
            return (i >= 0 && i < n && a) ? a[i] : nullptr;
        }
        T get_trace() const {
            T trace(0);
            if(!a) return trace;
            int c = n < m ? n : m;
            for(int i(0); i < c; ++i)
                trace += a[i][i];
            return trace;
        }
        int get_n() const { return n; }
        int get_m() const { return m; }
        void init(T (*generator)()) {
            for(int i(0); i < n; ++i)
                for(int j (0); j < m; ++j)
                    a[i][j] = generator();
        }
};

using namespace std;

template<typename T>
ostream &operator <<(ostream &out, Matrix<T> const &matrix) {
    int n(matrix.get_n()), m(matrix.get_m()), i(0), j(0);
    T const *row(matrix[i]);
    out << "[\r\n  [ " << row[j];
    for(++j; j < m; ++j)
        out << ", " << row[j];
    out << " ]";
    for(++i; i < n; ++i) {
        row = matrix[i];
        out << ",\r\n  [ " << row[j = 0];
        for(++j; j < m; ++j)
            out << ", " << row[j];
        out << " ]";
    }
    out << "\r\n]";
    return out;
}

#endif
// Main.cpp

#include <ctime>
#include <iostream>
#include "Matrix.h"

int main(int argc, char const *argv[]) {
    Matrix<int> matrix(3, 5);
    srand(time(nullptr));
    matrix.init([]() -> int { return rand() % 10; });
    /*//
    matrix[0][0] = 2;
    matrix[1][1] = 3;
    matrix[2][2] = 4;
    //*/
    std::cout << "Matrix : " << matrix << "\r\n";
    std::cout << "Trace : " << matrix.get_trace() << endl;
    return 0;
}

А Matrix.cpp можна видалити.

Гм, кілька порад:
1) n, m - швидше за все не можуть бути від’ємними, бо якщо це так, то це погано для нас, краще їх зробити беззнаковими цілими (unsigned), а ще краще size_t; на те чи вони рівні 0 я б теж перевірив;
2) Якщо вже користуєтесь списком ініціалізацій в конструкторі нема сенсу спочатку a присвоювати nullptr, а потім одразу викликати new, можна все зробити в списку ініціалізацій;
3) new - сам кидає винятки, тож до вашої перевірки в if, діло не дійде, користуйтесь розумними вказівниками, вони все за вас зроблять або позначайте оператор new як nothrow, або змінюйте тактику обробки винятків;

І раз вже така справа, то для більшої оптимальності я б робив лише одне виділення пам’яті.

Подякували: leofun01, MMORPG2

11

Re: Клас "слід матриці"

adziri написав:

Гм, кілька порад: ...

Переробив код з врахуванням всіх ваших рекомендацій.

// Matrix.h

#ifndef MATRIX_H
#define MATRIX_H

#include <iostream>

using namespace std;

template<typename T>
class Matrix {
    private:
        size_t n, m, len;
        T *a;
    public:
        Matrix(size_t n, size_t m) : n(n), m(m), len(n * m), a(new T[len]) {
            for(size_t i(0); i < len; ++i)
                a[i] = 0;
        }
        ~Matrix() {
            if(!a) return;
            delete[] a;
            a = nullptr;
        }
        T *operator [](size_t i) {
            return (i >= 0 && i < n && a) ? i * m + a : nullptr;
        }
        T const *operator [](size_t i) const {
            return (i >= 0 && i < n && a) ? i * m + a : nullptr;
        }
        T get_trace() const {
            T trace(0);
            if(!a) return trace;
            size_t c = n < m ? n : m;
            for(size_t i(0); i < c; ++i)
                trace += (*this)[i][i];
            return trace;
        }
        size_t get_n() const { return n; }
        size_t get_m() const { return m; }
        void init(T (*generator)()) {
            for(size_t i(0); i < len; ++i)
                a[i] = generator();
        }
};

#endif

Так, це краще ніж було до того.

Оператор << для ostream & не змінився, його можна взяти з попереднього коду, main теж.

Подякували: wander, MMORPG2