无法正确排序2d字符数组

时间:2015-11-20 17:31:37

标签: c string quicksort

我从文件中取出最多100个字符串并将它们放入2d字符数组中。 STRING_LEN = 1000

char** read_from_file(char* fname, int * size)  {

    FILE *fp = fopen(fname, "r");

    int lines = 0;
    while(fscanf(fp, "%s", buff) != EOF) {
        lines++;
    }
    *size = lines;
    if(*size > 100) {
        *size = 100;
    }

    rewind(fp);

    char** file_array = malloc(*size * sizeof(char*));

        int counter;
        for(counter = 0; counter < *size; counter++) {
            file_array[counter] = malloc((STRING_LEN + 1) * sizeof(char));
        }
    for(counter = 0; counter < *size; counter++) {
           fscanf(fp, "%s", &file_array[counter]);
        }

    fclose(fp);
    return file_array;
}

快速排序将按字符串长度排序。

void quick_sort(char** words, int first, int last) {

    int pivot, j, i;
    char *temp = malloc((STRING_LEN + 1)* sizeof(char));

    if(first < last) {
        pivot = first;
        i = first;
        j = last;

        while(i < j) {
            while(strlen(&words[i]) <= strlen(&words[pivot]) && i < last)
                i++;
            while(strlen(&words[j]) > strlen(&words[pivot]))
                j--;

                if(i < j) {
                    strcpy(temp, &words[i]);
                    strcpy(&words[i], &words[j]);
                    strcpy(&words[j], temp);
                }
        }

        strcpy(temp, &words[pivot]);
        strcpy(&words[pivot], &words[j]);
        strcpy(&words[j], temp);
        free(temp);
        quick_sort(words, first, j-1);
        quick_sort(words, j+1, last);
    }
}

快速排序功能可以正常用于某些文件,但对于其他文件,信息会失真。 文件内容

car 
x 
house 
door 
ash 
a 
elephantback 
back

快速排序后

x 
a 
ash 
car 
back 
door 
house 
elephanthouse

正如您所看到的,最后一个单词已经重新排列,如果文件中有更多单词,则会变得更糟。为什么像这样将strcpy组合在一起呢?

2 个答案:

答案 0 :(得分:1)

您的排序函数中有未定义的行为:表达式&words[j]返回指向存储在words[j]的指针的指针,即它的类型为{{ 1}}而不是char **。删除所有那些address-of运算符,并仅使用char *来获取指向字符串的指针。

答案 1 :(得分:0)

这里的问题是你将字符串从一个数组复制到另一个数组,但每个数组都有足够的空间容纳它所包含的字符串。因此,例如,如果您尝试将5个字符的字符串复制到仅分配了3个字符的空间,则会超出分配的内存,从而导致未定义的行为。

不要复制完整的字符串,只需复制指针:

phantomjs

编辑:

显然我错过了所有字符串都分配了相同(大)的空间。因此,这不是未定义行为的原因。正如Joachim Pileborg在他的回答中提到的那样,使用像temp = words[i]; words[i] = words[j]; words[j] = temp; ... temp = words[pivot]; words[pivot] = words[j]; words[j] = temp; 这样的表达式是根本原因。

尽管如此,如上所述交换指针比复制实际字符串更有效,并且因为它解决了相同的错误代码行,它仍然可以解决问题。