アプリ版:「スタンプのみでお礼する」機能のリリースについて

文字列を分割して変数に格納したいのですがうまくいきません。

---以下ソース---
#include<stdio.h>
#include<string.h>

void main(void){

char tai[]="name1=value1&name2=value2&name3=value3&name4=value4";
char *tp;

int a;
int b;
int i;
int co=0;

a=strlen(tai);

for(i=0;i<a;i++){
if(tai[i] == '='){
co++;
}
}

b=co;

char *nameset[b];
char *valueset[b];

*nameset[0]=*strtok( tai,"&=" );

i=1;
co=0;

while ( tp != NULL ) {

if(0==i%2){ co=i/2; *nameset[co] = *strtok( NULL,"&=" ); }
else{ co=i/2; *valueset[co] = *strtok( NULL,"&=" );}
i++;
}

for(i=0;i<b;i++){
printf("%s : %s\n",nameset[i],valueset[i] )
}
}
---ソースここまで---

どうしたらちゃんと変数に格納されますか?

A 回答 (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;
}

この回答への補足

あの後自分なりに皆さんの指摘を参考にソースを再構築してみました
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]);
}

}

補足日時:2012/10/05 17:30
    • good
    • 0

>「名前=値」のリストが & で連結されているので, 最初の forループ内では '=' とではなく '&' と比較するのが筋だと思います>#6.



まあ、それは考え方のちょっとした違いでしかなくて、
どっちでもいいかな、と思います。

この回答への補足

私自身もどちらも同じだと思うのですが=で判定せよ
っと説明を受けたので=で判定するようにしました

補足日時:2012/10/05 17:21
    • good
    • 0

他の回答者への突っ込み+補足のみ.



「名前=値」のリストが & で連結されているので, 最初の 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];

ここら辺を修正する事にします

補足日時:2012/10/05 17:18
    • good
    • 0

#3です。



●2 *nameset[0]=*strtok( tai,"&=" );
Q。つまり指定先が間違っているのですね
A。代入先も間違っているし代入元も間違っています。多分。

●3 tpの初期化は必要はないのです。tpにstrtokで分割した文字列が入っていれば問題はないと思います

どこでtpに文字列を入れる文がありますか ? 見当たりませんが。
また、初期化しなくてよい理由はありません。私にはtpに何が入っているかわからないで
while(tp !=NULL)
を実行する意味が理解できません。たまたまtpがNULLならwhile内は実行されますが、そうでなければ実行されないという博打のようなプログラムですよ。

この回答への補足

ああすみません。
よく見たら非常におかしな事を書いていました

修正をなんどもっしているうちにへんなことになってたみたいです
申し訳ありませんでした。

補足日時:2012/10/05 17:13
    • good
    • 0

そもそも、どういう結果になることをお望みなんでしょうか。

この回答への補足

strtokを使ってtai[]を分割した文字列を

setneme[]={"name1,"name2","name3"};
setvalue[]={"value1","valu2","value3"};

のように格納したいのです。

補足日時:2012/10/02 18:12
    • good
    • 0

完成までは大分道が遠そうだと感じました。



いくつか指摘するだけにしておきたいと思います。

(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で分割した文字列が入っていれば問題はないと思います

補足日時:2012/10/02 18:06
    • good
    • 0

いろいろツッコミどころが……



>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[]の寿命に影響される点にはご注意を。

注意しますごしてきありがとうございました

補足日時:2012/10/02 17:56
    • good
    • 0

分割した後の文字列を格納するための領域を確保している部分が見当たらないし、初期化していないポインタを使用している部分も散見されるので、ちゃんと勉強しなおしたほうがいいですよ。

この回答への補足

私が勉強不足なのは理解しています
そのため実践を通してプログラムを組もうとしているのです

補足日時:2012/10/02 17:46
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!