web-dev-qa-db-ja.com

Cで文字列を2つの文字列に分割する方法

1つの文字列を取得し、スペースなどの区切り文字で2つに分割し、2つの部分を2つの別々の文字列に割り当てる方法を考えていました。 strtok()を使用しようとしましたが、役に立ちませんでした。

38
Mark Szymanski
#include <string.h>

char *token;
char line[] = "SEVERAL WORDS";
char *search = " ";


// Token will point to "SEVERAL".
token = strtok(line, search);


// Token will point to "WORDS".
token = strtok(NULL, search);

更新

一部のオペレーティングシステムでは、strtokのmanページで言及されていることに注意してください。

このインターフェイスはstrsep(3)によって廃止されました。

strsepの例を以下に示します。

char* token;
char* string;
char* tofree;

string = strdup("abc,def,ghi");

if (string != NULL) {

  tofree = string;

  while ((token = strsep(&string, ",")) != NULL)
  {
    printf("%s\n", token);
  }

  free(tofree);
}
56
ereOn

このような目的のために、私はstrtok()の代わりにstrtok_r()を使用する傾向があります。

例えば ​​...

int main (void) {
char str[128];
char *ptr;

strcpy (str, "123456 789asdf");
strtok_r (str, " ", &ptr);

printf ("'%s'  '%s'\n", str, ptr);
return 0;
}

これは出力されます...

「123456」「789asdf」

さらに区切り文字が必要な場合は、ループします。

お役に立てれば。

11
Sparky
char *line = strdup("user name"); // don't do char *line = "user name"; see Note

char *first_part = strtok(line, " "); //first_part points to "user"
char *sec_part = strtok(NULL, " ");   //sec_part points to "name"

注:strtokは文字列を変更するため、文字列リテラルへのポインターを渡さないでください。

3
N 1.1

その例にはstrtok()を使用できます:それは私のために機能します

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

int main ()
{
    char str[] ="- This, a sample string.";
    char * pch;
    printf ("Splitting string \"%s\" into tokens:\n",str);
    pch = strtok (str," ,.-");
    while (pch != NULL)
    {
        printf ("%s\n",pch);
        pch = strtok (NULL, " ,.-");
    }
    return 0;
}
3
mkafkas

これは、strtok()のような関数を実装する方法です( zStringと呼ばれるBSDライセンスのC用文字列処理ライブラリ から取得)。

以下の関数は、標準のstrtok()とは異なりますが、標準のstrtok()はそうではありません。

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;
}

以下は、使用法を示すサンプルコードです。

  Example Usage
      char str[] = "A,B,,,C";
      printf("1 %s\n",zstring_strtok(s,","));
      printf("2 %s\n",zstring_strtok(NULL,","));
      printf("3 %s\n",zstring_strtok(NULL,","));
      printf("4 %s\n",zstring_strtok(NULL,","));
      printf("5 %s\n",zstring_strtok(NULL,","));
      printf("6 %s\n",zstring_strtok(NULL,","));

  Example Output
      1 A
      2 B
      3 ,
      4 ,
      5 C
      6 (null)

Whileループを使用することもできます(標準ライブラリのstrtok()はここでも同じ結果になります)。

char s[]="some text here;
do {
    printf("%s\n",zstring_strtok(s," "));
} while(zstring_strtok(NULL," "));
1
fnisi

元の文字列を変更する場合は、区切り文字を\0に置き換えるだけで済みます。元のポインターは最初の文字列を指し、区切り文字の後の文字を指すポインターは2番目の文字列を指します。良いことは、新しい文字列バッファーを割り当てることなく、両方のポインターを同時に使用できることです。

1
Mehrdad Afshari

Char配列が割り当てられている場合は、'\0'を必要な場所に配置できます。次に、新しく挿入された'\0'の直後の位置を指す新しいchar *ポインターをポイントします。

'\0'を配置した場所にもよりますが、これは元の文字列を破棄します

1
Brian R. Bondy

できるよ:

char str[] ="Stackoverflow Serverfault";
char piece1[20] = ""
    ,piece2[20] = "";
char * p;

p = strtok (str," "); // call the strtok with str as 1st arg for the 1st time.
if (p != NULL) // check if we got a token.
{
    strcpy(piece1,p); // save the token.
    p = strtok (NULL, " "); // subsequent call should have NULL as 1st arg.
    if (p != NULL) // check if we got a token.
        strcpy(piece2,p); // save the token.
}
printf("%s :: %s\n",piece1,piece2); // prints Stackoverflow :: Serverfault

複数のトークンを期待する場合は、strtokの戻り値がstrtokになるまで、whileループでNULLの2回目以降の呼び出しを呼び出す方が適切です。

1
codaddict