SegFault в линии реверса 2D массива - PullRequest
2 голосов
/ 08 апреля 2020

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

double** revArr = new double*[m];
for (int i = 0; i < m; i++)
    revArr[i] = new double[n];

Я заканчиваю тем, что копирую исходный массив в обращенный массив обычным способом

for (int i = 0; i < m; i++)
    for (int j = 0; j < n; j++)
        revArr[i][j] = arr[i][j];

Теперь вот идет кикер! Затем я пытаюсь перевернуть строку массива и попробовал несколько разных способов.

int start = 0, end = n;
for (int i = 0; i < m; i++) {
    while (start < end)
    {
        double *temp = revArr[start];
        revArr[start] = revArr[end];
        revArr[end] = temp;
        start++; end--;
    }
}

Что, поскольку массив представляет собой массив типа double *, выдает SegFault, в котором я не совсем уверен как исправить!

Я пытался использовать std::swap, я пытался использовать std::reverse, я не совсем уверен, куда обратиться.

Минимальный воспроизводимый пример:

#include <iostream>

int main() {
    int m = 4, n = 4;

    double* arr = new double[m];
    for (int i = 0; i < m; i++)
        arr[i] = new double[n];

    for (int i = 0; i < m; i++)
        for (int j = 0; j < n; j++)
            arr[i][j] = i + j;

    int start = 0; end = n;
    for (int i = 0; i < m; i++) {
        while (start < end)
        {
            double *temp = arr[start];
            arr[start] = arr[end];
            arr[end] = temp;
            start++; end--;
        }
    }
}

Ответы [ 3 ]

4 голосов
/ 08 апреля 2020

Редактировать: Из комментария ОП ниже видно, что он хотел поменять местами цифры в каждой строке вместо самих строк. Код должен быть изменен на:

for (int i = 0; i < m; i++) {
    for (int j = 0; j < n / 2; j++) {
        std::swap(arr[i][j], arr[i][n - j - 1]);
    }
}

Вот несколько советов от меня:

  1. Использовать стандартную библиотеку : стандартная библиотека существует по причине, и нет причины не использовать он . Например, вы можете легко перевернуть массив следующим образом:
for (int i = 0; i < m; i++)
    std::reverse_copy(arr[i], arr[i] + n, revArr[i]); // if you are copying the reversed array onto another

ИЛИ

for (int i = 0; i < m; i++)
    std::reverse(arr[i], arr[i] + n);              // Copy the reversed result onto the same array
Всегда не забывайте delete[] свои new[] -элементные массивы после использования или рассмотрите возможность использования интеллектуальных указателей или даже std::vector. В этом случае:
for (int i = 0; i < m; i++)
    delete[] arr[i];
delete[] arr;
1 голос
/ 08 апреля 2020

У меня это нормально работает:

int m = 4, n = 4;

double** arr = new double*[m];
for (int i = 0; i < m; i++)
    arr[i] = new double[n];

for (int i = 0; i < m; i++)
    for (int j = 0; j < n; j++)
        arr[i][j] = static_cast<double>(i) + static_cast<double>(j);

for (int i = 0; i < m; i++)
    for (int j = 0; j < (n / 2); j++) {//note : i think, a "for" loop is more explicit
        double temp = arr[i][j];
        arr[i][j] = arr[i][n - j - 1];
        arr[i][n - j - 1] = temp;
    }

for (int i = 0; i < m; i++)
    delete[] arr[i];
delete[] arr;

Но, как уже было сказано, лучше использовать стандартную библиотеку.

0 голосов
/ 08 апреля 2020

Если вы хотите поменять число в каждой (отдельной) строке, вам не следует поменять местами указатели. Каждый указатель будет находиться в начале каждой строки, и вы можете получить доступ к n-му элементу m-й строки в виде простого double значения, arr[m][n].

Далее, обратите внимание на последний элемент массива с n элементами имеет индекс n-1, , а не n, поэтому вы должны инициализировать end как n-1, или arr[end] будет вне -предельные значения при первом запуске через обмен l oop (что является причиной исключения SegFault).

Затем вам необходимо сбросить start и end в начале каждый обмен строк - то есть внутри внешний for l oop.

Итак, учитывая вышесказанное, ваш код обращения должен выглядеть (примерно) так:

    for (int i = 0; i < m; i++) {
        int start = 0; end = n - 1; // These need to be reset for EACH LINE.
        while (start < end)
        {
            double temp = arr[m][start];
            arr[m][start] = arr[m][end];
            arr[m][end] = temp;
            start++; end--;
        }
    }

Кроме того, вам также необходимо освободить память, выделенную вашим операторам new, когда вы закончите работу с данными. Итак, в (или около) конце вашего main, вы должны иметь такой код:

//...
    for (int i = 0; i < m; i++)
        delete[] arr[i]; // Delete this 'line'
    delete[] arr; // And the delete the array of line pointers
    return 0; // Good practice to explicitly return 0 (success code) from main!
}

И, наконец, вы будете далеко лучше использовать std::vector контейнер, а не динамически создаваемые массивы. Вот как вы могли бы сделать это с std::vector:

#include <iostream>
#include <vector>
#include <algorithm> // For std::reverse
int main()
{
    size_t m = 4, n = 4;
    // Create/populate vectors:
    std::vector< std::vector<double> > arr(m);
    for (size_t i = 0; i < m; i++) {
        for (size_t j = 0; j < n; j++) {
            arr[i].push_back(double(i + j));
        }
    }
    // Reverse each line:
    for (size_t i = 0; i < m; i++) {
        std::reverse(arr[i].begin(), arr[i].end());
    }
    // Display results:
    for (auto a: arr) {
        for (auto d : a) {
            std::cout << d << " ";
        }
        std::cout << std::endl;
    }

    return 0;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...