尝试在C语言中交换二维数组元素

3
我正在编写一个方法,用于交换二维数组的元素。我已经寻找了这方面的答案,但好像没有很好的答案来解决这种类型的交换问题。与传统的交换不同之处在于,我不是试图交换长度为2的数组中的整数,而是试图交换一对长度为2的数组,更具体地说是它们的指针。我对C语言还比较陌生(试图从Java转换)。当我编译下面的代码时,会收到一个警告“assignment makes integer from pointer without a cast”。非常感谢任何帮助。预先致谢。
void swap(int array[][2], int indexA, int indexB)
{
    int *temp = array[indexA];
    *array[indexA] = array[indexB];
    *array[indexB] = temp;
}

编辑:我也尝试了下面的代码来替换最后两行(不包括括号),但这导致编译器报错“将类型为‘int *’的值分配给类型为‘int [2]’的变量不兼容”。

array[indexA] = array[indexB];
array[indexB] = temp;

编辑:下面是数组声明,swap函数作为快速排序实现的一部分被调用。调用swap方法的sort方法使用与我在swap中使用的参数声明相同类型(即“int array [][2]”)。

int counts[256][2];

我们是否正确地认为这是一个真正的2D连续数组?交换的参数表明这种情况,但我想澄清一下以确保。无论哪种情况,交换数组的值都需要移动内存,除非它被嵌入到结构体中并且值分配可以为您完成。如果可能的话,您能展示至少一个从调用者那里调用此函数的例子吗? - WhozCraig
不确定您所说的“真实”,但我没有使用任何结构体。 - user786683
我的意思是你没有使用指向指针的基础。即 int **base; 用于你的二维数组,而你显然现在没有这样做,因为你发布了调用方参数。(这是一件好事。你的是一个真正的二维连续数组)。 - WhozCraig
3个回答

3

您的代码试图为具有两个元素的数组进行赋值操作,这是不允许的(对于两个元素的数组或任何其他长度的数组都是如此),除非它们被嵌套在结构中。

要移动数据,您有几个选项。如果想保留现有的原型,可以执行以下操作:

void swap(int array[][2], int indexA, int indexB)
{
    int temp[2];
    memcpy(temp, array[indexA], sizeof(temp));
    memcpy(array[indexA], array[indexB], sizeof(array[indexA]));
    memcpy(array[indexB], temp, array[indexB]);
}

或者,您可以使用元素循环:

void swap(int array[][2], int indexA, int indexB)
{
    for (size_t i=0;sizeof(array[0])/sizeof(array[0][0]);++i)
    {
        int temp = array[indexA][i];
        array[indexA][i] = array[indexB][i];
        array[indexB][i] = temp;
    }
}

最后,您也可以考虑使用类似这样的内容:

void swap(int (*a)[2], int (*b)[2])
{
    int temp[sizeof(*a)/sizeof((*a)[0])];
    memcpy(temp,a,sizeof(temp));
    memcpy(a,b,sizeof(*a));
    memcpy(b,temp,sizeof(*b));
}

在调用方面这样调用:

swap(counts[indexA], counts[indexB]);

在我看来,以下示例更易读。如下所示:
#include <stdio.h>
#include <stdlib.h>

void swap(int (*a)[2], int (*b)[2])
{
    int temp[sizeof(*a)/sizeof((*a)[0])];
    memcpy(temp,a,sizeof(temp));
    memcpy(a,b,sizeof(*a));
    memcpy(b,temp,sizeof(*b));
}

int main(int argc, char *argv[])
{
    int counts[10][2];
    int indexA = 1, indexB = 2;
    counts[indexA][0] = counts[indexA][1] = 1;
    counts[indexB][0] = counts[indexB][1] = 2;
    swap(counts[indexA], counts[indexB]);

    // better be 2 2
    printf("%d %d\n", counts[indexA][0], counts[indexA][1]);
    return 0;
}

输出

2 2

太好了!谢谢你们两个。只是一个快速的问题,对于最后一次调用memcpy,你不想让第三个参数为sizeof(array[indexB])吗? - user786683
我总是使用目标大小,尽管它们应该是相同的。如果我要超出边界,我宁愿在读取大小而不是写入大小上这样做,但在这种情况下,它不应该有影响;一切都是相同的大小。 - WhozCraig

2

这应该解决警告,如果我理解你的情况是正确的话,它会起作用。

这样做可以解决警告问题,如果我的理解是正确的话,这个方法会起作用。
int *temp = array[indexA];
array[indexA] = array[indexB];
array[indexB] = temp;

请记住,由于您有一个二维数组,因此“array[x]”的值仍然是指针。
编辑:
请尝试这种方法。
int temp[2];
memcpy(temp, array[indexA], sizeof(temp));
memcpy(array[indexA], array[indexB], sizeof(temp));
memcpy(array[indexB], temp, sizeof(temp));

我可能应该在原始帖子中写这个,但我也尝试了这个并收到了错误消息“error: incompatible types when assigning to type ‘int[2]’ from type ‘int *’”,针对最后两行代码。 - user786683
1
这不是一个指针数组。它是一个由连续值组成的真正的二维数组。 - WhozCraig
刚刚更新了我的答案,如果这是一个真正的二维数组,你将无法操纵指针。请使用memcpy代替。 - Jonatan Goebel
+1,而且样例不出奇地与我构思的一样。 - WhozCraig

0

针对我的情况进行验证,可以使用std::swap()

#include <algorithm> // C++98
#include <utility> //C++11

int array[3][2] = { {1, 2}, {3, 4}, {5, 6} };
std::swap(array[0], array[2]);
// Now it's { {5, 6}, {3, 4}, {1, 2} }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接