使用strtok()分割字符串提取SIP URI手机号返回NULL问题排查
嘿,我来帮你排查下这个strtok返回NULL的问题!你的核心需求很清晰:从SIP URI里截取出@前面的部分,纯数字直接返回,这个逻辑没问题,但strtok的使用确实容易踩坑,大概率是这几个原因导致的:
为什么你的strtok()会返回NULL?
最常见的坑有这两个:
- 传入了不可修改的字符串:strtok的工作原理是直接修改输入字符串,把分隔符替换成
'\0'来分割。如果你的输入是字符串字面量(比如"12345@example.com")或者用const char*修饰的指针,尝试修改它会触发未定义行为,轻则返回NULL,重则程序崩溃。 - 第一次调用strtok时传了NULL:strtok的规则是第一次调用必须传入目标字符串,后续调用才传NULL。如果第一次就传NULL,肯定直接返回NULL。
另外如果输入是空字符串或者只有@符号,也会返回NULL,但应该不是你的核心场景。
修正后的实现方案
我们需要先把输入字符串复制到一个可修改的缓冲区,再用strtok处理,同时处理各种边界情况。这里给你两种实现思路:
方案1:修复strtok的使用问题
#include <string.h> #include <stdlib.h> char* extract_phone_number(const char* sip_uri) { // 先处理空输入的边界情况 if (!sip_uri || *sip_uri == '\0') { return NULL; } // 分配可修改的临时缓冲区,复制原字符串 char* temp_buf = malloc(strlen(sip_uri) + 1); if (!temp_buf) { return NULL; // 内存分配失败 } strcpy(temp_buf, sip_uri); // 用@分割字符串,第一次调用传入temp_buf char* phone = strtok(temp_buf, "@"); // 把结果复制到新的内存块(避免返回临时缓冲区的指针,防止后续free失效) char* result = NULL; if (phone) { result = malloc(strlen(phone) + 1); if (result) { strcpy(result, phone); } } free(temp_buf); // 释放临时缓冲区 return result; }
注意:这个函数返回的是堆内存分配的字符串,调用者必须记得用free()释放,避免内存泄漏。
方案2:更安全的替代方案(推荐)
strtok不是线程安全的,而且需要修改原字符串,其实用strchr()直接找@的位置会更简单安全:
#include <string.h> #include <stdlib.h> char* extract_phone_number(const char* sip_uri) { if (!sip_uri || *sip_uri == '\0') { return NULL; } // 找到@符号的位置 const char* at_pos = strchr(sip_uri, '@'); // 计算电话号码的长度:有@就取@前面的长度,没有就取整个字符串长度 size_t phone_len = at_pos ? (at_pos - sip_uri) : strlen(sip_uri); // 分配内存并复制内容 char* result = malloc(phone_len + 1); if (!result) { return NULL; } strncpy(result, sip_uri, phone_len); result[phone_len] = '\0'; // 手动添加终止符,因为strncpy不一定会自动加 return result; }
这个方案不需要修改原字符串,也没有线程安全问题,逻辑更直观,推荐使用。
内容的提问来源于stack exchange,提问作者Cinder Biscuits
相关产品推荐
相关产品推荐

