web-dev-qa-db-ja.com

Cでの文字列のトークン化

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

編集:以下を使用したトークン化:

strtok(string, " ");

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

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

次のようにします:

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*にはできません。

41
gbjbaanb

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

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

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

35
Evan Teran

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

#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;
}
3
Ferruccio

このコードは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);
} 
2
Fernando

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

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

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_変数に依存しており、連続する呼び出し間の最後の区切り文字の位置を保持するため、処理中は特に注意が必要ですマルチスレッドアプリケーション。

0
fnisi

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

0
xtofl