25

スペースを区切り文字として使用して文字列をトークン化しようとしましたが、うまくいきません。なぜそれが機能しないのかについての提案はありますか?

編集:次を使用してトークン化:

strtok(string, " ");

コードは次のようなものです

pch = strtok (str," ");
while (pch != NULL)
{
  printf ("%s\n",pch);
  pch = strtok (NULL, " ");
}
4

8 に答える 8

46

次のようにします。

char s[256];
strcpy(s, "one two three");
char* token = strtok(s, " ");
while (token) {
    printf("token: %s\n", token);
    token = strtok(NULL, " ");
}

注:strtok文字列のトークン化を変更するため、const char*.

于 2008-11-05T19:57:39.180 に答える
39

strtokこれは使用例です。これstrtokは入力文字列を破壊することに注意してください (したがって、文字列定数では使用できません)。

char *p = strtok(str, " ");
while(p != NULL) {
    printf("%s\n", p);
    p = strtok(NULL, " ");
}

基本的に注意すべきことはNULL、最初のパラメーターとしてa を渡すと、strtok以前にトークン化した文字列から次のトークンを取得するように指示することです。

于 2008-11-05T19:57:53.673 に答える
7

strtok は非常に危険です。スレッドセーフではありません。その使用目的は、ループ内で何度も呼び出され、前の呼び出しからの出力を渡すことです。strtok 関数には、strtok 呼び出しの状態を格納する内部変数があります。この状態は各スレッドに固有のものではなく、グローバルです。他のコードが別のスレッドで strtok を使用すると、問題が発生します。追跡したい種類の問題でもありません。

正規表現の実装を探すか、sscanf を使用して文字列を引き離すことをお勧めします。

これを試して:

char strprint[256];
char text[256];
strcpy(text, "My string to test");
while ( sscanf( text, "%s %s", strprint, text) > 0 ) {
   printf("token: %s\n", strprint);
}

注: 「テキスト」文字列は分離されると破棄されます。これは好ましい動作ではないかもしれません =)

于 2008-11-05T20:14:22.160 に答える
2

追加の変数を導入することで、コードを簡略化できます。

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

int main()
{
    char str[100], *s = str, *t = NULL;

    strcpy(str, "a space delimited string");
    while ((t = strtok(s, " ")) != NULL) {
        s = NULL;
        printf(":%s:\n", t);
    }
    return 0;
}
于 2008-11-05T20:02:26.270 に答える
2

このコードは PIC18F プロセッサで実行することを目的としているため、可能な限り少ないポインタを使用して、値を分割するためにいくつかの文字列関数を作成しました。これらのプロセッサは、使用可能な空き RAM がほとんどない場合、ポインターをうまく処理できません。

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

char POSTREQ[255] = "pwd=123456&apply=Apply&d1=88&d2=100&pwr=1&mpx=Internal&stmo=Stereo&proc=Processor&cmp=Compressor&ip1=192&ip2=168&ip3=10&ip4=131&gw1=192&gw2=168&gw3=10&gw4=192&pt=80&lic=&A=A";

int findchar(char *string, int Start, char C) {
    while((string[Start] != 0)) { Start++; if(string[Start] == C) return Start; }
    return -1;
}

int findcharn(char *string, int Times, char C) {
   int i = 0, pos = 0, fnd = 0;

    while(i < Times) {
       fnd = findchar(string, pos, C);
        if(fnd < 0) return -1;
        if(fnd > 0) pos = fnd;
       i++;
   }
   return fnd;
}

void mid(char *in, char *out, int start, int end) {
    int i = 0;
    int size = end - start;

    for(i = 0; i < size; i++){
        out[i] = in[start + i + 1];
    }
    out[size] = 0;
}

void getvalue(char *out, int index) {
    mid(POSTREQ, out, findcharn(POSTREQ, index, '='), (findcharn(POSTREQ, index, '&') - 1));
}

void main() {
   char n_pwd[7];
   char n_d1[7];

   getvalue(n_d1, 1);

   printf("Value: %s\n", n_d1);
} 
于 2013-09-02T20:00:06.397 に答える
0

これは、連続した区切り文字を認識する機能を持つ別のstrtok()実装です (標準ライブラリstrtok()にはこれがありません)。

この関数は、zStringと呼ばれる BSD ライセンスの文字列ライブラリの一部です。あなたが貢献することは大歓迎です:)

https://github.com/fnoyanisi/zString

char *zstring_strtok(char *str, const char *delim) {
    static char *static_str=0;      /* var to store last address */
    int index=0, strlength=0;       /* integers for indexes */
    int found = 0;                  /* check if delim is found */

    /* delimiter cannot be NULL
    * if no more char left, return NULL as well
    */
    if (delim==0 || (str == 0 && static_str == 0))
        return 0;

    if (str == 0)
        str = static_str;

    /* get length of string */
    while(str[strlength])
        strlength++;

    /* find the first occurance of delim */
    for (index=0;index<strlength;index++)
        if (str[index]==delim[0]) {
            found=1;
            break;
        }

    /* if delim is not contained in str, return str */
    if (!found) {
        static_str = 0;
        return str;
    }

    /* check for consecutive delimiters
    *if first char is delim, return delim
    */
    if (str[0]==delim[0]) {
        static_str = (str + 1);
        return (char *)delim;
    }

    /* terminate the string
    * this assignmetn requires char[], so str has to
    * be char[] rather than *char
    */
    str[index] = '\0';

    /* save the rest of the string */
    if ((str + index + 1)!=0)
        static_str = (str + index + 1);
    else
        static_str = 0;

        return str;
}

以前の投稿で述べたようにstrtok()、または上記で実装したものは、連続する呼び出し間の最後の区切り文字の位置を保持するために変数に依存しているstatic *charため、マルチスレッド アプリケーションを扱うときは特に注意する必要があります。

于 2016-02-18T22:44:24.957 に答える
0

strtok のドキュメントを読むと、最初の「初期化」呼び出しの後に NULL ポインターを渡す必要があることがわかります。多分あなたはそれをしなかった。もちろん、ただの推測です。

于 2008-11-05T19:51:27.197 に答える