C语言实现字符串拆分单词(禁用strdup)程序触发段错误求助
字符串拆分C代码段错误修复
我写了一段C语言代码,用来把字符串拆分成单词,要求不能用strdup函数,必须用malloc和strcpy实现。目标是当char *cmd = "Hello world baby"时,让argv[0] = "Hello"、argv[1] = "world"、argv[2] = "baby"。
原代码如下:
#include <stdio.h> #include <stdlib.h> #include <string.h> #define buf_size 128 int main() { char *argv[16]; memset(argv, 0, sizeof(argv)); int words = 0; char *cmd = "Hello world baby"; unsigned int len = strlen(cmd); int start = 0; for(unsigned int i = 0; i <= len; i++){ if(cmd[i] == ' ' | cmd[i] == '\0'){ ++words; char *w = (char *)malloc(sizeof(char)*(i-start) + 1); strcpy(w, cmd + start); w[i-start] = '\0'; argv[i] = w; start = i + 1; } } for(int i = 0; i < words; i++){ printf("%s\n", argv[i]); free(argv[i]); } return 0; }
期望输出:
Hello world baby
但程序运行到printf时触发了段错误。
错误原因
- 索引赋值错误:这是触发段错误的核心原因。原代码将拆分出的单词赋值给
argv[i],这里的i是循环到的字符位置(比如第一个空格在第5位,就赋值给argv[5]),但后续printf循环遍历的是0到words-1(即0、1、2),这三个位置的argv元素都是初始的空指针,printf访问空指针直接引发段错误。 - 逻辑运算符误用:判断条件中使用了按位或
|,正确应该用逻辑或||。虽然当前测试用例下该错误未直接触发问题,但会导致逻辑判断不符合预期(例如某些字符按位或后会被误判为分隔符)。
修正后的代码
#include <stdio.h> #include <stdlib.h> #include <string.h> #define buf_size 128 int main() { char *argv[16]; memset(argv, 0, sizeof(argv)); int words = 0; int idx = 0; // 新增索引变量,用于正确给argv数组赋值 char *cmd = "Hello world baby"; unsigned int len = strlen(cmd); int start = 0; for(unsigned int i = 0; i <= len; i++){ // 将按位或|替换为逻辑或|| if(cmd[i] == ' ' || cmd[i] == '\0'){ // 跳过连续空格,避免生成空单词 if(i == start){ start = i + 1; continue; } ++words; // 分配内存,计算单词长度+1用于存储结束符 char *w = (char *)malloc(sizeof(char) * (i - start) + 1); if(w == NULL){ // 检查内存分配是否成功 perror("malloc failed"); // 释放已分配的内存,避免泄漏 for(int j = 0; j < idx; j++){ free(argv[j]); } return 1; } // 安全复制单词内容,并手动添加字符串结束符 strncpy(w, cmd + start, i - start); w[i - start] = '\0'; argv[idx++] = w; start = i + 1; } } for(int i = 0; i < words; i++){ printf("%s\n", argv[i]); free(argv[i]); } return 0; }
额外优化说明
- 连续空格处理:遇到连续空格时跳过,不会生成空单词,避免无效的内存分配和输出。
- 内存分配失败检查:添加malloc失败的判断,此时会释放已分配的内存并退出程序,防止内存泄漏。
- 安全字符串复制:将
strcpy替换为strncpy,避免复制超出分配内存范围的内容,提升代码安全性。
内容的提问来源于stack exchange,提问作者Seil Lee
相关产品推荐
相关产品推荐

