1. 问题背景与需求分析
在C语言编程学习中,字符串处理是最基础也是最重要的技能之一。统计一行文本中的单词数量看似简单,但其中蕴含着许多值得深入探讨的编程技巧和算法思想。这个练习不仅考察对字符输入输出的掌握,更考验逻辑思维能力和边界条件处理能力。
核心需求:编写一个C程序,能够接收用户输入的一行字符(以#号作为结束标志),准确统计其中单词的数量。这里的"单词"被定义为连续的非空格字符序列,单词之间由一个或多个空格分隔。
注意:在实际编程中,我们通常使用换行符(\n)作为输入结束标志,但本例中使用#号是为了简化输入处理,避免多行输入的复杂性。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 算法设计与思路解析
2.1 状态机思想的应用
这个问题的经典解法采用了有限状态机(FSM)的思想,通过维护一个状态变量(word)来跟踪当前是否处于单词内部:
- 初始状态:word=0(表示不在单词中)
- 状态转换规则:
- 遇到空格:将word置为0(表示离开单词或保持不在单词状态)
- 遇到非空格且当前word=0:表示进入一个新单词,计数器加1,并将word置为1
- 遇到非空格且当前word=1:表示仍在当前单词中,不做任何操作
c复制int count=0; // 单词计数器
int word=0; // 状态标志:0表示不在单词中,1表示在单词中
char c; // 当前读取的字符
while((c=getchar())!='#'){
if(c==' ') {
word=0; // 遇到空格,重置状态
}
else if(word==0){ // 非空格且之前不在单词中
word=1; // 标记进入单词
count++; // 计数器增加
}
// 其他情况(非空格且已在单词中)不做处理
}
2.2 边界条件考虑
一个健壮的算法必须考虑各种边界情况:
- 前导空格:输入以多个空格开头
- 尾部空格:输入以多个空格结尾
- 连续空格:单词之间有多个空格
- 空输入:直接输入#号
- 仅空格:只输入空格和#号
示例代码已经很好地处理了这些情况:
- 前导空格不会触发计数器增加
- 连续空格被视为单一分隔符
- 尾部空格不影响已统计的单词数
3. 代码实现与逐行解析
让我们详细分析提供的示例代码:
c复制#include <stdio.h>
int main(){
int count=0; // 初始化单词计数器
int word=0; // 状态标志:0=不在单词中,1=在单词中
char c; // 存储当前读取的字符
// 循环读取字符,直到遇到#号
while((c=getchar())!='#'){
