在C语言token循环中调用函数触发段错误,求排查方案
问题分析与修复方案
你的段错误核心原因是直接修改strtok返回的原缓冲区指针指向的内容,导致缓冲区溢出,进而破坏内存结构(包括strtok的内部状态)。
具体问题点
strtok返回的token指针指向sentence_copy数组内部的内存区域,该区域的空间仅为原单词长度+1。但转换后的猪拉丁语单词更长(比如cat→atcay,长度从3变为5),直接在原位置执行strcpy和strcat会溢出,覆盖数组其他数据甚至越界访问内存。- 代码未处理全辅音单词(比如
myth)的情况,此时first_vowel保持-1,直接执行strcat(input, end)依然可能触发缓冲区溢出。
修复后的代码
#include <stdio.h> #include <string.h> #include <ctype.h> // 转换单个单词为猪拉丁语,结果存入提前分配好的output缓冲区 void pigLatinConsonant(const char input[], char output[]) { const char end[] = "ay"; int length = strlen(input); int first_vowel = -1; // 查找第一个元音(支持大小写) for (int i = 0; i < length; i++) { char c = tolower(input[i]); if (strchr("aeiou", c)) { first_vowel = i; break; } } if (first_vowel != -1) { // 先拷贝元音起始的部分 strcpy(output, input + first_vowel); // 拼接开头的辅音簇 strncat(output, input, first_vowel); } else { // 全辅音单词直接拷贝原内容 strcpy(output, input); } // 拼接后缀"ay" strcat(output, end); } int main() { char sentence[100]; printf("Enter a sentence: "); fgets(sentence, sizeof(sentence), stdin); // 移除fgets读取的换行符 sentence[strcspn(sentence, "\n")] = '\0'; char sentence_copy[sizeof(sentence)]; strcpy(sentence_copy, sentence); char *token = strtok(sentence_copy, " "); // 为转换后的单词分配足够空间(原单词长度+3,满足最长扩展需求) char translated_word[100]; while (token != NULL) { pigLatinConsonant(token, translated_word); printf("Translated word: %s\n", translated_word); token = strtok(NULL, " "); } return 0; }
关键修改说明
- 重构
pigLatinConsonant函数,新增独立的输出缓冲区,不再直接修改原输入字符串,彻底避免缓冲区溢出。 - 补充全辅音单词的处理逻辑,保证所有场景下的内存安全。
- 移除
fgets带入的换行符,避免最后一个单词的转换被干扰。 - 新增大小写元音兼容处理,提升代码通用性。
内容的提问来源于stack exchange,提问作者Tanya Kumari
相关产品推荐
相关产品推荐

