如何解读统计字符串字符出现次数的C代码?求简化实现方案
问题描述
作业要求:统计无长度限制的输入字符串中指定字符的出现次数并输出,且仅使用do或do-while循环实现。找到一段C代码,但作为编程新手,对代码中的str[i]含义、变量ch的作用及整体运行逻辑有疑问,需要逐段解读代码,同时想知道是否有更简单的实现方式。
原代码如下:
#include <stdio.h> #include <string.h> int main() { char str[10], ch; int i, Count; i = Count = 0; printf("\n Please Enter any String : "); gets(str); printf("\n Please Enter the Character that you want to Search for : "); scanf("%c", &ch); while (str[i] != '\0') { if (str[i] == ch) { Count++; } i++; } printf("\n The Total Number of times '%c' has Occurred = %d ", ch, Count); return 0; }
一、代码逐段解读
1. 头文件引入
#include <stdio.h> #include <string.h>
#include <stdio.h>:引入标准输入输出库,让程序能使用printf、scanf这类输入输出函数。#include <string.h>:引入字符串处理库,但这段代码完全没用到库中函数,实际上可以删掉。
2. 变量定义与初始化
char str[10], ch; int i, Count; i = Count = 0;
char str[10]:定义一个固定长度的字符数组,最多存9个有效字符(最后一位要留给字符串结束符\0),这和作业要求的「无长度限制」冲突,输入过长会直接导致内存溢出出错。char ch:用来存储用户要搜索的目标字符。int i, Count:i是遍历字符串的计数器,Count是目标字符的出现次数计数器。i = Count = 0:把两个计数器初始化为0,避免内存里的垃圾值影响统计结果。
3. 输入字符串
printf("\n Please Enter any String : "); gets(str);
printf用来提示用户输入;gets(str)读取输入的字符串并存入str数组。但gets是被C标准废弃的不安全函数,输入长度超过数组上限会直接触发内存溢出,实际开发中绝对不能用。
4. 输入目标字符
printf("\n Please Enter the Character that you want to Search for : "); scanf("%c", &ch);
- 提示用户输入要搜索的字符,
scanf("%c", &ch)读取一个字符存入ch。这里有个坑:用户输入字符串后按的回车会留在输入缓冲区,scanf会直接读取这个回车符,导致ch变成回车,统计结果完全错误。
5. 循环统计逻辑
while (str[i] != '\0') { if (str[i] == ch) { Count++; } i++; }
str[i]:C语言中字符串本质是字符数组,str[i]表示数组第i个位置的字符(数组下标从0开始,比如str[0]是字符串第一个字符)。str[i] != '\0':C语言字符串必须以\0(空字符)结尾,这个条件表示只要还没遍历到字符串末尾,就继续循环。- 循环内部:如果当前字符
str[i]等于目标字符ch,就把Count加1;然后i自增,遍历下一个字符。
6. 输出结果
printf("\n The Total Number of times '%c' has Occurred = %d ", ch, Count); return 0;
- 用
printf输出统计结果,%c用来输出字符,%d用来输出整数;return 0表示程序正常结束。
二、符合要求的简化实现(无长度限制+do-while循环)
原代码有两个核心问题:一是字符串长度固定,不符合「无长度限制」要求;二是用了while循环,不满足作业要求。下面是优化后的两种实现:
实现方式1:以Ctrl+D/Ctrl+Z作为输入结束标志
#include <stdio.h> int main() { char ch, target; int count = 0; printf("请输入任意字符串(按Ctrl+D结束输入):"); getchar(); // 清空输入缓冲区的换行符 printf("\n请输入要搜索的字符:"); scanf("%c", &target); getchar(); // 再次清空缓冲区 printf("\n你输入的字符串:"); // do-while循环:先执行一次读取,再判断是否结束 do { ch = getchar(); putchar(ch); // 输出字符让用户确认输入 if (ch == target) { count++; } } while (ch != EOF); // EOF是输入结束标志,Windows用Ctrl+Z,Linux/macOS用Ctrl+D printf("\n字符'%c'总共出现了%d次\n", target, count); return 0; }
实现方式2:以回车作为输入结束标志(更符合日常习惯)
#include <stdio.h> int main() { int count = 0; char target; printf("请输入要搜索的字符:"); scanf("%c", &target); getchar(); // 吃掉输入后的回车符 printf("请输入字符串:"); char ch; do { ch = getchar(); if (ch == target) count++; } while (ch != '\n'); // 输入回车就结束统计 printf("字符'%c'出现次数:%d\n", target, count); return 0; }
优化点说明
- 无长度限制:用
getchar()逐字符读取输入,不需要预先定义固定长度的数组,支持任意长度的字符串。 - 满足do-while要求:先执行循环体(读取字符),再判断结束条件,完全符合作业要求的循环类型。
- 解决输入缓冲区问题:用
getchar()清空缓冲区里的回车符,避免读取到错误字符。 - 安全性:摒弃了废弃的
gets函数,不会出现内存溢出问题。
内容的提问来源于stack exchange,提问作者cadou
相关产品推荐
相关产品推荐

