C语言函数参数返回值问题:字符串大写与元音计数始终为0
问题分析与代码修复:大写字母和元音计数始终为0的问题
嘿,我帮你定位到代码里的几个关键问题啦,正是它们导致你的大写字母和元音计数一直返回0,咱们一步步拆解并修复:
1. 计数变量未初始化
在main函数里,你声明了int upper, chars;但没有给它们初始值。C语言的局部变量默认不会自动初始化为0,它们的初始值是内存里的随机垃圾值。当你在StringChange函数里对*upper和*chars做累加操作时,本质是在垃圾值上修改,最终结果自然不对(你看到的0只是巧合的未定义行为)。
修复方式:在main里显式初始化这两个变量:
int upper = 0, chars = 0;
2. 循环索引越界 + 统计范围遗漏
你的循环是for (i = 1; i <= length; i++),这里有两个核心问题:
- 当
i == length时,text[i]访问的是字符串的结束符'\0',这属于数组越界访问,会触发未定义行为; - 循环只处理了
text[1]到text[length-1]的内容,而text[0]你单独做了大写转换,但完全没把它纳入大写字母的统计范围。
修复方式:调整循环范围为从0到length-1,同时给text[i-1]的判断加边界保护:
for (i = 0; i < length; i++) { // 加i>0避免访问text[-1]越界 if (i > 0 && text[i-1] == '*' && (text[i] >= 'a' && text[i] <= 'z')) { text[i] -= 32; } // 其余逻辑调整索引后正常执行 }
另外,别忘了在处理text[0]的大写转换后,手动统计这个大写字母。
3. 元音统计未覆盖大写情况
你的代码只检查了小写的元音字母(a/e/i/o/u/y),但大写的元音(A/E/I/O/U/Y)完全没被统计进去,这会导致计数偏少,甚至如果字符串全是大写元音的话计数为0。
修复方式:要么直接把大写元音加入判断条件,要么用标准库函数统一转小写后判断(更简洁):
// 方式1:直接加大写判断 if (text[i] == 'a' || text[i] == 'e' || text[i] == 'i' || text[i] == 'o' || text[i] == 'u' || text[i] == 'y' || text[i] == 'A' || text[i] == 'E' || text[i] == 'I' || text[i] == 'O' || text[i] == 'U' || text[i] == 'Y') { *chars += 1; } // 方式2:转小写后判断(需要包含<ctype.h>头文件) char c = tolower(text[i]); if (c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u' || c == 'y') { *chars += 1; }
完整修复后的代码
#include <stdio.h> #include <conio.h> #include <string.h> #include <ctype.h> // 用于tolower/toupper等字符处理函数 char *StringChange(char *text, int *upper, int *chars); int main(void) { char text[40]; int upper = 0, chars = 0; // 显式初始化计数变量 puts("Type a string"); gets(text); // 注意:gets函数存在安全风险,实际开发建议用fgets替代 StringChange(text, &upper, &chars); puts("Change words to start with upper case and change white space to *"); puts(text); printf("Quantity of upper case in string: %d\n", upper); printf("Quantity of vowels: %d", chars); getch(); return 0; } char *StringChange(char *text, int *upper, int *chars) { int i, length; length = strlen(text); for (i = 0; i < length; i++) { // 处理单词首字母大写(仅当前一个字符是*时) if (i > 0 && text[i-1] == '*' && islower(text[i])) { text[i] = toupper(text[i]); } // 空格转* if (text[i] == ' ') { text[i] = '*'; } // 统计大写字母 if (isupper(text[i])) { (*upper)++; } // 统计元音(大小写都算) char c = tolower(text[i]); if (c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u' || c == 'y') { (*chars)++; } } // 处理第一个字符的大写转换,并统计 if (islower(text[0])) { text[0] = toupper(text[0]); (*upper)++; } return text; }
额外说明:我把手动的ASCII加减替换成了isupper、islower这些标准库函数,让代码更可读且跨平台。另外,gets函数存在缓冲区溢出风险,实际开发中建议用fgets(text, sizeof(text), stdin)替代,记得处理输入末尾的换行符。
内容的提问来源于stack exchange,提问作者Ondřej Javorský
相关产品推荐
相关产品推荐

