计算C中每个字符的出现次数

时间:2017-09-06 15:46:09

标签: c list

我正试图从Brian Kernighan的C编程语言书中练习1-14。

我正在使用一个列表,其中索引号对应于ASCII值,因此列表[65]应该打印出“A”出现在输入中的次数。

不幸的是我的程序似乎没有增加。任何帮助将不胜感激!

#include <stdio.h>
#define MAXLEN 1000

int main()
{
    int c, i;
    int chartype[MAXLEN];

    for(i = 0; i < MAXLEN; ++i)
        chartype[i] = 0;

    while((c = getchar()) != EOF){
        ++chartype[c - '0'];
    }


    for(i = 0; i < MAXLEN; ++i){
        if(chartype[i]>0)
            printf("%c, %d\n", i, chartype[i]);
    }
    return 0;
}
输出:53,? 56,?

5 个答案:

答案 0 :(得分:3)

这里的问题是第二个循环中的c - '0'

当你输入'A'时,你正在递增索引位置c - '0'的整数,即c - 48.所以对于'A',它是递增整数17(65-48),这是一些特殊的角色。

只需输入++chartype[c],即可增加数组中字符的位置并解决问题。

当您在输入控制台上按Enter键或遇到输入文件中的行尾时,getchar()也会接受输入。每次按下Enter键或遇到行尾时,它将递增索引10处的值。所以只需在最后一个循环中添加一个条件以避免打印。或者您可以参考其他一些来源来检查getchar()如何避免输入键或行尾。

我也使用了Phil Kiener给出的建议。

#include <stdio.h>

int main()
{
    int c, i;
    int chartype[256] = { 0 }; // maximum value for an unsigned char

    while((c = getchar()) != EOF) {
        ++chartype[c]; // no need to subtract '0'
    }

    for(i = 0; i < 255; ++i) {
        if(chartype[i] > 0 && i!='\n') { //avoiding printing value present at index 10
            printf("%c, %d\n", i, chartype[i]);
        }
    }

    return 0;
}

答案 1 :(得分:0)

这里的问题是方括号内的c - '0'

当你输入'A'时,它应该增加索引为65的整数,这样当你打印值为65的字符时,它会给你'A'。

相反,您正在递增索引位置c - '0'中的整数,即c - 48。在这里,当你输入'A'时,它会增加整数17(65 - 48),这是一些特殊字符。

只需放置++chartype[c];,就可以增加数组中的正确位置并解决问题。

两个旁白:

  • c - '0'仅在您的输入是一串数字时使用,并且您想要计算数组的第0个位置中的'0'的次数等。

  • 您不需要为简单的字符分配如此大的数组。 c有256个可能的值,因此256的MAXLEN就足够了。

答案 2 :(得分:0)

你的代码可能会混淆了一些东西。

int chartype[MAXLEN];

您希望存储字符在数组中出现的频率,其中每个索引对应一个字符。但是没有1000个字符,只有256个字符。

++chartype[c - '0'];

“成语”c - '0'通常用于从数字中快速获取数值('9'变为9);你不想在这里这样做。

要实际计算字符出现的频率,请执行以下操作:

#include <stdio.h>

int main()
{
    int c, i;
    int chartype[256] = { 0 }; // maximum value for an unsigned char

    while((c = getchar()) != EOF) {
        ++chartype[c]; // no need to subtract '0'
    }


    for(i = 0; i < 256; ++i) {
        if(chartype[i] > 0) {
            printf("%c, %d\n", i, chartype[i]);
        }
    }

    return 0;
}

getchar()返回unsigned char,投放到int以容纳EOF,因此长度为256的数组足以捕获所有字符。

int chartype[256] = { 0 };将该数组中的所有值初始化为0,因此您不需要第一个循环。

(另外,chartype是一个不好的名字。char_frequency或类似的东西在可读性方面会更好。)

答案 3 :(得分:0)

这里的问题是你的索引。你可能有小写字母,大写字母和数字(忽略我假设的符号)。由于大写字母从ascii的65开始,48的数字和97的小写字母,我建议使用三个表来计算每个表,并使用isupper和string.h提供的isdigit方法。如果这是一个禁止使用string.h的大学练习,那么我建议使用以下伪代码

If character larger or equal to a
Remove 97, increment position in lowercase letters array
Else if larger or equal to A
Remove 65, increment position in uppercase letters array
Else
Remove 48, increment position in digits array

答案 4 :(得分:0)

++chartype[c - '0'];可以轻松写入[0 ... MAXLEN)的界限。

示例' ' - '0'可以是32 - 48或-16。最好基于零进行抵消。

  1. 使chartype[];大到足以使用任何unsigned char作为索引。有UCHAR_MAX + 1可能unsigned charfgetc()会返回unsigned charEOF范围内的值。

    #include <limits.h>
    ... 
    // int chartype[MAXLEN]; // not right sized
    int chartype[UCHAR_MAX + 1];
    
  2. 足够 chartype[]元素初始化为零。

    int chartype[UCHAR_MAX + 1] = {0};
    
  3. 基于零偏移而不是字符 '0'进行增量和打印。

    while((c = getchar()) != EOF){
      // chartype[c - '0']
      ++chartype[c];
    }
    
    for (int i = 0; i <= UCHAR_MAX; i++) {
      if(chartype[i]>0) {
        printf("%c, %d\n", i, chartype[i]);
      } 
    }
    
  4. 注意:unsigned char范围达到/超出int范围的稀有平台需要不同的代码。