C语言 从字符串中提取子字符串时出现意外行为



>我正在尝试打印包含在一个大字符串中的所有子字符串,每个子字符串都由'/'字符分隔。我的函数没有像我预期的那样工作,但我不明白它有什么问题。这是我写的函数:

void print_serial_list(char *serial_list) {
char *iter = serial_list;
while (*iter != '') { // 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("%sn", string);
print_serial_list(string);

我遇到分段错误:

Lorem.ipsum/dolor-sit-amet/consectetur/adipiscing.elit/
Segmentation fault (core dumped)

使用get_string()函数

另一方面,如果我运行这个:

char *string = get_string();
printf("%sn", 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 != '') { // 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 = %zun", tmp_fn, tmp_size);
iter = iter + tmp_size;
first = false;
}

我得到的输出仍然存在一些问题,但与我想要的更相似!

Lorem.ipsum/dolor-sit-amet/consectetur/adipiscing.elit/
Extracted entry: 'Lorem.ipsum' - size = 11

If I run this function like this, I get a segmentation fault:

char *string = "Lorem.ipsum/dolor-sit-amet/consectetur/adipiscing.elit/";

您的程序在尝试修改字符串文本时具有未定义的行为,因为您要将字符串文本传递给strtok()

char * strtok ( char * str, const char * delimiters );

将字符串拆分为标记

对此函数的一系列调用将 str 拆分为标记,这些标记是由分隔符中的任何字符分隔的连续字符序列。

string是指向字符串文本的指针,其内容无法修改。尝试通过指针修改它们是未定义的行为。

要解决此问题,您只需执行以下操作:

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()将在将字符串传递给strtok()时修改字符串string。如果不希望在调用函数后修改输入字符串print_serial_list()请在print_serial_list()函数中复制它。


从斯特托克:

错误 使用这些功能时要小心。如果您确实使用它们,请注意:

*这些函数修改其第一个参数。

*这些函数不能用于常量字符串。

*分隔字节的标识丢失。

感谢@David C. Rankin在评论中分享这些strtok()错误。

相关内容

  • 没有找到相关文章

最新更新