• ベストアンサー

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

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

  • ベストアンサー
  • route156
  • ベストアンサー率85% (93/109)
回答No.5

> 静的なバッファ…  "変数領域" に確保する配列のことです。例えば、関数の外で定義した配列は "静的" になります。(関数内で定義することもできますが…詳細は割愛します) > ポインターとはconst array …  この場合の "3453/5252" は "定数領域" にありますので const になります。ですので char *chk = "3453/5252" とすると chk に代入されるのは const ポインタです。  関数内で char chk[] = "3453/5252" とすると、文字列はスタック上の領域(auto 変数)にコピーされ、chk にはその領域を指すポインタが代入されます。これは const ではありません。 > chkにはユーザーが入れた値を代入したいので…  いずれにしても入力された文字列を蓄えておく領域(文字配列・バッファ)は必要でしょうし、予想される文字数が十分入るサイズを確保した上で、文字数超過でバッファがあふれないようにする対策も避けて通れないと思います。

northcurlcurl
質問者

お礼

route156さん、deagleさん、分かりやすい説明をしてくださって、ありがとうございました。ポインターと配列に関する疑問が、もうそろそろ解けそうな気がしてきました。本当にありがとうございました。

その他の回答 (4)

noname#25358
noname#25358
回答No.4

 これは変数 chk を定義するときに一緒に文字列を代入してしまっているのが原因です。  これは route156 さんがおっしゃっているのと同じことです。  しかし、   char chk[] = "123";   char *chk = "123";  この2つは同じ意味なので、実際にはこうしなければいけません。   char chk[10];  strcpy( chk, "123/456" );  これならば、chk の中身が改変可能になるのでエラーは出ません。  で、上記の例では [10] というふうに文字列の長さを固定してしまっていますが、このような宣言の変数を「静的変数」といいます。  逆に、   char *chk;   chk = (char*)malloc(10);  というように、文字列の長さをプログラム内で可変的に作成した変数を「動的変数」といいます。  なお、C言語では、「文字列の長さを決めずに処理をする」のは不可能です。もしそれをやりたければC++の CString などを使わなければいけません。  これは、C言語がもともと、「システムを直接操作する」ことを目的とした言語だからです。

  • route156
  • ベストアンサー率85% (93/109)
回答No.3

 strtok() は与えられた文字列内の区切り文字の部分に '\0' を書き込みますので、Access Violation は定数として文字列を与えているのが原因だと思います。  文字列を収める場所を別に確保してみてはどうでしょう。 int main(void) {  char chk[] = "3453/5252";  …以下略 ※ malloc() を使っても、静的なバッファに strcpy() しても良いと思います。

northcurlcurl
質問者

補足

実は、chkにはユーザーが入れた値を代入したいので、配列を使うとなると、要素の大きさを決めなければいけなくなりどこかでエラーになるような気がするのです。後もう二つ質問させてください。 静的なバッファとはなんでしょう? どこかで聞いたことがあるのですが、ポインターとはconst arrayなのでしょうか?

  • ranx
  • ベストアンサー率24% (357/1463)
回答No.2

ごめんなさい。No.1は無視して下さい。 勘違いしました。 で、あれ?おかしいところは見当たりませんけれど。 ひょっとして、strtok()の入っているダイナミックライブラリの アクセス権がないとか...。

northcurlcurl
質問者

補足

ダイナミックライブラリとはDLLのことですか?ネットワークに繋がれてない、WIN98で動かしているので、アクセス件の問題ではないと思うのですが。。。

  • ranx
  • ベストアンサー率24% (357/1463)
回答No.1

strtok(NULL, "/") は何を意図しているのでしょう。 明らかに第1引数のNULLが問題ですが。

関連するQ&A

  • 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について

    strtokを使うにあって注意すべき点がしりたいのですが、 test1やtest2は書き換わるので、変わっては困る場合は あらかじめコピーしておくのは理解しましたが、 strtokをネストして使う場合、(1)で必ずNULLになります。 strtokはネストでは使えないのでしょうか? また、他に注意点があるのでしたら教えてください。 あと、C++では、strtokより便利なものはありますか? char test1[] = "111,222,333"; char test2[] = "333,222,111"; char *p, *q; int flag; p = strtok(test1, ","); while ( p != NULL ) { flag = 0; q = strtok(test2, ","); while ( q != NULL ) { if (0 == strcmp(p, q)) { flag = 1; break; } q = strtok( NULL, ","); } if (flag == 0) { return 1; } p = strtok( NULL, ","); // <------- (1)ここで必ずNULL }

  • 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という函數ありますよね。 第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'に置き換わるかどうかは しょり系によって異なるのでしょうか。

  • strtokのしくみについて

    よろしくお願い致します。 strtokは以下のように使いますよね。 (と言っても今回初めて使うのですが) 1回目はstrを渡しているので自然ですが、2回目以降はNULLですよね。なのにどうしてstrを続けて分解するということが出来るのでしょうか? うまく説明できませんが、要はstrtokはどういうコードで実現されているのでしょうか? int main(void) { char str[] = "ABCD ef.1234.G"; char *tp; /* スペース.を区切りに文字列を抽出 */ tp = strtok( str, " ." ); puts( tp ); while ( tp != NULL ) { tp = strtok( NULL," ." ); if ( tp != NULL ) puts( tp ); } return 0; }

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

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

  • ファイルの入出力に関する質問

    CSVファイルを読み込んで、処理をするプログラムを書いています。 しかし、うまくいきません。 CSVファイルは 単語1,数値データ 単語2,数値データ のようになっており、 これをsの配列に格納したいと思っています。 プログラムは以下の通りなんですが。。。 strtokはhttp://www9.plala.or.jp/sgwr-t/lib/strtok.html を参考にしました。 どなたかおしえていただけないでしょうか? #include<stdio.h> #include <string.h> int main(void) { FILE *fp; char s[1000][1000]; char tp[256]; int i=0; if((fp=fopen("in.csv","r"))==NULL){ printf("ファイルオープンできませんよ\n"); exit(1); } while(fgets(tp,256,fp)!=NULL){ tp=strtok(fp,","); puts(s[i][0]=tp); while (tp != NULL ) { tp = strtok(NULL,","); if (tp= NULL ){ puts(s[i][1]=tp); }}i++; } 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) { : : } }

  • 複数のファイルへの一括処理(困ってます)

    あるディレクトリ内の全てのファイルに同じ処理(添付のプログラムによるtest1.csvファイルに対する処理と同一の処理)をしたいと考えています。 どのようなプログラムを組めば良いのですか? 手法については検討もつかない状況です。 教えていただけないでしょうか? よろしくお願いいたします。 (1)添付のプログラム #include <stdio.h> #include <conio.h> #include <string.h> #include <stdlib.h> int main () { FILE *fp; char a[50]; double b; char *p; if((fp = fopen("test1.csv", "r")) == NULL) return 0; while(fscanf(fp, "%s\n", &a) != EOF){ p = strtok( a, "," ); b = atof(a); printf("%lf ", b); while(p != NULL) { p=strtok(NULL, ","); if(p != NULL) { b = atof(p); printf("%lf\n", b); } getch(); } } fclose(fp); return 0; } (2)プログラムで使うCSVファイル -749.95,1.499894061 -749.9,2.371277071 -749.85,3.01070131 -749.8,-0.92298313 -749.75,3.111961134 -749.7,-1.642278763 -749.65,2.759562723 -749.6,0.869387239 -749.55,1.400240703 -749.5,-0.574988131 -749.45,-2.282041367 -749.4,-1.104953718 -749.35,2.45568825 -749.3,-1.391859875 -749.25,-1.600438736 -749.2,0.116074589 -749.15,2.973864166 -749.1,2.652719198 -749.05,1.584699094 -749,2.129474673 -748.95,1.847275561 -748.9,2.974398019 -748.85,1.561458246 -748.8,2.897905731 -748.75,2.655075544 -748.7,-2.677451989 -748.65,-0.871814301 -748.6,-3.098832888 -748.55,2.565297638 -748.5,-2.073626148 -748.45,-0.300440285 -748.4,0.515248274 -748.35,2.983715685 -748.3,-2.47909508