strtok_r 保存状态行为
strtok_r save state behaviour
correct使用strtok_r
的方法如下:
char* str = strdup(string);
char* save;
char* ptr = strtok_r(str, delim, &save);
while(ptr) {
puts(ptr);
ptr = strtok_r(NULL, delim, &save);
}
当试图检查 save
中实际存储的内容时,我发现它只是未解析字符串的其余部分。所以我试着让第二个调用看起来像第一个,并写了一个包装器如下。
char* as_tokens(char** str, const char* const delim) {
return strtok_r(NULL, delim, str);
}
这可以像下面这样使用,这样就不那么冗长了。我们不必区分第一次通话和休息。
char* str = strdup(string);
char* ptr;
while(ptr = as_tokens(&str, delim))
puts(ptr);
这种方法有什么缺点吗?我是否导致任何未定义的行为?我尝试了一些极端情况,两种方法的工作原理相似。
在线编译器:https://wandbox.org/permlink/rkGiwXOUtzqrbMpP
P.S。为简洁起见忽略内存泄漏。
更新
已经存在一个与我的 as_tokens
几乎相似的函数:strsep。
当存在连续的定界符时情况不同。 strsep
returns 一个空字符串,而 as_tokens
(即 strtok_r)将它们视为一个。
Are there any downsides in this approach?
是的,它失去了 str
的原始值,因此无法(在本例中)释放它。因此,您有内存泄漏。这可以通过保留指针的单独副本来解决,但这归结为与您的第一个代码几乎相同的东西。
此外,正如在评论中观察到的,它不符合 strtok_r
的规范,因为定义了使用第一个参数 NULL
调用 strtok_r
的行为仅在先前调用 strtok_r
的上下文中提供了第三个参数指向的值。
此外,它偏离了 strtok_r
惯用的、易于理解的用法,甚至将其隐藏在不同的函数中。正常的成语并不繁琐,而且是众所周知和理解的。聪明一点会让你的代码更难维护。
Am I causing any undefined behavior?
是的,在 "behavior that is not defined" 的意义上,与明确称为 un 定义的行为相反。但相关标准对这些替代品赋予了同样的重要性。见上文。
correct使用strtok_r
的方法如下:
char* str = strdup(string);
char* save;
char* ptr = strtok_r(str, delim, &save);
while(ptr) {
puts(ptr);
ptr = strtok_r(NULL, delim, &save);
}
当试图检查 save
中实际存储的内容时,我发现它只是未解析字符串的其余部分。所以我试着让第二个调用看起来像第一个,并写了一个包装器如下。
char* as_tokens(char** str, const char* const delim) {
return strtok_r(NULL, delim, str);
}
这可以像下面这样使用,这样就不那么冗长了。我们不必区分第一次通话和休息。
char* str = strdup(string);
char* ptr;
while(ptr = as_tokens(&str, delim))
puts(ptr);
这种方法有什么缺点吗?我是否导致任何未定义的行为?我尝试了一些极端情况,两种方法的工作原理相似。
在线编译器:https://wandbox.org/permlink/rkGiwXOUtzqrbMpP
P.S。为简洁起见忽略内存泄漏。
更新
已经存在一个与我的 as_tokens
几乎相似的函数:strsep。
当存在连续的定界符时情况不同。 strsep
returns 一个空字符串,而 as_tokens
(即 strtok_r)将它们视为一个。
Are there any downsides in this approach?
是的,它失去了 str
的原始值,因此无法(在本例中)释放它。因此,您有内存泄漏。这可以通过保留指针的单独副本来解决,但这归结为与您的第一个代码几乎相同的东西。
此外,正如在评论中观察到的,它不符合 strtok_r
的规范,因为定义了使用第一个参数 NULL
调用 strtok_r
的行为仅在先前调用 strtok_r
的上下文中提供了第三个参数指向的值。
此外,它偏离了 strtok_r
惯用的、易于理解的用法,甚至将其隐藏在不同的函数中。正常的成语并不繁琐,而且是众所周知和理解的。聪明一点会让你的代码更难维护。
Am I causing any undefined behavior?
是的,在 "behavior that is not defined" 的意义上,与明确称为 un 定义的行为相反。但相关标准对这些替代品赋予了同样的重要性。见上文。