簡體   English   中英

需要首先在 C 中對輸入的字符串進行最頻繁的排序(qsort)

[英]Need to sort a string input by the most frequent characters first in C (qsort)

我設法按字母順序對其進行了排序,但之后我需要先按最常見的字符對其進行排序。 由於我是 C 編程的新手,我不確定是否需要這種字母排序。 我也考慮過使用結構,但不確定如何使用它來完成整個過程。

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

int cmpfunc(const void *a, const void *b) {
    return *(char*)a - *(char*)b;
}

void AlphabetOrder(char str[]) {
    qsort(str, (size_t) strlen(str), (size_t) sizeof(char), cmpfunc);
    printf("%s\n", str);
}

void Max_Occurring(char *str)
{
    int i;
    int max = 0;

    int freq[256] = {0};

    for(i = 0; str[i] != '\0'; i++)
    {
        freq[str[i]] = freq[str[i]] + 1;
    }

    for(i = 0; i < 256; i++)
    {
        if(freq[i] > freq[max])
        {
            max = i;
        }
    }
    printf("Character '%c' appears %d times", max, freq[max], str);
}

int main() {
    char str1[20];
    printf("Enter a string: ");
    scanf("%s", &str1);

    AlphabetOrder(str1);
    Max_Occurring(str1);

    return 0;
}

我使用@WeatherVane 提到的想法給你寫了一個頻率分類器:

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

struct cfreq {
    unsigned char c;
    int freq;
};

int freqcmp(const void *a, const void *b) {
    struct cfreq *a2 = (struct cfreq *) a;
    struct cfreq *b2 = (struct cfreq *) b;
    if(a2->freq < b2->freq) return -1;
    if(a2->freq == b2->freq) return 0;
    return 1;
}

int freqcmpdesc(const void *a, const void *b) {
    return -freqcmp(a, b);
}

void FrequencyOrder(const char str[]) {
    struct cfreq cfreqs[256];
    for(int i = 0; i < sizeof(cfreqs) / sizeof(*cfreqs); i++) {
        cfreqs[i].c = i;
        cfreqs[i].freq = 0;
    }
    for(int i = 0; str[i]; i++) cfreqs[str[i]].freq++;
    qsort(cfreqs, sizeof(cfreqs) / sizeof(*cfreqs), sizeof(*cfreqs), freqcmpdesc);
    for(int i = 0; i < sizeof(cfreqs) / sizeof(*cfreqs); i++) {
        if(cfreqs[i].freq) printf("%c", cfreqs[i].c);
    }
    printf("\n");
}

int main() {
    char str1[20];
    printf("Enter a string: ");
    scanf("%s", &str1);
    FrequencyOrder(str1);
    return 0;
}

這是一個示例 session (注意:output 對於具有相同頻率的字母不是確定性的):

Enter a string: buzz
zbu

如果您想在 output 中出現重復的字母,則使用沿這些行的循環替換打印:

while(cfreqs[i].freq--) printf("%c", cfreqs[i].c);

我不確定是否需要這種字母排序。

它不是必需的,但如果完成, Max_Occurring()可以利用已排序的字符串。

由於在調用Max_Occurring()之前對字符串進行了排序,因此通過計算每個char的相鄰重復次數來計算出現的最大值。

// Untested illustrative code.
// str points to a sorted string.
void Max_Occurring(const char *str) {
  char max_ch = '\0';
  size_t max_occurence = 0;

  char previous = '\0';
  size_t occurrence = 0;

  while (*str) {
    if (*str == previous) {
      occurrence++; 
    } else {
      occurrence = 1; 
    } 

    if (occurrence > max_occurence) {
      max_occurence = occurrence;
      max_ch = *str;   
    } 

    previous = *str;
    str++;
  }
  printf("Character '%c' appears %zu times", max_ch, max_occurence);
}

在多個字符具有相同的最大出現次數的情況下,此代碼僅報告一個最大值。


避免緩沖區溢出

不要使用scanf("%s"...沒有寬度限制。

提示:啟用所有警告以節省時間,並在應該使用str1時查看使用&str1的問題。

char str1[20];
...
// scanf("%s", &str1);
scanf("%19s", str1);

避免負索引

如果仍然想要頻率表,請注意char簽名並且代碼使用str[i] < 0來索引數組的情況。

反而:

const unsigned char *ustr = (const unsigned char *) str;

size_t freq[UCHAR_MAX + 1] = {0};

for(size_t i = 0; ustr[i] != '\0'; i++) {
    freq[ustr[i]]++;
}

這是另一種可能更簡單的選擇。

void freqOrder( char *p ) {
#define ASCIIcnt 128  // 7bit ASCII

    // to count occurences of each character
    int occur[ ASCIIcnt ];
    memset( occur, 0, sizeof occur );

    int maxCnt = 0; // remember the highest count

    // do the counting
    for( ; *p; p++ )
        if( ++occur[ *p ] > maxCnt )
            maxCnt = occur[ *p ];

    // output most frequent to least frequen
    for( ; maxCnt; maxCnt-- )
        for( int i = 0; i < ASCIIcnt; i++ )
            if( occur[i] == maxCnt )
                while( occur[i]-- )
                    putchar( i );
    putchar( '\n' );
}

int main( void ) {
    freqOrder( "The quick brown fox jumps over the lazy dog" );
    return 0;
}

Output

'        ooooeeehhrruuTabcdfgijklmnpqstvwxyz'

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM