Как я мог поменять местами строки в 2D-массиве, определенном с помощью указателей на массив? - PullRequest
1 голос
/ 07 мая 2020

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

    double (*mat)[N];
    mat = (double(*)[N])malloc(m*sizeof(double [N]));
    ...
    swap(mat, mat+1); 

Но мой swap(mat, mat+1); меняет местами только первый элемент в каждой строке.

void swap(double **a,double **b){
    double *temp;
    temp = *a;
    *a = *b;
    *b = temp;
}

тот же своп работает, если я использую его как 2D-массив, определенный double **mat; с динамически распределенными строками и строками.

Ответы [ 2 ]

0 голосов
/ 07 мая 2020

Вы правы - вы должны передать указатель на указатель в int в качестве параметров вашей функции подкачки. Зачем? Вы хотите изменить сами указатели. Передав простой указатель, функция получит копию, и при возврате любые изменения будут потеряны. Зачем? строки содержатся в только что выделенном последовательном блоке памяти. Вы можете просто объявить массив указателей в начале каждой строки в выделенной вами коллекции данных, а затем поменять местами указатели в массиве указателей , например

#define MAXI 10
...

    int (*a)[MAXI] = calloc (MAXI, sizeof *a),      /* pointer to array  */
        *p[MAXI];                                   /* array of pointers */

    for (int i = 0; i < MAXI; i++) {                /* loop */
        *a[i] = i, a[i][MAXI-1] = i;                /* set first/last each row */
        p[i] = a[i];                                /* set pointer to each row */
    }

Теперь вы можете поменять местами указатели с помощью функции, принимающей параметры указатель на указатель , например

void swpptr (int **a, int **b)                      /* swap pointers */
{
    void *tmp = *a;
    *a = *b;
    *b = tmp;
}

, например:

    puts ("\nswapping every other row...");
    for (int i = 1; i < MAXI; i+=2)                 /* loop */
        swpptr (&p[i-1], &p[i]);                    /* swap every other row */

Короткий пример:

#include <stdio.h>
#include <stdlib.h>

#define MAXI 10

void swpptr (int **a, int **b)                      /* swap pointers */
{
    void *tmp = *a;
    *a = *b;
    *b = tmp;
}

void prn_ptr2ptr (int **p, int n)                   /* print n int per-pointer */
{
    for (int i = 0; i < MAXI; i++) {
        for (int j = 0; j < n; j++)
            printf (" %d", p[i][j]);
        putchar ('\n');
    }
}

int main (void) {

    int (*a)[MAXI] = calloc (MAXI, sizeof *a),      /* pointer to array  */
        *p[MAXI];                                   /* array of pointers */

    for (int i = 0; i < MAXI; i++) {                /* loop */
        *a[i] = i, a[i][MAXI-1] = i;                /* set first/last each row */
        p[i] = a[i];                                /* set pointer to each row */
    }

    puts ("pre-swap:");                             /* ouput pre-swap pointers */
    prn_ptr2ptr (p, MAXI);

    puts ("\nswapping every other row...");
    for (int i = 1; i < MAXI; i+=2)                 /* loop */
        swpptr (&p[i-1], &p[i]);                    /* swap every other row */

    puts ("\npost-swap:");                          /* output post-swap pointers */
    prn_ptr2ptr (p, MAXI);
}

Пример использования / вывода

$ ./bin/ptr2arrayswap
pre-swap:
 0 0 0 0 0 0 0 0 0 0
 1 0 0 0 0 0 0 0 0 1
 2 0 0 0 0 0 0 0 0 2
 3 0 0 0 0 0 0 0 0 3
 4 0 0 0 0 0 0 0 0 4
 5 0 0 0 0 0 0 0 0 5
 6 0 0 0 0 0 0 0 0 6
 7 0 0 0 0 0 0 0 0 7
 8 0 0 0 0 0 0 0 0 8
 9 0 0 0 0 0 0 0 0 9

swapping every other row...

post-swap:
 1 0 0 0 0 0 0 0 0 1
 0 0 0 0 0 0 0 0 0 0
 3 0 0 0 0 0 0 0 0 3
 2 0 0 0 0 0 0 0 0 2
 5 0 0 0 0 0 0 0 0 5
 4 0 0 0 0 0 0 0 0 4
 7 0 0 0 0 0 0 0 0 7
 6 0 0 0 0 0 0 0 0 6
 9 0 0 0 0 0 0 0 0 9
 8 0 0 0 0 0 0 0 0 8

Посмотрите все и дайте мне знать, если у вас возникнут какие-либо вопросы.

0 голосов
/ 07 мая 2020
void swap(double **a,double **b)

Это работает, потому что в этом случае вы меняете местами указатель. Но когда вы объявляете:

double (*mat)[N];

Это указатель на массив. это причина, по которой он просто меняет местами первое значение каждой строки.

Если вы хотите поменять местами два массива, просто используйте указатель (не используйте двойной указатель):

void swap( double *m1, double *m2, size_t n )
{
    for ( size_t i = 0; i < n; i++ )
    {
        double tmp = m1[i];
        m1[i] = m2[i];
        m2[i] = tmp;
    }
}

Затем, когда вы хотите поменять местами две строки:

swap(mat[0], mat[1], N);
...