我正在尝试打印一个大字符串中包含的所有子字符串,每个字符串由'/'
个字符分隔。我的功能没有像我期望的那样工作,但我没有弄到它有什么问题。这是我写的函数:
void print_serial_list(char *serial_list) {
char *iter = serial_list;
while (*iter != '\0') { // Traverse the whole string
char *tmp_fn;
tmp_fn = strtok(iter,"/");
printf("Extracted entry: '%s'\n", tmp_fn);
iter = iter + sizeof(tmp_fn);
}
}
如果我像这样运行这个函数:
char *string = "Lorem.ipsum/dolor-sit-amet/consectetur/adipiscing.elit/";
printf("%s\n", string);
print_serial_list(string);
我遇到了分段错误:
Lorem.ipsum/dolor-sit-amet/consectetur/adipiscing.elit/
Segmentation fault (core dumped)
get_string()
函数另一方面,如果我运行它:
char *string = get_string();
printf("%s\n", string);
print_serial_list(string);
我得到以下输出(仍然错误):
Lorem.ipsum/dolor-sit-amet/consectetur/adipiscing.elit/
Extracted entry: 'Lorem.ipsum'
Extracted entry: 'sum'
Extracted entry: 'r-sit-amet'
Extracted entry: 'et'
Extracted entry: 'ctetur'
Extracted entry: 'dipiscing.elit'
Extracted entry: 'g.elit'
Extracted entry: '�'
Extracted entry: 'x[�V'
Extracted entry: 'x[�V'
为了清楚起见,我希望输出在两种情况下:
Lorem.ipsum/dolor-sit-amet/consectetur/adipiscing.elit/
Extracted entry: 'Lorem.ipsum'
Extracted entry: 'dolor-sit-amet'
Extracted entry: 'consectetur'
Extracted entry: 'adipiscing.elit'
( 注意 :我希望get_string()
的代码不需要理解这个问题......我想尝试一下保持帖子不会太长)
在评论中提出了几条建议后,我以这种方式编辑了这个功能:
char *iter = serial_list;
bool first = true;
while (*iter != '\0') { // Traverse the whole string
char *tmp_fn;
if (first)
tmp_fn = strtok(iter, "/");
else
tmp_fn = strtok(NULL, "/");
size_t tmp_size = strlen(tmp_fn);
printf("Extracted entry: '%s' - size = %zu\n", tmp_fn, tmp_size);
iter = iter + tmp_size;
first = false;
}
我得到的输出仍有一些问题,但与我想要的更相似!
Lorem.ipsum/dolor-sit-amet/consectetur/adipiscing.elit/
Extracted entry: 'Lorem.ipsum' - size = 11
答案 0 :(得分:2)
If I run this function like this, I get a segmentation fault:
char *string = "Lorem.ipsum/dolor-sit-amet/consectetur/adipiscing.elit/";
您的程序正在尝试修改字符串文字时遇到undefined behavior,因为您正在将字符串文字传递给strtok()
。
char * strtok(char * str,const char * delimiters);
将字符串拆分为标记
对此函数的一系列调用将str拆分为标记,标记是由作为分隔符一部分的任何字符分隔的连续字符序列。
string
是指向字符串文字的指针,其内容无法修改。并尝试通过指针修改它们是Undefined Behavior。
要解决此问题,您只需执行此操作:
char string[] = "Lorem.ipsum/dolor-sit-amet/consectetur/adipiscing.elit/";
^^
在print_serial_list()
函数中,你可以这样做:
void print_serial_list(char *serial_list) {
char *iter = serial_list;
if (serial_list == NULL)
return;
char *tmp_fn = strtok(iter, "/");
while (tmp_fn != NULL)
{
printf ("Extracted entry: '%s'\n", tmp_fn);
tmp_fn = strtok(NULL, "/");
}
}
print_serial_list()
输出(对于Lorem.ipsum/dolor-sit-amet/consectetur/adipiscing.elit/
输入字符串):
Extracted entry: 'Lorem.ipsum'
Extracted entry: 'dolor-sit-amet'
Extracted entry: 'consectetur'
Extracted entry: 'adipiscing.elit'
此处需要注意的是print_serial_list()
将修改字符串string
,因为它会将其传递给strtok()
。如果您不希望在调用print_serial_list()
函数后修改输入字符串,请在print_serial_list()
函数中复制它。
来自strtok:
错误 使用这些功能时要小心。如果您确实使用它们,请注意:
*这些函数修改了他们的第一个参数。
*这些函数不能用于常量字符串。
*分隔字节的标识丢失。
感谢@David C. Rankin在评论中分享这些strtok()
个错误。