C言語のプログラムの流れについて

このQ&Aのポイント
  • C言語のプログラムの流れを順番に教えてください。
  • 特にadd関数とinsert関数の中身の動きについてが分からないので教えていただきたいです。
  • リスト構造を用いて、read関数で読み込んだ単語をアルファベット順にソートしてリストのセルに入れ、同じ単語はまとめてその単語と個数を順に表示するプログラムです。
回答を見る
  • ベストアンサー

C言語のプログラムの流れについて

下に貼り付けたプログラムの流れを順番に教えて頂きたいです。 特にadd関数とinsert関数の中身の動きについてが分からないので教えていただきたいです。 (a,b,c,sentouなどの動きなど。) 参考にですが リスト構造を用いて、read関数で読み込んだ単語をアルファベット順にソートしてリストのセルに入れ、同じ単語はまとめてその単語と個数を順に表示するプログラムです。 1からの説明を要求して申し訳ありませんがよろしくお願いいたします。 #include<stdio.h> #include<stdlib.h> #include<string.h> #include<ctype.h> typedef struct moji{ char w[50]; int cnt; struct moji *next; }moji; int main(){ FILE *fp; char data[50]; moji *sentou; moji *p=NULL; if((sentou=(moji *)malloc(sizeof(moji)))==NULL){ printf("malloc error\n"); exit(1); } fp=fopen("tango.txt","r"); if((fp = fopen("tango.txt","r"))==NULL){ printf("can't open\n"); exit(1); } while(read(data,fp)){ add(data,sentou); } p=sentou->next; while(p != NULL){ printf("%s %d\n",p->w,p->cnt); free(p); p=p->next; } fclose(fp); return (0); } int read(char data[],FILE *fp){ /*1つの単語(連続したアルファベット)をdataに格納して、スペースで区切られたらそこで格納をやめ、値1を返す。再度単語を格納するときはdataを初期化し、再度1つの単語を取得する。ファイルの単語がなくなれば(EOFなら)0を返す関数read()*/ } void add(char data[],moji *sentou){ moji *a,*c; for(c=sentou;c!=NULL;c=c->next){ if(strcmp(c->w,data)==0){ c->cnt++; return; } if(strcmp(c->w,data)>0){ break; } else{ a=c; } } insert(a,c,data); } void insert(moji *a,moji *c,char data[]){ moji *b; if((b=(moji *)malloc(sizeof(moji)))==NULL){ printf("malloc error\n"); exit(1); } strcpy(b->w,data); b->cnt=1; a->next=b; b->next=c; }

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

  • ベストアンサー
回答No.3

No.2です。 aやcが何をしているか分からないということで、ポインタやアドレスを理解されてないのでしょうか? プログラム内で moji *a; のように宣言されているのがポインタです。 ポインタにはアドレスが入ります。 例えば構造体1のアドレスが1番地にあった場合、 a=構造体1のアドレスと置くことで変数aに1番地と言う物が入ります。 そして、このaを使用して構造体1にアクセスできるようになります。 このプログラムではmallocで構造体のメモリを確保して、a,b,c,sentouは構造体のアドレスを割り振ってアクセスしています。 下の説明では変数と構造体の関係が分かるように、変数(構造体名)でsentou(構造体:1)のように書きます。 ※構造体名は適当です。この場で勝手につけています。 また、大きな流れとして 1、読み込み。 2、addで今まで読み込んだものと比較、挿入箇所があれば3へ。 3、instertで挿入。 4、EOFで無ければ1に戻る、EOFであれば5へ。 5、表示 のように動いています。 これらを念頭においてみてください。 [book text book computer] がtxtに入力されているときの動きと言うことで。 最初に構造体1のメモリを確保します。 そして、sentouでアクセス出来るようにしています。 中身は恐らく[data,cnt,next]=["",0,NULL]のような形になっているはずです。 ここからループに入ります。 ・1週目 read "book"が読み込まれます。 ↓ add "book"とsentou(構造体:先)のアドレスが渡されます。 c=sentou(構造体:先)としているのでcは(構造体:先)を参照しています。 for文の中で、"book"と(構造体:先)の中の""が比較されます。 "book"の方が大きいのでa=c;としてa(構造体:先)となります。 そして、c=c->next;としています。c(構造体:先)のnextはNULLですので、次のループは行われません。 ループを抜けたらinsert関数に行きます。 insertに送るもの (a,c,data)=(構造体:先,構造体:先,"text") ↓ insert まず(構造体:1)のメモリが確保され、b(構造体:1)の状態になります。 そうしたら、a(構造体:先)の中身を["",0,(構造体:1)のアドレス]にします。 そして、b(構造体:1)の中身を["book",1,NULL]にします。 現在の構造体の中身 (構造体:先) ["",0,(構造体:1)のアドレス] (構造体:1)  ["book",1,NULL] ・2週目 read "text"が読み込まれます。 ↓ add "text"とsentou(構造体:先)のアドレスが渡されます。 c=sentou(構造体:先)としているのでcは(構造体:先)を参照しています。 ここら辺は1週目と同様です。 for文の中で、"text"と(構造体:先)の中の""が比較されます。 "text"の方が大きいのでa=c;としてa(構造体:先)となります。 そして、c=c->next;としています。c(構造体:先)のnextは(構造体:1のアドレス)です。 よって、c(構造体:1)の状態になります。 そしたら、次は"text"と(構造体:1)の中の"book"が比較されます。 "text"の方が大きいのでa=c;としてa(構造体:1)となります。 そして、c=c->next;としています。c(構造体:1)のnextはNULLですので、次のループは行われません ループを抜けたらinsert関数に行きます。 (a,c,data)=(構造体:1,構造体:1,"text") ↓ insert まず(構造体:2)のメモリが確保され、b(構造体:2)の状態になります。 そうしたら、a(構造体:1)の中身を["book",1,(構造体:2)のアドレス]にします。 そして、b(構造体:2)の中身を["text",1,NULL]にします。 現在の構造体の中身 (構造体:先) ["",0,(構造体:1)のアドレス] (構造体:1)  ["book",1,(構造体:2)のアドレス] (構造体:2)  ["text",1,NULL] ・3週目 read "book"が読み込まれます。 ↓ add "book"とsentou(構造体:先)のアドレスが渡されます。 c=sentou(構造体:先)としているのでcは(構造体:先)を参照しています。 ここら辺は1,2週目と同様です。 for文の中で、"book"と(構造体:先)の中の""が比較されます。 "book"の方が大きいのでa=c;としてa(構造体:先)となります。 そして、c=c->next;としています。c(構造体:先)のnextは(構造体:1のアドレス)です。 よって、c(構造体:1)の状態になります。 そしたら、次は"book"と(構造体:1)の中の"book"が比較されます。 これは同じものですので、c(構造体:1)のカウントを1増やし中身を["book",2,(構造体:2のアドレス)]にしてから returnします。 insert関数は行われません。 現在の構造体の中身 (構造体:先) ["",0,(構造体:1)のアドレス] (構造体:1)  ["book",2,(構造体:2)のアドレス] (構造体:2)  ["text",1,NULL] ・4週目 read "computer"が読み込まれます。 ↓ add "computer"とsentou(構造体:先)のアドレスが渡されます。 c=sentou(構造体:先)としているのでcは(構造体:先)を参照しています。 ここら辺は1,2,3週目と同様です。 for文の中で、"computer"と(構造体:先)の中の""が比較されます。 "computer"の方が大きいのでa=c;としてa(構造体:先)となります。 そして、c=c->next;としています。c(構造体:先)のnextは(構造体:1のアドレス)です。 よって、c(構造体:1)の状態になります。 そしたら、次は"computer"と(構造体:1)の中の"book"が比較されます。 "computer"の方が大きいのでa=c;としてa(構造体:1)となります。 そして、c=c->next;としています。c(構造体:1)のnextは(構造体:2のアドレス)です。 よって、c(構造体:2)の状態になります。 次は"computer"と(構造体:2)の中の"text"が比較されます。 "text"の方が大きいので何もせずにbreakしてforを抜けます。 ループを抜けたらinsert関数に行きます。 (a,c,data)=(構造体:1,構造体:2,"computer") ↓ insert まず構造体3のメモリが確保され、b(構造体3)の状態になります。 そうしたら、a(構造体:1)の中身を["book",2,(構造体:3)のアドレス]にします。 そして、b(構造体:3)の中身を["computer",1,,(構造体:2)のアドレス]にします。 現在の構造体の中身 (構造体:先) ["",0,(構造体:1)のアドレス] (構造体:1)  ["book",1,(構造体:3)のアドレス] (構造体:3)  ["computer",1,(構造体:2)のアドレス] (構造体:2)  ["text",1,NULL] これでループ終了して、後は表示します。 なるべく分かりやすいようには書きましたが、テキスト形式ではこれが限界です。 また、アドレスを理解できないとこれを理解するのは難しいです。。 a,b,cは今どの構造体のアドレスを管理しているか、構造体の中身はどうなっているのか、ここら辺を重点的に見ていけば良いと思います。 長くなりましたがこんな所です。

qwewqwe
質問者

お礼

本当にありがとうございます。 確かにポインタなどアドレスについての理解が弱かったです。 非常に助かりました!

その他の回答 (2)

回答No.2

addは同じ文字列があった場合のカウントと、アルファベット順で先にくるかの摘出。 insertはaddで摘出された文字を挿入。 ですかね?多分。 実際に動きを見たわけではないので予定通りに動いていることを前提としたaddとinsertの動きは、 addでcの構造体の中の文字列と一つ一つ比較され、 同じであれば、カウントの増加してaddを終了。 挿入箇所が見つかれば比較を終了してinsertへ。 insertでは、addで摘出された文字列をそこに格納してそれ以降の文を後ろにずらしています。 分かりづらいですが、前の構造体で次の構造体のアドレスを管理というような鎖みたいな形で管理しています。 例えば、構造体1で構造体2のアドレスを管理、構造体2で構造体3のアドレスを管理というような感じです。 このとき、構造体2の次に構造体4を入れる場合は、 構造体2に構造体4のアドレスを管理させて、構造体4に構造体3のアドレスを管理させる。 そんな感じで挿入しているのではないかと思います。 一つ一つについて動作を確認した訳ではないので詳しい所は分かりませんが、おおよそそんなことをしたいのだと思います。 少々気になった所は、sentou周りの式がおかしいですね。 表示のときのp=sentou->next;とadd内のc=sentou;はどちらかにそろえた方がいいのではないでしょうか。 加えてこの状態ではsentouが解放されませんね。 また、表示のときに構造体のメモリを解放してから次の構造体のアドレスを参照しているようです。 この2点が気になりましたが、現状で上手く動いていますか? 蛇足ですがファイルオープンを2回しているように見えるのですが気のせいですかね? mallocもそうですが、条件式と同時に色々やりたがる部分が見られます。 実際にこういったことをしているのですから分けて考えた方がいい気がします。 他にもコメントアウトがないし、変数もどれが何をしているか分からないしで、少々いい加減のような気もします。 人が見ても分かりやすいプログラミングを心がければ多少改善するのではないでしょうか。

qwewqwe
質問者

補足

dataに[ book text book computer]と順番に格納された場合(mainのwhileループ4回分)のadd関数の動きを変数(a,b,c..)を使いながら順を追って説明していただくことはできないでしょうか。。 非常にめんどくさいとは思いますがお願いします。。

  • bid
  • ベストアンサー率0% (0/1)
回答No.1

一つ一つ追っていけば良いのではないでしょうか。 add なら、  リストのノードを指すためのポインタを用意して、  for でリストの先頭から最後までたどる間に、  data の文字列とノードに格納されている文字列を比較して等しいならカウントアップ、、 のように。 そうするとコードのおかしな部分にも気づくと思います。

qwewqwe
質問者

補足

全体的な流れも教えていただきたいのですが、特にaddのfor分の()の中と、main分の1つ目のwhileを抜けた後の流れが特によくわからないのです。。

関連するQ&A

  • C言語でセグメンテーションエラー

    環境はUbuntu Feisty Fawn gcc 4.1.2 #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX 32 #define DEBUG struct node{ char *moji; struct node *left,*right; }; typedef struct node NODE; void error(char *msg){ fflush(stdout); fprintf(stderr, "%s\n", msg); exit(1); } NODE *createNode(char *x){ NODE *new; new = malloc(sizeof(NODE)); if(new == NULL){ error("メモリがありません。\n"); } new->moji = x; new->left = NULL; new->right = NULL; return new; } NODE *insertNode(NODE *p, char *x){ if(p == NULL){ p = createNode(x); }else if(strcmp(p->moji, x) == 0){ return NULL; }else if(strcmp(p->moji, x) > 0){ p->left = insertNode(p->left, x); }else{ p->right = insertNode(p->right, x); } return p; } void printTree(NODE *p){ if(p == NULL) return; printTree(p->left); printf("%s\n",p->moji); printTree(p->right); } int main(int argc, char *argv[]){ FILE *fp; char *buf = malloc(sizeof(char) * MAX); char *ans = malloc(sizeof(char) * MAX); NODE *p = malloc(sizeof(NODE)); if( argc > 2 ){ printf("ファイルの指定は一つだけです。\n"); return -1; }else if(argc == 1){ printf("ファイルを指定してください。\n"); return -1; } fp = fopen( argv[1] , "r" ); if( fp == NULL ){ printf("ファイル読み込みに失敗しました。\n"); return -1; } while(fscanf(fp,"%s",buf) == 1){ ans = strtok(buf," -,."); p = insertNode(p, ans); while(ans != NULL){ ans = strtok(NULL," -,."); if(ans != NULL){ p = insertNode(p, ans); } } } printTree(p); fclose(fp); return 0; } このファイルを読み込んで記憶させたいんです。 file.txt ここから下がファイルの中身 The Java programming language is a general-purpose, concurrent, class-based, object-oriented language. It is designed to be simple enough that many programmers can achieve fluency in the language. どこがいけないとおもいますか?

  • csvファイルの実績データをC言語で解析するのですが...

    C言語を学び始めたばかりなのに、csvファイルの実績データでフィールドが15あり、レコード数が1000000近くあるファイルの15番目のフィールドを足し合わせて、出力するということをやっているのですが、まだまだわからないことだらけです。 1レコード目がカラム名なので2レコード目から足し合わせるんですがそこのところもよくわからずじまいで... 一応、書いたプログラムが #include <stdio.h> #include <stdlib.h> #include <string.h> int main() { FILE *fp; char buffer[50],*p; int cnt, num, sum; fp = fopen("j0.csv","r"); if(fp == NULL){ printf("ファイルが開けませんでした。\n"); exit(-1); } while(fgets(buffer,fp) != NULL){ p = strtok(buffer,","); cnt = 1; while(p!=NULL){ num = atoi(p); printf("%d:%d,",cnt,num); p = strtok(NULL,","); cnt++; if(cnt==15) sum=sum+num } printf("\b\b \n"); } printf(%d \n",num); fclose(fp); return(0); } と書いたんですが、ぜんぜんな状態です。誰かご教授願えませんか?

  • 1000000レコードもあるcsvファイルの実績データをC言語で計算しているのですが...

    C言語を学び始めたばかりなのに、csvファイルの実績データでフィールドが15あり、レコード数が1000000近くあるファイルの15番目のフィールドを足し合わせて、出力するということをやっているのですが、まだまだわからないことだらけです。 一応、書いたプログラムが #include <stdio.h> #include <stdlib.h> #include <string.h> int main() { FILE *fp; char buffer[50],*p; int cnt, num, sum; fp = fopen("j0.csv","r"); if(fp == NULL){ printf("ファイルが開けませんでした。\n"); exit(-1); } while(fgets(buffer,fp) != NULL){ p = strtok(buffer,","); cnt = 1; while(p!=NULL){ num = atoi(p); printf("%d:%d,",cnt,num); p = strtok(NULL,","); cnt++; if(cnt==15) sum=sum+num } printf("\b\b \n"); } printf(%d \n",num); fclose(fp); return(0); } と書いたんですが、ぜんぜんな状態です。誰かご教授願えませんか?

  • C言語のプログラムを修正追加お願いします。

    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; /*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) { 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; }

  • C言語のプログラム組んだのですが完成させてください

    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; do { printf("**************身長・体重の表示***************\n\n"); printf(" データファイルの読み込み・・・・・(1)\n"); printf(" 全てのデータを表示・・・・・・・・(2)\n"); printf(" 特定のデータを表示・・・・・・・・(3)\n"); printf(" 終わり・・・・・・・・・・・・・・(4)\n\n"); printf("処理番号を入力してください\n"); scanf("%d",&a); } while(a<1 || a>4); return a; } /*read_file関数の宣言*/ int 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関数の宣言*/ int 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); } } 最初の処理番号を入力した所で終わってしまいます、何とか改変してくださいお願いします 補足

  • C言語について

    以下のプログラムについてです test.txtから単語を読み込んでその異なる単語の数を求めるプログラムです。 #include<stdio.h> #include<stdlib.h> #include<string.h> #include<stddef.h> #include<ctype.h> #define NMAX 80 #define LMAX 5000 void count(FILE*, int); void all_words(FILE *); FILE *fp, *fp2; char *fn="test.txt"; char *fn2="total word.txt"; const char *ignore="\n !?()*-;:.,_\"[]"; int main(void){ int p=0, x=0, c, l, t=0,k=0; char word3[LMAX][NMAX]; char word1[NMAX]; char word2[NMAX]; char *tp; char *tp2; if((fp=fopen(fn,"r"))==NULL){ printf("Can't open '%s'.\n",fn); return -1; } if((fp2=fopen(fn2,"w"))==NULL){ printf("Can't open '%s'.\n",fn2); return -1; } for(c=0;c<LMAX;c++){ if(fgets(word3[c],NMAX,fp)==NULL)break; p++; } for(c=0;c<p;c++){ for(x=0;x<NMAX;x++){ word1[x]=tolower(word3[c][x]); } tp=word1; while((tp2=strtok(tp,ignore))!=NULL){ if(*tp2=='\''){ if(*(tp2+1)=='`'){ t=1; } tp2++; } free(tp); strcpy(word2,tp2); k=l=strlen(word2)-1; if(word2[k]==('\'' & l)){ word2[l]='\0'; } if(word2[0] =='\'' &&t==0){ if(word2[1]!='\0'){ fputs(word2+1,fp2); fputc('\n',fp2); } } else{ if(word2[0]!='\0'){ fputs(word2,fp2); fputc('\n',fp2); } } tp=NULL; } } fclose(fp); fclose(fp2); all_words(fp2); return 0; } void all_words(FILE* fp2){ char word3[NMAX]; int n=0; if((fp2=fopen(fn2,"r"))==NULL){ printf("Can't open '%s'.\n", fn2); return; } for(;;){ if(fgets(word3, NMAX,fp2)==NULL){ break; } n++; } fclose(fp2); count(fp2,n); } void count(FILE* fp2, int n){ int c, x, y=0; char *m=(char *)malloc(n*NMAX); char *xp; char *yp; if((fp2=fopen(fn2,"r"))==NULL){ printf("Can't open '%s'.\n", fn2); free(m); return; } for(c=0,xp=m; c<n;c++,xp+=NMAX){ fgets(xp,NMAX,fp2); } qsort(m,n,NMAX,(int (*)(const void*, const void*))strcmp); c=1; for(x=0,xp=m,yp=m+NMAX;x<n-1;xp+=NMAX,yp+=NMAX,x++){ if(strcmp(xp,yp)==0){ y++; c++; } else{ c=1; } } printf("KIDN OF WORD:%d\n",n-y); free(m); fclose(fp2); } このプログラムについてメモリリークになってしまうのですが 確保していないメモリー領域に代入しているのが原因らしいのですが 具体的にどこを直せば良いのでしょうか? よろしくお願いします

  • 連結リストによるデータ管理プログラムの解説

    ★から★までのプログラムが、各行ごとにどのような動きをしているのか簡潔な言葉で説明を書いていただきたいのです。必要がないと判断した行はとばして下さって構いません。 (例) printf("hello!"); …hello!と表示 if(a==0){ …aが0なら #include <stdio.h> #include <stdlib.h> struct CELL{ struct CELL *next; char data; }; /* Head CELL CELL CELL +-------+ +-------+ +-------+ +-------+ | ? | *----> | 5 | *----> | 6 | *----> | 8 | / | +-------+ +-------+ +-------+ +-------+ */ main(void){★ struct CELL head; struct CELL *p, *wp; char a; head.next=NULL; printf("?\n"); scanf("%c %*c",&a); while(a!='0'){ printf("mode?\n"); scanf("%c",&mode); if(mode=="a"){ p=&head; while(p->next!=NULL){ p=p->next; } wp=(struct CELL *)malloc(sizeof(struct CELL)); if(wp==NULL){ printf("cannot allocate enough memory.\n"); return 0; } p->next=wp; p->next->data=a; p->next->next=NULL; printf("?\n"); scanf("%c %*c",&a); } if(mode=="p"){ printf("\n\nNow...\n"); p=&head; while(p->next!=NULL){ printf("%c --> \n",p->next->data); p=p->next; } printf("NULL\n"); if(mode=="d"){ p=&head; while(p->next->data==a){ p=p->next; } if(p==NULL) break; wp=p->next->next; while(p->next->data==a) p=wp;★ } } return 0; }

  • c言語の問題です。ファイルからデータを読み込み連結リストに記憶しソートするプログラムです。お願いします

    ソート部分がどうしてもできません。 またソートは以下のアルゴリズムで行うものです 与えられたリストをリストA、ソート済みのリストをリストBとする。処理の開始段階では、リストBは空である。 1.リストAの要素の中で、最大値をもつ要素Cを探す。 2.要素CをリストAから削除する。 3.要素CをリストBの先頭に挿入する。 4.リストAが空であれば終了。空でなければ 1. にもどる。 #include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct physical Physical; struct physical { char name[41]; int age; float height; float weight; Physical *next; }; void read_data(char *file,Physical *p,Physical *tail); int comp1(const Physical *, const Physical *); int comp2(const Physical *, const Physical *); int comp3(const Physical *, const Physical *); int comp4(const Physical *, const Physical *); void sort(char *arg,Physical *p,Physical *q); Physical *listsort(Physical *p, int (*compar)(const void *, const void *)); int main(void) { char s[20],t,u[20]; Physical *p,*tail,*q; p=malloc(sizeof(Physical)); q=malloc(sizeof(Physical)); tail=malloc(sizeof(Physical)); while(1) { printf("CMD>"); fflush(stdout); fgets(s,20,stdin); sscanf(s,"%c %s",&t,u); switch(t){ case 'q':exit(0); case 'r':read_data(u,p,tail); break; case 's':sort(u,p,q); break; case 'd': while(q!=NULL) { printf("%s %d %.1f %.1f ",q->name,q->age,q->height,q->weight ); q=q->next;} break; } } free(p); return 0; } void read_data(char *file,Physical *p,Physical *tail){ FILE *fp; char string[100]; Physical header; tail=&header; header.next = NULL; p->next = NULL; tail->next = p; tail = p; if ((fp = fopen(file, "r")) == NULL) { exit(1); } while(fgets(string,sizeof(string),fp)!= NULL) { sscanf(string,"%s %d %f %f",p->name,&p->age,&p->height,&p->weight); Physical *tail2; tail2=malloc(sizeof(Physical)); tail2->next=NULL; p->next=tail2; p=tail2; } fclose(fp); } void sort(char *arg,Physical *p,Physical *q){ if(strcmp(arg,"name") == 0) q=listsort(p,(int(*)(const void*, const void*))comp1); if(strcmp(arg,"age") == 0) q=listsort(p,(int(*)(const void*, const void*))comp2); if(strcmp(arg,"height") == 0) q=listsort(p,(int(*)(const void*, const void*))comp3); if(strcmp(arg,"weight") == 0) q=listsort(p,(int(*)(const void*, const void*))comp4); } Physical *listsort(Physical *p,int (*compar)(const void *, const void *)){ Physical *q, *max,*s,*head; s=malloc(sizeof(Physical)); head=malloc(sizeof(Physical)); head=NULL; while(p->next){max = p, q = p->next; while( q->next ) { if( compar(q->next,max->next) ) max = q; q = q->next;} s=max->next; max->next=max->next->next; if(head==NULL) {head=s;} s->next=s; } return head; } int comp1(const Physical *a, const Physical *b){ return (strncmp(a->name,b->name,sizeof(Physical))); } int comp2(const Physical *a, const Physical *b){ if(a->age > b->age) return 1; else return 0; } int comp3(const Physical *a, const Physical *b){ if(a->height > b->height) return 1; else return 0; } int comp4(const Physical *a, const Physical *b){ if(a->weight > b->weight) return 1; else return 0; }

  • C言語について

    以下のプログラムについてです。 test.txtというファイルを読み込み、その中の異なる単語の数を求めるプログラムです。 #include<stdio.h> #include<stdlib.h> #include<string.h> #include<stddef.h> #include<ctype.h> #define NMAX 80 #define LMAX 5000 void count(FILE*, int); void all_words(FILE *); FILE *fp, *fp2; char *fn="test.txt"; char *fn2="total word.txt"; const char *ignore="\n !?()*-;:.,_\"[]"; int main(void){ int p=0, x=0, c, l, t=0; char word3[LMAX][NMAX]; char word1[NMAX]; char word2[NMAX]; char *tp; char *tp2; if((fp=fopen(fn,"r"))==NULL){ printf("Can't open '%s'.\n",fn); return -1; } if((fp2=fopen(fn2,"w"))==NULL){ printf("Can't open '%s'.\n",fn2); return -1; } for(c=0;c<LMAX;c++){ if(fgets(word3[c],NMAX,fp)==NULL)break; p++; } for(c=0;c<p;c++){ for(x=0;x<NMAX;x++){ word1[x]=tolower(word3[c][x]); } tp=word1; while((tp2=strtok(tp,ignore))!=NULL){ if(*tp2=='\''){ if(*(tp2+1)=='`'){ t=1; } tp2++; } strcpy(word2,tp2); l=strlen(word2)-1; if(word2[l]==('\'' && l)){ word2[l]='\0'; } if(word2[0] =='\'' &&t==0){ if(word2[1]!='\0'){ fputs(word2+1,fp2); fputc('\n',fp2); } } else{ if(word2[0]!='\0'){ fputs(word2,fp2); fputc('\n',fp2); } } tp=NULL; } } fclose(fp); fclose(fp2); all_words(fp2); return 0; } void all_words(FILE* fp2){ char word3[NMAX]; int n=0; if((fp2=fopen(fn2,"r"))==NULL){ printf("Can't open '%s'.\n", fn2); return; } for(;;){ if(fgets(word3, NMAX,fp2)==NULL){ break; } n++; } count(fp2,n); } void count(FILE* fp2, int n){ int c, x, y=0; char *m=(char *)malloc(n*NMAX); char *xp; char *yp; if((fp2=fopen(fn2,"r"))==NULL){ printf("Can't open '%s'.\n", fn2); free(m); return; } for(c=0,xp=m; c<n;c++,xp+=NMAX){ fgets(xp,NMAX,fp2); } qsort(m,n,NMAX,(int (*)(const void*, const void*))strcmp); c=1; for(x=0,xp=m,yp=m+NMAX;x<n-1;xp+=NMAX,yp+=NMAX,x++){ if(strcmp(xp,yp)==0){ y++; c++; } else{ c=1; } } printf("KIDN OF WORD:%d\n",n-y); free(m); fclose(fp2); } このプログラムでメモリリークの原因が確保していないメモリ領域に代入しているのが原因らしいのですがどこをどう直して良いかわかりません 具体的に教えていただけないでしょうか? よろしくお願いします

  • C言語について

    以下のプログラムについて alice.txtからテキストを読み込みその中の異なる単語の数を求めるプログラムです #include<stdio.h> #include<stdlib.h> #include<string.h> #include<stddef.h> #include<ctype.h> #define NMAX 80 #define LMAX 5000 void count(int); void all_words(void); FILE *fp, *fp2; char *fn="alice.txt"; char *fn2="total word.txt"; const char *ignore="\n !?()*-;:.,_\"[]"; int main(void){ int p=0, x=0, c, l, t=0; char word3[LMAX][NMAX]; char word1[NMAX]; char word2[NMAX]; char *tp; char *tp2; if((fp=fopen(fn,"r"))==NULL){ printf("Can't open '%s'.\n",fn); return -1; } if((fp2=fopen(fn2,"w"))==NULL){ printf("Can't open '%s'.\n",fn2); return -1; } for(c=0;c<LMAX;c++){ if(fgets(word3[c],NMAX,fp)==NULL) break; p++; } for(c=0;c<p;c++){ for(x=0;x<NMAX;x++){ word1[x]=tolower(word3[c][x]); } tp=word1; while((tp2=(char*)strtok(tp,ignore))!=NULL){ if(*tp2=='\''){ if(*(tp2+1)=='`'){ t=1; } tp2++; } strcpy(word2,tp2); l=strlen(word2)-1; if(word2[l]=='\''){ word2[l]='\0'; } if(word2[l]==l){ word2[l]='\0'; } if(word2[0] =='\'' &&t==0){ if(word2[1]!='\0'){ fputs(word2+1,fp2); fputc('\n',fp2); } } else{ if(word2[0]!='\0'){ fputs(word2,fp2); fputc('\n',fp2); } } tp=NULL; } } fclose(fp); fclose(fp2); all_words(); return 0; } void all_words(void){ char word3[NMAX]; int n=0; if((fp2=fopen(fn2,"r"))==NULL){ printf("Can't open '%s'.\n", fn2); return; } for(;;){ if(fgets(word3, NMAX,fp2)==NULL){ break; } n++; } fclose(fp2); count(n); } void count(int n){ int c, x, y=0; char *m=(char *)malloc(n*NMAX); char *xp; char *yp; if((fp2=fopen(fn2,"r"))==NULL){ printf("Can't open '%s'.\n", fn2); free(m); return; } for(c=0,xp=m; c<n;c++,xp+=NMAX){ fgets(xp,NMAX,fp2); } qsort(m,n,NMAX,(int (*)(const void*, const void*))strcmp); c=1; for(x=0,xp=m,yp=m+NMAX;x<n-1;xp+=NMAX,yp+=NMAX,x++){ if(strcmp(xp,yp)==0){ y++; c++; } else{ c=1; } } printf("%d\n",n-y); free(m); fclose(fp2); } このプログラムを実行するとメモリリークになってしまうのですが 確保していないメモリ領域に代入しているのが原因らしいのですが いろいろ試してみたのですがメモリリークが直りません どうしたらよいでしょうか? よろしくお願いします

専門家に質問してみよう