You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言大小写转换程序输入异常求助:fgets/gets无法获取输入

解决C语言fgets跳过输入问题及大小写互转代码优化

核心问题:输入缓冲区残留换行符导致fgets跳过输入

你用scanf("%c", &ans)读取字符后,用户按下的回车键(\n)会留在输入缓冲区中。后续调用fgets()时,它会直接读取这个残留的换行符,导致程序看起来跳过了字符串输入步骤。

两种解决方法:

  • 方法1:在scanf后手动清除换行符
    在scanf之后调用getchar()吃掉缓冲区里的换行:
    scanf("%c", &ans);
    getchar(); // 清除输入缓冲区的换行符
    
  • 方法2:修改scanf格式字符串
    在%c前加一个空格,让scanf自动跳过所有空白字符(包括换行、空格、制表符):
    scanf(" %c", &ans); // 注意%c前的空格
    

代码中的其他问题及优化

除了输入问题,你的代码还有几个需要修正的地方:

1. 函数返回值类型错误

lower和upper函数声明返回char,但实际是原地修改传入的字符串,应该改为返回void或者char*(如果需要返回原字符串指针)。当前的返回值类型会导致编译警告。

2. 大小写转换逻辑完全颠倒

  • 标注的upper函数本应实现小写转大写,但代码里是str[i] + 32(这会把小写字母变成非字母字符),正确的小写转大写应该是str[i] - 32。
  • lower函数本应实现大写转小写,但代码里是str[i] - 32,正确的应该是str[i] + 32。

3. 用strstr判断字母效率低下

strstr是用来查找子串的,用来判断单个字符是否为字母完全没必要,建议引入<ctype.h>头文件,使用isupper()和islower()宏来判断字符类型,代码更简洁高效。

4. 循环中重复计算strlen

strlen(str)在循环条件里会每次遍历字符串计算长度,效率低,建议先把长度存到变量里再循环。


修正后的完整代码

#include <stdio.h>
#include <string.h>
#include <ctype.h> // 引入ctype.h使用isupper/islower

void to_upper(char *str); // 改为void,因为原地修改
void to_lower(char *str);

int main() {
    char ans;
    printf("Enter U for Lower case -> Upper case\nEnter L for Upper case -> Lower case:\n");
    scanf(" %c", &ans); // 用空格跳过空白字符

    char str[100];
    printf("Enter the string:\n");
    fgets(str, 100, stdin);

    // 去掉fgets读取的换行符(如果存在)
    size_t len = strlen(str);
    if (len > 0 && str[len-1] == '\n') {
        str[len-1] = '\0';
    }

    if (ans == 'U' || ans == 'u') {
        to_upper(str);
    } else if (ans == 'L' || ans == 'l') {
        to_lower(str);
    } else {
        printf("Try entering a valid input.\n");
        return 1; // 非法输入直接退出
    }
    
    printf("Result: %s\n", str);
    return 0;
}

void to_upper(char *str) {
    size_t len = strlen(str); // 先计算长度一次
    for (size_t i = 0; i < len; i++) {
        if (islower((unsigned char)str[i])) { // 用islower判断
            str[i] = str[i] - 32; // 小写转大写
        }
    }
}

void to_lower(char *str) {
    size_t len = strlen(str);
    for (size_t i = 0; i < len; i++) {
        if (isupper((unsigned char)str[i])) { // 用isupper判断
            str[i] = str[i] + 32; // 大写转小写
        }
    }
}

额外优化说明:

  • 加入了去除fgets读取的换行符的逻辑,避免输出时多一行空行。
  • 非法输入时直接返回非0值,符合程序退出码规范。
  • 使用size_t作为循环变量类型,和strlen的返回类型匹配,避免类型警告。

内容的提问来源于stack exchange,提问作者Shashank Gupta

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 22:28:10