总结最近学习成果17-统计字符串的各个字母有几个,并按字母表顺序输出

本文介绍了一种使用桶排序思想的算法,用于统计给定字符串中每个字母的出现次数,并按字母表顺序输出结果。该算法通过遍历一个初始化为0的桶数组来实现,桶数组的下标对应ASCII码值,桶内的值记录对应字符的出现次数。

统计字符串的各个字母有几个,并按字母表顺序输出 ddkafadf —> a2d3f2k1

//套用桶排序的思想,遍历桶,只有桶里面的数字不是0 说明出现过这个字母,然后从前往后输出就行
void FindSum(char* s){
      char* t = s;
      int buck[128] = { 0 };
      while (*s){
            buck[*s++]++;
      }
      s = t;
      for (int i = 0; i < 127;i++){
            if (buck[i] != 0){
                  printf("%c%d", i, buck[i]);
                  s++;
            }
      }
}
<think> 我们要求:输入一个字符串(长度小于1000),统计其中大小写字母的出现次数,字母ASCII码由低到高的顺序输出每个字母的个数。 注意:只统计字母('A'~'Z'和'a'~'z'),其他字符忽略。输出时,按ASCII码升序,也就是先大写字母(ASCII码65~90)然后是小写字母(ASCII码97~122)。注意,大写字母和小写字母在ASCII码表中是不连续的(中间有其他字符),所以我们需要分别输出大写和小写,且各自按ASCII码顺序。 思路: 1. 定义一个数组来统计每个字母出现的次数。由于字母分为大写和小写,我们可以定义两个数组,也可以用一个数组但覆盖所有字母。为了方便,我们可以分别用两个数组(或一个数组但大小足够)来统计。 2. 但是题目要求按ASCII码由低到高输出,所以我们可以先统计所有大写字母的次数,再统计小写字母?实际上,我们可以用一个数组来记录52个字母(26个大写+26个小写)的次数,但是输出时先输出大写(从'A'到'Z'),然后输出小写(从'a'到'z')。或者,我们也可以分别用两个数组:一个给大写(26个),一个给小写(26个)。但是要注意,题目要求按ASCII码顺序,而大写的ASCII码都小于小写,所以先输出大写,再输出小写。 3. 另一种思路:用一个数组,下标0~25表示大写字母'A'~'Z',26~51表示小写字母'a'~'z'。然后输出时,先输出0~25(对应的字母就是'A'+下标),再输出26~51(对应的字母就是'a'+(下标-26))。 4. 更简单的思路:我们创建一个大小为128的int数组(ASCII码范围0~127),然后遍历字符串时,对于每个字符,如果它在'A'~'Z'或'a'~'z'范围内,就在对应的ASCII码位置计数。然后我们遍历整个数组,但是只输出字母部分:先遍历65~90(大写),再遍历97~122(小写)。这样输出顺序就是ASCII码升序。 5. 方法4虽然简单,但遍历整个128个元素的数组效率也可以接受。不过我们也可以只遍历我们关心的部分。 我们选择方法4: int count[128] = {0}; // 初始化所有元素为0 char str[1001]; 输入字符串(使用fgets,因为题目没有说不能有空格,所以不能用scanf,用fgets安全) 遍历字符串,直到遇到结束符'\0',对于每个字符c: if (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') count[(int)c]++; 然后输出: for (int i = 'A'; i <= 'Z'; i++) { if (count[i] > 0) { printf("%c:%d\n", i, count[i]); } } for (int i = 'a'; i <= 'z'; i++) { if (count[i] > 0) { printf("%c:%d\n", i, count[i]); } } 但是注意:题目要求按ASCII码由低到高,这样输出就是先大写后小写,且每个字母范围内都是升序。 但是,如果某个字母没有出现,我们也要输出0吗?题目只要求输出每个字母的个数,但没有说没有出现的字母要不要输出。根据题意,应该是只输出出现的字母?但是题目要求“输出每个字母的个数”,这里“每个字母”可以理解为出现的字母,也可以是26*2个字母。但是题目没有明确。我们再看题目要求:按字母ASCII码由低到高的顺序输出每个字母的个数。注意是“每个字母”,但这里可能是指字符串中出现的字母,因为如果字符串中只出现了几个字母,那么输出所有52个字母(包括0次)显然不合理。但是题目没有明确,我们通常的做法是:只输出出现过的字母?还是全部字母? 再读题:“统计其中大小写字母的出现次数,字母ASCII码由低到高的顺序输出每个字母的个数”。这里“每个字母”应该是指字符串中出现了的字母。因为如果要求输出所有的52个字母,题目会明确说明。而且,如果字符串中没有某个字母,那么统计次数为0,输出0次也是合理的?但是题目示例中没有要求输出0次的情况。为了安全,我们可以按照出现过的字母输出(即次数大于0的)。如果题目要求无论是否出现都要输出,那么我们就需要输出52行(每个字母一行,包括0次)。但是题目没有明确,我们按照示例来。 然而,题目没有给示例输出,所以我们按照一般理解:只输出字符串中出现的字母(即出现次数大于0的字母),且按ASCII码顺序(先大写后小写,各自内部升序)。 但是,如果题目要求输出所有字母(包括0次),那么我们就需要循环所有大写字母和所有小写字母。这里我决定:按照题目要求“每个字母”的通常理解,输出所有字母(52个)的次数,包括0次。因为题目要求统计大小写字母的出现次数,那么每个字母都应该有一个次数,即使为0。但是这样输出太多,而且题目没有明确,我们折中一下:按照题目要求,如果要求输出每个字母,我们就输出所有52个字母(包括0次)。但是,题目描述中没有这样强制要求,所以我们可以按照实际出现的输出。 让我们看用户提供的引用[1]中的例子:它过滤掉字母,然后输出字符串和字符个数。它没有输出0次。所以这里我们采用:只输出出现的字母(次数>0)。 但是,如果题目要求输出所有字母,那么我们就需要输出52个(每个字母一行)。为了明确,我们再看用户的问题描述:“输出每个字母的个数”,这个“每个”可以理解为字符串中出现的每个字母,也可以理解为所有字母。根据常识,如果要求输出所有字母(即使0次)也会明确说明。例如,题目要求“输出26个英文字母各自出现的次数”,那么即使0也要输出。但这里没有,所以我们只输出出现过的字母。 因此,我们按照以下步骤: 1. 定义计数数组,大小为128,初始化为0。 2. 读取一行字符串(使用fgets,避免溢出)。 3. 遍历字符串的每个字符,如果是字母(不论大小写),则对应的计数加1。 4. 遍历ASCII码从65到90(即大写字母),如果该字母的计数>0,则输出字母和次数。 5. 遍历97到122(小写字母),同样如果计数>0则输出。 注意:题目要求按ASCII码由低到高,所以先65~90然后97~122。 但是,用户要求用C语言实现,下面我们写代码。 注意:输入字符串长度小于1000,我们定义字符数组为1001(包括最后的'\0')。 另外,使用fgets会读入换行符,我们需要处理掉吗?换行符不是字母,不会影响统计,但是为了安全,我们可以在遍历时跳过非字母,所以换行符不会被统计。 代码实现如下: </think> 以下是使用C语言实现输入字符串统计大小写字母出现次数按ASCII码顺序输出的程序代码: ```c #include <stdio.h> #include <ctype.h> void countLetters(const char* str) { int count[256] = {0}; // 初始化所有ASCII字符计数为0 // 统计每个字符出现的次数 for (int i = 0; str[i] != '\0'; ++i) { unsigned char c = str[i]; count[c]++; // 对应ASCII位置的计数增加 } // 先输出大写字母 (A-Z, ASCII 65-90) for (int i = 65; i <= 90; ++i) { if (count[i] > 0) { printf("%c: %d\n", (char)i, count[i]); } } // 再输出小写字母 (a-z, ASCII 97-122) for (int i = 97; i <= 122; ++i) { if (count[i] > 0) { printf("%c: %d\n", (char)i, count[i]); } } } int main() { char input[1001]; // 分配1001字符空间(包括结束符) printf("请输入字符串(长度<1000): "); fgets(input, sizeof(input), stdin); // 安全读取含空格的字符串 printf("\n字母出现次数统计:\n"); countLetters(input); return 0; } ``` ### 程序说明: 1. **输入处理**: - 使用`fgets()`安全读取含空格的字符串[^2] - 缓冲区大小1001(1000字符 + 结束符`\0`) 2. **统计原理**: - 创建`count[256]`数组统计所有ASCII字符 - 遍历字符串时,对每个字符的ASCII值对应下标计数 - 示例:`'A'(ASCII 65)` → `count[65]++` 3. **输出规则**: -输出大写字母(ASCII 65-90) -输出小写字母(ASCII 97-122) -输出出现次数>0的字母 - 按ASCII码升序自动排序 4. **示例运行**: ``` 请输入字符串(长度<1000): Hello World! 字母出现次数统计: H: 1 W: 1 d: 1 e: 1 l: 3 o: 2 r: 1 ``` ### 关键函数说明: - `isalpha()`(未直接使用但原理类似):通过ASCII范围判断字母字符 - `fgets()`:替代不安全的`gets()`,防止缓冲区溢出[^2] - 双重循环:分别处理大写和小写字母区间
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值