strtok()関数の使い方と意味について解説

このQ&Aのポイント
  • strtok()関数を使ったプログラムの使い方と意味についてです。
  • プログラムを実行すると入力待ち画面になりますが、何を入力すれば何が得られるのかわからない方に解説します。
  • 入力には「1」を入力し、プログラムを終了するには[Ctrl]+[c]を押します。結果の表示についても説明します。
回答を見る
  • ベストアンサー

次のソースの使い方(strtok()関数)

 次のソースプログラムについてです。 (“□”は、タブを表します) ◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆ #include <stdio.h> #include <stdlib.h> /* EXIT_SUCCESS */ #include <string.h> /* strtok() */ int main(void) { □int i, n; □char str[10], *token1, *token2; □scanf("%d", &n); □for (i=0; i<n; i++) { □□scanf("%s", str); □□token1 = strtok(str, ","); □□token2 = strtok(NULL, ","); □□printf("hello = %s , world = %s\n" ,token1 ,token2); □} □return EXIT_SUCCESS; } ◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆  これを実行すると、入力待ち画面になって、何を入力すれば何が得られるのか、てんで分からないのですが、どなたか、このプログラムの使い方と意味について、解説をお願いします。  ちなみに、“1”を入力した後、[Ctrl]+[c]で抜けると、結果は、 ◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆ hello = ヒヒz@俳・, world = (null)◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆ となりました。

  • utu-ne
  • お礼率96% (674/702)

質問者が選んだベストアンサー

  • ベストアンサー
  • maiko0318
  • ベストアンサー率21% (1483/6970)
回答No.1

はじめに単語の個数を入れて 次に単語数分の単語を入れます。 5 word,apple quit,desk orange,flag radio,TV DVD,blulay

utu-ne
質問者

お礼

 ありがとうございます。大変よく分かりました。  ご教示を受けて、ソースを次のように書き換えてみました。 (“□”はタブ) ◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆ #include <stdio.h> #include <stdlib.h> /* EXIT_SUCCESS */ #include <string.h> /* strtok() */ int main(void) { □int i, n; □char str[10], *token1, *token2; □printf("入力する文字列の個数を入力して下さい。\n"); □scanf("%d", &n); □printf("入力は、 %d です。\n", n); □printf("文字列を %d 個入力して下さい。\n", n); □printf("(半角10字以内)\n"); □for (i=0; i<n; i++) { □□scanf("%s", str); □□printf("入力は、 %s です。\n", str); □□token1 = strtok(str, ","); □□token2 = strtok(NULL, ","); □□printf("hello = %s , world = %s\n" ,token1 ,token2); □} □return EXIT_SUCCESS; } ◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆  そして、入力文字列が2つ以上のコンマで区切られていたらどうなるか、疑問に思いましたので、次の入力を行ってみました。 5 ab,cd,ef gh,ij,kl mn,op,qr st,uv,wx yz,ab,cd  その実行結果は、次のようになりました。 ◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆ 入力する文字列の個数を入力して下さい。 入力は、 5 です。 文字列を 5 個入力して下さい。 (半角10字以内) 入力は、 ab,cd,ef です。 hello = ab , world = cd 入力は、 gh,ij,kl です。 hello = gh , world = ij 入力は、 mn,op,qr です。 hello = mn , world = op 入力は、 st,uv,wx です。 hello = st , world = uv 入力は、 yz,ab,cd です。 hello = yz , world = ab ◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆  ここでのプログラムの働きはどうなっているのでしょうか。2つ目のトークンをtoken2に読み込んだところで、あとの部分は読み捨てられているのでしょうか。

その他の回答 (1)

  • maiko0318
  • ベストアンサー率21% (1483/6970)
回答No.2

□□token1 = strtok(str, ","); □□token2 = strtok(NULL, ","); この働きは、 http://hitorilife.com/strtok.php を読んでください。

utu-ne
質問者

お礼

 ありがとうございました。

関連するQ&A

  • malloc関数(strtok関数の自作版)につきまして分からないこと

    malloc関数(strtok関数の自作版)につきまして分からないことがあります。 以下のプログラムにmallo関数がフリーする最適な位置を明示しなさいといわれました。 文字が分離した時にfreeすると助言されたのですが いまいち理解できません・・・。 条件式の中で使用するともいわれていました。(おそらくif文・・・。) 色んな意見を参考にしたいので詳しい方助言のほうよろしくおねがいします。 なおプログラムはほかの箇所を変更したり、他の場所でもmalloc関数を使用することが認められています。 またfreeする場所はメイン関数ではなくあくまでもstrtok関数の中で宣言するようです。 よろしくお願いします。 #include <string.h> #include <stdio.h> #include <stdlib.h> main(){ char* s2 = ",/"; char* result; char* r1; char* r2; char* r3; char* r4; result = strtok("//123//,45/,678,9/","/,"); r1 = strtok(NULL, s2); r2 = strtok(NULL, s2); r3 = strtok(NULL, s2); r4 = strtok(NULL, s2); printf("%s\n",result); printf("%s\n",r1); printf("%s\n",r2); printf("%s\n",r3); printf("%s\n",r4); return; } char *strtok(char *s1, const char *s2) { int i,len; char *str1, *str2 , *str3; static char *tok ; static char* mstr; if(s1 != NULL) { str1 = s1; } else { str1 = tok; } str2 = str1 + strspn(str1, s2); /* strspnを利用 */ if (*str2 == '\0') { return (NULL); } len = 1; i = 0; while(*(str2 + i) != '\0'){ len++; i++; } mstr = (char*)malloc(sizeof(char)*len); if(mstr == (NULL)) { return 0; } i = 0; while(*(str2 + i) != '\0'){ *(mstr + i) = *(str2 + i ); i++; } *(mstr + i ) = '\0'; str3 = mstr + strcspn(mstr, s2); /* strcspnを利用 */ if (*str3 != '\0'){ *str3 = '\0'; str3 = str3 + 1; } tok = str3; return (mstr); }

  • C言語でファイルの内容を strtok関数 を使って数字と文字を分けて

    C言語でファイルの内容を strtok関数 を使って数字と文字を分けて配列に格納したいのですが、うまくできません。 どこが駄目なのかご指摘をお願いします! ファイル内容 20 田中 10 鈴木 #include <stdio.h> #include <string.h> #include <stdlib.h> int main(int argc,char *argv[]) { FILE *fp; char str[256]; char *tp; int i=0; int num[10]; char na[10]; fp=fopen(argv[1],"r"); while(fgets(str,sizeof str,fp)!=NULL); tp = strtok ( str, " " ); while(tp != NULL ) { num[i]=atoi(tp); tp = strtok( NULL," "); if ( tp != NULL ){ na[i]=*tp; } i++; } printf("%d\n%s",num[0],na[0]); printf("%d\n%s",num[1],na[1]); fclose(fp); return 0; }

  • c#でC言語のstrtokに相当する関数は何か

    文字列から指定した文字でデータを区切る関数strtokがC言語にはある これに相当するC#の関数は何か 例えばCでは以下のように書く。 char data1[]= " 123 , 456 Yamada " ; char *token ; strtok( data, " ," ) ; /* スペースとカンマを区切りに文字列を抽出 */ token = strtok( str, " ." ); printf(" token chat = %s\n", token ) ; while ( token != NULL ) { token = strtok( NULL," ." ); if ( token != NULL ) printf(" token chat = %s\n", token ) ; } これに相当するc#のSplit関数を使用すると 不要な空白を取り出しているようである 知っている方がおりましたら、教えて下さい。

  • 助けてください。困っています

    初めまして 課題でメイン関数(メインメニュー)から呼び出されるサブシステムの「かな氏名検索」を作っているのですが、 自分なりに頑張ってみたものの全くの初心者のため完全に行き詰ってしまい、どこが悪いのかもわからない状態です。 なので、皆さんに教えて頂きたいと思い、 お願いにまいりました。 100人分のデータから「ふりがな」を部分一致で検索して、一致した人のデータを表示させるもので、 探すデータ(社員データ)はカンマ区切りテキストで 社員番号 名前 ふりがな 郵便番号 住所 電話番号 生年月日 入社年月日 役職コード 所属コード 性別 の順に 0523,鈴木一郎,すずきいちろう,105-0000,東京都どこどこ, ,19830101,20090404,01,01,M のように入っています。空白部には半角スペースが入ってます。 現在の自分で作ったソースは #include <stdio.h> #include <string.h> #include "CFUNC.h" #include "display.h" #define NUM 200 typedef struct shain{ char id[5]; char name[21]; char hurigana[31]; char yubin[9]; char jusyo[101]; char tel[14]; int birth; int nyusya; char yakusyokucode[3]; char syozokucode[3]; char seibetsu[2]; }shain; int main(void) { int j; int i; int cnt = 0; shain data[100]; FILE *fp; char *token; char s[NUM]; char mes[25] = "該当する結果がありません"; char mes2[30] = "該当するメニューがありません"; char str[30]; fp = fopen("shain.txt","r"); if(fp==NULL){ printf("ファイルオープンに失敗しました。\n"); return 1; } for(i=0; i<100; ++i){ fgets(s,NUM-1,fp); token= strtok(s, ","); /* str1の分割(1回目) */ strcpy(data[i].id,token); token = strtok(NULL, ","); strcpy(data[i].name,token); token = strtok(NULL, ","); strcpy(data[i].hurigana,token); token = strtok(NULL, ","); strcpy(data[i].yubin,token); token = strtok(NULL, ","); strcpy(data[i].jusyo,token); token = strtok(NULL, ","); strcpy(data[i].tel,token); token = strtok(NULL, ","); data[i].birth =(int)token; token = strtok(NULL, ","); data[i].nyusya=(int)token; token = strtok(NULL, ","); strcpy(data[i].yakusyokucode,token); token = strtok(NULL, ","); strcpy(data[i].syozokucode,token); token = strtok(NULL, "\n"); strcpy(data[i].seibetsu,token); } cls(); /*検索画面*/ printf("*****************************************************\n"); printf("[かな氏名検索]\n"); printf("かなを入力してください:\n"); printf(" \n"); printf(" \n"); printf(" 0:メニューに戻る\n"); printf("*****************************************************\n"); printf("メッセージ:\n"); for(;;){ setLocate(24,3); scanf("%s",str); if(strcmp(str,"0")==0){ break; } for(i=0; i<100; ++i){ if(strncmp(str,data[i].hurigana,5)==0){ cnt++; if(cnt==1){ /*検索結果画面*/ printf("*****************************************************\n"); printf("[かな氏名検索結果]\n"); printf("社員番号 氏名  ふりがな  入社年度  所属  性別 役職\n"); printf(" %s  %s  %5s %d %s %s %s %s\n",  data[i].id,data[i].name,data[i].hurigana,data[i].nyusya,  data[i].syozokucode,data[i].seibetsu,data[i].yakusyokucode); } else{ printf(" %s  %s  %5s %d %s %s %s %s\n", data[i].id,data[i].name,data[i].hurigana,data[i].nyusya, data[i].syozokucode,data[i].seibetsu,data[i].yakusyokucode); } } //見たつからなかった時 if (cnt==0){ setLocate(12,8); printf("%s\n",mes); } //メッセージ setLocate(24,3); scanf("%s",str); setLocate(12,8); printf("%s\n",mes); } } printf("\n"); fclose(fp); return 0; } 所々変なところもあり見にくいと思いますが、 とりあえず単独で検索だけしっかり出来るようにしたいです。 検索は1回だけでなく、何回も出来るようにしたいです。 下手な文章のうえ長文でまことにすいませんが、よろしくお願いします。

  • ファイルの入出力を行っての文字列反転

    入力した文字列を反転させて出力したいのですが どうしたらよいでしょうか? #include <stdio.h> #include <stdlib.h> #include <string.h> /* 定数 */ #define DELIMITER "/ ," /* 区切り文字 */ int main(void) { FILE *fin,*fout; char infile[40],outfile[40],s[256],s2[256]; char *token; char *strch[50]; int count = 0; int i; printf("入力ファイル名="); gets(infile); printf("出力ファイル名="); gets(outfile); if( (fin=fopen(infile,"r"))==NULL) { /* 入力ファイルオープン */ printf("入力ファイルがオープンできません\n"); exit(EXIT_FAILURE); } if( (fout=fopen(outfile,"w"))==NULL) { /* 出力ファイルオープン */ printf("出力ファイルがオープンできません\n"); exit(EXIT_FAILURE); } while(fgets(s,256,fin)!=NULL) { /* 入力ファイルから読み込んだデータを */ token = strtok(s, DELIMITER); while (token != NULL) { strch[count] = token; token = strtok(NULL, DELIMITER); count++; } for(i = count; i > 0; i--) { strcat(s2, strch[i]); } fputs(s2,fout); /* 出力ファイルに書き込み */ } fclose(fin); /* 入力ファイルクローズ */ fclose(fout); /* 出力ファイルクローズ */ return 0; }

  • strtok

    strtokの問題というよりも、文字列とポインターの考え方がまだちゃんと分かってないせいだとは思うんですが、strtok()のところで、Access Violationとでます。すごく単純そうな問題だとは思いますが、教えてください。お願いします。 #include <iostream.h> #include <string.h> int main() { char *chk = "3453/5252"; char *tokenPtr; tokenPtr = strtok(chk, "/"); while (tokenPtr != NULL) { tokenPtr = strtok(NULL, "/"); } return 0; }

  • strtok関数の使い方

    http://oshiete1.goo.ne.jp/kotaeru.php3?q=2361151 で、質問させて頂いた者です。 先日は大変にお世話になりました。 先日の質問の続きという感じなんですが… ------------------ 「ex」ファイルのデータ 41 4352 42 2341 43 5411 --------- これらのデータを kihokyu[1].tosi=41 kihokyu[1].kan=4352 kihokyu[2].tosi=42 kihokyu[2].kan=2341 という感じで格納したいのです。 ------------------------ 回答者の方にご指導して頂いたように、 ・ ・ ・ while(fgets(buff,sizeof buff,fp) != NULL){ if ( i > 50 ){ break; } kihokyu[i].tosi = atoi(strtok(buff , " ")); kihokyu[i].kan = atoi(strtok(NULL , " \n")); printf("%d\n",kihokyu[i].tosi); i++; } というstrtok関数を使ってみました。 ところが 41 42 43 と、表示されたあと 強制終了になってしまいます。 >kihokyu[i].kan = atoi(strtok(NULL , " \n")); を削除すると スムーズに処理が終了します。 >printf("%s\n",NULL); と、「NULL」の値を調べたところ 「{NULL}」と表示されました。 たぶん、strtok関数の使い方がおかしいと思うのですが ご教授して頂けたら幸いです。

  • C言語 strtok

    失礼します。現在こちらでアドバイスを頂きfgetcを使用して配列に格納をすることができたのですが、CSVをカンマ区切りで格納したいのですが上手くいかず困っています。strtokを使用方法をドキュメントを読んでもうまく区切ったものを配列に入れる方法がわかりません 何卒よろしくお願いします。 ソースコード #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include<string.h> #define MAXITEM 1400 int split(char *str, const char *delim, char *outlist[]) { char *tk; int cnt = 0; tk = strtok(str, delim); while (tk != NULL && cnt < MAXITEM) { outlist[cnt++] = tk; tk = strtok(NULL, delim); } return cnt; } int main(void) { FILE *fp; char *fname = "testfile.csv"; char *tp; char *array[1400]; char *test[11][1400]; char c; int i = 0; int n,y; char *tp[1400]; fp = fopen(fname, "r"); if (fp == NULL) { printf("%sファイルが開けません¥n", fname); return -1; } while ((c = fgetc(fp)) != EOF) { array[i] = (char)c; i++; } tp = strtok(array, ","); puts(*tp); while (tp != NULL) { tp = strtok(NULL, ","); if (tp != NULL)puts(tp); } for (n = 0; n < 11; n++) { for (y = 0; y < 1400; y++) { test[n][y] = tp[y]; printf("%c", test[n][y]); } } fclose(fp); return 0; }

  • strtokでの空文字への置き換え

    大したことじゃないと言えばそうかもしれませんが、ちょっと氣になるんで質問させてください。 C言語でstrtokという函數ありますよね。 第1引數の文字列を、第2引數の文字列を構成する文字で區切る。 第2引數の文字を見つけたら、それを空文字('¥0')に置き換える。 字句の最初の文字へのポインタを返す。 このようなものだと理解しています。 次のプログラムを實行してみました。 #include <stdio.h> #include <string.h> int main(void) { char string[]="XYZ1231ABC"; int i; printf("%s\n", string); putchar('\n'); printf("%s\n", strtok(string, "1A")); printf("%s\n", strtok(NULL, "1A")); printf("%s\n", strtok(NULL, "1A")); printf("%s\n", strtok(NULL, "1A")); putchar('\n'); for(i=0; i<=10; i++) printf("string[%d]=%c\n", i, string[i]); return 0; } 結果 XYZ1231ABC XYZ 23 BC (null) string[0]=X string[1]=Y string[2]=Z string[3]= string[4]=2 string[5]=3 string[6]= string[7]=A string[8]=B string[9]=C string[10]= 私が思うには、string[7]は空文字に置き換わってしまうはずだと思うんですが、 結果は'A'のままです。 ここが '¥0'に置き換わるかどうかは しょり系によって異なるのでしょうか。

  • ファイルの入出力を行って文字を変換する

    入力するファイルにa~zを記入しておき、 出力するファイルにaなら1、bなら2、zなら26に変換させたいのですがどうしたらよいでしょうか? #include <stdio.h> #include <string.h> #define DELIMITER "/ ," /* 区切り文字 */ int main(void) { FILE *fin,*fout; int count=0; int i; char s[256], s2[256]; char alpha[]={'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'}; int kazu[]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26}; char *taken; char *strch[50]; if( (fin=fopen("file1.txt","r"))==NULL) { printf("入力ファイルがオープンできません\n"); exit(EXIT_FAILURE); } if( (fout=fopen("file2.txt","w"))==NULL) { printf("出力ファイルがオープンできません\n"); exit(EXIT_FAILURE); } while(fgets(s,256,fin)!=NULL) { while (token != NULL) { strch[count]=token; token = strtok(NULL, DELIMITER); count++; } memset(s2, NULL, sizeof(s2)); fprintf(fout,"%d\n",s2); } fclose(fin); fclose(fout); return 0; }