• ベストアンサー

reallocでうまくメモリを拡張出来ていない?気がしますが・・・

OS:WindowsXP SP3 コンパイラ:Visual C++ 2008Express Edition with Service Pack 1 質問なんですが、 ttp://homepage3.nifty.com/mmgames/c_guide/ ↑こちらの練習問題19の3-1なんですが、4人以上のデータを入力して showdata関数で表示させると4人目からのデータが入力したデータと 違います。 (reallocのところが間違っているような気がするのですが?です) どなたかアドバイスお願いします。 他の問題点も良ければアドバイス頂けると幸いです。 *******************以下自分で書いたソース******************** #include <stdio.h> #include <stdlib.h> //構造体 typedef struct { char name[64]; int age; int sex; } stat; //プロトタイプ宣言 int status(stat * ,int *); void showdata(stat *, int); int main() { int cnt, max = 3; //構造体ポインタの宣言 stat *data; //動的配列の宣言 data = (stat *)malloc(sizeof(stat) * max); if ( data == NULL ) { exit(0); } //入力用関数の呼び出し cnt = status(data, &max); //出力用関数の呼び出し showdata(data, cnt); //メモリの開放 free(data); return 0; } int status(stat *data, int *max) { int i = 0; //年齢に-1が入力されるまでループ do { if ( (i + 1) > (*max) ) { *max += 10; data = (stat *)realloc(data, sizeof(stat) * (*max) ); if ( data == NULL ) { exit(0); } } printf("名前入力:"); scanf("%63s", data[i].name); getchar(); fflush(stdin); printf("年齢入力(-1入力で入力終了):"); scanf("%d", &data[i].age); getchar(); //1か2でない場合再入力 do { printf("性別を入力(1.男性 2.女性) <1 or 2>:"); scanf("%d", &data[i].sex); getchar(); if ( (data[i].sex < 1) || (data[i].sex > 2) ) { data[i].sex = 3; printf("1か2で入力してください\n"); } } while ( (data[i].sex) == 3 ); i++; } while ( (data[i-1].age) != -1 ); return i - 1; } void showdata(stat *data, int cnt) { int i; for ( i = 0; i < cnt; i++ ) { printf("\n%d人目のデータ\n", i + 1); printf("名前:%s\n", data[i].name); printf("年齢:%d\n", data[i].age); if ( data[i].sex == 1 ) { printf("性別:男性\n"); } else { printf("性別:女性\n"); } } return; }

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

  • ベストアンサー
  • S117
  • ベストアンサー率40% (18/45)
回答No.8

とりあえず理解を助けるためにアドバイス。 ポインタとは、 「"値"が格納された場所を示すための"値"」 です。 これは、ポインタが場所を示すものであるということのほかに、ポインタ自身が値に過ぎないことを示します。すなわち、ポインタがポインタを指すことができます。 int func(int a*) { *a = 10; } int main(void) { int a = 0; func(&a); printf("%d", a); //10 } このコードは読めますよね? 重要なのは、書き換えたい変数の型と、関数に渡す型の関係です。 int型の変数を書き換えたいのでint*型の値を渡しています。 一般化すれば、 「T型の変数を呼び出し先の関数で書き換えたいとき、渡すべき値はT*型となる。」 ということになります。 そして今回はTがstat*なので、渡すべき型はstat**なのです。 どういうポインタを使えばいいのか悩む必要はありません。型をみればすぐにわかります。

phenom
質問者

お礼

こちらで質問してから何度か挫折しそうになりましたが みなさんのおかげで解決することが出来ました。 ありがとうございました。 これからも質問することがあると思うのでまたよろしくお願いします。 (ここに出来上がったソースを貼り付けようとしたんですが、文字数が多い!と怒られました。)

phenom
質問者

補足

ありがとうございます。 >int func(int a*) { >*a = 10; >} >int main(void) { >int a = 0; >func(&a); >printf("%d", a); //10 >} >このコードは読めますよね? 大体分かるんですがint func(int a*)が分かりません。 a*というやり方は初めて見ました。それとなぜvoidでなくintなのかも 分かりません・・・。 >重要なのは、書き換えたい変数の型と、関数に渡す型の関係です。 >int型の変数を書き換えたいのでint*型の値を渡しています。 >一般化すれば、 >「T型の変数を呼び出し先の関数で書き換えたいとき、渡すべき値はT*型となる。」 >ということになります。 >そして今回はTがstat*なので、渡すべき型はstat**なのです。 >どういうポインタを使えばいいのか悩む必要はありません。型をみればすぐにわかります。 すごく分かりやすく説明してくれていて大変参考になりました。 ありがとうございます。

その他の回答 (8)

  • S117
  • ベストアンサー率40% (18/45)
回答No.9

#8 >大体分かるんですがint func(int a*)が分かりません。 すみません、そこはただの書き間違えです。 int *a で、読んでください。 混乱させて申し訳ありません。

phenom
質問者

お礼

>すみません、そこはただの書き間違えです。 >int *a >で、読んでください。 >混乱させて申し訳ありません。 そうだったんですね、こちらこそ失礼しました。 最後まで付き合って頂いてありがとうございました!

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

>自分ではcnt = status(data, &max);のdataは配列dataの先頭アドレス"のつもり"で引数にしていました。 そのdataの値を、status関数の中でrealloc関数を使って書き換えていますね。 ということは、呼び出し元からstatus関数を呼び出す際、 dataのアドレス、つまり&dataを引数として渡さねばなりません。 今、dataはstat *型ですので、引数として渡すのはstat **型となります。

phenom
質問者

補足

ありがとうございます。 仮引数がポインタのポインタになっているから、実引数は&data(箱のアドレスを持っているポインタ自身のアドレス:うまく表現出来てないかもしれま せんが頭の中では理解出来ました)になるということですね。 あと、入力のところで悩んでたんですが色々調べて scanf("%d", &(*data)[i].age) という風にしたらうまく実行出来るようになりました。

  • chie65535
  • ベストアンサー率43% (8508/19344)
回答No.6

>status()内でrealloc()が成功したとしてもアドレスが変わっている為に >問題が出ているということでしょうか? >main()内でrealloc()を使うようにするしかないですか? 貴方、自分で >//入力用関数の呼び出し >cnt = status(data, &max); って呼んでおいて >int status(stat *data, int *max) >{ >(略) >if ( (i + 1) > (*max) ) { >*max += 10; ってやってるよね? これって「mainで定義されてるmaxを、statusの中で書き替えてる」んじゃないの? だったら >status()内でrealloc()が成功したとしてもアドレスが変わっている為に >問題が出ているということでしょうか? >main()内でrealloc()を使うようにするしかないですか? って悩むのはおかしいよね? 「maxをstatusの中で書き替えてるのと同じ方法で、dataもstatusの中で書き替えれる」よね? それが理解できてないのに「誰かが書いたコードを鵜呑みにして、理解せずに使う」から、こういう事になる。 「本当に理解して書いてるなら、ここで質問する筈がない」と思うんだけど、どうだろう? >stat **にしたのですがコンパイルでエラーになり、調べてみたら >stat **がポインタのポインタらしい事はわかったのですが・・・ >色々試してみてもうまくいきませんでした statusを呼ぶ時に、maxの中身をstatusの中で書き替えてもらうから >cnt = status(data, &max); って感じで「maxに&を付けてる」でしょ? だったら、何でdataの方にも&を付けないの? 「何の為にポインタ渡しをしているか?」が理解できない限り、質問文にあるプログラムは「貴方にとって、まだ高度過ぎて、今、手を付けるべきじゃない」ので、そこを勉強し直してから出直した方が良いですよ。

phenom
質問者

補足

すみません、自分ではcnt = status(data, &max);のdataは配列dataの 先頭アドレス"のつもり"で引数にしていました。 なのでdataには&を付けませんでした。 **(ポインタのポインタ)はここで初めて目にしたので、 未だになぜ**じゃないとダメなのかもわかりません。 まだ勉強始めたばかりで知らないことのほうが多い為、 >status()内でrealloc()が成功したとしてもアドレスが変わっている為に >問題が出ているということでしょうか? >main()内でrealloc()を使うようにするしかないですか? こういう疑問も沸いてきました。 上級者の方から見るとトンでもない事言ってるんでしょうね・・・。 すみませんでした。

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

status を呼び出す方も修正しておいてね. あとついで: Visual Studio では fflush(stdin); とできますが, ほかの処理系でも使えるとは思わないでください.

phenom
質問者

補足

ありがとうございます。 呼び出しのほうは、 cnt = status(&data, &max); としてみました。 2回目の名前入力でエラーが出るようになりましたが 今、どこがダメなのか探してる途中です。 fflush(stdin)はそのままにしてありますが参考になりました。

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

int status(stat **data, int *max) if ( ( data2 = (stat *)realloc(*data, sizeof(stat) * (*max) ) ) != 0 ) { *data = data2; } else { free(*data); *data = NULL; exit(0); }

phenom
質問者

補足

ありがとうございます。 回答通りにしてint status()関数内のdata.xxxの.を->に変えて やってみましたが、今度は2回目の名前入力が終わったところで エラーが出るようになってしまいました。 もう少し頑張ってみます。

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

関数 status の第1引数を stat ** にすれば問題は 1つ解決. あと, realloc を使うときには if ((tmp = realloc(p, ....)) != 0) { p = tmp; } else { /* 確保失敗 */ } とやるのが鉄則. こうすれば realloc に失敗しても最低限なんとかなります.

phenom
質問者

補足

>関数 status の第1引数を stat ** にすれば問題は 1つ解決 stat **にしたのですがコンパイルでエラーになり、調べてみたら stat **がポインタのポインタらしい事はわかったのですが・・・ 色々試してみてもうまくいきませんでした >if ((tmp = realloc(p, ....)) != 0) { >p = tmp; >} else { >/* 確保失敗 */ >} こちらはなんとかなりました ありがとうございます if ( ( data2 = (stat *)realloc(data, sizeof(stat) * (*max) ) ) != 0 ) { data = data2; } else { free(data); exit(0); } としました よろしければstat **についてもう少しヒントをいただけませんか?

  • Wr5
  • ベストアンサー率53% (2177/4070)
回答No.2

もう1つ忘れていました。 status()内でrealloc()が成功した場合、呼び出し元のmain()のローカル変数dataが指している先のメモリブロックは解放済みということになりますので、 その後のアクセス(showdata()内での参照)で吹っ飛ぶ場合があります。 # 環境依存…てすが。

phenom
質問者

補足

レスありがとうございます。 status()内でrealloc()が成功したとしてもアドレスが変わっている為に 問題が出ているということでしょうか? main()内でrealloc()を使うようにするしかないですか? さらに混乱してきました・・・。 ># 失敗した(拡張できなかった)ときに元のメモリがリークします。 こちらは今の僕の知識では解決出来ない気がしますが、 どうすれば解決するのでしょうか? お手数ですがお願いします。

  • Wr5
  • ベストアンサー率53% (2177/4070)
回答No.1

main()関数内の >//構造体ポインタの宣言 >stat *data; と、 status()関数の引数で受けているdataは別のモノですが、その辺りは理解されています? 関数内のローカル変数を書き換えても、呼び出し元に影響を与えることはできませんが。 # ついでに…realloc()の使い方に問題があります。 # 失敗した(拡張できなかった)ときに元のメモリがリークします。 # 今回の場合はプログラム終了しているので影響はほとんど無いでしょうが。

関連するQ&A

  • 配列の和を求めるプログラム

    キーから入力したデータを配列に入力した後、その和を求めるプログラムを作成したいのですが、プログラミング初心者の私にはさっぱりわかりません。 和を求めたいのに平均値が出てきてしまいます。 どこが間違っているのか教えてください。 #include <stdio.h> float data[5]; float total(int max); void main(void) { int cnt = 0; float d; printf("please input a data: "); scanf("%f", &d); while((cnt < 5) && (d > 0.0)) { data[cnt] = d; cnt++; printf("please input a data: "); scanf("%f", &d); } printf("total data: %5.2f\n", total(cnt)); } float total(int max) { int i; float total = 0.0; for(i = 0; i < max; i++) { total += data[i]; } return total / max; }

  • reallocとstrtokの併用について

    fscanfで文字列を読み込み、strtokでカンマ区切りにするという関数を作りたいのですが、 reallocすると先頭から徐々にデータが文字化けしていきます。 まず最初に4つ分のchar*を取ります。 もし、5つ目が見つかったらさらに4つ増やし、9つ目が見つかったらさらに。。。というようになっております。 n個目の判定はcntがn-1で真になり、reallocが成功したら個数を増やすようになってます。 5つ目が見つかった時点では出力に問題は無いのですが、6個目から侵食が始まっていきます。 原因がどうしても自分では分からなかったので、誰かお願い致します。 words.txtの内容(末尾改行なし) iii,jjj,kkkkkkkkk,l,m,n,ooooo,pppppppp,a,s,d,f,g main.c #include<stdio.h> #include<stdlib.h> #include<string.h> #include"C:\borland\bcc55\Include\malloc.h" int readlinefile(FILE *fp,char **words){ int cnt=0,len; char *line=(char *)malloc(256); char *tmp; if(line==NULL) return 0; if(fscanf(fp,"%s",line)!=EOF){ if((tmp=(char *)realloc(line,sizeof(char)*(strlen(line)+1)))==NULL){//できるだけメモリを節約してみる return 0; }else{ line=tmp; } len=strlen(line); printf("line:%d:%d:%s\n",len,_msize(line),line); if(len>1){//ファイル終端の改行を排除 int i; char *tok=strtok(line,",");//カンマで区切ったアドレスを得る while(tok){ if(cnt==0)printf("tok:1st:%x\n",tok); if(cnt>3&&cnt%4==0){//サイズが足りなくなった時 char **tmp2; if((tmp2=(char **)realloc(words,sizeof(char *)*(4+4*(cnt%4))))==NULL){ printf("words realloc ERROR\n"); break; }else{ printf("realloc\n"); words=tmp2;//reallocを適用 } } words[cnt]=tok; if(cnt){ printf("line(func)"); for(i=0;i<len+1;i++){ printf("%c",words[0][i]); } printf("\n"); } tok=strtok(NULL,","); printf("words[%d]:%x:%s\n",cnt,words[cnt],words[cnt]); printf("\n"); printf("tok:%d回目:%x\n",cnt+1,tok); cnt++; } return cnt;//正常終了した }else{ free(line); } } return 0; } int main(){ FILE *fp=fopen("words.txt","r"); if(fp){ int cnt=1; while(cnt){ int i; char **words=(char **)malloc(sizeof(char *)*4); words[0]=NULL; cnt=readlinefile(fp,words); printf("mainに戻りました\n"); if(cnt) printf("words:%d\n",cnt); for(i=0;i<cnt;i++){ printf("words[%d]:%x:%s\n",i,words[i],words[i]); } free(words[0]); words[0]=NULL; printf("\n"); free(words); } }else{ printf("file open ERROR\n"); } return 0; } 実行結果 なぜかコピペできないので実行するか斧でダウンロードお願いします。 http://www1.axfc.net/u/3352789.txt 全てまとめたもの http://www1.axfc.net/u/3352796.zip

  • C言語

    はじめまして。 C言語を学習しております。 参考書の練習問題19(下記)で以下の部分がどうしても理解できません。 1、【(People*)mallock】の部分で、mallockの前のPeopleを()でくくる意味とPeopleの後に*を付ける意 味がわかりません。 2、InputPeople関数とShowPeople関数の最後の部分(●の印をしている部分)になぜretutn 0がいらないのでしょうか(原文にはretutn 0の記述がありません)。 3、【while (1)】の部分で、while文の使い方は、「while(条件式){ 繰り返す文;}」のはずですが、なぜ条件式の部分が1なのでしょうか(a > bなどの形ではないのでしょうか)。 4、【while (1)】の部分で、InputPeople関数の引数としてdata[count]がありますが、何を意味しているのかがわかりません。People型の変数dataとint型の変数countを組み合わせてどういう意味合いになるのでしょうか。dataとcountはどういう関係でしょうか。 5、【while (1)】の部分で、count++する意味がわかりません。 6、【while (1)】文内の下記の記述が何を意味しているのかがわかりません。       if (count >= datasize) {       datasize += 10;       data = (People*)realloc(data,sizeof(People) * datasize);      } ここでつまづいて先に進めず困っております。 どうか教えていただきたく、お願い致します。 ●練習問題19 練習問題16(一番下に参考として解答を載せています)の、 「3人分の、名前、年齢、性別、を入力して表示するプログラムを作りなさい。 ただし、データは構造体で記憶することとし、 また、データの入力と表示はそれぞれ専用の関数を作って行うこととする。」 という問題を元に、何人分でも入力できるように改造しなさい。 なお、年齢に-1が入力されれば入力終了とする。 ※配列番号がint型なのでint型の最大値まで扱えれば良い。 ●練習問題19の解答 #include <stdio.h> #include <string.h> #include <stdlib.h> typedef struct { char name[256]; int age; int sex; } People; void InputPeople(People *data); void ShowPeople(People data); int main(void) { int i,count,datasize; People *data; datasize = 10; data = (People*)malloc(sizeof(People) * datasize); count = 0; while (1) { InputPeople(&data[count]); if (data[count].age == -1) break; count++; if (count >= datasize) { datasize += 10; data = (People*)realloc(data,sizeof(People) * datasize); } } for (i = 0;i < count;i++) { ShowPeople(data[i]); } free(data); return 0; } void InputPeople(People *data) { printf("名前:"); scanf("%s",data->name); printf("年齢:"); scanf("%d",&data->age); printf("性別(1-男性、2-女性):"); scanf("%d",&data->sex); printf("\n");     /*●retutn 0は不要?*/ } void ShowPeople(People data) { char sex[16]; printf("名前:%s\n",data.name); printf("年齢:%d\n",data.age); if (data.sex == 1) { strcpy(sex,"男性"); } else { strcpy(sex,"女性"); } printf("性別:%s\n",sex); printf("\n");     /*●retutn 0は不要?*/ } ●練習問題16の解答 #include <stdio.h> #include <string.h> typedef struct { char name[256]; int age; int sex; } People; void InputPeople(People *data); void ShowPeople(People data); int main(void) { People data[3]; int i; for (i = 0;i < 3;i++) { InputPeople(&data[i]); } for (i = 0;i < 3;i++) { ShowPeople(data[i]); } return 0; } void InputPeople(People *data) { printf("名前:"); scanf("%s",data->name); printf("年齢:"); scanf("%d",&data->age); printf("性別(1-男性、2-女性):"); scanf("%d",&data->sex); printf("\n"); } void ShowPeople(People data) { char sex[16]; printf("名前:%s\n",data.name); printf("年齢:%d\n",data.age); if (data.sex == 1) { strcpy(sex,"男性"); } else { strcpy(sex,"女性"); } printf("性別:%s\n",sex); printf("\n"); }

  • getchar()について 教えてください。

    visual studio 2010 professinalで以下のソースをデバッグして ”続行するには何かキーを押してください!”  で待機させたいのですが getchar()一個だけでは実現しません。   2個重ねるとOKです。どうしてでしょうか。  -------------- 以下のようにscanf関数がなければokということは突き止めたのですが、、、。  ご教授ください。 #include <stdio.h> int main(void) { int i; printf("なにか数字を入力してください。\n"); scanf("%d",&i); printf("今あなたが入力した数字は%dです。\n",i); printf("続行するには何かキーを押してください!"); getchar(); //getchar(); return 0; } ---------------------------------------------------------------- int main(void) { printf("続行するには何かキーを押してください!"); getchar();   return 0; }

  • ポインタエラー?

    コンパイルエラーで、つまづいてます 型が合ってないというのはわかるのですが どうしたらいいのかわかりません どこを改善すればいいでしょうか 問題とソースです↓ ソースは色々てを加えたので変なものが混じってます。 関数ichi()を作成し、プログラムを完成させよ。 main内部を変更してはならない。 (見つからない場合も考慮されている事に注意せよ。) #include <stdio.h> #define MAX 10 int *ichi(int *,int); int main() { int x[MAX], i, n, *p; for (i = 0; i < MAX; ++i) { scanf("%d", &x[i]); } scanf("%d", &n); p = ichi(x, n); if (p) { printf("%d ha %d ko me ni arimashita\n", n, p-x); } else { printf("%d ha arimasen desita\n", n); } return 0; } int *cnt; int * ichi(int *x,int n) { //int cnt; //cnt = 0; while(*x){ if(*x == n){ cnt = &n; //cnt = x; //return x; return cnt; } *x++; } return NULL; }

  • このプログラムの復元処理教えでください。助けてくだ

    #include <stdio.h> int main(void) { char a[51]; char b[101]; char c[51]; int i,k; int cnt; printf("文字例-->"); scanf("%s",a); i = 0; k = 0; while(a[i] !='\0') { cnt = 0; b[k] = a[i]; while(b[k] = a[i]) { cnt++; i++; } k++; b[k] = cnt + 48; k++; } b[k]='\0'; printf("b=%s\n",b); printf("c=%s\n",c); //-------------------------------------------------- getchar(); return 0; }

  • 下記のプログラムを実行したところ、不正な処理をしたので強制終了しましたとでました。何故でしょうか?

    #include <stdio.h> #include <stdlib.h> #include <float.h> int main( void ) { int val; int sum = 0; int max = -DBL_MAX; int cnt; char FileName[FILENAME_MAX]; FILE *fp; printf("入力ファイル名>>>"); scanf("%s", FileName ); if( (fp = fopen( FileName, "r" )) == NULL ) { printf("ファイルが見つかりません------%s\n",FileName ); exit( EXIT_FAILURE ); } for(cnt=0; ;cnt++) { fscanf(fp,"%d",&val); /*合計を求める*/ if(val == 0) { break; } sum += val; /*最大値を求める*/ if( max < val) { max = val; } } if( cnt > 0) { printf("平均は%g,最大値は%dです\n",(double)sum / cnt, max); } fclose( fp ); return EXIT_SUCCESS; } コンパイルはできるのですが実行すると このプログラムは不正な処理をしたので強制終了しますとでました 入力ファイル名>>>ってのも表示されません やはりこれは僕のパソコンがおかしいのでしょうか? 何か原因があるのなら教えてください

  • 素数判定の繰返し

    繰返し素数判定を行ない、CtrlーDで終了するプログラムをつくっています。 まず繰返しなしの素数判定プログラムを作り #include<stdio.h> int main(void) { int a,i; printf("自然数を入力:"); scanf("%d",&a); if(a<=0) printf("入力エラーです。\n"); else if(a==1) printf("1は素数ではない。\n"); else{ for(i=2; i*i<=a; i++){ if(a%i==0) break; } if(i*i>a) printf("%dは素数です。\n",a); else printf("%dは素数ではない。\n",a); } return(0); } これはちゃんとできたのですがそれを繰り返すことができません。 #include<stdio.h> int main(void) { int a,i; printf("自然数を入力:"); scanf("%d",&a); while((a=getchar())!=EOF){ if(a<=0) printf("入力エラーです。\n"); else if(a==1) printf("1は素数ではない。\n"); else{ for(i=2; i*i<=a; i++){ if(a%i==0) break; } if(i*i>a) printf("%dは素数です。\n",a); else printf("%dは素数ではない。\n",a); } printf("自然数を入力:"); scanf("%d",&a); } printf("プログラムを終了します。\n"); return(0); } これは訳わからないことになっちゃいます。。。 どうしたらいいんでしょうか??

  • このCのプログラムの修正と追加してくれませんか

    完成まで近いのですが、詰まっております このサイトでコンパイルなど出来ます http://ideone.com/ 以下の問題を解きました また問題文の指示には必ずしたがってください。また、この文章の条件でなく、人数が4人とかそれ以外の時でも出来るようなプログラムでお願いします。実行結果のとおりになるようお願いします http://i.imgur.com/nuzJv2v.png http://i.imgur.com/c7f3Vh2.png http://i.imgur.com/5aCqDO0.png http://i.imgur.com/9u8hHIM.png 問題は画像になっています、実行結果も含まれています #include<stdio.h> #include<string.h> /*構造体型struct Dataの宣言*/ struct Data{ char name[20]; int height; double weight; } data[100]; int cnt; int main(void) { int a; while(1) { printf("**************身長・体重の表示***************\n\n"); printf(" データファイルの読み込み・・・・・(1)\n"); printf(" 全てのデータを表示・・・・・・・・(2)\n"); printf(" 特定のデータを表示・・・・・・・・(3)\n"); printf(" 終わり・・・・・・・・・・・・・・(4)\n\n"); printf("処理番号を入力してください\n"); scanf("%d",&a); } if (a==1){ read_file(); } if (a==2){ p_all(); } if (a==3){} if(a==4){ break; } return a; } /*read_file関数の宣言*/ void read_file(void) { FILE *fp; char filename[20]; cnt=0; printf("読み込むファイルの名前を入力してください。\n"); scanf("%s",filename); fp=fopen(filename,"r"); if(fp==NULL){ printf("ファイルをオープンできませんでした。\n"); return 1; } while(fscanf(fp,"%c %d %lf",data[cnt].name,data[cnt].height,data[cnt].weight)!=EOF){ cnt++; fclose(fp); printf("ファイルを読み込みました。\n"); } return 0; } /*p_all関数の宣言*/ void p_all(void) { int i; printf("名前 身長(cm) 体重(kg)\n"); for(i=0;i<cnt;i++) { printf("%-2s %5d %.2f\n",data[i].name,data[i].height,data[i].weight); } } int main(void) { }

  • 数字文字をカウントするプログラムの動作について

    良い質問のタイトルが思い浮かばず、分かりづらいタイトルで申し訳ありません、C言語について質問させて頂きます。 C言語の参考書を買って夏休み中にプログラムの勉強をしているのですが、何故動作するのかがわからない例があります、ソースは以下の通りです。 #include <stdio.h> int main(void) { int i,ch; int cnt[10] = {0}; while(1) { ch = getchar(); if (ch==EOF) break; switch(ch) { case '0' : cnt[0]++;printf("%d\n",ch);break;/* printfは確認の為 */ case '1' : cnt[1]++;printf("%d\n",ch);break; case '2' : cnt[2]++;printf("%d\n",ch);break; case '3' : cnt[3]++;printf("%d\n",ch);break; case '4' : cnt[4]++;printf("%d\n",ch);break; case '5' : cnt[5]++;printf("%d\n",ch);break; case '6' : cnt[6]++;printf("%d\n",ch);break; case '7' : cnt[7]++;printf("%d\n",ch);break; case '8' : cnt[8]++;printf("%d\n",ch);break; case '9' : cnt[9]++;printf("%d\n",ch);break; } } puts("数字文字の出現回数"); for(i=0;i<10;i++) printf("'%d':%d\n",i,cnt[i]); getchar();getchar(); return(0); } といったプログラムです。 実行し、数値を入力、CTRL+Zで入力を終了し、出現回数を表示させる、という動作自体は無事にできるのですが、何故chの値が変更していくのかがわかりません、数値を入力した時点で51や49といったそれぞれ違う数値が表示されるのですが、chの値を変更させる命令を、何が引き起こしているのかが理解できません、3(51)と判定されて同じ数が無限にカウントされないのは何故なのでしょうか・・・・? また、その後の無限ループからの脱出をCTRL+Zがどうして引き起こすのかも理解できず困っています、教科書には「CTRL+Zは入力の終了を意味する」とあるのですが、これは一体どういう意味なのでしょうか、強制的に割り込んでEOFを代入するということなのでしょうか・・・? お時間がある時にでも、教えて頂けると助かります、よろしくお願いします。