C语言字符串分割程序问题:修复段错误与输出格式优化
修复C程序的名字分割问题(段错误+输出格式修正)
原问题描述
需要编写C程序将输入字符串分割为名字(first)和姓氏(last):
- 正常输入为两个首字母大写的名字拼接(如
JoeSmith),需分割为Joe和Smith - 若仅输入单个名字(如
Joe),需输出only the first name is provided并换行打印该名字
原代码在输入单个名字时触发zsh: segmentation fault ./run错误,且单个名字的输出不符合要求。
原代码的核心问题
- 未初始化变量导致段错误:
index变量无初始值,输入单个名字时,第一个循环找不到第二个大写字母,index会是随机垃圾值,后续复制姓氏数组时会用非法索引访问内存,触发越界错误。 - 循环终止条件错误:用
i <=20作为循环终止条件,而非检查字符串结束符'\0',会超出输入字符串的实际长度访问无效内存。 - 字符串终止符处理混乱:原代码添加
'\0'的位置逻辑错误,导致字符串无法正确终止,引发乱码或内存问题。 - 单个名字判断逻辑错误:
if(first[i])的判断完全不符合需求,无法识别是否仅输入单个名字。 - 输出格式不符合要求:单个名字场景的输出未按要求打印提示并换行展示名字。
修复后的代码
#include <stdio.h> #include <ctype.h> int main() { char name[20], first[20], last[20]; printf("Enter FirstLast name or enter First: "); scanf("%s", name); int i, j; int has_last_name = 0; int last_start_idx = 0; // 遍历字符串,分割名字和姓氏 for (i = 0; name[i] != '\0'; i++) { first[i] = name[i]; // 跳过第一个字符,寻找姓氏的起始大写字母 if (i > 0 && isupper((unsigned char)name[i])) { last_start_idx = i; has_last_name = 1; break; } } // 给名字字符串添加终止符 first[i] = '\0'; if (has_last_name) { // 复制姓氏到last数组 for (j = 0; name[last_start_idx] != '\0'; j++, last_start_idx++) { last[j] = name[last_start_idx]; } last[j] = '\0'; printf("first name: %s\nlast name: %s\n", first, last); } else { // 仅输入单个名字的场景 printf("only the first name is provided\n"); printf("%s\n", first); } return 0; }
修复关键点说明
- 标记变量替代未初始化索引:用
has_last_name标记是否找到姓氏起始位置,彻底避免非法索引访问的问题。 - 正确的循环终止逻辑:所有循环以
name[i] != '\0'为终止条件,只访问字符串的有效内存区域。 - 规范的字符判断:使用
isupper函数判断大写字母,比直接比较ASCII值更符合C语言规范,同时强制转换为unsigned char避免字符值为负的异常情况。 - 正确添加字符串终止符:在复制完字符后,立即在数组对应位置添加
'\0',保证字符串能被正确识别。 - 符合需求的输出逻辑:通过
has_last_name判断输入类型,严格按照要求输出内容格式。
内容的提问来源于stack exchange,提问作者billyjoe2
相关产品推荐
相关产品推荐

