2012-11-10 82 views
1

给定任何类型的数组(本例中为整数)和一个Map,该数组指示应该在数组中交换哪些索引。我试图做一个干净的交换,但遇到我使用memcpy的方式的问题。使用memcpy问题进行C置换

这是我迄今为止:

目标:给定的[1,3,-1,2]的数据阵列和[[0,3的映射],[3,2], [2,1],[1,0]],一个干净的排列将是[3,-1,2,1]。

我当前的实现:0 3 -1 2 ...我想我有一个错误的地方。

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <math.h> 
#define MAP_SIZE 4 

typedef struct MapEntry { 
    int indexFrom; 
    int indexTo; 
} MapEntry; 

typedef MapEntry * Map; 

int permute(void *data, int nblobs, int szblob, const Map map); 

void build_map(Map); 
void build_data(int *); 
int is_map_valid(Map); 
void print_map(Map); 
int is_valid(Map); 

int map_comparator(const void * a, const void * b); 

int main(int argc, char const *argv[]) 
{ 
    int nblobs, * data, i; 
    size_t szblob; 
    Map map = (Map)malloc(sizeof(Map)); 
    data = (int *) malloc(sizeof(int) * 4); 

    build_map(map); 

    data[0] = 1; 
    data[1] = 3; 
    data[2] = -1; 
    data[3] = 2; 

    nblobs = 4; 
    szblob = sizeof(int); 

    if (!permute(data, nblobs, szblob, map)) { 
     printf("Invalid Map\n"); 
     return 0; 
    } 

    i = 0; 
    for (i = 0; i < szblob; ++i) { 
     printf("%d ", data[i]); 
    } 

    return 0; 
} 

void print_map(Map map){ 
    int i; 
    for (i = 0; i < MAP_SIZE; ++i) { 
     printf("[%d - %d]\n", map[i].indexFrom, map[i].indexTo); 
    } 
} 

int map_comparator(const void *a, const void *b) 
{ 
    const MapEntry *s1 = a; 
    const MapEntry *s2 = b; 
    if (s2->indexFrom != s1->indexFrom) { 
     return s1->indexFrom - s2->indexFrom; 
    } else { 
     return s1->indexTo - s2->indexTo; 
    } 
} 

int is_map_valid(Map map) { 
    int i,j; 
    for (i = 1; i < MAP_SIZE; ++i){ 
     j = i - 1; 
     if (map[j].indexFrom == map[i].indexFrom) 
      return 0; 
     if (map[j].indexTo == map[i].indexTo) 
      return 0; 
    } 
    return 1; 
} 

int is_valid(Map map) { 
    qsort(map, MAP_SIZE, sizeof(MapEntry), map_comparator); 
    if (!is_map_valid(map)) return 0; 
    return 1; 
} 


int permute(void *data, int nblobs, int szblob, const Map map){ 
    int i, tmpFrom, tmpTo; 
    void * a = (void *)malloc(szblob); 
    char *p = data; 

    /* check if map has duplicate keys */ 
    /* sort the list, then check whether or not the map is valid */ 
    if (!is_valid(map)) return 0; 
    /* where issues occur */ 

    for (i = 0; i < nblobs; ++i){ 

     tmpFrom = map[i].indexFrom; 

     tmpTo = map[i].indexTo; 

     memcpy(a, &p[tmpFrom*szblob], szblob); 

     memcpy(&p[tmpFrom*szblob], &p[tmpTo*szblob], szblob); 

     memcpy(&p[tmpTo*szblob], a, szblob); 

    } 

    return 1; 

} 
/* build mapping */ 
void build_map(Map map){ 
    map[0].indexFrom = 0; 
    map[0].indexTo = 3; 
    map[1].indexFrom = 3; 
    map[1].indexTo = 2; 
    map[2].indexFrom = 2; 
    map[2].indexTo = 1; 
    map[3].indexFrom = 1; 
    map[3].indexTo = 0; 

} 
+0

为什么MapEntry中的索引是“int *”而不是普通的“int”?特别是在64位机器上,在结构中使用动态分配的指针而不是简单的'int'会浪费内存的_lot_(如果MapEntry是动态分配的,则使用类似48字节的动态分配开销而不是16个字节)或8 if不是这样)。 –

+0

我不知道这一点。代码现在应该反映固定的结构。首先是 –

回答

5

你是默认启用和allowspointer arithmetics上的指针作废和指针由治疗无效的函数或大小为1。该扩展功能非标准GCC扩展的受害者可以通过使用-std选项(例如-std=c99(详情请参见gcc manual page))将C标准指定为C99来禁用。或者,您可以通过指定-Wpointer-arith选项,让gcc对这些情况发出警告。

回到问题,考虑当你写&data[tmpFrom]会发生什么。采用data指向的地址,然后将tmpFrom字节添加到该地址。你想要的是添加tmpFrom * sizeof(int)字节。为此,您必须根据tmpFrom的值和int类型的值手动计算所需的字节数,或者将data指针声明为指向int类型的指针。第二个是首选的方法,但如果你真的希望你的函数支持任意数据类型,那么你必须回到更困难的第一种方法。

下面是铛产生警告的列表(通常好了很多与诊断):

$ clang -Wall -pedantic -o test ./test.c 
./test.c:109:18: warning: subscript of a pointer to void is a GNU extension [-pedantic,-Wpointer-arith] 
       memcpy(a, &data[tmpFrom], szblob); 
       ~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~ 
/usr/include/secure/_string.h:55:36: note: expanded from macro 'memcpy' 
    ? __builtin___memcpy_chk (dest, src, len, __darwin_obsz0 (dest))  \ 
           ^
./test.c:109:13: warning: ISO C forbids taking the address of an expression of type 'void' [-pedantic] 
       memcpy(a, &data[tmpFrom], szblob); 
       ~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~ 
/usr/include/secure/_string.h:55:36: note: expanded from macro 'memcpy' 
    ? __builtin___memcpy_chk (dest, src, len, __darwin_obsz0 (dest))  \ 
           ^
./test.c:109:18: warning: subscript of a pointer to void is a GNU extension [-pedantic,-Wpointer-arith] 
       memcpy(a, &data[tmpFrom], szblob); 
       ~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~ 
/usr/include/secure/_string.h:56:33: note: expanded from macro 'memcpy' 
    : __inline_memcpy_chk (dest, src, len)) 
           ^
./test.c:109:13: warning: ISO C forbids taking the address of an expression of type 'void' [-pedantic] 
       memcpy(a, &data[tmpFrom], szblob); 
       ~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~ 
/usr/include/secure/_string.h:56:33: note: expanded from macro 'memcpy' 
    : __inline_memcpy_chk (dest, src, len)) 
           ^
./test.c:111:15: warning: subscript of a pointer to void is a GNU extension [-pedantic,-Wpointer-arith] 
       memcpy(&data[tmpFrom], &data[tmpTo], szblob); 
       ~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
/usr/include/secure/_string.h:54:21: note: expanded from macro 'memcpy' 
    ((__darwin_obsz0 (dest) != (size_t) -1)        \ 
        ^
/usr/include/secure/_common.h:38:55: note: expanded from macro '__darwin_obsz0' 
#define __darwin_obsz0(object) __builtin_object_size (object, 0) 
                 ^~~~~~ 
./test.c:111:10: warning: ISO C forbids taking the address of an expression of type 'void' [-pedantic] 
       memcpy(&data[tmpFrom], &data[tmpTo], szblob); 
       ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
/usr/include/secure/_string.h:54:21: note: expanded from macro 'memcpy' 
    ((__darwin_obsz0 (dest) != (size_t) -1)        \ 
        ^
/usr/include/secure/_common.h:38:55: note: expanded from macro '__darwin_obsz0' 
#define __darwin_obsz0(object) __builtin_object_size (object, 0) 
                 ^~~~~~ 
./test.c:111:15: warning: subscript of a pointer to void is a GNU extension [-pedantic,-Wpointer-arith] 
       memcpy(&data[tmpFrom], &data[tmpTo], szblob); 
       ~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
/usr/include/secure/_string.h:55:30: note: expanded from macro 'memcpy' 
    ? __builtin___memcpy_chk (dest, src, len, __darwin_obsz0 (dest))  \ 
          ^
./test.c:111:10: warning: ISO C forbids taking the address of an expression of type 'void' [-pedantic] 
       memcpy(&data[tmpFrom], &data[tmpTo], szblob); 
       ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
/usr/include/secure/_string.h:55:30: note: expanded from macro 'memcpy' 
    ? __builtin___memcpy_chk (dest, src, len, __darwin_obsz0 (dest))  \ 
          ^
./test.c:111:31: warning: subscript of a pointer to void is a GNU extension [-pedantic,-Wpointer-arith] 
       memcpy(&data[tmpFrom], &data[tmpTo], szblob); 
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~ 
/usr/include/secure/_string.h:55:36: note: expanded from macro 'memcpy' 
    ? __builtin___memcpy_chk (dest, src, len, __darwin_obsz0 (dest))  \ 
           ^
./test.c:111:26: warning: ISO C forbids taking the address of an expression of type 'void' [-pedantic] 
       memcpy(&data[tmpFrom], &data[tmpTo], szblob); 
       ~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~ 
/usr/include/secure/_string.h:55:36: note: expanded from macro 'memcpy' 
    ? __builtin___memcpy_chk (dest, src, len, __darwin_obsz0 (dest))  \ 
           ^
./test.c:111:15: warning: subscript of a pointer to void is a GNU extension [-pedantic,-Wpointer-arith] 
       memcpy(&data[tmpFrom], &data[tmpTo], szblob); 
       ~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
/usr/include/secure/_string.h:55:62: note: expanded from macro 'memcpy' 
    ? __builtin___memcpy_chk (dest, src, len, __darwin_obsz0 (dest))  \ 
                  ^
/usr/include/secure/_common.h:38:55: note: expanded from macro '__darwin_obsz0' 
#define __darwin_obsz0(object) __builtin_object_size (object, 0) 
                 ^~~~~~ 
./test.c:111:10: warning: ISO C forbids taking the address of an expression of type 'void' [-pedantic] 
       memcpy(&data[tmpFrom], &data[tmpTo], szblob); 
       ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
/usr/include/secure/_string.h:55:62: note: expanded from macro 'memcpy' 
    ? __builtin___memcpy_chk (dest, src, len, __darwin_obsz0 (dest))  \ 
                  ^
/usr/include/secure/_common.h:38:55: note: expanded from macro '__darwin_obsz0' 
#define __darwin_obsz0(object) __builtin_object_size (object, 0) 
                 ^~~~~~ 
./test.c:111:15: warning: subscript of a pointer to void is a GNU extension [-pedantic,-Wpointer-arith] 
       memcpy(&data[tmpFrom], &data[tmpTo], szblob); 
       ~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
/usr/include/secure/_string.h:56:27: note: expanded from macro 'memcpy' 
    : __inline_memcpy_chk (dest, src, len)) 
         ^
./test.c:111:10: warning: ISO C forbids taking the address of an expression of type 'void' [-pedantic] 
       memcpy(&data[tmpFrom], &data[tmpTo], szblob); 
       ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
/usr/include/secure/_string.h:56:27: note: expanded from macro 'memcpy' 
    : __inline_memcpy_chk (dest, src, len)) 
         ^
./test.c:111:31: warning: subscript of a pointer to void is a GNU extension [-pedantic,-Wpointer-arith] 
       memcpy(&data[tmpFrom], &data[tmpTo], szblob); 
       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~ 
/usr/include/secure/_string.h:56:33: note: expanded from macro 'memcpy' 
    : __inline_memcpy_chk (dest, src, len)) 
           ^
./test.c:111:26: warning: ISO C forbids taking the address of an expression of type 'void' [-pedantic] 
       memcpy(&data[tmpFrom], &data[tmpTo], szblob); 
       ~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~ 
/usr/include/secure/_string.h:56:33: note: expanded from macro 'memcpy' 
    : __inline_memcpy_chk (dest, src, len)) 
           ^
./test.c:113:15: warning: subscript of a pointer to void is a GNU extension [-pedantic,-Wpointer-arith] 
       memcpy(&data[tmpTo], a, szblob); 
       ~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~ 
/usr/include/secure/_string.h:54:21: note: expanded from macro 'memcpy' 
    ((__darwin_obsz0 (dest) != (size_t) -1)        \ 
        ^
/usr/include/secure/_common.h:38:55: note: expanded from macro '__darwin_obsz0' 
#define __darwin_obsz0(object) __builtin_object_size (object, 0) 
                 ^~~~~~ 
./test.c:113:10: warning: ISO C forbids taking the address of an expression of type 'void' [-pedantic] 
       memcpy(&data[tmpTo], a, szblob); 
       ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~ 
/usr/include/secure/_string.h:54:21: note: expanded from macro 'memcpy' 
    ((__darwin_obsz0 (dest) != (size_t) -1)        \ 
        ^
/usr/include/secure/_common.h:38:55: note: expanded from macro '__darwin_obsz0' 
#define __darwin_obsz0(object) __builtin_object_size (object, 0) 
                 ^~~~~~ 
./test.c:113:15: warning: subscript of a pointer to void is a GNU extension [-pedantic,-Wpointer-arith] 
       memcpy(&data[tmpTo], a, szblob); 
       ~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~ 
/usr/include/secure/_string.h:55:30: note: expanded from macro 'memcpy' 
    ? __builtin___memcpy_chk (dest, src, len, __darwin_obsz0 (dest))  \ 
          ^
./test.c:113:10: warning: ISO C forbids taking the address of an expression of type 'void' [-pedantic] 
       memcpy(&data[tmpTo], a, szblob); 
       ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~ 
/usr/include/secure/_string.h:55:30: note: expanded from macro 'memcpy' 
    ? __builtin___memcpy_chk (dest, src, len, __darwin_obsz0 (dest))  \ 
          ^
./test.c:113:15: warning: subscript of a pointer to void is a GNU extension [-pedantic,-Wpointer-arith] 
       memcpy(&data[tmpTo], a, szblob); 
       ~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~ 
/usr/include/secure/_string.h:55:62: note: expanded from macro 'memcpy' 
    ? __builtin___memcpy_chk (dest, src, len, __darwin_obsz0 (dest))  \ 
                  ^
/usr/include/secure/_common.h:38:55: note: expanded from macro '__darwin_obsz0' 
#define __darwin_obsz0(object) __builtin_object_size (object, 0) 
                 ^~~~~~ 
./test.c:113:10: warning: ISO C forbids taking the address of an expression of type 'void' [-pedantic] 
       memcpy(&data[tmpTo], a, szblob); 
       ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~ 
/usr/include/secure/_string.h:55:62: note: expanded from macro 'memcpy' 
    ? __builtin___memcpy_chk (dest, src, len, __darwin_obsz0 (dest))  \ 
                  ^
/usr/include/secure/_common.h:38:55: note: expanded from macro '__darwin_obsz0' 
#define __darwin_obsz0(object) __builtin_object_size (object, 0) 
                 ^~~~~~ 
./test.c:113:15: warning: subscript of a pointer to void is a GNU extension [-pedantic,-Wpointer-arith] 
       memcpy(&data[tmpTo], a, szblob); 
       ~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~ 
/usr/include/secure/_string.h:56:27: note: expanded from macro 'memcpy' 
    : __inline_memcpy_chk (dest, src, len)) 
         ^
./test.c:113:10: warning: ISO C forbids taking the address of an expression of type 'void' [-pedantic] 
       memcpy(&data[tmpTo], a, szblob); 
       ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~ 
/usr/include/secure/_string.h:56:27: note: expanded from macro 'memcpy' 
    : __inline_memcpy_chk (dest, src, len)) 
         ^
24 warnings generated. 

一旦上述警告是固定的,它应该有工作。但是,还有两个问题...

第一个问题是不正确的预期结果。它应该是3, -1, 1, 2而不是3, -1, 2, 1。该映射将被排序是这样的:

0,3 
1,0 
2,1 
3,2 

而且排列应分四步进行:

1) 2, 3, -1, 1 
2) 3, 2, -1, 1 
3) 3, -1, 2, 1 
4) 3, -1, 1, 2 

第二个问题是不正确排序。通过执行两种排序,首先对“from”值和第二个“to”值进行排序,最终得到一个仅由“to”排序的映射(您调用的最后一个排序)。我们应该做的是使用谓词来比较每个元素的“from”和“to”。例如:

int map_comparator(const void *a, const void *b) 
{ 
    const MapEntry *s1 = a; 
    const MapEntry *s2 = b; 
    if (*s2->indexFrom != *s1->indexFrom) { 
     return *s1->indexFrom - *s2->indexFrom; 
    } else { 
     return *s1->indexTo - *s2->indexTo; 
    } 
} 

一旦上述问题得到解决,一切都会奏效。除此之外,您的代码中只有几条建议可能会有所帮助:

  1. 您正在使用太多的动态分配方式。考虑重新思考你是如何做到的。例如,我看不到需要有indexFromindexTo字段的MapEntry结构动态分配。
  2. 您有不必要的剧照到void *。例如:void * a = (void *)malloc(szblob);应该只是void *a = malloc(szblob);
  3. 不需要从void *转换为其他指针类型,如int *。这在C中没有必要,其中void *指针可以隐式转换为其他类型的指针。但是,这不适用于C++。
  4. 不要typedef结构,除非目标是创建一个不透明类型(这不是你的情况)。键入struct可能看起来像很多输入,但它对于那些阅读您的代码的C开发人员来说是一个很好的提示。例如,请参阅Linux Kernel Coding Style的第5章以获得很好的解释。

我鼓励你自己解决您的代码,但这里是你的代码以最小的必要的修改,使其工作,供大家参考:

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <math.h> 
#define MAP_SIZE 4 

typedef struct MapEntry { 
    int * indexFrom; 
    int * indexTo; 
} MapEntry; 

typedef MapEntry * Map; 

int permute(void *data, int nblobs, int szblob, const Map map); 

void build_map(Map); 
void build_data(int *); 
int is_map_valid(Map); 
void print_map(Map); 
int is_valid(Map); 

int map_comparator(const void * a, const void * b); 

int main(int argc, char const *argv[]) 
{ 
    int nblobs, * data, i; 
    size_t szblob; 
    Map map = (Map)malloc(sizeof(Map)); 
    data = (int *) malloc(sizeof(int) * 4); 

    build_map(map); 

    data[0] = 1; 
    data[1] = 3; 
    data[2] = -1; 
    data[3] = 2; 

    nblobs = 4; 
    szblob = sizeof(int); 

    if (!permute(data, nblobs, szblob, map)) { 
     printf("Invalid Map\n"); 
     return 0; 
    } 

    i = 0; 
    for (i = 0; i < szblob; ++i) { 
     printf("%d ", data[i]); 
    } 

    return 0; 
} 

void print_map(Map map){ 
    int i; 
    for (i = 0; i < MAP_SIZE; ++i) { 
     printf("[%d - %d]\n", *map[i].indexFrom, *map[i].indexTo); 
    } 
} 

int map_comparator(const void *a, const void *b) 
{ 
    const MapEntry *s1 = a; 
    const MapEntry *s2 = b; 
    if (*s2->indexFrom != *s1->indexFrom) { 
     return *s1->indexFrom - *s2->indexFrom; 
    } else { 
     return *s1->indexTo - *s2->indexTo; 
    } 
} 

int is_map_valid(Map map) { 
    int i,j; 
    for (i = 1; i < MAP_SIZE; ++i){ 
     j = i - 1; 
     if (*map[j].indexFrom == *map[i].indexFrom) 
      return 0; 
     if (*map[j].indexTo == *map[i].indexTo) 
      return 0; 
    } 
    return 1; 
} 

int is_valid(Map map) { 
    qsort(map, MAP_SIZE, sizeof(MapEntry), map_comparator); 
    if (!is_map_valid(map)) return 0; 
    return 1; 
} 


int permute(void *data, int nblobs, int szblob, const Map map){ 
    int i, tmpFrom, tmpTo; 
    void * a = (void *)malloc(szblob); 
    char *p = data; 

    /* check if map has duplicate keys */ 
    /* sort the list, then check whether or not the map is valid */ 
    if (!is_valid(map)) return 0; 
    /* where issues occur */ 

    for (i = 0; i < nblobs; ++i){ 

     tmpFrom = *map[i].indexFrom; 

     tmpTo = *map[i].indexTo; 

     memcpy(a, &p[tmpFrom*szblob], szblob); 

     memcpy(&p[tmpFrom*szblob], &p[tmpTo*szblob], szblob); 

     memcpy(&p[tmpTo*szblob], a, szblob); 

    } 

    return 1; 

} 
/* build mapping */ 
void build_map(Map map){ 
    int i; 
    for (i = 0; i < MAP_SIZE; ++i) { 
     map[i].indexFrom = (int *)malloc(sizeof(int)); 
     map[i].indexTo = (int *)malloc(sizeof(int)); 
    } 

    *map[0].indexFrom = 0; 
    *map[0].indexTo = 3; 

    *map[1].indexFrom = 3; 
    *map[1].indexTo = 2; 

    *map[2].indexFrom = 2; 
    *map[2].indexTo = 1; 

    *map[3].indexFrom = 1; 
    *map[3].indexTo = 0; 

} 

希望它能帮助。保持温暖,祝你好运!

+0

。荒谬有用的职位,谢谢。其次,1)固定2)我将删除这些3)这是为了使数据类型抽象。因此映射重新排序操作可以在任何类型上执行,而不仅仅是整数。4)非常有趣的是,我认为typedef'结构有助于可读性,但是顶部和底部的整个命名让我感到困惑。感谢您的比较代码。 –

1

除了易于被Vlad Lazarenko列举的问题之外,我认为你有一些内存分配问题。 (我不是在谈论在结构指针所需的过度分配,无论)

main(),您有:

Map map = (Map)malloc(sizeof(Map)); 

这种分配的一个MapEntry *的大小map,而你可能想要分配至少MapEntry的空间,并且可能为4 MapEntry值分配空间。然后调用:

build_map(map); 

,并在函数内部,你对待它,如果你有4个MapEntry值的数组。您应该,因此,写:

Map map = (Map)malloc(MAP_SIZE * sizeof(*map)); 

如果运行valgrind下的代码,它肯定会告诉你关于这个问题了。那些在C语言中使用与malloc()一起使用的程序员的程序员是非法的;我不是其中之一(我经常使用自己的演员)。但要注意批评的原因。

您可以通过使用简化代码:

int data[MAP_SIZE] = { 1, 3, -1, 2 }; 

或许这只是在使用malloc()尽可能多地练习。

你甚至可以走得急,并避免任何动态内存分配:

typedef struct MapEntry 
{ 
    int indexFrom; 
    int indexTo; 
} MapEntry; 

int main(void) // argc, argv unused 
{ 
    int nblobs, i; 
    size_t szblob; 
    MapEntry map[] = { { 0, 3 }, { 3, 2 }, { 3, 1 }, { 1, 0 } }; 
    enum { NUM_MAPENTRIES = sizeof(map)/sizeof(map[0]) }; 
    int data[]  = { 1, 3, -1, 2 }; 
    enum { NUM_DATAENTRIES = sizeof(data)/sizeof(data[0]) }; 

我觉得你permute()功能需要多一个参数 - 通过映射条目的数量。


还有一个问题;您的is_valid()函数会对您的map数组进行排序(排序),因此main()中指定的操作顺序不是在permute()中执行的操作顺序。此外,我认为,is_valid_map()检查是用来检查任何两个映射是否与索引相同或相同。你可以在没有排序的情况下做到这一点,尽管用O(N )复杂度代替O(N log N)复杂度。但是在做这件事时你不会排列地图。

我结束了:

#include <assert.h> 
#include <stdio.h> 
#include <string.h> 

typedef struct MapEntry 
{ 
    int indexFrom; 
    int indexTo; 
} MapEntry; 

static int permute(void *data, size_t nblobs, size_t szblob, MapEntry *map, size_t szmap); 
static void print_data(const char *tag, int *data, size_t ndata); 
static void print_map(const char *tag, MapEntry *map, size_t szmap); 

int main(void) 
{ 
    MapEntry map[] = { { 0, 3 }, { 3, 2 }, { 3, 1 }, { 1, 0 } }; 
    enum { NUM_MAPENTRIES = sizeof(map)/sizeof(map[0]) }; 
    int data[]  = { 1, 3, -1, 2 }; 
    enum { NUM_DATAENTRIES = sizeof(data)/sizeof(data[0]) }; 

    print_data("Initial data", data, NUM_DATAENTRIES); 
    print_map(" Initial map", map, NUM_MAPENTRIES); 

    if (!permute(data, NUM_DATAENTRIES, sizeof(int), map, NUM_MAPENTRIES)) 
    { 
     printf("Invalid Map\n"); 
     return 0; 
    } 

    print_data("Result", data, NUM_DATAENTRIES); 

    return 0; 
} 

static void print_data(const char *tag, int *data, size_t ndata) 
{ 
    const char *pad = ": "; 
    fputs(tag, stdout); 
    for (size_t i = 0; i < ndata; ++i) 
    { 
     printf("%s%2d", pad, data[i]); 
     pad = ", "; 
    } 
    putchar('\n'); 
} 

static void print_map(const char *tag, MapEntry * map, size_t szmap) 
{ 
    printf("%s:", tag); 
    for (size_t i = 0; i < szmap; ++i) 
     printf(" [%d - %d]", map[i].indexFrom, map[i].indexTo); 
    putchar('\n'); 
} 

static int is_map_valid(MapEntry *map, size_t szmap) 
{ 
    for (size_t i = 0; i < szmap; ++i) 
    { 
     for (size_t j = i + 1; j < szmap; ++j) 
     { 
      if ((map[j].indexFrom == map[i].indexFrom) && 
       (map[j].indexTo == map[i].indexTo)) 
      { 
       printf("map[%zu].indexFrom = %d = map[%zu].indexFrom = %d\n", 
         j, map[j].indexFrom, i, map[i].indexFrom); 
       printf("map[%zu].indexTo = %d = map[%zu].indexTo = %d\n", 
         j, map[j].indexTo, i, map[i].indexTo); 
       return 0; 
      } 
     } 
    } 
    return 1; 
} 

static int permute(void *data, size_t nblobs, size_t szblob, MapEntry *map, size_t szmap) 
{ 
    char tmp[szblob]; 
    char *base = data; 

    if (!is_map_valid(map, szmap)) 
     return 0; 

    for (size_t i = 0; i < szmap; ++i) 
    { 
     print_map("Switch", &map[i], 1); 
     print_data("Before", data, nblobs); 
     size_t tmpFr = map[i].indexFrom; 
     size_t tmpTo = map[i].indexTo; 
     assert(tmpFr < nblobs && tmpTo < nblobs); 
     char *src = base + (tmpFr * szblob); 
     char *tgt = base + (tmpTo * szblob); 
     memcpy(tmp, src, szblob); 
     memcpy(src, tgt, szblob); 
     memcpy(tgt, tmp, szblob); 
     print_data(" After", data, nblobs); 
    } 

    return 1; 
} 

输出示例:

Initial data: 1, 3, -1, 2 
Initial map: [0 - 3] [3 - 2] [3 - 1] [1 - 0] 
Switch: [0 - 3] 
Before: 1, 3, -1, 2 
After: 2, 3, -1, 1 
Switch: [3 - 2] 
Before: 2, 3, -1, 1 
After: 2, 3, 1, -1 
Switch: [3 - 1] 
Before: 2, 3, 1, -1 
After: 2, -1, 1, 3 
Switch: [1 - 0] 
Before: 2, -1, 1, 3 
After: -1, 2, 1, 3 
Result: -1, 2, 1, 3 

这是你所期望的结果不同,但我不知道你如何让你从开始期待什么数据。

+0

+1,我注意到了这些,但却懒得继续:) – 2012-11-10 06:36:04