Home > Mobile >  Need to sort a string input by the most frequent characters first in C (qsort)
Need to sort a string input by the most frequent characters first in C (qsort)

Time:08-12

I managed to sort it alphabetically but I need to sort it by the most frequent characters first after that. Since I'm new to C programming Im not sure if this alphabetical sort is needed. Also I thought about using a struct but not sure how to do the whole process with it.

#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;
}

CodePudding user response:

I wrote you a frequency sorter using the idea that @WeatherVane mentioned:

#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;
}

and here is a sample session (note: output is not deterministic for letters with same frequency):

Enter a string: buzz
zbu

If you want duplicate letters in the output then replace the print with a loop along these lines:

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

CodePudding user response:

Im not sure if this alphabetical sort is needed.

It is not needed, yet if done, Max_Occurring() can take advantage of a sorted string.

Since the string is sorted before calling Max_Occurring(), compute the max occurring via a count of adjacent repetitions of each 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);
}

In the case of multiple characters with the same max occurrence, this code only reports one max.


Avoid buffer overflow

Do not use scanf("%s"... without a width limit.

Tip: enable all warnings to save time and see the problem of using &str1 when str1 should be used.

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