简体   繁体   English

strtok_r() 对 strtok() 做了哪些更改? 结果看起来还是一样,它改变了原来的字符串

[英]What changes strtok_r() did over strtok()? Result still looks the same, it changes the original string

I was stuck on strtok() why it modifies the original string... But then someone told strtok_r() won't do that... While I test it out I find no change.我被困在strtok()上,为什么它会修改原始字符串……但后来有人告诉strtok_r()不会那样做……当我测试它时,我发现没有任何变化。 strtok_r() also modifies the original string. strtok_r()还修改了原始字符串。 At the end of the call to strtok_r() original string has changed.在对strtok_r()的调用结束时,原始字符串已更改。

What is the use of variable - char* rest = str变量有什么用 - char* rest = str

Here is my code.这是我的代码。

#include <stdio.h>
#include <string.h>

int main(void) {

        char str[] = "Tom Jerry Hary Potter";
        char* token;
        char* rest = str;

        printf("\n\nOriginal String before while loop: %s", str);
        printf("\n\nOriginal String length before while loop: %lu\n\n", strlen(str));

        while ((token = strtok_r(rest, " ", &rest)))
                printf(" %s :", token);

        printf("\n\nOriginal String after while loop: %s", str);
        printf("\n\nOriginal String length after while loop: %lu\n\n", strlen(str));

        return (0);
}

Output Output

Original String before while loop: Tom Jerry Hary Potter

Original String length before while loop: 21

 Tom : Jerry : Hary : Potter :

Original String after while loop: Tom

Original String length after while loop: 3

was stuck on strtok() why it modifies the original string... But then someone told strtok_r() won't do that... While I test it out I find no change.卡在 strtok() 上,为什么它会修改原始字符串……但后来有人告诉 strtok_r() 不会那样做……当我测试它时,我发现没有任何变化。 strtok_r() also modifies the original string. strtok_r() 还修改了原始字符串。 At the end of the call to strtok_r() original string has changed.在调用 strtok_r() 结束时,原始字符串已更改。

This is not true.这不是真的。 strtok_r(3) does change the original string, as strtok(3) did previously, what it does differently is to accept a pointer to char * from you, to store the information (the point it was when it found the last string) it needs to use between calls, so it can be reentered from different threads making the function reentrant. strtok_r(3)确实更改了原始字符串,就像strtok(3)之前所做的那样,它的不同之处在于接受您的指向char *的指针,以存储信息(找到最后一个字符串时的位置)需要在调用之间使用,因此它可以从不同的线程重新进入,使 function 可重入。

Strtok is an archaic function, that predates from the times of early C. It modifies the original string to avoid using dynamically allocated memory, which is faster, but if you want to preserve the original string you can always call strdup(3) on the original string, operate on the obtained copy, and then return the memory used with free(3) when you are finished. Strtok 是一个古老的 function,早于 C 的时代。它修改原始字符串以避免使用动态分配的 memory,这更快,但如果你想保留原始字符串,你可以随时调用strdup(3)原始字符串,对得到的副本进行操作,完成后返回free(3)使用的memory。

Anyway, even if you use strtok(2) in a locally memory allocated buffer, it continues to be non-reentrant, as it uses global static data to remember the position on the string it is parsing, so it can continue where it stopped to get the next substring. If you want to use strtok(3) nested in another loop, or you want it to be reentered recursively in a recursive procedure, then you have to switch to the _r suffixed one, or you'll lost the pointer in the outer call with the calls to the inner loop strtok() .无论如何,即使您在本地 memory 分配的缓冲区中使用strtok(2) ,它仍然是不可重入的,因为它使用全局 static 数据来记住它正在解析的字符串上的 position,因此它可以在它停止的地方继续得到下一个substring。如果你想在另一个循环中使用strtok(3) ,或者你想在递归过程中递归地重新进入它,那么你必须切换到_r后缀的那个,否则你会丢失指针在外部调用中调用内部循环strtok() For example:例如:

char buffer[] = "root:0:0:x:System Administrator,Administrators Dept.,5742,+300 40 86 26:/root:/bin/sh";
/* look for password fields */
for(p = strtok(string, ":"); p; p = strtok(NULL, ":")) {
    /* separate items with commas */
    for (q = strtok(p, ","); q; q = strtok(NULL, ",")) {
        .... /* the last call to strtok(NULL, ",") broke the point where 
              * the first call to strtok(NULL, ":") was looking at, in the
              * outer loop. */

you need to change to:您需要更改为:

char *p1;
for(p = strtok_r(string, ":", &p1); p; p = strtok_r(NULL, ":", &p1)) {
    char *p2;
    for (q = strtok_r(p, ",", &p2); q; q = strtok_r(NULL, ",", &p2)) {
        .... /* nothing breaks, if p1 and p2 are different variables. */

an example of using strdup() could be:使用strdup()的示例可能是:

char *p1, *working_string = strdup(original_string);
for(p = strtok_r(workin_string, ":", &p1); p; p = strtok_r(NULL, ":", &p1)) {
    char *p2;
    for (q = strtok_r(p, ",", &p2); q; q = strtok_r(NULL, ",", &p2)) {
        .... /* nothing breaks, if p1 and p2 are different variables. */
    }
}
...
free(working_string); /* or whenever you feel it can be freed */

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM