Неправильный вывод при создании нижнего диагонального треугольника

#c

#c

Вопрос:

Я пытаюсь создать программу, которая принимает меньшие значения диагонали и сохраняет их в одномерном массиве, а затем просто распечатывает его.

Ввод:

1 0 0

2 3 0

4 5 6

ожидаемый результат

1 0 0

2 3 0

4 5 6

текущий вывод

2 0 0

2 4 0

4 5 6

обратите внимание, что я уже указал размер 3 .

код:

 #include <bits/stdc  .h>
using namespace std;
class matrix
{
    int size;
    int *a;

public:
    matrix(int size)                          //Matrix class
    {
        this->size = size;
        a = new int[(size * (size   1) / 2)];           //creating 1-D array to store values
    }
    void set(int i, int j, int val)               //Function to set values in array "a".
    {
        if (i >= j)
            a[((i * (i - 1)) / 2)   (j - 1)] = val;
    }
    
    void display()                               //function to display values
    {
        for (int i = 0; i < size; i  )
        {
            for (int j = 0; j < size; j  )
            {
                if (i >= j)
                    cout << a[((i * (i - 1)) / 2)   (j - 1)] << " ";
                else
                    cout << "0 ";
            }
            cout << endl;
        }
    }
};
int main()
{
    int n = 3;                                   //dimension of matrix
    matrix a(n);
    for (int i = 0; i < n; i  )                //entering the values
    {
        int val;
        for (int j = 0; j < n; j  )
        {
            cin >> val;
            a.set(i, j, val);
        }
    }
    a.display();

    return 0;
}
 

Прилагаемый компилятор: https://onlinegdb.com/IrzmB04dB

Комментарии:

1. Очевидно cout << a[((i * (i - 1)) / 2) (j - 1)] << " "; , это неправильно. Вы можете увидеть, вычисляете ли вы для i = 0 и j = 0 . Вы не можете получить доступ a[-1] . В массиве есть size * (size - 1) / 2 элементы, но вложенный цикл display повторяется size * size раз.

2. В вашем коде, ИМХО, слишком много ошибок. Способы вычисления размера и индексов вашего a массива совершенно неверны.

3. Я мог бы опубликовать «исправленную» версию вашей программы. Но, поскольку это, вероятно, проблема домашней работы, я не думаю, что это, в конечном счете, было бы полезно.

4. Но подумайте об этом. Если есть только size * (size - 1) / 2 возможные индексы, но вы пытаетесь получить доступ size * size к разным элементам, вам нужно выйти за пределы или вам придется обращаться к одним и тем же элементам несколько раз.

5. Нет, если size 5 вы сохраняете 10 элементы. 5 * (5 - 1) / 2 == 10 . Если size 3 вы сохраняете 3 элементы: 3 * (3 - 1) / 2 == 3 .

Ответ №1:

Ваша формула для поиска элемента матрицы i,j в представлении плоского массива (которое вы вызываете a в своем коде) указанной матрицы a[((i * (i - 1)) / 2) (j - 1)] верна только в том случае, если индексы i,j начинают отсчет с 1 , как в Fortran, а не с 0 , как в C .

Кроме того, размер нижней треугольной матрицы должен включать основную диагональ в вашем соглашении, поэтому он должен быть (size * (size - 1) / 2) size добавлен size в конструктор.

Учитывая это, ваш код становится:

 #include <iostream>

using namespace std;

class matrix
{
    int size;
    int *a;

public:
    //Matrix class, ADD '  size' TO a 
    matrix(int input_size): size(input_size), a(new int[size * (size   1) / 2]   size) {}    

    void set(int i, int j, int val)               //Function to set values in array "a".
    {
        if (i >= j) {
            //i  ; j  ;                            // !!HERE!! START i,j AT 1
            //a[((i * (i - 1)) / 2)   (j - 1)] = val;
            // OR, EQUIVALENTLY
            a[((i * (i   1)) / 2)   j] = val;
        }
    }

    void display()                               //function to display values
    {
        for (int i = 1; i <= size; i  )        // START i AT 1
        {
            for (int j = 1; j <= size; j  )    // START j AT 1
            {
                if (i >= j)
                    cout << a[((i * (i - 1)) / 2)   (j - 1)] << " ";
                else
                    cout << "0 ";
            }
            cout << endl;
        }
    }
};


int main()
{
    int n = 3;                                   //dimension of matrix
    matrix a(n);
    for (int i = 0; i < n; i  )                //entering the values
    {
        int val;
        for (int j = 0; j < n; j  )
        {
            cin >> val;
            a.set(i, j, val);
        }
    }
    a.display();

    return 0;
}
 

Результирующий вывод:

 1
0
0
2
3
0
4
5
6
1 0 0
2 3 0
4 5 6
 

Комментарии:

1. Вы правы, это будет читаться лучше. Также this->size в конструкторе не слишком хорошо работает. Можно было бы вызвать входной параметр каким-либо другим способом, скажем input_size , и установить size = input_size .

2. Да, в списке инициализатора. Я обновлю свой ответ.

3. В качестве последнего шага вы могли бы заменить циклы на основе 1 циклами на cout << a[((i * (i - 1)) / 2) (j - 1)] << " "; основе 0 и cout << a[i * (i 1) / 2 j] << " ";

4. Я хочу оставить i,j = 1 исправление очевидным, чтобы оператору было легче видеть, что нужно изменить, а также чтобы код больше соответствовал тексту моего ответа. Трудно передать идею о том, что все зависит от начальных значений display() , если я изменю формулу. set() С другой стороны, внутри функции было проще представить оба подхода.