関数の中のループについて

このQ&Aのポイント
  • 関数の中のループについて説明します。
  • 質問文章の中では、hikaku関数でループがまわらないという問題が発生しています。
  • hikaku関数内の条件判断が正しく行われていない可能性があります。
回答を見る
  • ベストアンサー

関数の中のループについて

typedef struct{ int num; char basic_gainen[MAX][32]; int particle[MAX]; }Gainen; int main (void){ Gainen g1, g2; char str1[256] = "外国_の_大型_の_船"; char str2[256] = "大型_の_船"; char buf[256]; divide(&g1, str1);//文字列の中から助詞と名詞を取得 divide(&g2,str2);//文字列の中から助詞と名詞を取得 printf("gainen:%s\n",print(&g1,buf)); printf("gainen:%s\n",print(&g2,buf)); if(hikaku(&g1,&g2)==1) printf("一部の単語は一致する\n"); } //二つの文字列を比較し、一部一致するかどうかの判定 int hikaku(Gainen *g1, Gainen *g2){ int n,i; if(g1->num != g2->num){ if(g1->num >= g2->num) n = g2->num; else n = g1->num; printf("n:%d\n",n); for(i=n;i>0;i--){ printf("inside loop i:%d\n",i); if(g1->particle[n] != g2->particle[n]) return 0; else if(strcmp(g1->basic_gainen[n],g2->basic_gainen[n]) != 0 ) return 0; } } return 1; } divide関数を省略させて頂きます。 hikaku関数のところで、二つの文字列の助詞と名詞が一致しなかったら0を返すその以外は1と返すというふうにしたいですが、実行したらhikaku関数から0の値wが返された。ループの数を表示したら、上のやり方でループがまわらないというのはわかったんです。上の条件判断はいけないですか?ご教授よろしくお願いします。

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

  • ベストアンサー
  • php504
  • ベストアンサー率42% (926/2160)
回答No.8

divide関数ですが void divide(Gainen *gainen,char* str){ int i,k,count,particle; k = 0; particle = 0; count = 1; for(i=0;i<strlen(str);i++){ if(str[i] == '_'){ count++; } } gainen->num = count; i = 0; while(str[i]){ i++; if(str[i] == '_'){ --count; strncpy(gainen->basic_gainen[count], &str[k], i-k); gainen->basic_gainen[count][i-k]=0; k = i + 1; particle = get_jyoshi(gainen->basic_gainen[count]); gainen->particle[count] = particle; } } if(count == 1){ strncpy(gainen->basic_gainen[0],&str[k],i-k); gainen->basic_gainen[0][i-k]=0; particle = get_jyoshi(gainen->basic_gainen[0]); gainen->particle[0] = particle; } } こうすれば g1->particleに 0,1,0,1,0 g1->basic_gainenに "船" "の" "大型" "の" "外国" が代入されますがこういう仕様のほうがわかりやすいのでは

g_loyd
質問者

お礼

ありがとうございます。確かにこのやりかたの方が解りやすいですが。自分がやったのはbasic_gainenに助詞に当たる部分、この例では"の"、を除いて、名詞だけ格納するようにしてました。でもphp504が言ったとおり別々にすると先の初期化の問題が出てしまって、処理が難しくなりますね。 どうもありがとうございます。 参考になりますm(_ _)m

その他の回答 (8)

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.9

#4 で「意味がわからん」と書いたのは, つまるところ「num が数えているものと basic_gainen に入れているものくいちがっているんだけど, どっちが正しいのかがわからん」ってことがあるわけで. つまり, 現状だと num は「単語の数」を表すように見えるんだけど, basic_gainen に入っているのは「単語」じゃないのでおかしい. 一方, basic_gainen に入っているのは「文節」と考えられるんだけど, そうすると num には「文節」の数を入れなきゃならない. だから, 今のプログラムをそのまま使うなら num の値を修正しないとダメ. あるいは, #8 のように単語ごとに入れるという手もある. どっちにするかは「このあとどのような処理を想定しているか」によります. もちろん「なぜ basic_gainen に逆順に入っているのか」という疑問は残る. 逆順にする理由は全くわかりません.

  • 6yemon
  • ベストアンサー率69% (25/36)
回答No.7

char str1[256] = "外国_の_大型_の_船"; char str2[256] = "大型_の_船"; divide(&g1, str1); //文字列の中から助詞と名詞を取得 divide(&g2, str2); //文字列の中から助詞と名詞を取得 ということは、devide()によってstr1, str2が処理され、その結果がg1, g2にセットされたのでしょう。どのような値がg1, g2にセットされたのか、わかっていますか。 "外国…"と"大型…"という、異なるデータを処理したなら、g1とg2に異なる結果が格納されたであろう、と推測できますから、むしろhikaku()が「一致しない」という意味の0を返すほうが自然に思えますけど。 結局、devide()が処理した結果(途中経過)が分からないことには、hikaku()の処理が適切かどうかということも判断のしようがありません。 まずは、devide()の仕様を確認するとか、g1, g2 にどんな内容がセットされたのか表示してみる、といったことが先決ではないでしょうか。

  • titokani
  • ベストアンサー率19% (341/1726)
回答No.6

>これでも、まだ返す値が0です。1が帰ってほしかったのに。=_=" とにかく、printfで動作中の各値を確認しましょう。デバッグの基本です。

g_loyd
質問者

補足

そうでしたね。m(_ _)m printfで動作確認したら、以下のようになります。 これならやっぱり値が0になってますね。^_^;; gainen:外国_の_大型_の_船 gainen:大型_の_船 n:2 ループ内 i:2 比較するもの : gainen1[2]:外国,jyoshi1[2]:1 gainen2[2]:55.0.2.ELsmp,jyoshi2[2]:2727536 助詞一致しない

  • php504
  • ベストアンサー率42% (926/2160)
回答No.5

g1->num や g2->numポインタです。g1 や g2 が持つnumというメンバーを指します。 そういうのはここの回答者であれば見ればわかります(g1は構造体のポインタですがnumは整数なのもわかります)) そういうことを聞いているのではなく g1->numは"外国_の_大型_の_船"の文節の数('_'の数+1)を現します とか言うことが知りたいのですよ "外国_の_大型_の_船"の例だと g1->particle[ ]は0-1しか値が代入されてないし g1->basic_gainen[ ]は0-2しか値が入らないと思いますよ 残りは初期化してないので不定な値が入っています g1->numは5なのでg1->particle[4]とかを見ても意味がないです

g_loyd
質問者

補足

そうでしたか?質問の意味伝わらなくてすみませんでした。m(_ _)m どうやって初期化するんですか?

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.4

気になるところ: ・g1, g2 が初期化されていない. ・g1->num や g2->num の意味が分からん. ・(それと関連するけど) divide の仕様が理解不能.

g_loyd
質問者

お礼

後、追加ですが、g1->num や g2->numポインタです。g1 や g2 が持つnumというメンバーを指します。 ポインタと構造体わかる方お願いします。

g_loyd
質問者

補足

一応構造体やってますのでg1,g2はインスタンス化してますので、初期化は関係ないと思います。 ご意見ありあがとうございます。

  • titokani
  • ベストアンサー率19% (341/1726)
回答No.3

>if(g1->particle[i] != g2->particle[i]) この場合のiはnから始まりますよね。 nの値は、 > n = g2->num; もしくは > n = g1->num; ですから、範囲外ではないでしょうか? ついでに > for(i=n;i>0;i--){ ですから、添え字が0のの要素も比較されませんね。 for(i=n-1;i>=0;i--){ だと、どうでしょう。

g_loyd
質問者

補足

なんてごちゃごちゃなコード載せてしまった。ー。ー;;すみませんでした。 訂正すると int hikaku(Gainen *g1, Gainen *g2){ int n,i,count; count = 0; if(g1->num != g2->num){ if(g1->num >= g2->num) n = g2->num; else n = g1->num; for(i=0;i<n;i++){ if(g1->particle[i] != g2->particle[i]){ return 0; } else if(strcmp(g1->basic_gainen[i],g2->basic_gainen[i]) != 0 ) return 0; } } return 1; } これでも、まだ返す値が0です。1が帰ってほしかったのに。=_="

回答No.2

 forループそのものは問題ないように見えます。  普通は先頭から比較するものですが、趣味の問題ですから。  プログラマが何をしたいかよく分からんですが以下の行の [n]は[i]ではないのかな。? if(g1->particle[n] != g2->particle[n])

g_loyd
質問者

補足

すみません、そうでしたね。 if(g1->particle[i] != g2->particle[i]) ありがとうござあいます。 でもまだうまく実行できないです。 何をやりたいか。。伝わってないか~~ 説明が下手ですみません-.-;;

  • asuncion
  • ベストアンサー率33% (2126/6286)
回答No.1

省略したdivide関数が肝心だと思います。 構造体の各メンバーにどういう風にどんな値をセットしているか、 提示のコードではわかりません。

g_loyd
質問者

補足

すみません。divideは以下のようになります。よろしくお願いします char* divide(Gainen *gainen,char* str){ int i,j,k,pnum,gnum; int count,particle; char buf[256],buf2[256]; k = pnum = gnum = 0; count = 1; particle = 0; for(i=0;i<strlen(str);i++){ if(str[i] == '_'){ count++; } } gainen->num = count; gnum = count/2; pnum = count/2 - 1; i = 0; while(str[i]){ i++; if(str[i] == '_'){ --count; strncpy(buf,&str[k],i-k); buf[i-k] = 0; particle = get_jyoshi(buf); if(particle){ gainen->particle[pnum] = particle; pnum--; k = i + 1; } else{ strncpy(&gainen->basic_gainen[gnum],&str[k],i-k); gainen->basic_gainen[gnum][i-k]=0; k = i + 1; gnum--; } } } if(count == 1){ while(str[i]) i++; strncpy(&gainen->basic_gainen[gnum],&str[k],i-k); gainen->basic_gainen[gnum][i-k]=0; } return 1; } int get_jyoshi(char* name){ if(strcmp(name,"の")==0) { return 1; } else{ return 0; } }

関連するQ&A

  • (C言語)関数の中で文字列比較できない。

    全体のソースコード省略させていただきます。 問題のある点だけあげたいと思います。 あるstr型:"初恋の人からの手紙" その文字列から助詞にあたるものを取得したいとする。 Phrase p_load(Phrase *p, char *str){ ....「省略」 str->particle[n] = get_jyoshi(js);//助詞番号取得 1。 printf("助詞:%d,jyoshi:%d\n", str->particle[n],get_jyoshi(js)); ===>>>get_jyoshiの関数はこんな感じです。 int get_jyoshi(char* js){ int num; if(strcmp(js,"の")==0){ return num = 1;} if(strcmp(js,"からの")==0){ return num = 2;} .......「省略」 else return 0; } 1。と書いてあるところに助詞の番号を表示しようとしたら助詞番号は"0"、つまりget_jyoshiの関数で文字列比較するときに失敗ということですね。。余談ですが、作ってるソースコードけっこう大きめですいくつかの再利用ソースコードと依存してます。そのため、試しで助詞番号を取得するための簡単な単体プログラムを作りました。そしたら、うまく行きましたが。問題はなんなんでしょうか?さっぱりわからないです。ご教授よろしくお願いします。

  • 関数化

    #include <ctype.h> #include <string.h> #include <stdlib.h> void swap(char p[], char q[]); char *get(char *str, char buf[], int line, int field); typedef struct { int number; char *class_type; char* name; char *subject; } my; my *data; int main(int argc, char* argv[]) { FILE *fp; int field = 0, line = 0; char buf[1000], *str; char *bufG; int line2 = 0; if((fp=fopen("test3.csv","r"))==NULL){ printf("ファイルが開けません"); } while(fgets(buf, 1000, fp) != NULL){ line2++; } fclose(fp); printf("%d\n", line2); if((fp=fopen("test3.csv","r"))==NULL){ printf("ファイルが開けません"); } data = (my *)malloc(sizeof(my) * line2); while(fgets(buf,1000,fp) != NULL){ str = buf; while(*str != '\0'){ bufG = get(str, buf, line, field); switch(field){ case 0: data[line].number = atoi(bufG); break; case 1: data[line].class_type = (char *)malloc(strlen(bufG) +1); strcpy(data[line].class_type, bufG); break; case 2: data[line].name = (char *)malloc(strlen(bufG) + 1); strcpy(data[line].name, bufG); break; case 3: data[line].subject =(char *)malloc(strlen(bufG) + 1); strcpy(data[line].subject, bufG); break; } str++; field++; } line++; field = 0; } fclose(fp);     for(int m = 1; m < line; m++){ printf("%d\n", data[m].number); printf("%s\n", data[m].class_type); printf("%s\n", data[m].name); printf("%s\n", data[m].subject);     } return 0; } char *get(char *str, char buf[], int line, int field) { char bufG[1111]; int i; for(i = 0; *str != ',' && *str != '\0' ; i++){ if(*str == '\n'){ bufG[i] = '\0'; } else{ bufG[i] = *str; } str++; } bufG[i] = '\0'; return bufG; } 前回の質問 http://okwave.jp/qa5094929.html で提示していただいたサンプルの関数化をはかりましたが うまくいきません。これを実行すると1しか表示されません。 原因はおそらくポインタだと思いますがどうすればいいのか わかりません。教えて下さい。bufを引数にする意味ないのでは という意見は今の所はとりあえずなしで fieldの値によってbufGが色々とってくる。 例えば1,A,山田,数学の場合 field = 0のときbufGは1 filed=1のときbufGはA field=2のときbufGは山田 filed=3のときbufGは数学という ような値が返ってくるようにしたいです。

  • 一番大きい奇数を表示する

    scanf関数を使って数字を10回入力して一番大きなものを表示させるプログラムをつくったのですが、 さらに一番大きな奇数を表示するにはどうすればいいのでしょうか? 偶数=割り切れる 奇数=割り切れない というところまでは分かるのですが、以下のプログラムに奇数を判別するソースを追加するのにはどうすればいいのでしょうか。 #include <stdio.h> int main(void) { char str[1024]; char buf[10]; int i; int w; printf("文字列を10回入力して下さい:\n"); memset(str, 0, sizeof(str)); for (i = 0; i < 10; i++) { memset(buf, 0, sizeof(buf)); printf("input>\n"); scanf("%s", buf); } for (i = 0; i < 10; i++) { if ((buf[i] & 1) == 1) /* 奇数であるか */ { if (strcmp(buf, str) > 0) { strcpy(str, buf); } } } printf("output>\n%s\n" , str); getchar(); }

  • 一番大きい奇数を表示する

    scanf関数を使用して、文字列を10回入力し一番大きい文字列を表示するプログラムを作ったのですが、 一番大きい「奇数」を表示するように条件を加えた場合どうすればよいのでしょうか? 偶数=割り切れる 奇数=割り切れない ということまでは分かるのですがその先が分かりません。 一応一番大きい文字列を表示するプログラムを貼っておきます。 #include <stdio.h> int main(void) { char str[1024]; char buf[10]; int i; printf("文字列を10回入力して下さい:\n"); memset(str, 0, sizeof(str)); for (i = 0; i < 10; i++) { memset(buf, 0, sizeof(buf)); printf("input>\n"); scanf("%s", buf); } if (strcmp(buf, str) > 0) { strcpy(str, buf); } printf("output>\n%s\n" , str); getchar(); }

  • またまたテストの復習なんですが・・・

    処理内容 基数、および変換対象数値(10進数)を入力させ、それに応じた基数変換を行う。その結果を画面に出力する。 ソースプログラム #include<stdio.h> #define MAX_OUT (16) int InputNum(int, int); char ChangeNum(int); /* メイン処理 */ main(){ int i; /* カウンタ */ int num; /* 対象数値 */ int num_base /* 基数 */ int num_next, num_out; char str[MAX_OUT]; /* 変換後文字格納用 */ while (1){ printf("基数を入力してください(2~32)\n"); printf("(2~32以外の入力で終了)\n"); num_base=InputNum(2,32); if (-1==num_base) { break; } printf("対象の数値を入力してください(0~65535)\n"); printf("(0~65535以外の入力で終了)\n"); num=InputNum(0,65535); if (-1==num) { break; } /* 変換開始 */ ( 1 ) for (i=0; i<MAX_OUT; i++){ /* 変換終了か判定する */ if (num_base>num_next){ /* 変換後文字の格納 */ str[i++]=ChangeNum(num_next); break; } /* 数値文字を抽出 */ num_out=( 2 ) str[i]=ChangeNum(num_out); /* 次の行へ */ num_next=( 3 ) } /* 変換結果を出力 */ printf("対象数値%dの%d進数表現は\n",num, num_base); for (i -= 1; 0<=i; i--) { printf("%c", str[i]); } printf("\nです\n"); } printf("終了します\n"); } /* 数値入力処理 */ int InputNum(int min, int max){ int ret; scanf("%d", &ret); if ((min>ret) || (max<ret)){ ret=-1; } return ret; } /* 数値を文字に変換 */ char ChargeNum(int num){ char ret=0; if (10>num){ ret=num+'0'; } else{ ret=( 4 )+'A'; } return ret; } という問題なんですが、(1)~(4)の答えと説明をどなたかして頂けないでしょうか?どうぞよろしくお願いします!ちなみにwhile(1)は無限ループです。

  • atoi関数の自作

    C言語でatoi関数を自作したのですが、正確な答えが出てきません 以下にソースを貼るのでどの当たりを直したらよいのかご教授願います。 1~9までの文字列を一つずつ配列に格納して変換する事を目的として作っています。 実行すると桁あふれしたような値が出てきてしまいます #include<stdio.h> #include<stdlib.h> int pow_10(int m) { int i,prod=1; for(i=0;i<m;i++){ prod=prod*10; } return prod; } ascii2int(char number[]){ int i,j,n[10],num; if(!strcmp(number,"")){ printf("Null string\n"); exit(1); } i=0; while(n[i]!='\0'){ n[i]=n[i]-48; i++; } num=0; for(j=0;j<i;j++){ num=num+n[j]*pow_10(i-1-j); } return num; } main(){ char su[10]; for(;;){ printf("Enter an integar:"); gets(su); if(!strcmp("x",su)){ break; } printf("%d\n",ascii2int(su)); } }

  • C言語でファイルの内容を strtok関数 を使って数字と文字を分けて

    C言語でファイルの内容を strtok関数 を使って数字と文字を分けて配列に格納したいのですが、うまくできません。 どこが駄目なのかご指摘をお願いします! ファイル内容 20 田中 10 鈴木 #include <stdio.h> #include <string.h> #include <stdlib.h> int main(int argc,char *argv[]) { FILE *fp; char str[256]; char *tp; int i=0; int num[10]; char na[10]; fp=fopen(argv[1],"r"); while(fgets(str,sizeof str,fp)!=NULL); tp = strtok ( str, " " ); while(tp != NULL ) { num[i]=atoi(tp); tp = strtok( NULL," "); if ( tp != NULL ){ na[i]=*tp; } i++; } printf("%d\n%s",num[0],na[0]); printf("%d\n%s",num[1],na[1]); fclose(fp); return 0; }

  • ループ

    #include<stdio.h> int main(void) { int i=1,sum=0; int num=1; while(num>0) { printf("整数を入力してください。(マイナスの値で終了)\n"); scanf("%d",&num); printf("%dが入力されました。(%d番目の繰り返しです)\n",num,i); sum+=i; printf("1から%dまでをたすと%dです。\n",i,sum); i++; } printf("繰り返しが終わりました。\n"); printf("加算値は%dです。\n",sum); printf("%d回繰り返しました。\n",i); return 0; } このプログラムで101以上の数値は加算しないようにするにはどうすればいいですか。

  • プログラム問題(3)

    以下の問題のプログラムをやったのですが、コマンドプロンプトで実行してみるとエラーになってしまうのですが、どなたか問題点を指摘していただけないでしょうか? 【問題】 3桁の整数の値を入力していき、-9999が入力されたところで、それまでに入力された数の個数と合計を整数で、平均を浮動小数点数で出力するプログラム。 【プログラム】 #include <stdio.h> #include <stdlib.h> #include <string.h> #define streq(a, b) !strcmp((a), (b)) int main(int argc, char *argv[]) { int i, num, sum = 0; double avg; char buf[256]; char *endptr; for (i = 0;; i++) { printf("INPUT>"); if (fgets(buf, sizeof buf, stdin) == NULL) { perror("fgets"); exit(1); } if (streq(buf, "-9999") || streq(buf, "-9999\n")) { break; } if (streq(buf, "") || streq(buf, "\n")) { fprintf(stderr, "数値を入力してください。\n"); exit(1); } num = (int) strtol(buf, &endptr, 0); if (! (*endptr == '\n' || *endptr == '\0')) { fprintf(stderr, "数値を入力してください。\n"); exit(1); } sum += num; } printf("入力数:%d 合計:%d 平均:%g\n", i, sum, (double) sum / i); return 0; }

  • C言語の、ポインターの問題を教えて下さい

    C言語の、ポインターを使って大文字と小文字を入れ替えるプログラムを教えて下さい。 作ったのですが、うまくいかず困っています。 分かる方、訂正してください。 よろしくお願いいたします。 #include<stdio.h> void reverse(char *str) { int i; for(i=0;str[i]!='\0';i++) { if(str[i]>=0x61) {str[i]-0x20;} if(0x40<str[i]<0x5B) {str[i]+0x20;} } return(str); } int main(void) { int num; char *str="AddsssEEEEwwwJojoHoih"; printf("Before reverse %s \n",str) str=reverse(str); printf("After reverse %s \n",str); return 0; }

専門家に質問してみよう