-1

Given a string, I'm trying to count the occurrence of each letter in the string and then sort their frequency from highest to lowest. Then, for letters that have similar number of occurrences, I have to sort them alphabetically.

The sort of occurencies was succesful, but I dont know how to add to them the correct letter of alphabet.

Can you help me, as I am really beginner in C?

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

void main() {
  printf("Enter: \n");

  char sifra[10000];
  int pole[26] = {0};
  char pismeno, znak;
  int i;

  int l, max, pomm;
  int m, x, y;
  char abeceda[26] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K',
      'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'};

  gets(sifra);

  int n = strlen(sifra);

  for (i = 0; i < n; i++) {
    pismeno = tolower(sifra[i]);

    if (pismeno >= 97 && pismeno <= 122) {
      pole[pismeno - 97]++;
    }
  }

  for (i = 97; i <= 122; i++) {
    printf("%c --- %d -times\n", toupper(i), pole[i - 97]);
  }

  //sorting it here

  l = 25;
  do {
    max = 0;
    for (x = 0; x <= l; x++) {
      if (pole[x] > pole[max])
        max = x;
    }

    l--;
  } while (l != 0);

  for (y = 25; y > -1; y--) {
    printf("%c  =  %d, ", toupper(122 - y), pole[y]);
  }
  printf(" \n ");

  return 0;
}

The output should looks something like Z=15, C=5, A=1, B=1...

kukoOO
  • 11
  • 1
  • The code `char abeceda[25] = { … };` shouldn't compile; there are 26 letters in the alphabet and I don't see which one you omitted. Consider using `= "ABC…XYZ";` for the initializer; it's more compact. – Jonathan Leffler Oct 04 '18 at 15:11
  • See [Why `gets()` is too dangerous to be used — ever!](https://stackoverflow.com/questions/1694036/why-is-the-gets-function-so-dangerous-that-it-should-not-be-used) – Jonathan Leffler Oct 04 '18 at 15:13
  • 2
    @JonathanLeffler: but it *actually* reads `char abeceda[25}= { …`. This cannot compile. The statement made in the question that "sort of occurencies was successful" cannot be true. – Jongware Oct 04 '18 at 15:20
  • @usr2564301: Yeah; I just found that when trying to reformat the code automatically — the `}` in place of `]` threw the indentation off. – Jonathan Leffler Oct 04 '18 at 15:21
  • 2
    kukoOO `char abeceda[25} = {'A', 'B', 'C'...` is a problem for 2 reasons. 1) `]` expected, not `}`. 26 expected, not 25. Please edit to what you are truly compiling and post the input used. Enable all warnings and post any warnings exactly you cannot solve. You may want to delete your post, add improvements and then un-delete as it could take you some time to fix this. – chux - Reinstate Monica Oct 04 '18 at 15:25
  • @chux my bad, i really sorry for that mistake as i am posting here for 1.time ever I edited code little bit here, now I rewrited that mistake in original post BUT still dont know how to sort it correctly :( – kukoOO Oct 04 '18 at 15:33
  • 1
    kukoOO, What was the exact input used, output seen and output expected? (be sure to add `#include `) – chux - Reinstate Monica Oct 04 '18 at 15:39
  • kukoOO A good compiler would provide many warnings/error with this code, enable all warnings. `void main() { .... return 0; }` questions the veracity of the post. – chux - Reinstate Monica Oct 04 '18 at 15:44
  • @chux the input is any sentence, for example: Hello. - then it count each letter of alphabet and I have to sort it, so it should looks like: L=2 /times/, E=1, H=1, O=1, B=0, C=0, D=0...... but my output is wrong: A=2(the count of L), B=1(the count of E), C=1, D=1, E=0... – kukoOO Oct 04 '18 at 15:53

2 Answers2

0

When you sort your array, you lose the order of the letters.

There are a few ways to fix this, however probably the easiest is to turn the array pole should be turned into a 2 dimensional array.

So change the pole declaration to:

int pole[26][2] = {0,0};

And then add a loop to set the second row equal to a corresponding letter in the alphabet.

for (i = 0; i < 26; i++) {
  pole[i][1] = i;
}

This should make an array that looks like

0, 0, 0, 0, ..., 0 <--- This row is the occurrences (e.g. 10 appearances of the letter A)

0, 1, 2, 3, ..., 25 <--- This row represents the value (e.g. 0 = A, 1 = B, 2 = C)

Now you can change your sort to also sort the second column.

do {
  max = 0;
  for (x = 0; x <= l; x++) {
    if (pole[x][0] > pole[max][0])
      max = x;

  }
  int tempNum = pole[l][0];     
  int tempLetter = pole[l][1];

  pole[l][0] = pole[max][0];
  pole[l][1] = pole[max][1];

  pole[max][0] = tempNum;
  pole[max][1] = tempLetter;
  l--;
} while (l != 0);

This will sort your array, so it'll end up looking like:

15, 5, 1, 1, ..., 0

25, 2, 0, 1, ..., 12

(Z, C, A, B, ..., M) <-- this is the second row as letters in stead of numbers

You can get these values by doing something like...

for (i = 0; i < 26; i++) {
  printf("%c --- %d -times\n", pole[i][0], pole[i][1])
}

This is my best attempt to explain this to you, hope you understand.

DubDub
  • 1,277
  • 1
  • 10
  • 24
  • May I ask you if u could check that code, it seems that I have some problem(I think its in counting part) //cant get here full code, bcs its too long, so this part: ` int n = strlen(sifra); for (i = 0; i < n; i++) { pismeno = tolower(sifra[i]); if (pismeno >= 97 && pismeno <= 122) { pole[pismeno - 97]++; } }` – kukoOO Oct 04 '18 at 20:36
  • or if u could post full code, because I am still having troubles. Thank you – kukoOO Oct 04 '18 at 21:01
  • Sorry, I don't know C fully, only C#, hence I tried to explain the concept to you, I don't know the full answer. Honestly you should try and learn the concept as the code isn't important so much as the approach. The reason you're getting errors is because when using a 2D array, you've got to reference both row and column. (e.g. pole[0] isn't allowed when pole is a 2D array) it's got to be pole[0][0], hence update the part where "pole[pisemeno -97]++" to "pole[pisemeno-97][0]++" – DubDub Oct 05 '18 at 08:14
0

Here is a possible solution that is close to your original code:

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

#define MAXBUF 10000

int main()
{
    printf("Enter: \n");

    char sifra[MAXBUF];
    int pole[26]={0};
    char pismeno, znak;
    int i;

    int  l, max, temp;
    int m, x, y;
    char abeceda[26] = {'A','B','C','D','E','F','G','H','I','J','K','L','M',
       'N','O','P','Q','R','S','T','U','V','W','X','Y','Z'};

    fgets(sifra, MAXBUF, stdin);

    int n=strlen(sifra);
    for(i=0; i<n; i++)
    {
        pismeno= tolower(sifra[i]);
        if(pismeno>=97 && pismeno<=122)
        {
            pole[pismeno-97]++;
        }
    }

    for(i=97; i<=122; i++)
    {
        printf("%c --- %d -times\n",toupper(i),pole[i-97]);
    }


    // Sorting it here
    l= 25;
    do
    {
        max=0;
        for (x=0; x<=l; x++)
        {
            if (pole[x]>pole[max])
                max=x;
            else if (pole[x] == pole[max])
                if (abeceda[x] < abeceda[max])
                    max = x;
        }

        temp=pole[l];
        pole[l]=pole[max];
        pole[max]=temp;

        znak=abeceda[l];
        abeceda[l]=abeceda[max];
        abeceda[max]=znak;

        l--;
    }while (l!=0);

    for(y=25; y>-1; y--)
    {
        printf("%c  =  %d, ",toupper(abeceda[y]), pole[y]);
    }
    printf(" \n ");

    return 0;
}  

The fixed issues and comments:

  • As mentioned in the comments you were missing the ctype.h library that provides the functions tolower and toupper - though I'm assuming this was a typo.
  • Similarly as you said, there was a typo in initialization of abeceda - it should have 26 characters rather than 25 and the closing bracket was supposed to be square. Note that you can also write char abeceda[] = {your list} and the compiler will deduce the array size on its own. Stating it explicitly seems like a better idea to me in this case though since we're dealing with a known set - the alphabet, of a known size. Turning it into a separate variable and reusing that variable in the loops also seems like a good choice.
  • Like @JonathanLeffler wrote - use fgets instead of gets (and read the posts from the link he provided) - this is implemented along with an upfront defined max buffer size MAXBUF.
  • Instead of printing the letters of alphabet in order in the last loop, you want to print the letters in abeceda as sorted.
  • Finally, as it was in the OP the sorting effectively mixed up the letters with equal count. What it does now is that it sorts those entries based on the letters alphabetical order which is what I understood was the goal.
  • main() should return an int rather than void (in fact you return an int and that would not compile on my machine).
  • Some variable names could use improvement, at least in my opinion, while znak ("sign") makes some sense, pomm could be simply replaced by temp. Also careful with one letter variables like x and and y (and n, m...) - it's better to be a bit more verbose or at least stick to i,j,k which are commonly used in loops. n would be more readable to me if it was something like nchar.
  • Use indentation to improve readability. I'd also use less spaces in between parts of code.

The output for the word Hello would now be:

L  =  2, E  =  1, H  =  1, O  =  1, A  =  0, B  =  0, C  =  0, D  =  0, F  =  0, G  =  0, I  =  0, J  =  0, K  =  0, M  =  0, N  =  0, P  =  0, Q  =  0, R  =  0, S  =  0, T  =  0, U  =  0, V  =  0, W  =  0, X  =  0, Y  =  0, Z  =  0,

If you want to get rid of the last comma, you can also do:

for(y=25; y>0; y--)
{
    printf("%c  =  %d, ",toupper(abeceda[y]), pole[y]);
}
printf("%c  =  %d ",toupper(abeceda[y]), pole[y]);
printf(" \n ");

One thing to note is that normally you would want to use a more modular design. In this case at least a function for sorting rather than directly typing everything in main. When you progress in your studies I recommend you start writing functions, the sooner the better. They improve programs readability and ease the debugging.

atru
  • 4,699
  • 2
  • 18
  • 19
  • thank you so much for help and explanation, but during testing it I found, that if I use input string, that I have from my teacher it has still some problem... Intput: GOQLLGABAQLNYQSBCQKWQZZYDETGSBGSOYCGTAQBGKZEKGDGESSEDHSXESMASGQNCGDWOYECSERKALFGSMOYZQLDGQNGDYTELBEOAKDGXZADKKWANEKDSEEZZELDHSGDYETZLEXHLGSMDWEKAETDWAOEKDQMLAAQRNAVGSBCAWQBRGLBKMENBTGKWQTGSABEMLQRRGDKQKOQNNOESVAYQSBQXQDDWGKNQDDALCQKQLAOQLVQRNYNQLMAQSBRAQHDGTHNQSGOQNASDGLANYRNQXVQSBKQMQXGEHKDEQSQKDESGKWGSMBAMLAAGSKZAQVGSMETWGKGSDANNGMASXAOYCGTACWEQDWA output: (https://imgur.com/y7cq0ge) – kukoOO Oct 04 '18 at 19:51
  • 1
    @kukoOO sorry for the late reply, it was a bug on my side. See the updated if statement in the sorting part, it needed `else if (pole[x] == pole[max])` instead of the wrong original `else`. – atru Oct 04 '18 at 21:55