C Radix排序数组的字符串

时间:2016-11-20 19:40:03

标签: c string sorting counting radix

首先,我要感谢你,让我慢慢来。我也想为我的英语道歉,这不是我的第一语言。

我编写了一个小程序,它使用基数排序和计数排序对字符串数组进行排序。问题是它无法正常工作。当所有字符串的长度相同时,输出是正确的,但是当字符串名称超过10个字符时,程序给出错误的答案。我发现在NAJDLUZSZY函数中增加sortPozycyjne后,一切正常,但我不明白为什么。

以下是代码:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>      // na potrzeby tolower

#define DLUGOSC_NAPISU  30
#define ILOSC_NAPISOW   7
#define ZAKRES_WARTOSCI_A 128

char **A; // input array to sort
char **B; // output sorted array
char **pom;

// Sortowanie pozycyjne - tablice indeksowane od 1

void sortPrzezZliczanie(char **A, char **B, int ilosc, int pozycja) { //counting sort
    int i, j;
    int C[2048]; // pomocnicza tablica 'licznikow', ile razy wystepuje jaki znak w A

    for (i = 0; i <= ZAKRES_WARTOSCI_A; i++)
        C[i] = 0;
    for (j = 1; j <= ilosc; j++)
         C[A[j][pozycja]] += 1;
    for (i = 1; i <= ZAKRES_WARTOSCI_A; i++)
         C[i] = C[i] + C[i - 1];
    for (j = ilosc; j > 0; j--) {
        B[C[A[j][pozycja]]] = A[j];
        C[A[j][pozycja]] = C[A[j][pozycja]] - 1;
    }
}

void sortPozycyjne(char **A, char **B, int NAJDLUZSZY) {   // radix sort
    int i;
    for (i = NAJDLUZSZY; i >= 0; i--) {
        sortPrzezZliczanie(A, B, ILOSC_NAPISOW, i);
        pom = A; A = B; B = pom;     // input array to output
    }
}

void drukuj(char **tablica, int ilosc) {
    FILE *fp;

    if ((fp = fopen("output.txt", "w")) == NULL) {
        printf("Nie mogê otworzyæ pliku input.txt do zapisu!\n");
        return;
    }

    int i;
    for (i = 1; i <= ilosc; i++)
        //tablica[i]=toupper(tablica[i]);               
        fprintf(fp, "%s \n", tablica[i]);

    fclose(fp);
}

void czytaj(char **tablica, int ilosc) {
    FILE *fp;
    //int tmp;
    if ((fp = fopen("input.txt", "r")) == NULL) {
        printf("Nie mogê otworzyæ pliku output.txt do zapisu!\n");
        return;
    }

    char slowo[DLUGOSC_NAPISU];
    int i, j;
    for (i = 1; i <= ilosc; i++) {
        //fscanf (fp, "%d", &tmp);
        fscanf(fp, "%s", &slowo);
        // for (j = 0; j < strlen(slowo); j++)
        //     slowo[j] = tolower(slowo[j]); // zmniejszam wielkosc litery
        tablica[i] = (char*) malloc(sizeof(char) * DLUGOSC_NAPISU);
        strcpy(tablica[i], slowo);
    }
    fclose (fp);
}

int najdluzszyNapis(char **tablica, int ilosc) {  // finds maximum length of word
    int i, max = 0;
    for (i = 1; i <= ilosc; i++)
        if (strlen(tablica[i]) > max)
            max = strlen(tablica[i]);
    return max;
}

void taSamaDlugosc(char **tablica, int ilosc, int NAJDLUZSZY) {  
    // if string is lower than maximum then fill with nulls

    int i, j;
    for (i = 1; i <= ilosc; i++)
        for (j = 0; j <= NAJDLUZSZY; j++)
            if (!(96 < (int)tablica[i][j] && (int)tablica[i][j] < 123)) 
                tablica[i][j] = 0;
}

int main() {
    A = (char**)malloc(ILOSC_NAPISOW * sizeof(char*));
    B = (char**)malloc(ILOSC_NAPISOW * sizeof(char*));
    pom = (char**)malloc(ILOSC_NAPISOW * sizeof(char*));
    int NAJDLUZSZY; // length of the longest word

    printf("Wpisz napisy do tablicy A:\n");
    czytaj(A, ILOSC_NAPISOW);
    NAJDLUZSZY = najdluzszyNapis(A, ILOSC_NAPISOW);
    taSamaDlugosc(A, ILOSC_NAPISOW, NAJDLUZSZY);

    sortPozycyjne(A, B, NAJDLUZSZY);

    printf("\nSlownikowo posortowana tablica:\n");
    drukuj(B, ILOSC_NAPISOW);
    printf("%d", NAJDLUZSZY);
    return 0;
}

我为波兰的变量和函数名称道歉。 减少NAJDLUZSZY也可以使答案正确。

1 个答案:

答案 0 :(得分:1)

我重新格式化了您的代码以使其可读。使用适当且一致的压痕和间距是清晰度的关键。尝试并学习这种风格。

以下是我的笔记:

  • 如果您要在代码中使用波兰语,请将其用于注释,而不是函数或变量名称。这些评论将帮助波兰读者理解代码,非波兰读者仍有机会从变量和函数名称中理解代码。此外,它更加一致,因为关键字仍然是英文。我和法语的程序员在法国生活和工作,我们甚至不再用法语评论......

  • 所有<=都很可能不正确。数组0基于C:数组索引值通常从0n按以下方式排除:

    for (i = 0; i < size; i++) {
        ...
    }
    
  • 转换malloc()的返回值被视为错误样式。我建议你使用calloc()来分配初始化为所有位零的数组:

    A = calloc(ILOSC_NAPISOW, sizeof(*A));
    ...
    
  • 总是使用{}大括号进行非平凡的循环和测试:你有一些带有3级无支撑语句的构造,这很容易出错。

  • 您应该避免使用全局变量,尤其是ABpom这样的名称。

尽管Radix排序是你最喜欢的算法之一,但这是我在几分钟内给出的尽可能多的建议,试图理解波兰语是太过分了。