- ベストアンサー
文字列を分割して変数に格納する方法
- 文字列を分割して変数に格納する方法について詳しく教えてください。
- ソースコードの説明として、文字列を分割して変数に格納する方法について説明します。
- ソースコードの最後に結果を表示する部分がありますが、正しく変数に格納されない原因がわかりません。
- みんなの回答 (8)
- 専門家の回答
質問者が選んだベストアンサー
ちゃんと動くかどうかは、わかりません。 #include <stdio.h> #include <stdlib.h> #include <string.h> int main(void) { char str[] = "name1=value1&name2=value2&name3=value3&name4=value4"; char **name, **value, *tp, *dlm = "=&"; int n, i; for (n = i = 0; str[i]; i++) { if (str[i] == '=') { n++; } } name = (char **) malloc(sizeof(char *) * n); value = (char **) malloc(sizeof(char *) * n); if (!name || !value) { exit(0); } tp = strtok(str, dlm); for (i = 0; tp && i < n; i++) { if (tp) { name[i] = tp; tp = strtok(NULL, dlm); if (tp) { value[i] = tp; tp = strtok(NULL, dlm); } } } for (i = 0; i < n; i++) { printf("name =%s\n", name[i]); printf("value=%s\n", value[i]); } free(name), free(value); return 0; }
その他の回答 (7)
- asuncion
- ベストアンサー率33% (2127/6289)
>「名前=値」のリストが & で連結されているので, 最初の forループ内では '=' とではなく '&' と比較するのが筋だと思います>#6. まあ、それは考え方のちょっとした違いでしかなくて、 どっちでもいいかな、と思います。
補足
私自身もどちらも同じだと思うのですが=で判定せよ っと説明を受けたので=で判定するようにしました
- Tacosan
- ベストアンサー率23% (3656/15482)
他の回答者への突っ込み+補足のみ. 「名前=値」のリストが & で連結されているので, 最初の forループ内では '=' とではなく '&' と比較するのが筋だと思います>#6. いや, 結局同じなんだけどさ. あと, char *nameset[b]; char *valueset[b]; などは C99 (以降) なら OK です>#2. C++ では 11 でも NG ですが, C++ なら std::vector でもつかっとけということで.
補足
<<「名前=値」のリストが & で連結されているので, 最初の forループ内では '=' とではなく '&' と比較するのが筋だと思います>#6. いや, 結局同じなんだけどさ. 私自身もどちらも同じだと思うのですが=で判定せよ っと説明を受けたので=で判定するようにしました <<あと, char *nameset[b]; char *valueset[b]; ここら辺を修正する事にします
- hashioogi
- ベストアンサー率25% (102/404)
#3です。 ●2 *nameset[0]=*strtok( tai,"&=" ); Q。つまり指定先が間違っているのですね A。代入先も間違っているし代入元も間違っています。多分。 ●3 tpの初期化は必要はないのです。tpにstrtokで分割した文字列が入っていれば問題はないと思います どこでtpに文字列を入れる文がありますか ? 見当たりませんが。 また、初期化しなくてよい理由はありません。私にはtpに何が入っているかわからないで while(tp !=NULL) を実行する意味が理解できません。たまたまtpがNULLならwhile内は実行されますが、そうでなければ実行されないという博打のようなプログラムですよ。
補足
ああすみません。 よく見たら非常におかしな事を書いていました 修正をなんどもっしているうちにへんなことになってたみたいです 申し訳ありませんでした。
- asuncion
- ベストアンサー率33% (2127/6289)
そもそも、どういう結果になることをお望みなんでしょうか。
補足
strtokを使ってtai[]を分割した文字列を setneme[]={"name1,"name2","name3"}; setvalue[]={"value1","valu2","value3"}; のように格納したいのです。
- hashioogi
- ベストアンサー率25% (102/404)
完成までは大分道が遠そうだと感じました。 いくつか指摘するだけにしておきたいと思います。 (1) 途中で以下の定義が現れます。 char *nameset[b]; char *valueset[b]; 私のコンパイラでは翻訳エラーが出ます。質問者のコンパイラではエラーが出ないものとして話を続けます。 (2) 次の行では *nameset[0]=*strtok( tai,"&=" ); が現れます。 strtokは検索した文字列の検索結果のポインタを返します。でも*をつけるとそこが指している実体になります。格納先のnameset [0]はポインタを格納する領域を配列としてb個分用意したものですが、まだそこには何が書かれているかわかりません。その何が格納されているかわからない内容をアドレスとして代入したら、往生しまっせ。 (3) 後ろの方に while ( tp != NULL ) { という文がありますが、tpは初期化もされていないし、だれも更新しないようですね。それでOKですか?
補足
●1 その部分はいろいろ修正してみる事にします ●2 つまり指定先が間違っているのですね ●3 初期化は必要はないのです tpにstrtokで分割した文字列が入っていれば問題はないと思います
- Wr5
- ベストアンサー率53% (2173/4061)
いろいろツッコミどころが…… >while ( tp != NULL ) { tpの値は不定値のまま更新されていません。 よって、ほぼ確実に無限ループします。 >*nameset[0]=*strtok( tai,"&=" ); nameset[0]が指すアドレス(不定値)に…strtok()の戻り値のアドレスに格納されている1文字をコピー…って事になるんですかね。 どこに書き込むかは不明ですので最近のOSならアクセス違反などの例外になるかと思われます。 >char *nameset[b]; >char *valueset[b]; C99で可能…なんでしたっけ? VC++2010EEでは「error C2057: 定数式が必要です。」となります。 正しく動作する…と思われる修正を行ったとして… nameset[]とvalueset[]に入るアドレスはstrtok()によって書き換えられたtai[]になります。 よって…tai[]の寿命に影響される点にはご注意を。
補足
<<tpの値は不定値のまま更新されていません。 よって、ほぼ確実に無限ループします。 事前に部分的につくりはしたのですがそのときは無限ループはしなかったようです。 <<nameset[0]が指すアドレス(不定値)に…strtok()の戻り値のアドレスに格納されている1文字をコピー…って事になるんですかね。 どこに書き込むかは不明ですので最近のOSならアクセス違反などの例外になるかと思われます。 一文字コピーになるのですか¥0で区切られた文字が入るのかと思いました。 >char *nameset[b]; >char *valueset[b]; 無理なのですね すみません他の方法を考えてみますね <<正しく動作する…と思われる修正を行ったとして… nameset[]とvalueset[]に入るアドレスはstrtok()によって書き換えられたtai[]になります。 よって…tai[]の寿命に影響される点にはご注意を。 注意しますごしてきありがとうございました
- m-take0220
- ベストアンサー率60% (477/782)
分割した後の文字列を格納するための領域を確保している部分が見当たらないし、初期化していないポインタを使用している部分も散見されるので、ちゃんと勉強しなおしたほうがいいですよ。
補足
私が勉強不足なのは理解しています そのため実践を通してプログラムを組もうとしているのです
補足
あの後自分なりに皆さんの指摘を参考にソースを再構築してみました whoilがなくなったので固定数になりましたが 6さんの教えていただいたソースも参考にしますね ありがとうございました。 #include <stdio.h> #include <string.h> void main(void){ char tai[]="name1=value1&name2=value2&name3=value3&name4=value4"; char *nameset[4]; char *valueset[4]; int i; nameset[0]=strtok( tai,"&=" ); for(i=1;i<8;i++){ if(i%2==0){ nameset[i/2]=strtok( NULL,"&=" ); } else{ valueset[i/2]=strtok( NULL,"&=" ); } } for(i=0;i<4;i++){ printf("%s %s\n",nameset[i],valueset[i]); } }