文字列を分解して特定の項目を別の変数に入れる方法は?

このQ&Aのポイント
  • 文字列を分解して特定の項目を別の変数に入れたい場合、条件式を満たす項目を抽出し、別の変数に格納することで実現できます。
  • ポイントは、文字列をループして項目を分解し、条件式で判定することです。条件式を満たす場合は別の変数に格納し、満たさない場合は元の変数に格納します。
  • 例えば、与えられた文字列から項目を分解する場合、'='で分解して項目名と値を取得し、条件式で判定します。その後、条件式を満たす場合は別の配列に格納し、満たさない場合は元の配列に格納します。
回答を見る
  • ベストアンサー

文字列を分解して特定の項目を別の変数に

文字列を分解して特定の項目を別の変数に入れたいのですが、条件式を満たさないので別の変数に入れれません 下にソースを書くのですが 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]); }

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

  • ベストアンサー
  • chie65535
  • ベストアンサー率43% (8481/19299)
回答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]); }

nanaka2222
質問者

補足

>>>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に戻してみたらすぐやってみますね ソースを張り切って書いていただきありがとうございます。 ソースを書いていただけるのは本当にうれしいです うれしいのですがこちらは質問のために作ったソースなのでこのプログラムを実行しちゃうと大本のプログラムにエラーが出てきそうです ですが、書いていただいたソースと似たような書き方をすることがこの先あるかもしれません そのときは遠慮なく使わせてもらいますね 本当にソースを書いていただきありがとうございました

その他の回答 (2)

  • chie65535
  • ベストアンサー率43% (8481/19299)
回答No.3

因みに、ANo.1の >if(strncmp(han, "age", 3)==0) { と言う修正は「良くやるミス」なので駄目です。 これでは agesage=sage agent=yes など、頭3文字が「age」になっている「4文字以上のname項目」も全部引っ掛かります。 つまり「age=15以外も引っ掛かる」ので、期待した動作をしません。

nanaka2222
質問者

補足

なるほど確かにそうなりますね たぶん未来の私が気づいたらNAMEの名前に気をつけるなりするんでしょうね d法はならなかったわけですが

  • kabe64
  • ベストアンサー率72% (13/18)
回答No.1

検証はしておらすコードだけ見てます。 if(strcmp(han,"age")==0){ の部分でhanが参照できる文字列は"age=15&like=momo"となっているはずです。 ですので当然"age"とは一致しません。 単純にこの問題だけクリアしたいだけなら、 if(strncmp(han, "age", 3)==0) { のように比較する文字数に制限を掛けられる関数を使いましょう。 しかし難解に記述されてますね。'='や'&'で文字列を分解したいのであれば、strtokを使えばグっと楽になりますよ。

nanaka2222
質問者

補足

<<の部分でhanが参照できる文字列は"age=15&like=momo"となっているはずです。 ああそうなんですかだからおかしかったのですね <<しかし難解に記述されてますね。'='や'&'で文字列を分解したいのであれば、strtokを使えばグっと楽になりますよ。 昔はstrtok使ってたのですがないようにNULLが含まれるとずれちゃうんですよ そのため使わなくなりました こんなのあるんだと発見したときは喜んだんですけどね

関連するQ&A

  • 文字列処理関数について

    おみくじのプログラムを書きました。初めのが私のもので、次のが参考書のものなのですが、なんでわざわざ 文字列処理関数を使うのかがわかりませんでした。 教えてください!! int main() {   int r =0;   int i =0;   srand(time(NULL));   r = rand()%3+1;   for(i=0;i<2;i++){    if(r == 1)    {  printf("大吉:充実した1日\n");    }    else if(r == 2)    {  printf("小吉:充実した1日\n");    }    else    {       printf("凶:衝動買いに注意\n");    }    return 0; } ********************** ********************** main(){     int kuji;     char kekka[6];     char str[45];     srand(time(NULL));     r = rand()%3+1;     switch(kuji){     case 1:           strcpy(kekka,"大吉");         strcpy(str,"金運アップ");         break;    /*case2,3は省略します*/           default:    break; } printf("%s:%s",kekka,str); return 0; }

  • 文字列を分割して変数に格納したい

    文字列を分割して変数に格納したいのですがうまくいきません。 ---以下ソース--- #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] ) } } ---ソースここまで--- どうしたらちゃんと変数に格納されますか?

  • 文字列から文字を探す

    以下のプログラムです。 #include <stdio.h> main () { char s[]="I love cat and dog."; char c='a'; char *p=s; int n=0; printf("\"%s\"の中から\'%c\'を探します。",s,c); while(*p != '\0') { if(*p == 0) { printf("%d文字目で発見しました。\n",p-s+1); n++; } p++; } if(n == 0) printf("1つも見つかりませんでした。\n"); else printf("全部で%d個見つかりました。\n",n); } C言語の本で勉強しています。 ・p-s+1の意味がわかりません。 ここには何が割り当てられているのでしょうか? ・*pとpの違いもあいまいです。 ・\"%s\"は「"」を印刷するためには必要なのでしょうか? どう質問していいのかもわからないのですが、よろしくお願いします。

  • C フォームから受け取った値をクッキーで発行

    (C言語)フォームから受け取った値をクッキーで発行するにはどのようにするのでしょうか? 問題として ・フォームから値を受け取る事は出来てもクッキーが発行できない もしくは ・フォームから値を受け取れないのにクッキーは発行できる のどっちかしか出来ないため困りました。 どうすればフォームから受け取った値をクッキーで発行できますか? ---以下ソース--- #include <stdio.h> #include <stdlib.h> #include <string.h> int Deta1(char *a,int b,char *nameset[],char *valueset[]); int Dcd(char *set,int a); int get_cookie(char *a,int b,char *nameset2[],char *valueset2[]); void set_cookie(char *valueset[]); void main(void){ int i; int a=0; char *chr=NULL; char *nameset[7]; char *valueset[7]; char *nameset2[7],*valueset2[7]; int b=200; int mode=0; char *ss=getenv("HTTP_COOKIE"); for(i=0;i<7;i++){ nameset2[i]=NULL; valueset2[i]=NULL; } printf("content-type: text/html\n"); //set_cookie(valueset); //ここでset_cookie関数を呼び出せばクッキーは発行出来るけれどフォームに入力された値が入らない printf("\n"); if(mode==0){ //省略しますがフォームで7つの項目があると思ってくださいね if ( getenv("CONTENT_LENGTH")!=NULL ){ a = atoi( getenv("CONTENT_LENGTH") ); } chr=(char *)malloc(a+1); scanf("%s",chr); chr[a] = '\0'; if (a==0){ return ; } printf("%s<br>",chr); int deta1=Deta1(chr,a,nameset,valueset); for(int i = 0;i<deta1;i++){ Dcd(nameset[i],strlen(nameset[i])); Dcd(valueset[i],strlen(valueset[i])); } for(i=0;i<7;i++){ printf("%s %s<br>",nameset[i],valueset[i]); } //set_cookie(valueset); //ここでset_cookie関数を呼び出せばフォームが入力された値が入るけれどクッキーは発行できない int deta2=get_cookie(ss,b,nameset2,valueset2); for(i=0;i<7;i++){ printf("%s %s<br>\n",nameset2[i],valueset2[i]); } free((void *)chr); } else if(mode==1){ //省略 } else{ //省略 } } int Deta1(char *a,int b,char *nameset[],char *valueset[]){ int i=0,cn=0; if(a[0]==NULL){ return(-1); } nameset[0]=a; while((a[++i]!=NULL)&&(i<b)){ if(a[i]=='='){ a[i]=NULL; valueset[cn]=a+i+1; } else if(a[i]=='&'){ a[i]=NULL; cn++; nameset[cn]=a+i+1; } } return cn+1; } int Dcd(char *set,int a){ int i,j; char buf,*tmp; if(a==0){ return -1; } tmp=(char*)malloc(a); for(i=0,j=0;i<a;i++,j++){ if(set[i]=='+'){tmp[j]=' ';continue;} if(set[i]!='%'){tmp[j]=set[i];continue;} if(set[++i]>='A'){buf=set[i]-'A'+10;} else{buf=set[i]-'0';} buf*=16; if(set[++i]>='A'){buf+=set[i]-'A'+10;} else{buf+=set[i]-'0';} tmp[j]=buf; } for(i=0;i<j;i++){ set[i]=tmp[i]; } set[i]='\0'; free(tmp); return 0; } int get_cookie(char *a,int b,char *nameset2[],char *valueset2[]){ int i=0,cn=0; if(a==NULL){ return(-1); } while((a[++i]!=NULL)&&(i<b)){ if(a[i]=='='){ a[i]=NULL; nameset2[0]=a+i+1; } if(a[i]=='-'){ a[i]=NULL; valueset2[cn]=a+i+1; } else if(a[i]=='&'){ a[i]=NULL; cn++; nameset2[cn]=a+i+1; } } return cn+1; } void set_cookie(char *valueset[]){ time_t timer; struct tm *tset; char expires[256]; char *name="sskchat"; int kikan=86400*90; char *set[7]; int i; for(i=0;i<7;i++){ set[i]=valueset[i]; } for(i=0;i<7;i++){ if(set[i]==NULL){ set[i]="no"; } } timer = time(NULL); timer += kikan; tset = gmtime(&timer); strftime(expires, 255, "%a, %d-%b-%Y %H:%M:%S GMT", tset); printf("Set-Cookie:%s=mode-%s&name-%s&mail-%s&hp-%s&cc-%s&gyo-%s&zkou-%s; expires=%s;\n",name,set[0],set[1],set[2],set[3],set[4],set[5],set[6],expires); } ---ソースここまで---

    • ベストアンサー
    • CGI
  • 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; }

  • C フォームから受け取った知をクッキーで発行 2

    前回 http://okwave.jp/qa/q7765400.html からあれこれしてフォームの値をクッキーに保存できるようになったのですが、バグが出てきました。 一、クッキーが存在しないとエラーが出る ニ、Deta1関数を使って文字列の分解を試みるもうまく分解されない この2つのバグを解決するにはどうしたら直せますか? ---以下ソース--- #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> char *nameset[2],*valueset[2]; char *nameset2[2],*valueset2[2]; int Deta1(char *a,int b); int Dcd(char *set,int a); void get_Form(void); void get_cookie(void); void set_cookie(void); int hen(char *buf, char *mae, char *ato); void Page(int mode); int main(void) { char *nameset[2],*valueset[2]; char *nameset2[2],*valueset2[2]; printf("Content-type: text/html\n"); get_Form(); set_cookie(); get_cookie(); printf("\n"); Page(0); } int Deta1(char *a,int b){ int i=0,cn=0; if(a[0]==NULL){ return(-1); } nameset[0]=a; while((a[++i]!=NULL)&&(i<b)){ /* 項目の分解 */ if(a[i]=='='){ a[i]=NULL; valueset[cn]=a+i+1; } /* データ項目で分解 */ else if(a[i]=='&'){ a[i]=NULL; cn++; nameset[cn]=a+i+1; } } return cn+1; } int Dcd(char *set,int a){ int i,j; char buf,*tmp; if(a==0){ return -1; } tmp=(char*)malloc(a); for(i=0,j=0;i<a;i++,j++){ if(set[i]=='+'){tmp[j]=' ';continue;} if(set[i]!='%'){tmp[j]=set[i];continue;} if(set[++i]>='A'){buf=set[i]-'A'+10;} else{buf=set[i]-'0';} buf*=16; if(set[++i]>='A'){buf+=set[i]-'A'+10;} else{buf+=set[i]-'0';} tmp[j]=buf; } for(i=0;i<j;i++){ set[i]=tmp[i]; } set[i]='\0'; free(tmp); return 0; } void get_Form(void){ int a=0; int i=0; char *chr=NULL; if ( getenv("CONTENT_LENGTH")!=NULL ){ a = atoi( getenv("CONTENT_LENGTH") ); } chr=(char *)malloc(a+1); scanf("%s",chr); chr[a] = '\0'; if (a==0){ return ; } int deta1=Deta1(chr,a); } void get_cookie(void){ int i=0,cn=0; int a=NULL; char *b; if( (getenv("HTTP_COOKIE"))!=NULL){ a=strlen(getenv("HTTP_COOKIE")); } if(a==NULL){ } b=getenv("HTTP_COOKIE"); while((b[++i]!=NULL)&&(i<a)){ if(b[i]=='='){ b[i]=NULL; nameset2[0]=b+i+1; } /* 項目の分解*/ if(b[i]=='-'){ b[i]=NULL; valueset2[cn]=b+i+1; } /*データ項目で分解*/ else if(b[i]=='&'){ b[i]=NULL; cn++; nameset2[cn]=b+i+1; } } for(i=0;i<cn+1;i++){ Dcd(nameset2[i],strlen(nameset2[i])); Dcd(valueset2[i],strlen(valueset2[i])); } } void set_cookie(void) { time_t timer; struct tm *tset; char expires[256]; char *name="sskchat"; int kikan=86400*90; char *set[2]; int i; for(i=0;i<2;i++){ set[i]=NULL; } for(i=0;i<2;i++){ set[i]=valueset[i]; } for(i=0;i<2;i++){ if(set[i]==NULL){ set[i]="no"; } } timer = time(NULL); timer += kikan; tset = gmtime(&timer); strftime(expires, 255, "%a, %d-%b-%Y %H:%M:%S GMT", tset); printf("Set-Cookie:%s=name-%s&mail-%s; expires=%s;\n",name,set[0],set[1],expires); } void Page(int mode){ FILE *fp; char *f1="!name!",*h1; char *f2="!mail!",*h2; if(valueset2[0]==NULL||strcmp("!name!",valueset2[0])==0){ h1=""; } else{ h1=valueset2[0]; } if(valueset2[1]==NULL||strcmp("!mail!",valueset2[1])==0){ h2=""; } else{ h2=valueset2[1]; } char buf[200]; char set[200]; fp = fopen("ren.html", "r+"); while( fgets( set, 200, fp ) != NULL ){ strcpy(buf,set); while(hen(buf, f1, h1)); while(hen(buf, f2, h2)); printf("%s", buf); } fclose(fp); } int hen(char *buf, char *mae, char *ato){ char *nw; size_t zen,go; zen = strlen(mae); go = strlen(ato); if(zen == 0 || (nw = strstr(buf, mae)) == NULL){ return 0; } memmove(nw + go, nw + zen, strlen(buf) - (nw + zen - buf ) + 1); memcpy(nw, ato, go); return 1; } ---ソースここまで--- ---ren.htmlの内容--- <form action="first.exe" method="post"> 名前:<input type="text" name="name" size="100" value="!name!"><br><br> メール:<input type="text" name="mail" size="100" value="!mail!"><br><br> 本文:<textarea name="text" cols="70" rows="10"></textarea><br><br> <input type="submit" value=" 送 信 "><br> </form>

    • ベストアンサー
    • CGI
  • 文字列処理

    513404250001969199219952002000340000134300003405001343730… 上のような文字列をバイト数を指定して分割するプログラムを以下の様に書いたところ画像の様な結果になってしまいます。NULL文字が関係しているのではと思い、分割後の文字列にNULL文字を付与してみましたが解決しません。ご指導よろしくお願いします。 【プログラム】 int head(char *hd){ 44 #define knum 6 45 #define ini 23 46 char splith[knum][9]; 47 char null[2]={'\0'}; 48 int dev[knum] = {3,3,7,7,7,7}; 49 int i; 50 int sum; 51 sum = ini; 52 for(i=0;i < knum;i++){ 53 //printf("%d\n",dev[i]); 54 //printf("%d\n",sum); 55 strncpy(&splith[i][0],hd + sum,dev[i]); 56 strcat(&splith[i][0],null); 57 printf("%d is %s\n",i,&splith[i][0]); 58 sum += dev[i]; 59 } 60 }

  • C言語 文字列の比較 compare

    プログラミング初心者です。 60文字以内の文字列を入力して、 大小関係を比較・表示するプログラムなのですが・・ 「AはBより大きい」という結果しか出ません。 どこが間違っているのか、ご指摘お願いしますっ。 #include<stdio.h> int main(void) { char moji1[61]; char moji2[61]; printf("文字列Aを入力===>"); scanf("%60s" ,&moji1); printf("文字列Bを入力===>"); scanf("%60s" ,&moji2); if(moji1-moji2>0){ printf("===AはBより大きい===\n"); } else if(moji1-moji2<0){ printf("===AはBより小さい===\n"); } else if(moji1-moji2==0){ printf("===AとBは等しい===\n"); } return 0; } int compare(char *x, char*y) { while(*x==*y){ if(*x=='\0') return 0; x++; y++; } return (*x-*y); }

  • 文字列

    下のプログラムは何をするためのプログラムなのか教えてください。 個人的にはJISコードに関係していると思うのですがさっぱりわかりません。 どなたか詳しい説明お願いします。 #include <stdio.h> #define LEN 255 int main(void) { char str[LEN]; char cipher[LEN]; int ikey; int i,n; printf("文字列を入力せよ : "); scanf("%s", str); printf("鍵を入力 : "); scanf("%d", &ikey); i = 0; while (str[i]!='\0') { n = (str[i]-'A'+ikey)%26; cipher[i] = 'A'+n; ++i; } cipher[i] = '\0'; printf("%s\n", cipher); return 0; }

  • 指定した文字列を探して・・・

        第1引数の文字列中に第2引数で指定した文字がある場合に、その     文字のあるアドレス(ポインタ)を返す関数doko()作成し、     プログラムを完成させよ。     指定した文字がない場合はNULL(ヌルポインタ)を返すものとする。     配列の[](カギカッコ)を利用しないで作る事     main内は変えないこと いろいろと模索したのですが、strcpyなどは使うのでしょうか? 参考サイトを見たりしたり、ほかの質問などを見たのですが なかなか理解できずに現在にいたってます 以下のコードのdokoは沢山やりすぎたので一番シンプルな間違い方をしています 何かご指摘あればお願いします #include <stdio.h> #define MAX 128 char* doko(char *,char); int main() { char buf[MAX]; char *p = "abcdef12345"; char *r; r = doko(p, 'f'); if (r == NULL) { printf("mojiretsu ni f toiu moji ha arimasen\n"); return 0; } printf("%s (= f12345)\n", r); scanf("%s", buf); r = doko(buf, 'x'); if (r == NULL) { printf("mojiretsu ni x toiu moji ha arimasen\n"); return 0; } printf("%s\n", r); return 0; } char* doko(char *p,char a) { while(*p){ if(*p == a){ return p; } if(*p != a){ return NULL; } ++p; } }