You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 06:25:27