strtok传入字符串指针时意外返回NULL的问题咨询
strtok处理字符串指针异常的问题
问题背景
我编写了一个getElementAfterE函数,用于提取字符串中-e之后的元素,比如输入"show -e LENA"应返回"LENA"。函数代码如下:
char *getElementAfterE(char *str) { const char *delimiter = " "; const char *flag = "-e"; char *result = NULL; char *token = strtok(str, delimiter); // 获取第一个token while (token != NULL) { if (strcmp(token, flag) == 0) { token = strtok(NULL, delimiter); // 获取下一个token printf("next token: %s\n", token); if (token != NULL) { result = token; } break; } token = strtok(NULL, delimiter); // 获取下一个token } return result; }
遇到的问题:传入char *str = "show -e LENA";这类字符串指针时,if语句后的strtok始终返回NULL;但传入char str[] = "show -e LENA";这类字符数组时功能正常。程序中需要传入字符串指针,请问是否需要先将指针指向的字符串复制到字符数组中再传入函数?
原因分析
char *str = "show -e LENA";这种写法中,指针指向的是只读的字符串常量,这类数据存储在程序的只读数据段中,不允许修改。strtok函数的工作原理是修改原字符串:它会把找到的分隔符替换为'\0'来分割出token,后续调用依赖被修改后的字符串状态。当尝试修改只读内存时,会触发未定义行为,导致后续strtok调用异常返回NULL。char str[] = "show -e LENA";是把字符串内容复制到栈上的可写内存区域,strtok可以正常修改这里的内容,因此功能正常。
解决方案
是的,必须先将字符串指针指向的内容复制到可写的内存区域(比如栈上的字符数组,或者堆上动态分配的内存),再传入函数。
示例1:使用栈上字符数组(适合已知字符串长度范围的场景)
#include <stdio.h> #include <string.h> // 原函数保持不变 char *getElementAfterE(char *str) { const char *delimiter = " "; const char *flag = "-e"; char *result = NULL; char *token = strtok(str, delimiter); while (token != NULL) { if (strcmp(token, flag) == 0) { token = strtok(NULL, delimiter); printf("next token: %s\n", token); if (token != NULL) { result = token; } break; } token = strtok(NULL, delimiter); } return result; } int main() { char *str_ptr = "show -e LENA"; // 定义足够大的栈数组,复制原字符串 char str_buf[100]; strcpy(str_buf, str_ptr); char *elem = getElementAfterE(str_buf); if (elem) { printf("提取结果: %s\n", elem); } return 0; }
示例2:使用动态分配内存(适合字符串长度不确定的场景)
#include <stdio.h> #include <string.h> #include <stdlib.h> char *getElementAfterE(char *str) { // 原函数代码不变 const char *delimiter = " "; const char *flag = "-e"; char *result = NULL; char *token = strtok(str, delimiter); while (token != NULL) { if (strcmp(token, flag) == 0) { token = strtok(NULL, delimiter); printf("next token: %s\n", token); if (token != NULL) { result = token; } break; } token = strtok(NULL, delimiter); } return result; } int main() { char *str_ptr = "show -e LENA"; // 动态分配足够的内存 char *str_buf = malloc(strlen(str_ptr) + 1); if (str_buf == NULL) { printf("内存分配失败\n"); return 1; } strcpy(str_buf, str_ptr); char *elem = getElementAfterE(str_buf); if (elem) { printf("提取结果: %s\n", elem); } free(str_buf); // 记得释放动态分配的内存 return 0; }
内容的提问来源于stack exchange,提问作者FGomes
相关产品推荐
相关产品推荐

