• 締切済み

トークンで分けた文字列をさらにトークンで分ける

初心者です。よろしければご教授下さい。 temp.c:12: warning: useless keyword or type name in empty declaration というような文字列がg_str02[0]に格納されている時に、まずは「 」(半角スペース)を区切り文字としてトークンごとに分け最初の2つのトークンをmretsu1[0]とmretsu1[1]の中に格納し、さらにmretsu1[0](上記で言う「temp.c:12:」)を「:」を区切り文字としてトークンごとに分けmretsu2[0]とmretsu2[1]に格納するような関数を作りたいのですが、コンパイルは成功するのですが、できた実行ファイルを実行するとエラーが起きて強制終了されてしまいます。 現在ソースは以下のようになっています。 ////////// char mretsu1[255][255]; char mretsu2[2][255]; char *token1 = " "; char *token2 = ":"; strcpy(mretsu1[0], strtok(g_str02[0], token1)); strcpy(mretsu1[1], strtok(NULL, token1)); strcpy(mretsu2[0], strtok(mretsu1[0], token2)); strcpy(mretsu2[1], strtok(NULL, token2)); ////////// デバッグをしてみた所、どうもmretsu1[0]をさらに分解しているところにエラーがあるようです。 よろしくお願いします。

みんなの回答

  • pochi2tama
  • ベストアンサー率35% (419/1164)
回答No.4

入力文字列のg_str02[0]は書き換え可能ですか? (これの定義が書かれていないので…) 最初の strcpy(mretsu1[0], strtok(g_str02[0], token1)); でg_str02[0]の中身をstrtokが書き換える(トークン部分を0にして文字列を分割する)ので、このバッファは書き換え可能でなければなりません。 g_str02[0]を、たとえば char buf[255]; strcpy(buf,g_str02[0]); などと安全なバッファにコピーしてから使ってみてはどうでしょうか? あと、質問者さんの使い方であればstrtok()で問題ないと思います。 (strtok関数内のスタティック変数はそれぞれの使用範囲において完結している=検索したい文字列を入れ子にしていないので)

回答No.3

>「strtok_rは定義されていない関数です。」というエラーが出ました。 お使いのコンパイラがVC++なら、かわりに strtok_s があるはず。

回答No.2

strtok()は関数の内部に情報を格納しているので 並行して別々の解析をしたい場合は、スレッドセーフな方のstrtok_r()を利用しましょう。 それと、二回目の「:」で解析するときには、文字列(mretsu1[1])のコピーを指定してあげてください。 # strtok()は入力の文字列(str)を変更するので。。。

参考URL:
http://www.linux.or.jp/JM/html/LDP_man-pages/man3/strtok.3.html
jovancampa
質問者

お礼

お返事ありがとうございます。 以下のようにソースを変更しました。 ////////// char mretsu1[255][255]; char mretsu2[2][255]; char k_mretsu[255]; char *token1 = " "; char *token2 = ":"; char *save1,*save2; strcpy(mretsu1[0], strtok(g_str02[1], token1)); strcpy(mretsu1[1], strtok(NULL,token1)); sprintf(k_mretsu,"%s",mretsu1[0]); strcpy(mretsu2[0], strtok_r(k_mretsu, token2, *save1)); strcpy(mretsu2[1], strtok_r(NULL, token2, *save2)); ////////// コンパイルしたところ「strtok_rは定義されていない関数です。」というエラーが出ました。 strtok_rは使用したことがないので何とも言えないのですが、これはstrtokと同様のヘッダーファイルに格納されているものなのではないのでしょうか? よろしければ教えて下さい。

回答No.1

空白を区切りとした切り分けが「すべて完了した後」、 各文字列を:で切り分けてみては?

jovancampa
質問者

お礼

すべて完了した後にやってみたんですが、同じエラーが出ました。 やはり他の回答者さんがおっしゃられている通り、同じ関数内での処理はできないみたいですね。

関連するQ&A

  • gccで入力した文字列をトークンで分割したい。

    現在キーボードから文字列を入力し、その文字列内にスペースが入っていた場合は、それをトークンしてそれぞれの文字列を分けたいと考えています。 そこでトークンに関して次のサイトを見つけました。 http://www1.cts.ne.jp/~clab/hsample/Func/Func08.html こちらのサイトで紹介されていたサンプルプログラムでzooの中に入っている文字列をトークンして分割する方法で実際やってみたところ、 printfでトークンされた文字列を表示することができることを確認しました。 char zoo[] = "Cat, Dog, Tiger, Bug, Bird, Fish, Seep, Cow, Pig, Rat"; あらかじめ文字列を用意しているやり方を、この文字列をキーボードで打ち込んだ文字列でも同じことができないかと思い scanf("%s", zoo); というふうにやってみたところ、コンパイルはできるのですが、 実行してみると、 strcpy(animal[0], strtok(zoo, token)); この時にSegmentation fault (core dumped) というエラーが発生してプログラムが停止してしまいます。 解決する方法を教えて頂きますよう、お願い致します。 (プログラム内容) #include <stdio.h> #define NUM_DATA 10 #define LEN_DATA 20 char zoo[] = "Cat, Dog, Tiger, Bug, Bird, Fish, Seep, Cow, Pig, Rat"; main(void) { //char s[100]; //char *s; char animal[NUM_DATA][LEN_DATA]; char *token = " ,"; /* 区切り文字はスペースとカンマ */ int i; printf("Please type:"); scanf("%s", &zoo); printf("original:\t"); printf("%s\n\n", zoo); /* トークンを取り出す文字列を表示 */ printf("got token results:\n"); strcpy(animal[0], strtok(zoo, token)); /* 1度目の呼び出し */ printf("%s\t", animal[0]); for (i = 1; i < NUM_DATA; i++) { /* 2度目以降の呼び出しは */ strcpy(animal[i], strtok(NULL, token)); /* 最初の引数にNULLを指定 */ printf("%s\t", animal[i]); } //if (animal[0] == "TOSHIO") if(strcmp(animal[0],"TOSHIO")==0) { printf("TOSHIO you typed. \n"); } else { printf("_%s_typed \n",animal[0]); } } //http://www1.cts.ne.jp/~clab/hsample/Func/Func08.html

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

  • 長い文字列を配列に入れるには?

    VBから長い文字列を送って,c言語で受け取りたいのですが,うまく配列に入れることが出来ません.文字列サイズは最低でも4000バイト必要です. #include <stdio.h> #include <stdlib.h> #include <string.h> //VBから送られてくるデータ char getch[4000]="start1T\tpose 0 0 -5 0 -5 0 -5 0 -5 0 0 0 0 0\ ..省略.. 25\t\n"; void main(void){ char *token; char seps[]="\t\n"; FILE *pose; pose=fopen("pose.txt","a"); if((token=strtok(getch,"\t"))==NULL){ printf("Error File1\n"); exit(1); } printf("%s\n",token); while(strcmp(token,"\n")!=0){ token=strtok(NULL,"\t"); fputs(token,pose); fputs("\n",pose); printf("%s\n",token); } fclose(pose); }

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

    初めまして 課題でメイン関数(メインメニュー)から呼び出されるサブシステムの「かな氏名検索」を作っているのですが、 自分なりに頑張ってみたものの全くの初心者のため完全に行き詰ってしまい、どこが悪いのかもわからない状態です。 なので、皆さんに教えて頂きたいと思い、 お願いにまいりました。 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回だけでなく、何回も出来るようにしたいです。 下手な文章のうえ長文でまことにすいませんが、よろしくお願いします。

  • sprintfを用いたフォーマット文字列攻撃

    sprintfを用いたフォーマット文字列攻撃に関する質問です。 main文の中で --------------------- int main(void){ char str[50]; sprintf(str,"%s"); puts(str); } --------------------- を実行すると(null)で帰ってきます。 しかし関数呼び出しを行うと結果が変わってきます。 --------------------- void f(){ char str[50]; sprintf(str,"%s"); puts(str); } int main(void){ f(); } --------------------- これを実行すると" ・L "のような文字化けしたものに変わりました。 sprintf(str,"%s%s");と記述することによって" ・L (null) "と、本来呼び出される箇所のものが格納されています。 なぜ関数呼び出しにすると変なところを参照してしまうのか(第3引数があると勘違いしてしまうのか)教えてください。 また、これによりどのような悪影響があるのか教えてください。 自分はプログラマが意図しない箇所を参照するため攻撃者のプログラムアドレスを格納してしまう恐れがあると考えています。

  • 文字列(丸数字)の文字化けについて

    今自分で関数を作成しているのですが、文字列(丸数字)の文字化けにかなり苦しんでいます。 (※注※)これ以降(1)など()の中に数字を入れて記述しているものは実際のソースコード上では丸数字で記入してます。教えてgooでは丸数字が記述できないようでして… 関数の内容としては、(1)あ(2)い(3)う……このように丸数字で区切られている文字列を配列名を$dataとすると、$data[0]には「あ」、$data[1]には「い」、$data[2]には「う」が入るような関数を作成しています。 この丸数字の数は(10)まで対応させようと考えてます。 実際のソースは function bunkai($str1){ if (strstr($str1, "(10)") != NULL){ define("kugiri","(1)(2)(3)(4)(5)(6)(7)(8)(9)(10)"); // 区切り文字 }else if (strstr($str1, "(9)") != NULL){ define("kugiri","(1)(2)(3)(4)(5)(6)(7)(8)(9)"); // 区切り文字 }else if (strstr($str1, "(8)") != NULL){ define("kugiri","(1)(2)(3)(4)(5)(6)(7)(8)"); // 区切り文字 }else if (strstr($str1, "(7)") != NULL){ define("kugiri","(1)(2)(3)(4)(5)(6)(7)"); // 区切り文字 }else if (strstr($str1, "(6)") != NULL){ define("kugiri","(1)(2)(3)(4)(5)(6)"); // 区切り文字 }else if (strstr($str1, "(5)") != NULL){ define("kugiri","(1)(2)(3)(4)(5)"); // 区切り文字 }else if (strstr($str1, "(4)") != NULL){ define("kugiri","(1)(2)(3)(4)"); // 区切り文字 }else if (strstr($str1, "(3)") != NULL){ define("kugiri","(1)(2)(3)"); // 区切り文字 }else if (strstr($str1, "(2)") != NULL){ define("kugiri","(1)(2)"); // 区切り文字 }else if (strstr($str1, "(1)") != NULL){ define("kugiri","(1)"); // 区切り文字 } $count = 0; $token = strtok($str1, kugiri); while ($token) { $data[$count] = $token; $token = strtok(kugiri); $count++; } $data[$count] = NULL; return $data; } なんですが、 $str1に"(3)した(名)(4)しも(名)(5)もと(名)(6)さ-げる(動ガ下一)(7)さ-がる(動ガ下一)(8)くだ-る(動ラ五[四])(9)くだ-す(動サ五[四])(10)くだ-さる(動ラ五[四])"という文字列を入れて $dataを表示させてみると $data[0]=した(名) $data[1]=しも(名) ここまではできるのですが、これ以降 $data[2]=も� $data[3]=(名) $data[4]=さ-げる(動ガ下一) $data[5]=さ-がる(動ガ下一) $data[6]=く� $data[7]=-る(動� : : となってしまい、ところどころでうまく丸数字を読み込めていません。特に$str1に違う文字列をいれてみても(1)(2)(3)(4)まではきちんと読み込めてその後の(5)でまず最初の文字化けが絶対発生してしまいます。でも(5)を通過したあとの(6)(7)はきちんと判別していたりとよく原因がわかりません……。 がんばってexplode関数で同じようなことしてもいいかなと考えているのですが、関数自体が長くなってしまうので、めんどくさいなーと思います。 どなたか、このバグの原因がわかるかた、または、こんな関数を使ってこんなことしたら丸数字を判別して配列に入れることができるよーという意見もあったら欲しいです。 お願いします。困ってます。

    • ベストアンサー
    • PHP
  • 文字列の扱いについて教えてください

    #include<cstdio> #include<cstring> #define _CRT_SECURE_NO_DEPRECATE 1 #define MAXBUFF 256 void s_swap(char* str_a, char* str_b) { char str_dummy[MAXBUFF]; strcpy_s(str_dummy,strlen(str_dummy),str_a); ★ strcpy_s(str_a,strlen(str_a),str_b); ★ strcpy_s(str_b,strlen(str_b),str_dummy); } void main(void) { char* str_a = "ABC"; char* str_b = "DEF"; int a; printf("呼出前:str_a=%s, str_b=%s\n", str_a, str_b); s_swap(str_a,str_b); printf("呼出後:str_a=%s, str_b=%s\n", str_a, str_b); } str_aとstr_bの中身を入れ替える処理で、エラーや警告はでないのですが ★のところで実行失敗します。 昔から文字列の処理は苦手でどのように攻略したらよいのか 解説していただけないでしょうか。

  • C言語 文字列操作

    トリム関数とリムーブ関数を作成してみました。改良点はありますでしょうか? ~~~~以下ソース~~~~ #include <stdio.h> #include <stdlib.h> #include <string.h> char *Trim(char *str); char *Remove(char *str, char *rmv); void main(void) {  char str[10], rmv[10], *p;  int c;  /* " abcd "をトリムする */  strcpy(str, " abcd ");  printf("トリム前 |%s|\n", str);  p = Trim(str);  printf("トリム後 |%s|\n", str);  /* 指定文字列を削除する */  printf("削除する文字列を入力してください :");  scanf("%s", rmv);  Remove(str, rmv);  printf("削除後 |%s|\n", str);  exit(0); } char *Trim(char *str) {  char space[] = " ";  char null[] = "";  int index = 0;  while(1){   if(strcmp(&(str[index]), null) == 0){    index--;    if(strncmp(&(str[index]), space, 1) == 0){     strcpy(&(str[index]), &(str[index]) + 1);    }else{     break;    }   }else{    if(strncmp(&(str[index]), space, 1) == 0 && index == 0){     strcpy(&(str[index]), &(str[index]) + 1);    }else{     index++;    }   }  }  return str; } char *Remove(char *str, char *rmv) {  int c, size, i;  char *p;  c = '\0';  p = strchr(rmv, c);  size = p - rmv;  for(i = 0; i < size; i++){   c = (int)rmv[i];   p = strchr(str, c);   if (p != NULL) {    strcpy(&(str[p-str]), p + 1);   }   else{    printf("""%c""は見つかりませんでした\n", c);   }  }  return str; }

  • 文字列クラスを作りたいと思っています

    文字列クラスを作りたいと思っています。 以下のようなところまでは作れましたが、 エラーがでてしまいます。 どこかおかしいところがあるのでしょうか? *********************************************** #include<stdio.h> #include<string.h> class stt { public: char *str; int len; bool maked; stt::stt() { len=0; str=NULL; maked=false; } stt::~stt() { delete[] str; } stt &operator =(char *c) { if(maked) { delete[] str; maked=false; } len=strlen(c); str=new char[len]; strcpy(str,c); maked=true; return (*this); } virtual operator char*() { return str; } }; int main() { stt s; s="Hello World"; printf(s); getchar(); return 0; } ***********************************************

  • C言語の文字列について

    C言語で文字列のヌルについて、理解があいまいな点があり、教えて欲しいのですが、以下のようにsprintfで書式し代入した際に最後は0(ヌル文字)をセットしてくれるのでしょうか?4バイト目の文字が何か知りたいです。 char temp[100];時では0で初期化されていることは保障されていませんが、大抵は0で埋まっていますが、sprintfの仕様が知りたいです。 char temp[100]; sprintf(temp, "test");とした時に 01234バイト目 test?????????????.... 話は変わりますが、以下のようにするとエラーになりましたが、 特定の位置の値をセットする方法はどのようなものがあるのでしょうか? temp[10] = (temp[10] == '0') ? (char)'1' : (char)'0';

専門家に質問してみよう