问题-首先按频率对字符串中的字符进行排序

时间:2018-10-04 15:02:42

标签: c arrays sorting

给出一个字符串,我试图计算字符串中每个字母的出现次数,然后将其频率从最高到最低排序。然后,对于出现次数相似的字母,我必须按字母顺序对其进行排序。

这种发生是成功的,但是我不知道如何向他们添加正确的字母。

我真的是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;
}

输出应类似于Z = 15,C = 5,A = 1,B = 1 ...

2 个答案:

答案 0 :(得分:0)

对数组进行排序时,会丢失字母的顺序。

有几种方法可以解决此问题,但是最简单的方法可能是将阵列极点转换为二维阵列。

因此将极点声明更改为:

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

然后添加一个循环以将第二行设置为等于字母表中相应的字母。

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

这应该使数组看起来像

0,0,0,0,...,0 <---此行是出现的次数(例如,字母A出现10次)

0、1、2、3,...,25 <---此行代表值(例如0 = A,1 = B,2 = C)

现在,您可以更改排序方式以对第二列也进行排序。

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);

这将对数组进行排序,因此最终看起来像这样:

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

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

(Z,C,A,B,...,M)<-这是第二行,而不是数字

您可以通过执行以下操作来获取这些值...

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

这是我最好的解释,希望您能理解。

答案 1 :(得分:0)

这是一种接近原始代码的可能解决方案:

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

已解决的问题和评论:

  • 如评论中所述,您缺少提供功能ctype.htolower的{​​{1}}库-尽管我认为这是一个错字。
  • 类似地,您在toupper的初始化中有一个错字-它应该有26个字符而不是25个字符,并且右括号应该是方括号。请注意,您还可以编写abeceda,编译器将自行推断出数组大小。在这种情况下,对我来说,明确地指出它似乎是一个更好的主意,因为我们正在处理的是已知大小的集合-字母。将其转换为单独的变量并在循环中重用该变量似乎是一个不错的选择。
  • 就像@JonathanLeffler写道-使用fgets而不是char abeceda[] = {your list}(并从他提供的link中读取帖子)-与预先定义的最大缓冲区大小{{ 1}}。
  • 您不是要按顺序在最后一个循环中打印字母,而是要按排序方式打印gets中的字母。
  • 最后,与在OP中一样,排序有效地混合了具有相等计数的字母。现在要做的是根据字母顺序对这些条目进行排序,这就是我所理解的目标。
  • MAXBUF应该返回abeceda而不是main()(实际上,您返回的是int,并且不会在我的计算机上编译)。
  • 至少在我看来,某些变量名可以使用改进,尽管void(“符号”)在某种意义上可以,int可以简单地用znak代替。还请注意一个字母变量,例如pommtemp(以及xy ...)-最好是更详细些或至少坚持i,j,k通常在循环中使用。如果n之类的东西m对我来说更具可读性。
  • 使用缩进来提高可读性。我还会在代码的各个部分之间使用较少的空格。

单词n的输出现在为:

nchar

如果要删除最后一个逗号,也可以执行以下操作:

Hello

要注意的一件事是,通常情况下,您会希望使用更加模块化的设计。在这种情况下,至少要有一个用于排序而不是直接在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, 中键入所有内容的函数。当您学习取得进步时,我建议您开始编写函数,越早越好。它们提高了程序的可读性并简化了调试。