自作ソート機能の実装方法

このQ&Aのポイント
  • 自作のソート機能を持つプログラムを作成するためのアルゴリズムや関数の説明です。
  • ソート機能を実装するために、一方向リストを使用します。
  • 与えられたリストを辞書順または数字の小さい順に並び替える処理の手順や関数の使い方を紹介します。
回答を見る
  • ベストアンサー

ソートを自作

一方向リストを使ってデータを記憶するプログラムに、ソート機能を持つ関数自作する。 機能は<名前:辞書順、数字:小さい順>に並び替える。 このとき以下のアルゴリズムしたがって作ります。 『与えられたリストをリストA、ソート済みのリストをリストBと呼ぶことにする。処理の開始段階では、リストBは空である。 1: リストAの要素の中で、最大値をもつ要素Cを探す。 2: 要素CをリストAから削除する。 3: 要素CをリストBの先頭に挿入する。 4: リストAが空であれば終了。空でなければ Step1 にもどる。 』 下のコードは自分で考えてみたものです。全部は長いので構造体、関数のみ載せます。 typedef struct member{ char name[40]; int number; struct member *next; } MEMBER; int compar_name(const MEMBER *x, const MEMBER *y){ return strcmp(x->name, y->name); } int compar_number(const MEMBER *x, const MEMBER *y){ return (x->number - y->number); } void remove_max(MEMBER *list, MEMBER *max, int(*compar)(const void*, const void*)){ /* 最大値maxをlistから削除 */ MEMBER *p, *q; p=list->next; q=list; if(p==NULL && compar(q,max)==0) { return; } else if(compar(q,max)==0) { q=p; } else{ while(compar(p,max)!=0) { q=p; p=p->next; } q->next=p->next; free(p); }} MEMBER *find_max(MEMBER *list, int(*compar)(const void*, const void*)){ /* 最大値maxを探す */ MEMBER *ptr, *max; for (ptr=max=list; ptr!=NULL; ptr=ptr->next){ if (compar(max,ptr)<0){ max=ptr; } } return max; } MEMBER *listsort(MEMBER *list, int(*compar)(const void*, const void*)){ /* ソート関数 */ MEMBER *sorted, *ret; ret=list; for (;ret->next; ret=ret->next){ MEMBER *tmp, *max=NULL; max=find_max(list, (int(*)(const void*, const void*))compar); remove_max(list, max, (int(*)(const void*, const void*))compar); sorted=(MEMBER *)malloc(sizeof(MEMBER)); strcpy(sorted->name, max->name); sorted->number=max->number; sorted=tmp; tmp=sorted; } return sorted; } 並べ替えるデータの例: OKITA 1 HARADA 10 TOUDOU 8 INOUE 6 SAITOU 3 NAGAKURA 2 TAKEDA 5 TANI 7 MATUBARA 4 SUZUKI 9 長いですが、教えて下さい。<(_ _)>

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

  • ベストアンサー
  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.5

> いろいろやってみたのですが、もう少しheadについて、教えてもらえないでしょうか? 特にこの辺を、というのがあると説明しやすいのですが 参考になるのは 単方向リスト(Singly Linked List) http://homepage1.nifty.com/daccho/program/algo/slinklst.htm とか。 このページの例ではダブルポインタを使ってますね。 んで、さっくりサンプルを書いてみました。 手抜きしているところがいくつかあるので、 その辺は注意してください #mallocの戻り値をチェックしてないとか #include <stdio.h> #include <stdlib.h> typedef int DATA_TYPE; struct CELL { DATA_TYPE val; struct CELL* next; }; typedef struct CELL CELL; CELL* list_append(CELL* headp, DATA_TYPE val) { CELL* newcell; newcell = (CELL *)malloc(sizeof (CELL)); newcell->val = val; newcell->next = headp->next; headp->next = newcell; return headp; } CELL* list_delete(CELL* headp, DATA_TYPE val) { CELL* prev = headp; CELL* p = prev->next; for (; p; prev=p, p=p->next) if (val == p->val) prev->next = p->next; return p; } CELL* list_find(CELL* headp, DATA_TYPE val) { CELL* p = headp->next; for (; p; p=p->next) if (val == p->val) return p; return NULL; } void list_print(CELL* headp) { CELL *p = headp->next; int count; for (count=0 ;p; p=p->next) printf("%d: %d\n", count++, p->val); } DATA_TYPE sampledata[] = {6, 3, 7, 2, 1, 9}; int main() { CELL theHead = {0, NULL}; int i; for (i=0; i<(sizeof sampledata / sizeof sampledata[0]); i++) { list_append(&theHead, sampledata[i]); } list_print(&theHead); list_delete(&theHead, 2); printf("%s\n", "#####"); list_print(&theHead); list_delete(&theHead, 9); printf("%s\n", "#####"); list_print(&theHead); return 0; } 実行例: 0: 9 1: 1 2: 2 3: 7 4: 3 5: 6 ##### 0: 9 1: 1 2: 7 3: 3 4: 6 ##### 0: 1 1: 7 2: 3 3: 6 コメントをつけてるひまはなかったので、ここがわからん というのがあれば例によって遠慮なくどうぞ。 参考URLの追加 データ構造 http://www5c.biglobe.ne.jp/~ecb/c/14_04.html それから C言語による最新アルゴリズム事典 http://amazon.jp/dp/4874084141 のような本を一冊手元に持っておくといいですよ。 この本はちょっと古いですけど、結構つかえます。 他にもこの手の本はいろいろありますので 本屋なりで探してみるのもよいと思います。

その他の回答 (4)

  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.4

> 方法として、先頭を削除するとき削除する前のノードがないとできないのはわかるので、 > 削除するノードのまえに空ノードを作ろうと考えたのですが、そのやり方がわかりません。 > 何度もすいません。もう一度アドバイスください。 ん、いいとこついていますね。 いろいろやり方はありますけど、たとえば MEMBER head; //ポインタ変数ではない という変数を宣言しておいて、 head.next は最初(つまりリストが空の場合)はNULLを入れておいて、 リストに要素を追加するときは p = ノード作成関数(); p->next = head.next; head.next = p; のようにして追加していきます。こうすることで、head.nextは 常にリストの先頭を指すようになります。 で、リストを扱う関数の引数には &head とそのアドレスを渡してやると。 リストを終端まで手繰る部分がちょっと変わりますが基本的には同じです。 もし複数のリストを一度に扱いたいのでheadのように固定的な宣言をした変数ではいやだというのなら、 headの役目をする変数も MEMBER *headp のようにしておいて、さらに 関数にはそのアドレス、つまり list_function(MEMBER **head, ...) のようにダブルポインタを渡すというやり方もあります。 もっと詳しく説明してほしいということなら遠慮なく補足で要求してください。 今は寝る直前なのでプログラム片で例を示すことはできませんでした。 ごめんして。

sy5399912
質問者

補足

いろいろやってみたのですが、もう少しheadについて、教えてもらえないでしょうか? 参考URLでもいいのでお願いします<(_ _)>

  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.3

これくらいの長さならまだ読めなくもないから良いですよ。 変数名のつけ方とかがめちゃくちゃだと 読む気にもなりませんけど(笑) んじゃあまず、 void remove_max(MEMBER *list, MEMBER *max, int(*compar)(const void*, const void*)){ /* 最大値maxをlistから削除 */ に、最大値が先頭要素であるリストとか、 要素が一つだけのリストを渡したときにどのように 動作するか、デバッガでステップ実行してみてください。 そうしたらどこがおかしいかわかるんじゃないかな。 もうひとつ、 remove_max(list, max, (int(*)(const void*, const void*))compar); sorted = (MEMBER *)malloc(sizeof(MEMBER)); strcpy(sorted->name, max->name); sorted->number = max->number; は、remove_max で最大値を持つ要素は取り除かれている (freeされている)から、そのあとで max->name, max->numberにアクセスするのはまずいです。

sy5399912
質問者

補足

アドバイスをみて、やってみました。 MEMBER *listsort(MEMBER *list, int(*compar)(const void*, const void*)){ /* ソート関数 */ の remove_max(list, max, (int(*)(const void*, const void*))compar); の位置が変だということわかりました。 void remove_max(MEMBER *list, MEMBER *max, int(*compar)(const void*, const void*)){ /* 最大値maxをlistから削除 */ に『先頭を削除する』ときに先頭が消せないという問題があるのは気付けたのですが、うまくできません。 方法として、先頭を削除するとき削除する前のノードがないとできないのはわかるので、削除するノードのまえに空ノードを作ろうと考えたのですが、そのやり方がわかりません。 何度もすいません。もう一度アドバイスください。

  • sakusaker7
  • ベストアンサー率62% (800/1280)
回答No.2

> 長いですが、教えて下さい。<(_ _)> 何を? とりあえず for (;ret->next; ret=ret->next){ MEMBER *tmp, *max=NULL; max=find_max(list, (int(*)(const void*, const void*))compar); remove_max(list, max, (int(*)(const void*, const void*))compar); sorted=(MEMBER *)malloc(sizeof(MEMBER)); strcpy(sorted->name, max->name); sorted->number=max->number; sorted=tmp; tmp=sorted; } return sorted; sorted=tmp の次の行で tmp=sorted ってのは 何を狙っているかわかりません。 それにこのループでは > 3: 要素CをリストBの先頭に挿入する。 をやろうとしているように感じられなくはありませんが できてませんね。 疑問に思っていること、質問したいことを もう少し具体的にしてみてください。 #正直手を入れたいところはたくさんありますが #我慢しておきます

sy5399912
質問者

補足

質問者のsy5399912です。 投稿してすぐ回答してもらってありがとうございます。 初投稿で、いろいろわかってなくてすいませんでしたm(_ _)m 短くしたつもりですが、やっぱり長すぎますよね~。 教えてほしいのは、listsort( , )で返すsortedをprintfしたとき、バグってしまいます。例えば、数の小さい順にしたとき、前に挙げたデータ例をソートすると、 『OKITA: 1.  OKITA: 1.  OKITA: 1.  <� a<� a: 2. <� a<� a: 3.  <� a<� a: 4.  <� a<� a: 5.  <� a<� a: 6.  <� a<� a: 7.  <� a<� a: 8.  <� a<� a: 9.  <� a<� a: 10.  %s: 0.     』 『名前が出てない、memberの数が変』みたいなことになってしまいます。 そこで、sortedがちゃんとprintfするにはどうすればいいか教えて下さい。 前に挙げたコード少し変えたのでその部分だけ載せます。また長くなっていますが、お願いします。 MEMBER *listsort(MEMBER *list, int(*compar)(const void*, const void*)){ MEMBER *sorted, *ret, *res, *tmp, *max; res=list, ret=list; int s=0; for(;res != NULL ;res = res->next){ s++; } /* listに入っているデータの数を数える。 */ for (; s!=0; ret=ret->next){ /* 3:要素CをリストBの先頭に挿入する。 */ max=NULL; max = find_max(list, (int(*)(const void*, const void*))compar); remove_max(list, max, (int(*)(const void*, const void*))compar); sorted = (MEMBER *)malloc(sizeof(MEMBER)); strcpy(sorted->name, max->name); sorted->number = max->number; sorted->next = tmp; tmp = sorted; s--; } /* 4:リストAが空であれば終了。空でなければ Step1 にもどる。 */ return sorted; } MEMBER *find_max(MEMBER *list, int(*compar)(const void*, const void*)){ /* 1:リストAの要素の中で、最大値をもつ要素Cを探す。 */ void remove_max(MEMBER *list, MEMBER *max, int(*compar)(const void*, const void*)){ /* 2:要素CをリストAから削除する。 */

noname#96023
noname#96023
回答No.1

全部読んでる暇は無いので回答は出来ませんが、 全体的にコメントが少ないです。 他人のプログラムを読むほど、時間がかかり苦労するものは無いと認識したほうが良いですよ。

関連するQ&A

  • 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; }

  • クイックソート

    #include<stdio.h> #include<stdlib.h> #define MAX 10 int comp(const void *i,const void *j); int main(void) { int sort[MAX], i ; for(i=0 ; i<MAX ; i++){ sort[i] = rand(); } qsort(sort, MAX, sizeof(int), comp); for( i=0; i<MAX ; i++) printf("%d\n", sort[i]); return 0; } int comp (const void *i, const void *j) { return *(int*)i - *(int*)j; } これはクイックソートのプログラムなのですが、 int comp (const void *i, const void *j) { return *(int*)i - *(int*)j; } この部分がわかりません。ここでソートしているのですか?

  • C言語・スタックを使用した逆ポーランド記法について

    C言語でスタック(リスト構造)を使用した逆ポーランド記法のプログラムを作りたいのですが 計算式(例:1234+*+)が入力された場合、どのようにして数字と演算子を区別すればいいのでしょうか? 一応スタック構造の部分は、 #include <stdio.h> #include <stdlib.h> /*スタック構造*/ typedef struct stack { int max; int ptr; int *stk; } Stack; /*スタックの確保・初期化*/ int StackAlloc(Stack *s, int max) { s->ptr = 0; if ((s->stk = calloc(max, sizeof(int))) == NULL) { s->max = 0; return (-1); } s->max = max; return (0); } /*スタック解放*/ void StackFree(Stack *s) { if (s->stk != NULL) { free(s->stk); s->max = s->ptr = 0; } } /*プッシュ*/ int StackPush(Stack *s, int x) { if (s->ptr >= s->max) return (-1); s->stk[s->ptr++] = x; return (0); } /*ポップ*/ int StackPop(Stack *s, int *x) { if (s->ptr <= 0) return (-1); *x = s->stk[--s->ptr]; return (0); } /*データのピーク*/ int StackPeek(const Stack *s, int *x) { if (s->ptr <= 0) return (-1); *x = s->stk[s->ptr - 1]; return (0); } /*スタックの大きさを返却*/ int StackSize(const Stack *s) { return (s->max); } /*データを返却*/ int StackNo(const Stack *s) { return (s->ptr); } /*スタックは空か*/ int StackEmpty(const Stack *s) { return (s->ptr <= 0); } /*スタックは満杯か*/ int StackFull(const Stack *s) { return (s->ptr >= s->max); } /*スタックを空にする*/ void StackClear(Stack *s) { s->ptr = 0; } といった感じで仕上げています。

  • qsortについて

    qsort()で構造体をソートする時に、qsortの第3,4引数時の、「size t_t size, int (*cmp)(const void *a, const void *b)」の使い方が分かりません。 何故これを使ってソートが出来るのでしょうか?そもそも、構造体を送った時に、自作関数内での書き方にも疑問があります。 int main(void){ MAX dt[5]={・・・・}; //構造体変数宣言 ・・・・・ qsort(dt,5,sizeof(MAX),sum); //(*1) .... return 0; } int sum(const void *a, const void *b){ MAX *p1 = (MAX *)a; //(*2) MAX *p2 = (MAX *)b; //(*2) ・・・・ return ~; } ---------------------------------------------------- *1: 第3引数のsizeof(MAX)って何ですか? *2: 例えばint型が渡されてreturnする場合は、「return *(int *)a - *(int *)b 」でいいのに、   何故構造体の場合はこう書かないといけないのですか?

  • 線形リストのコードでどーしても理解できない個所があります。

    線形リストのコードでどーしても理解できない個所があります。 (以下、コード部分) typedef struct __node { char name[20]; char tel[16]; struct __node *next; } Node; typedef struct { Node *head; Node *tail; } List; Node *AllocNode(void) { return ((Node *)calloc(1, sizeof(Node))); } /*--- 新たに生成したノードを先頭へ挿入 ---*/ void InsertNode(List *list, const char *name, const char *tel) { Node *ptr = list->head; list->head = AllocNode(); strcpy(list->head->name, name); strcpy(list->haed->tel, tel); list->head->next = ptr; } /*--- pが指すノードの直前にノードを挿入 ---*/ void PutNodeP(List *list, Node *p, const char *name, const char *tel) { if (p == list->head) InsertNode(list, name, tel); else { Node *temp = AllocNode(); if (p == list->tail) list->tail = temp; else *temp = *p; strcpy(p->name, name); strcpy(p->tel, tel); temp->next = p; } } 上の29行目以降の≪pが指すノードの直前にノードを挿入≫についてです。 if文部分については理解できますが、else文部分について、何をやっているのかわからないです。Cの基本的な部分(ポインタも含めて)については充分に理解しているつもりです。 どなたか御教授頂けないでしょうか。 長々と書いてしまいましたがよろしくお願いします。

  • リスト構造のソートで悩んでます。。。

    リスト構造のソートで悩んでます。プログラムの内容はファイルからデータをリスト構造の構造体に読み込み、名前順にソートし結果を表示する。というものです。データの追加や削除はできるのですがソートとなると頭が混乱してしまいお手上げ状態になってしまいました。。。。。 読み込み用のデータとプログラムソースを以下に記載するのでどなたか良きアドバイスをお願いしますm(_ _)m ○データ Sakuragi 16 Rukawa 16 Miyagi 17 Akagi 18 Mitsui 18 ○ソース #include <stdio.h> #include <stdlib.h> #include <string.h> #define MENBER 5 typedef struct data{ char name[BUFSIZ]; int age; struct data *next; }LIST; LIST *newLIST(void); LIST *sort(LIST *); int main(int argc,char *argv[]){ FILE *fp; LIST *p; LIST *np; LIST *npb; LIST *head; char namae[BUFSIZ]; int toshi,i; if((fp=fopen(argv[1],"r"))==NULL){ printf("no file\n"); exit(1); } head = newLIST(); npb =head; for(i=0;i<MENBER;i++){ np = newLIST(); fscanf(fp,"%s %d",namae,&toshi); strcpy(np->name,namae); np->age = toshi; npb->next =np; npb = np; } sort(head); for(p=head->next;p != NULL;p=p->next){ printf("%s\t%d\n",p->name,p->age); } for(p=head->next;p != NULL;p=np){ np = p->next; free(p); } fclose(fp); return(0); } LIST *newLIST(){ LIST *p; p = (LIST *)malloc(sizeof(LIST)); p->next = NULL; return(p); } LIST *sort(LIST *head){ }

  • C++のポインタの動作を教えてください

    ちょっと長いですが、ある部分の動作がわかりません そこを詳しく教えてください。 void queue::store(int i)の//リスト末尾に置くっていうところからで なぜ、if(tail)tail->next=item; tail=item; こう書くのかわからないです。 tail->next=itemの次にtail=itemを実行すると、tail->nextの内容も変わるのでは?と思っているのですがどうなっているのかわからないのでお願いします。 説明が下手ですがすみませんが教えてください。 //仮想関数の実例 #include <iostream> #include <cstdlib> #include <cctype> using namespace std; class list{ public: list *head; //リスト先頭へのポインタ list *tail; //リスと末尾へのポインタ list *next; //次項目へのポインタ int num; //格納される値 list(){ head=tail=next=NULL; } virtual void store(int i)=0; virtual int retrieve()=0; }; //キュー型リストの作成 class queue:public list{ public: void store(int i); int retrieve(); }; void queue::store(int i) { list *item; item=new queue; if(!item){ cout << "メモリ割り当てエラー" << endl; exit(1); } item->num=i; //リスト末尾に置く if(tail)tail->next=item; tail=item; item->next=NULL; if(!head)head=tail; } int queue::retrieve() { int i; list *p; if(!head){ cout << "リストは空です" << endl; return 0; } //リスト先頭から取り除く i=head->num; p=head; head=head->next; delete p; return i; } //スタック型リストの作成 class stack:public list{ public: void store(int i); int retrieve(); }; void stack::store(int i) { list *item; item=new stack; if(!item){ cout << "メモリ割り当てエラー" << endl; exit(1); } item->num=i; //スタックのような操作になるよう、リスト最前部におく if(head)item->next=head; head=item; if(!tail)tail=head; } int stack::retrieve() { int i; list *p; if(!head){ cout << "リストは空です" << endl; return 0; } //リスト先頭から取り除く i=head->num; p=head; head=head->next; delete p; return i; } class sorted:public list{ public: void store(int i); int retrieve(); }; void sorted::store(int i) { list *item; list *p,*p2; item=new sorted; if(!item){ cout << "メモリ割り当てエラー" << endl; exit(1); } item->num=i; //次項目のおき場所を見つける p=head; p2=NULL; while(p){ //中へ if(p->num>i){ item->next=p; if(p2)p2->next=item; //先頭要素ではない if(p==head)head=item; //新しい先頭要素 break; } p2=p; p=p->next; } if(!p){ //終わりへ if(tail)tail->next=item; tail=item; item->next=NULL; } if(!head)//先頭要素 head=item; } int sorted::retrieve() { int i; list *p; if(!head){ cout << "リストは空です" << endl; return 0; } //リスト先頭から取り除く i=head->num; p=head; head=head->next; delete p; return i; } int main() { list *p; //キューのデモ queue q_ob; p=&q_ob; //キューをさす p->store(1); p->store(2); p->store(3); cout << "キュー:"; cout << p->retrieve(); cout << p->retrieve(); cout << p->retrieve(); cout << endl; //スタックのデモ stack s_ob; p=&s_ob; //スタックをさす p->store(1); p->store(2); p->store(3); cout << "スタック:"; cout << p->retrieve(); cout << p->retrieve(); cout << p->retrieve(); cout << endl; //ソート済みリストのデモ sorted sorted_ob; p=&sorted_ob; p->store(4); p->store(1); p->store(3); p->store(9); p->store(5); cout << "ソ\ート:"; cout << p->retrieve(); cout << p->retrieve(); cout << p->retrieve(); cout << p->retrieve(); cout << p->retrieve(); cout << endl; return 0; }

  • ポインタの扱い

    すみません、構造体へのポインタの配列の扱いに困っています。 下記ソースの struct list *hashtable[HASHSIZE]; の箇所をmain部に入れた場合の処理がうまくいきません。。 どのように修正すれば良いのでしょうか。 申し訳ありませんが教えてください。 --------------------- #include <stdio.h> #include <stdlib.h> #include <string.h> #define HASHSIZE 40 #define MAX_KW_LEN 256 #define NUM_KW 23 #define TRUE 1 #define FALSE 0 struct list { char keyword[MAX_KW_LEN]; struct list *next; }; struct list *hashtable[HASHSIZE]; static char kw[NUM_KW][MAX_KW_LEN] = { "auto", "break", "double", "enum", "char", "continue", "extern", "float", "for", "int", "long", "register", "short", "signed", "static", "struct", "typedef", "union", "unsigned", "return", "void", "volatile", "while" }; int Hash(char *key); void InitHTable(void); int FindKeyWord(char *key); void ListKeyWord(void); void FreeKeyWord(void); int main(void); int Hash(char *key) { int hashval = 0; while (*key != '\0') hashval += *key++; return (hashval % HASHSIZE); } void InitHTable(void) { int i; struct list *p, *q; int hashval; for (i = 0; i < NUM_KW; i++) { printf("%d\n",i); if ((FindKeyWord(kw[i])) == FALSE) { if ((p = (struct list *)malloc(sizeof(struct list))) == NULL) { fprintf(stderr, "メモリ不足です。\n"); exit(2); } strcpy((*p).keyword, kw[i]); hashval = Hash(kw[i]); if (hashtable[hashval] == NULL) { hashtable[hashval] = p; p->next = NULL; } else { q = hashtable[hashval]; while (q->next != NULL) { q = q->next; } q->next = p; p->next = NULL; } } } } int FindKeyWord(char *key) { struct list *p; for (p = hashtable[Hash(key)]; p != NULL; p = p->next) if (!strcmp(key, (*p).keyword)) return (TRUE); return (FALSE); } void ListKeyWord(void) { int i; struct list *p; for (i = 0; i < HASHSIZE; i++) for (p = hashtable[i]; p != NULL; p = p->next) printf("予約語:%s ハッシュ値:%d:\n", (*p).keyword, Hash((*p).keyword)); } void FreeKeyWord(void) { int i; struct list *p, *q; for (i = 0; i < HASHSIZE; i++) for (p = hashtable[i]; p != NULL; ) { q = p->next; free(p); p = q; } } int main(void) { char word[MAX_KW_LEN]; int i; InitHTable( ); ListKeyWord( ); for (i = 0; i < 4; i++) { printf("Cの予約語を入力して下さい "); fgets(word, 128, stdin); if ((FindKeyWord(word)) == TRUE) printf("%s は登録済みです。\n", word); else printf("%s は未登録です。\n", word); } FreeKeyWord( ); }

  • プログラムについて

    今スタっクのファイルから読み込んだ文字列をスタっクへプっシュしたりポっプしたりする過程がわかるプログラムを作ってます 。 作りかけのプログラムですがどこをどうすればいいか教えてください!! 一応コンパイルできます。 使ってない関数があるかもしれません。 #include <stdio.h> #include <stdlib.h> #include <string.h> #define NUMBER 100 /*--- スタックを実現する構造体 ---*/ typedef struct { int max; /* スタックのサイズ */ int ptr; /* スタックポインタ */ char *stk; /* スタック(の先頭要素へのポインタ) */ } Stack; /*--- スタックの初期化 ---*/ int StackAlloc(Stack *s, int max) { s->ptr = 0; if ((s->stk = calloc(max, sizeof(int))) == NULL) { s->max = 0; /* 配列の確保に失敗 */ return (-1); } s->max = max; return (0); } /*--- スタックの後始末 ---*/ void StackFree(Stack *s) { if (s->stk != NULL) { free(s->stk); s->max = s->ptr = 0; } } /*--- スタックにデータをプッシュ ---*/ int StackPush(Stack *s, int x, int i,char *a[]) { if (s->ptr >= s->max) return (-1); if(x>=i) { puts("プッシュできる文字データはありません。"); return (-1); } strcpy(&s->stk[s->ptr++],&(*a)[x]); x++; return x; } /*--- スタックからデータをポップ ---*/ int StackPop(Stack *s, int x,char *a[]) { if (s->ptr <= 0) /* スタックは空 */ return (-1); strcpy(&s->stk[--s->ptr],&(*a)[x]); return (0); } /*--- スタックからデータをピーク ---*/ int StackPeek(const Stack *s, int *x) { if (s->ptr <= 0) /* スタックは空 */ return (-1); *x = s->stk[s->ptr - 1]; return (0); } /*--- スタックの大きさ ---*/ int StackSize(const Stack *s) { return (s->max); } /*--- スタックに積まれているデータ数 ---*/ int StackNo(const Stack *s) { return (s->ptr); } /*--- スタックは空か ---*/ int StackIsEmpty(const Stack *s) { return (s->ptr <= 0); } /*--- スタックは満杯か ---*/ int StackIsFull(const Stack *s) { return (s->ptr >= s->max); } /*--- スタックを空にする ---*/ void StackClear(Stack *s) { s->ptr = 0; } int main(void) { int i=0,j,ret,x=0; char *a[NUMBER]; char buffer[20]; FILE *fpin; Stack s; fpin=fopen("input2.txt","r"); //テキストファイルを読み取りモードで開く while(fgets(&buffer[0],sizeof(buffer),fpin) !=NULL ) { if(i>=NUMBER)//読み込む人数がNUMBERを超えてる時の処理 { puts("人数が100人を超えています"); goto END; } strcpy(&a[i][0],&buffer[0]); /*ret=sscanf(&buffer[0],"%s",&a[i][0]); //データ文字列を3分割 if(ret!=1) //1に分割できなかったときの処理 { puts("代入された入力項目の個数が3でありません"); goto END; }*/ i++; } for(j=0; j<i; j++) printf("%s\n",&(*a)[j]); if (StackAlloc(&s, 100) == -1) { puts("スタックの確保に失敗しました。"); return (1); } while (1) { int m; printf("現在のデータ数:%d/%d\n", StackNo(&s), StackSize(&s)); printf("(1) プッシュ (2) ポップ (0) 終了:"); scanf("%d", &m); if (m == 0) break; switch (m) { case 1: printf("データ:"); puts("こんちくしょ~"); if(StackPush(&s, x,i,&(*a)) == -1) puts("スタックへのプッシュに失敗しました。"); break; case 2: if(StackPop(&s, x,&(*a)) == -1) puts("ポップできません。"); else printf("ポップしたデータは%sです。\n", &s.stk[s.ptr]); break; } } StackFree(&s); END: fclose(fpin); return (0); }

  • 構造体へのポインタ

    すみません、構造体へのポインタの配列の扱いに困っています。 下記ソースの struct list *hashtable[HASHSIZE]; の箇所をmain部に入れた場合の 他の関数内での使用の仕方が全くわかりません。 どのように修正すれば良いのでしょうか。 申し訳ありませんが教えてください。 --------------------- #include <stdio.h> #include <stdlib.h> #include <string.h> #define HASHSIZE 40 #define MAX_KW_LEN 256 #define NUM_KW 23 #define TRUE 1 #define FALSE 0 struct list {  char keyword[MAX_KW_LEN];  struct list *next;   /* 次の list へのポインタ */ }; struct list *hashtable[HASHSIZE]; /* ハッシュテーブル */ /* キーワード ( Cの予約語 ) */ static char kw[NUM_KW][MAX_KW_LEN] = {   "auto", "break", "double",   "enum", "char", "continue", "extern", "float", "for", "int",   "long", "register", "short", "signed", "static",   "struct", "typedef", "union", "unsigned", "return",   "void", "volatile", "while" }; int Hash(char *key); void InitHTable(void); int FindKeyWord(char *key); void ListKeyWord(void); void FreeKeyWord(void); int main(void); int Hash(char *key) {  int hashval = 0;  while (*key != '\0')   hashval += *key++;  return (hashval % HASHSIZE); } void InitHTable(void) {  int i;  struct list *p, *q;  int hashval;  for (i = 0; i < NUM_KW; i++) {   printf("%d\n",i);   if ((FindKeyWord(kw[i])) == FALSE) { /* 登録されていなかったら */             /* メモリを割り付ける */    if ((p = (struct list *)malloc(sizeof(struct list))) == NULL) {     fprintf(stderr, "メモリ不足です。\n");     exit(2);    }    strcpy((*p).keyword, kw[i]);    hashval = Hash(kw[i]);    /* ハッシュ値を求めて */        if (hashtable[hashval] == NULL) { /* 未登録なら */     hashtable[hashval] = p;  /* p の指すアドレスを登録 */     p->next = NULL;    /* リストの末尾に NULL を追加 */    }    else {        /* 既に登録していたら */     q = hashtable[hashval];     while (q->next != NULL) {  /* データがなくなるまで */      q = q->next;    /* リストをたどる */     }     q->next = p;     /* リストの末尾に p の指すアドレスを登録 */     p->next = NULL;    /* その末尾に NULL を追加 */    }   }  } } int FindKeyWord(char *key) {  struct list *p;  for (p = hashtable[Hash(key)]; p != NULL; p = p->next)   if (!strcmp(key, (*p).keyword))  /* 登録済みなら */    return (TRUE);     /* TRUE を返す */   return (FALSE);      /* 未登録ならFALSE を返す */ } void ListKeyWord(void) {  int i;  struct list *p;  for (i = 0; i < HASHSIZE; i++)   for (p = hashtable[i]; p != NULL; p = p->next) /* p が NULL でなければ */               /* ハッシュ値とキーワードを表示 */    printf("予約語:%s ハッシュ値:%d:\n", (*p).keyword, Hash((*p).keyword)); } /* malloc( ) で割り付けたメモリを解放 */ void FreeKeyWord(void) {  int i;  struct list *p, *q;  for (i = 0; i < HASHSIZE; i++)   for (p = hashtable[i]; p != NULL; ) { /* p が NULL でなければ */    q = p->next;      /* p->next を保存 */    free(p);       /* メモリを解放 */    p = q;        /* p->next を p に代入 */   } } int main(void) {  char word[MAX_KW_LEN];  int i;  InitHTable( );  ListKeyWord( );  for (i = 0; i < 4; i++) {   printf("Cの予約語を入力して下さい ");   fgets(word, 128, stdin);   if ((FindKeyWord(word)) == TRUE)    printf("%s は登録済みです。\n", word);   else    printf("%s は未登録です。\n", word);  }  FreeKeyWord( ); }