strtokを使用したループ内でのstrtok

このQ&Aのポイント
  • C言語でstrtokを使用したプログラムを作成している際、for文内でのstrtokの使い方に問題があります。
  • ループ内のstrtokで値が正しく代入されないため、2回目のループに進むことができません。
  • 他の方はどのようなソースコードを作成しているのか、教えていただけないでしょうか?
回答を見る
  • ベストアンサー

strtokを使用したループ内でのstrtok

お世話になっております。 現在C言語で下記のようなstrtokを使用したプログラムを作成しております。 (関係なさそうな箇所については省略しております。) 【ソース】 str="abc.def,ghi.jkl,mnopq.r,kkk.bbb" for( a=strtok(str,",\n") , a , a=strtok(NULL,",\n"){ b=strtok(a,"."); c=strtok(NULL,"."): } 【質問内容】 上記の内容を使用したソースでは、for文のa=strtok(NULL,",\n")にてaに値がはいりません。 (2回目のループに行かない) 上記のような処理を実施したい場合、皆様どのようなソースを作成しているかご教示いただけないでしょうか。 よろしくお願いいたします。

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

  • ベストアンサー
  • chie65535
  • ベストアンサー率43% (8512/19350)
回答No.3

「b=strtok(a,".");」をやった瞬間、strは「abc+EOS」になります。この時点で、forの続きのstrtokは出来なくなります。 また、for文の中の「a=strtok(NULL,",\n")」は「b=strtok(a,".");」の続きのstrtokになります。 うまく動かすには、forループ用のstrは壊してはいけないし、forループが終わるまで、他のstrtokは行ってはいけません。 すると、以下のようなソースになります。 #include <stdio.h> #include <string.h> void main(void) {  int i,j;  char *str,*a[100],*b,*c;  str="abc.def,ghi.jkl,mnopq.r,kkk.bbb";  for( i = 0,a[0] = strtok(str,",\n") ; (a[i]) && (i < 100) ; a[++i] = strtok(NULL,",\n")) {;}  for( j = 0; j < i; j++) {   b=strtok(a[j],".");   c=strtok(NULL,".");   printf("b=%s\n",b);   printf("c=%s\n",c);  } }

oniku029
質問者

お礼

chie65535さん ご回答ありがとうございました。 やはり、ループの中でstrtokを使用したことが問題だったのですね。。。 ソースまで添付いただきありがとうございました。 本当にたすかりました。

その他の回答 (2)

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.2

自力で分解する. そもそもなぜうまくいかないか, 理解できていますか?

oniku029
質問者

お礼

tacosanさん ご回答ありがとうございます。 >そもそもなぜうまくいかないか, 理解できていますか? b=strtok(a,"."); を実施したため、 a=strtok(NULL,",\n") が正常に動作しないのではないか、という予想をしておりました。 しかし、WEBを調べても確信がもてなかったため、今回質問させていただきました。

  • nora1962
  • ベストアンサー率60% (431/717)
回答No.1

#include <stdio.h> #include <string.h> int main(){ char *str = "abc.def,ghi.jkl,mnopq.r,kkk.bbb"; char *a; a = strtok(str,",\n"); while( a != NULL ){ printf("%s\n",a ); a = strtok(NULL,","); } return 0; }

oniku029
質問者

お礼

nora1962さん ご回答ありがとうございました。

関連するQ&A

  • 次のソースの使い方(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)◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆◆ となりました。

  • Perlのキャプチャ

    プログラム #!/usr/bin/perl my $str = "abc,def,ghi"; ($a,$b,$c) = $str =~ /(.*),(.*),(.*)/; print $a,"\n"; print $b,"\n"; print $c,"\n"; 実行結果 abc def ghi このようなプログラムで ($a,$b,$c) = $str =~ /(.*),(.*),(.*)/;は それぞれ$a,$b,$cにabc,def,ghiが入ります. キャプチャしたすべてを変数に入れるならこの方法ですが, defだけが欲しいのに変数を3つ用意する必要がないと思います. 間違った表記ですが, ($b) = $str =~ /(.*),(.*),(.*)/$2/; 2つ目にキャプチャした$2が変数$bに入るような表記は出来ないのでしょうか?

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

  • 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関数を使用すると 不要な空白を取り出しているようである 知っている方がおりましたら、教えて下さい。

  • 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'に置き換わるかどうかは しょり系によって異なるのでしょうか。

  • バッチでfor文で文字列の中身を繰り返したい

    バッチで、for文で、半角スペースやタブ以外で区切られた文字列から、区切り文字毎に 取り出したいのですが、最初の1回しか取り出せません。最後まで繰り返しが行われませ ん。 バッチでは、そもそも、半角スペースやタブ以外では、文字列の中身を繰り返すことは できないのでしょうか。 それとも、他に良い方法があります。 やっていることは、 例えば、 for文で、スラッシュ「/」で区切られた文字列からスラッシュ毎に取り出そうとしている のですが、最初の1回目しか表示されず、最後まで繰り返しが行われません。 以下、色々と試したのですが..... set str=abc/def/ghi/jkl/mno/pqr/stu/vwx/yz for %%a in (%str%) do echo %%a の場合は、 1行そのまま表示されます。(あたりまえです。) for "delims=/" %%a in (%str%) do echo %%a for "delims=/" %%a in ('echo %str%') do echo %%a の場合は、 「"delims=/" の使い方が誤っています。」となります。 for /f "delims=/" %%a in ('echo %str%') do echo %%a の場合は、 最初の1回目の「abc」しか表示されず、そこで処理が終わり、残りが表示されない。 期待している結果は、 これを、 abc def ghi jkl mno pqr stu vwx yz と表示させたい。 set str=abc def ghi jkl mno pqr stu vwx yz for %%a in (%str%) do echo %%a の場合は、 abc def ghi jkl mno pqr stu vwx yz と表示されます。 バッチでは、そもそも、半角スペースやタブ以外では、文字列の中身を繰り返すことは できないのでしょうか。 できる場合、その方法を教えてください。また、他に良い方法がありましたら、教えて下さい。

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

  • strtok()について

    c言語にてstrtok()を使用しています。 以下の型をグローバル変数で宣言し、 (ヘッダ) typedef struct { char *pTmp; int len; } stAAA; (.cソース) stAAA stA; ある関数にてmalloc()によりstA.pTmpに動的に領域を割り当て、 "ABCDEFG:ABCDEFG:ABCDEFG:"という値を格納するとします。 その後他関数にてstA.pTmp内の":"をトークンとしstrtok()で 切り出す場合、stA.pTmpを切り出し後もアドレス移動させたく ないため strtok()使用関数にて以下のようにしたのですが・・・・ グローバル変数のアドレスが操作されてしまいます。 どうすればよいでしょうか?strtok()用にmalloc()する? int test(){ char *pTmp; char *pTok; pTmp = stA.pTmp; while ((pTok = strtok(pTmp, ":")) != NULL) { : : } }

  • C言語 比較抽出

    C言語 コンソール VC6.0で悩んでいます。 ABC.com ABC.com DEF.co.jp GHI.go.jp DEF.co.jp DEF.co.jp JKL.com JKL.com ABC.com 上記のようなデータがsData[i]にあり、 ABC.com  3回 DEF.co.jp  3回 GHI.go.jp  1回 JKL.com  2回 のように画面に出力したいのですが、表示も処理も一緒だとややこしいので 表示は後回しにして、一度sHost[i]とiNum[i]に格納しようと考えています。 strcmpでの比較をwhileやforで多重ループで回すくらいしか思い付きません。 何か案だけでもいただけないでしょうか。お願いします。

専門家に質問してみよう