在C中排序:交换指针会导致意外结果



在程序开始时,我为一系列char pointers分配内存:

char **buffer = calloc( 20, sizeof(char *) );

然后用户最多可以输入20个单词:

buffer[i] = calloc( 40, sizeof(char) );
fgets( buffer[i], 40, stdin )`

之后,我想对此数组进行排序。如果我使用交换函数如下:

,它可以按预期工作。
void swap(char *args1, char *args2) {
    char tmp[40];
    strcpy( tmp, args1 );
    strcpy( args1, args2 );
    strcpy( args2, tmp );
}
void sort( char **args, int count ) {
    ...
    swap( args[i], args[j] );
    ...
}

考虑到这一点后,我注意到这是CPU的浪费,因为我所要做的实际上是将指针重定向到相应的字符串。因此,我重写了交换功能:

void swap(char **args1, char **args2) {
    char *tmp = *args1;
    *args1 = *args2;
    *args2 = tmp;
}
void sort( char **args, int count ) {
    ...
    swap( &args[i], &args[j] );
    ...
}

但是,这根本不起作用,结果是非常出乎意料的,我无法弄清楚为什么(我尝试了几个printf呼叫和whats)...我的理解是,指针是重定向并因此交换的,可以说记忆看起来像这样:

(begin of char**):
100: *160
108: *200
116: *240
124: *280
...
(begin of char*):
160: Hello!
200: World!
...

我的想法是更改指针,而不是阵列以进行最低限度CPU(在这里:用108中的指针交换100中的指针):

(begin of char**):
100: *200
108: *160
116: *240
124: *280
...
(begin of char*):
160: Hello!
200: World!
...

我试图尽可能地解释这一点,如果这是太多的解释,我很抱歉。如果有人能够深入了解这一点并提供帮助!

我会很高兴!

可以在此处找到完整的代码(带有工作strcpy):http://pastie.org/5361481

您的排序功能应最终看起来像这样:

void sort(char ** args, const int start, const int end) {
        char **pivot = &args[end];
        int i = start-1, j = start;
        while( j < end ) {
                int cmp = strcmp( *pivot, args[j] );
                if( cmp > 0 )
                        swap( &args[++i], &args[j] );
                j++;
        }
        swap( &args[++i], pivot );
        if( start + 1 < i )
                sort( args, start, i - 1 );
        if( end - 1 > i )
                sort( args, i + 1, end );
}

我怀疑您没有使枢轴成为char**,而是将其作为char*。如果这样做,那么每当您进行交换时,您实际上并没有在数组中交换两个元素,而是将数组的一个元素与局部变量交换。枢轴变量最终指向另一个字符串,而不是指向另一个字符串的最后一个数组成员。

    char *pivot = args[end];
...
    swap( &args[++i], &pivot );

这是您的问题。您不想将指针与局部变量交换,而要与数组中的实际枢轴元素交换(即args+end)。在这里工作示例

最新更新