web-dev-qa-db-ja.com

C:strtok_rの正しい使用法

Strtokの代わりにstrtok_rを使用してこれを行うにはどうすればよいですか?

char *pchE = strtok(NULL, " ");

今、私はstrtok_rを適切に使用しようとしています...しかし、時々strtolで問題が発生します。 10回(同時に)実行するスレッドがあります。

char *savedEndd1;
char *nomeClass = strtok_r(lineClasses, " ", &savedEndd1);
char *readLessonS = strtok_r (NULL, " ", &savedEndd1);
char *readNTurma = strtok_r(NULL, " ",  &savedEndd1);

if (readNTurma==NULL)
printf("CLASS STRTOL begin %s %s\n",nomeClass, readLessonS );
int numberNTurma = strtol(readNTurma, NULL, 10);

readNTurma == NULLを何度かキャッチしています...なぜですか? NULLが来る理由を理解できない

36
Carlcox89

Strtok_rの ドキュメント は非常に明確です。

Strtok_r()関数は、リエントラントバージョンのstrtok()です。 saveptr引数は、同じ文字列を解析する連続した呼び出し間のコンテキストを維持するために、strtok_r()によって内部的に使用されるchar *変数へのポインターです。

Strtok_r()の最初の呼び出しで、strは解析される文字列を指す必要があり、saveptrの値は無視されます。後続の呼び出しでは、strはNULLである必要があり、saveptrは前の呼び出し以降変更されていない必要があります。

だからあなたは次のようなコードを持っているでしょう

char str[] = "Hello world";
char *saveptr;
char *foo, *bar;

foo = strtok_r(str, " ", &saveptr);
bar = strtok_r(NULL, " ", &saveptr);
39
tangrs

テスト済みの例:

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

int main(void)
{
    char str[] = "1,22,333,4444,55555";
    char *rest = NULL;
    char *token;

    for (token = strtok_r(str, ",", &rest);
         token != NULL;
         token = strtok_r(NULL, ",", &rest)) {   
        printf("token:%s\n", token);
    }

    return 0;
}

結果。

token:1
token:22
token:333
token:4444
token:55555

テスト: http://codepad.org/6xRdIecI

linux documentation から強調が私の場合:

char *strtok_r(char *str, const char *delim, char **saveptr);

Strtok_r()関数は、リエントラントバージョンのstrtok()です。 saveptr引数は、同じ文字列を解析する連続した呼び出し間のコンテキストを維持するために、strtok_r()によって内部的に使用されるchar *変数へのポインタです

strtok_r()の最初の呼び出しで、strは解析される文字列を指し、の値saveptrは無視されます。後続の呼び出しでは、strはNULLである必要があり、saveptrは前の呼び出しから変更されていない必要があります。

異なるsaveptr引数を指定するstrtok_r()の呼び出しシーケンスを使用して、異なる文字列を同時に解析できます。

13
MrHIDEn

ネストでstrtok()を使用する代わりにstrtok_r()の正しい使用方法を理解するために、テスト済みの例を投稿します。

最初に文字列「y.o.u、a.r.e、h.e.r.e」を取得し、区切り文字「、」と「。」を使用して区切ります。

strtok()を使用する

#include<stdio.h>
#include<string.h>
int main(void) {

        char str[]="y.o.u,a.r.e,h.e.r.e";
        const char *p=",", *q=".";
        char *a,*b;

        for( a=strtok(str,p) ; a!=NULL ; a=strtok(NULL,p) ) {
                printf("%s\n",a);
                for( b=strtok(a,q) ; b!=NULL ; b=strtok(NULL,q) )
                        printf("%s\n",b);
        }

        return 0;
}

出力:

君は
y
o
u

同じ例でstrtok_r()を使用できるようになりました

strtok_r()を使用する

#include<stdio.h>
#include<string.h>
int main(void) {

        char str[]="y.o.u,a.r.e,h.e.r.e";
        const char *p=",",*q=".";
        char *a,*b,*c,*d;

        for( a=strtok_r(str,p,&c) ; a!=NULL ; a=strtok_r(NULL,p,&c) ) {
                printf("%s\n",a);

                for( b=strtok_r(a,q,&d) ; b!=NULL ; b=strtok_r(NULL,q,&d) )
                        printf("%s\n",b);
        }

        return 0;
}

出力:

君は
y
o
u
a.r.e
a
r
e
ここに
h
e
r
e

したがって、strtok_r()にはリエントラントプロパティがありますが、strtok()はそのようには機能しません。

1
char str[]="string for sample";
char *reserve;
char *pchE = strtok_r(str, " ", &reserve);//when next call str -> NULL
1
BLUEPIXY