按ASCII码及其在文件中出现的次数对字母进行排序

brccelvz  于 12个月前  发布在  其他
关注(0)|答案(2)|浏览(129)

我做了一个函数来计算一个字母在一个文件中出现的次数。我不知道如何按频率排序,如果两个字母出现的次数相同,ASCII码中“大”的字母出现在另一个之前。

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

void process_input_file(const char* input_file, const char* output_file) {
    FILE* input = fopen(input_file, "r");
    if (input == NULL) {
        perror("Error opening the input file");
        exit(EXIT_FAILURE);
    }

    int occurrences[26] = {0};
    int c;
    while ((c = fgetc(input)) != EOF) {
        if (isalpha(c)) {
            c = toupper(c);
            occurrences[c - 'A']++;
        }
    }
    fclose(input);

    FILE* output = fopen(output_file, "w");
    if (output == NULL) {
        perror("Error opening the output file");
        exit(EXIT_FAILURE);
    }

    for (int i = 0; i < 26; i++) {
        if (occurrences[i] > 0) {
            fprintf(output, "%c", i + 'A');
        }
    }
    fclose(output);
}

int main() {
    char input_file[1000];
    printf("Enter the name of the input file: ");
    scanf("%s", input_file);
    process_input_file(input_file, "statistics.txt");

    return 0;
}

字符串
一个例子是一个文件,其中写入了以下内容:

"Ovo je primjer znakovne datoteke"


它应该在另一个文件中写入:

EOAJKNRTVDIMPZ


但它这样做:

ADEIJKMNOPRTVZ


我试着改变,所以我从数组的后面比较它,因为它们是ASCII中最大的字母,但它不起作用

for (int i = 26; i > 0; count--) {
    for (int j = 26 - 1; i >= 0; i--) {
        if (occurrences[j] == i) {
            fprintf(output, "%c", j + 'A');
        }
    }
}

kiayqfof

kiayqfof1#

你可以利用qsort来解决这个问题,方法是写一个比较器函数,比较包含一个字符和这些字符的计数的结构。这些结构的数组,每个字母表中的一个字母,就像一个查找表。
对输入字符串的单次遍历将字符计数到这个数组中。然后我们可以使用自定义比较器和qsort对它们进行相应的排序。
最后,我们循环遍历这些结构体,对于任何计数大于零的结构体(实际出现在输入字符串中的字符),我们将它们按顺序写入一个动态分配的char数组中。这是动态分配的,因此它的生存期可以在sorted函数中生存。
通过将问题分解成更小的问题,每个函数都更小,更容易理解。

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

struct char_info {
    char ch;
    size_t count;
};

int cmp_char_info(const void *a, const void *b) {
    struct char_info c = *(struct char_info *)a;
    struct char_info d = *(struct char_info *)b;

    if (c.count < d.count) return 1;
    if (c.count > d.count) return -1;
    if (c.ch < d.ch) return -1;
    if (c.ch > d.ch) return 1;

    return 0;
}

char *sorted(const char *input_str) {
    const char *alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

    struct char_info info[26];

    for (size_t i = 0; alphabet[i]; i++) {
        info[i] = (struct char_info){ alphabet[i], 0 };
    }

    for (size_t i = 0; input_str[i]; i++) {
        char ch = input_str[i];
        if (!isalpha(ch)) continue;
        ch = toupper(ch);
        info[ch - 'A'].count++;
    }

    qsort(info, 26, sizeof(struct char_info), cmp_char_info);

    char *result = calloc(27, 1);
    size_t j = 0;

    for (size_t i = 0; i < 26; i++) {
        if (info[i].count > 0) {
            result[j++] = info[i].ch;
        }
    }

    return result;
}

int main(void) {
    char *output = sorted("Ovo je primjer znakovne datoteke");

    printf("%s\n", output);

    free(output);
}

字符串
输出量:

EOAJKNRTVDIMPZ

qxgroojn

qxgroojn2#

在最后一个数组上迭代,找到最大值时消除值,因此每个下一个找到的值都是下一个最大的计数

const char ALPHABET[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

/* results
     occurrences  array of counts of letters in alphabetical order
     length       length of occurrences (always 26)
   fills occurrences with -1s after run, 0s may be left too
*/
void results(int occurrences[], const int length) {
    int tmp = -1;
    int idx = -1;
    while(1) {
        for(int i = 0 ; i < length ; i++)  // search for the largest value
            if (occurrences[i] > tmp) {
                idx = i;                   // save position of max value
                tmp = occurrences[idx];
            }
        if (tmp < 1) break;   // end while when all values are cleared
        tmp = ALPHABET[idx];  // just go ahead and re-use as a char
        printf("%c", tmp);
        occurrences[idx] = -1;  // flush member so next highest is found
        tmp = -1;               // reset tmp for the next loop
    }
    printf("\n");  // flush the buffer (alt: fill and write char[] + \n\0 );
}

字符串

相关问题