![](http://oshiete.xgoo.jp/images/v2/pc/qa/question_title.png?e8efa67)
文字列を分解して特定の項目を別の変数に入れたいのですが、条件式を満たさないので別の変数に入れれません
下にソースを書くのですが age の項目だけ別の変数に入れたいのです
どのようにすれば入れれますか?
#include <stdio.h>
#include <string.h>
char *nameset[12],*valueset[12];
char *nameset3[12],*valueset3[12];
void main(void){
int c=0;
int i=0,cn=0,dn=0;
char *tm=NULL;
char *han;
char *a="name=miku&age=15&like=momo";
int b=strlen(a);
nameset[0]=a;
while((a[++i]!=NULL)&&(i<b)){
/* 項目の分解 */
if(a[i]=='='){
a[i]=NULL;
if(c!=1){
valueset[cn]=a+i+1;
cn++;
}
else{
valueset3[dn]=a+i+1;
dn++;
c=0;
}
}
/* データ項目で分解 */
else if(a[i]=='&'){
a[i]=NULL;
han=a+i+1;
if(strcmp(han,"age")==0){
nameset3[dn]=han;
c=1;
}
else{
nameset[cn]=han;
}
}
}
printf("%s\n", nameset[0]);
printf("%s\n", valueset[0]);
printf("%s\n", nameset[1]);
printf("%s\n", valueset[1]);
printf("%s\n", nameset[2]);
printf("%s\n\n", valueset[2]);
printf("%s\n", nameset3[0]);
printf("%s\n", valueset3[0]);
}
No.2ベストアンサー
- 回答日時:
>char *a="name=miku&age=15&like=momo";
aは「書き換え不可能なメモリ領域を指している場合がある」ので、aが指すメモリを
>a[i]=NULL;
のように書き換えても、正しく書き変わる保証はありません。
文字列が「リードオンリーのメモリ」に置かれた場合には「実行時例外:メモリ????????が書き込み可になる事はありませんでした。実行プロセス??????.EXE、プロセスアドレス????????番地」という例外が出てプログラムが強制終了されます。
>if(strcmp(han,"age")==0){
この段階では、hanが指すポインタの文字列は「age=15&like=momo」になっていて、名前と値に分解されていません。
なので、このif文は成り立ちません。
とりあえず
if(strcmp(han,"age")==0){
を
if(strncmp(han,"age=",4)==0){
にすれば、希望通りになります。
以下、上記の添削を踏まえて、大幅に書き換えました。
#include <stdio.h>
#include <string.h>
char a[256]; //aは動的メモリ領域に置く
char *nameset[12],*valueset[12];
char *nameset3[12],*valueset3[12];
void main(void){
int token=0,token3=0;
char *p=a,c;
strcpy(a,"name=miku&age=15&like=momo"); //文字列を動的メモリ領域にコピー
nameset[token]=p;
while((c = *++p) != '\0') {
if((c == '=') || (c == '&')) {
*p++ = '\0'; //区切り文字をヌル文字に変える
if(c == '=') {
valueset[token++]=p; //valueを記録したらトークンを1つ進める
if(strcmp(nameset[token-1],"age")==0){ //分解後にnameがageだったと判ったら
nameset3[token3] = nameset[--token]; //namesetとvaluesetをnameset3とvalueset3にコピーして
valueset3[token3++] = valueset[token]; //トークンを1つ戻して、トークン3を1つ進める
nameset[token] = NULL; //nameset3にコピーされたnamesetを無効にする
valueset[token] = NULL; //valueset3にコピーされたvaluesetを無効にする
}
} else {
nameset[token] = p;
valueset[token] = NULL;
}
}
}
printf("%s\n", nameset[0]);
printf("%s\n", valueset[0]);
printf("%s\n", nameset[1]);
printf("%s\n", valueset[1]);
printf("%s\n", nameset[2]);
printf("%s\n\n", valueset[2]);
printf("%s\n", nameset3[0]);
printf("%s\n", valueset3[0]);
}
この回答への補足
>>>char *a="name=miku&age=15&like=momo";
aは「書き換え不可能なメモリ領域を指している場合がある」ので、aが指すメモリを
>a[i]=NULL;
のように書き換えても、正しく書き変わる保証はありません。
文字列が「リードオンリーのメモリ」に置かれた場合には「実行時例外:メモリ????????が書き込み可になる事はありませんでした。実行プロセス??????.EXE、プロセスアドレス????????番地」という例外が出てプログラムが強制終了されます。
今まで書き換わるものだと思っていたから私はage=15&like=momoに気づかなかったのですね
強制終了はしませんでしたが
<<if(strncmp(han,"age=",4)==0){
にすれば、希望通りになります。
教えていただきありがとうございました
プログラム製作可能なPCに戻してみたらすぐやってみますね
ソースを張り切って書いていただきありがとうございます。
ソースを書いていただけるのは本当にうれしいです
うれしいのですがこちらは質問のために作ったソースなのでこのプログラムを実行しちゃうと大本のプログラムにエラーが出てきそうです
ですが、書いていただいたソースと似たような書き方をすることがこの先あるかもしれません
そのときは遠慮なく使わせてもらいますね
本当にソースを書いていただきありがとうございました
No.3
- 回答日時:
因みに、ANo.1の
>if(strncmp(han, "age", 3)==0) {
と言う修正は「良くやるミス」なので駄目です。
これでは
agesage=sage
agent=yes
など、頭3文字が「age」になっている「4文字以上のname項目」も全部引っ掛かります。
つまり「age=15以外も引っ掛かる」ので、期待した動作をしません。
この回答への補足
なるほど確かにそうなりますね
たぶん未来の私が気づいたらNAMEの名前に気をつけるなりするんでしょうね
d法はならなかったわけですが
No.1
- 回答日時:
検証はしておらすコードだけ見てます。
if(strcmp(han,"age")==0){
の部分でhanが参照できる文字列は"age=15&like=momo"となっているはずです。
ですので当然"age"とは一致しません。
単純にこの問題だけクリアしたいだけなら、
if(strncmp(han, "age", 3)==0) {
のように比較する文字数に制限を掛けられる関数を使いましょう。
しかし難解に記述されてますね。'='や'&'で文字列を分解したいのであれば、strtokを使えばグっと楽になりますよ。
この回答への補足
<<の部分でhanが参照できる文字列は"age=15&like=momo"となっているはずです。
ああそうなんですかだからおかしかったのですね
<<しかし難解に記述されてますね。'='や'&'で文字列を分解したいのであれば、strtokを使えばグっと楽になりますよ。
昔はstrtok使ってたのですがないようにNULLが含まれるとずれちゃうんですよ
そのため使わなくなりました
こんなのあるんだと発見したときは喜んだんですけどね
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# プログラミング c言語 4 2023/03/07 01:05
- C言語・C++・C# プログラミングの授業の課題です 1 2023/01/17 22:15
- C言語・C++・C# c言語の問題です 3 2023/01/10 16:15
- C言語・C++・C# c言語の問題の説明、各所ごとに 5 2023/07/26 11:03
- C言語・C++・C# C言語のエラーについて 2 2022/07/11 13:56
- C言語・C++・C# c言語 プログラムのエラー 1 2023/02/11 20:31
- C言語・C++・C# c言語配列の結合についてです。 なぜうまくいかないのでしょうか。 #include <stdio.h 4 2022/05/30 22:42
- C言語・C++・C# 宣言する関数の形が決まっている状態で、 str1とstr2の文字列をこの順に引っ付けてstrに保存し 2 2022/05/30 18:21
- C言語・C++・C# バイナリファイルをコピーするのにかかる時間を測りたいのですが実行するとFatel error:gli 2 2022/11/03 01:10
- C言語・C++・C# C言語で再起関数とポインタを用いて文字列反転をする方法がわかりません。 4 2023/04/29 20:32
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
Enterキーを押されたら次の処理...
-
C言語のプログラムで、途中で止...
-
fscanfの使い方
-
C++で指定文字列のカウント方法...
-
#defineが使用するメモリ領域に...
-
C言語について。
-
信頼区間の1.96や1.65ってどこ...
-
2÷3などの余りについて
-
O(n log n)について2
-
大学数学の問題です。 加法群Z/...
-
#define _CRT_SECURE_NO_WARNIN...
-
教えてください。数学Bの二項分...
-
「Aに対するBの割合」と「Aに対...
-
EXCELの分散分析表のP-値が....
-
プログラムでの数字につく”f”の...
-
fgetsなどのときのstdinのバッ...
-
配列を使って魔方陣
-
独立係数について教えて下さい。
-
迷路を脱出する経路探索プログ...
-
複数桁10進数の*桁目だけを抽出...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
Enterキーを押されたら次の処理...
-
C言語で複数列のデータを1列の...
-
printf による16進表示について
-
C言語のプログラムで、途中で止...
-
char型2つを結合し、short型に...
-
矢印キーを押下してコンソール...
-
#defineが使用するメモリ領域に...
-
【C言語】全角文字の配列を、全...
-
終了条件Ctrl+zについて,結果表...
-
空白を含んだ文字列がうまく格...
-
プログラミングの授業の課題です
-
リストの作成と出力(C言語)
-
c言語で文書を読み込み、単語の...
-
構造体メンバの初期化
-
エラーについて質問です。
-
reallocでエラー
-
C言語でのCSVファイルの読み出...
-
なぜ無限ループになるかが分か...
-
Cプログラムについて
-
C++で指定文字列のカウント方法...
おすすめ情報