C语言中如何对开头带空格的句子执行tokenize?解决segmentation fault及替代方案
问题分析与解决方案
段错误的根源
你代码里的段错误是因为strtok会直接修改传入的字符串(它会把分隔符替换成\0来拆分出token),但char *buff = " push me"指向的是字符串常量——这类数据存在程序的只读内存区域,任何修改操作都会触发内存访问错误。
修复原代码的最简方式
把字符串常量改成可修改的字符数组,让strtok能正常工作:
#include <string.h> #include <stdio.h> int main() { char buff[] = " push me"; // 字符数组存储在栈上,支持修改 char *token; token = strtok(buff, " \n"); while (token) { printf("%s\n", token); token = strtok(NULL, " \n"); } return 0; }
无需修改原字符串的替代内置方案
如果不想改动原字符串(比如处理只读的字符串常量),可以用以下两种内置函数组合实现需求:
1. strspn + strcspn 手动拆分
strspn计算开头连续匹配分隔符的长度,strcspn计算连续不匹配分隔符的长度,两者配合可以跳过空格并提取单词,全程不修改原字符串:
#include <string.h> #include <stdio.h> int main() { const char *buff = " push me"; const char *delim = " \n"; const char *ptr = buff; // 跳过开头的空格等分隔符 ptr += strspn(ptr, delim); while (*ptr != '\0') { // 计算当前单词的长度 size_t word_len = strcspn(ptr, delim); // 输出或存储单词(这里用%.*s直接输出指定长度的字符串) printf("%.*s\n", (int)word_len, ptr); // 跳到下一个单词的起始位置 ptr += word_len; ptr += strspn(ptr, delim); } return 0; }
2. sscanf 循环提取
sscanf的%s格式符默认会跳过开头空白字符,每次提取一个单词,通过%n记录已读取的字符长度来移动指针:
#include <stdio.h> int main() { const char *buff = " push me"; const char *ptr = buff; char word[64]; // 根据实际需求调整缓冲区大小 int len; while (sscanf(ptr, "%s%n", word, &len) == 1) { printf("%s\n", word); ptr += len; // 移动指针到下一个单词的起始位置 } return 0; }
注意要保证word的缓冲区足够大,避免字符串溢出。
内容的提问来源于stack exchange,提问作者hawkins winja
相关产品推荐
相关产品推荐

