🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

5回答

4949閲覧

c言語でハッシュ表を実装したいです

kyapi

総合スコア5

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

0クリップ

投稿2021/01/08 08:09

編集2021/01/12 15:05

前提・実現したいこと

ハッシュ表をチェイン法で実現したいです
検索する関数とエラー関数で以下のエラーメッセージが発生しました。

発生している問題・エラーメッセージ

該当のソースコード

#include <stdio.h> #include <stdlib.h> /* ハッシュ法の定義 */ #define BUCKET_SIZE 10 /* ハッシュ表の大きさ */ typedef struct cell{ int key; double data; struct cell *next; } CELL; /* ハッシュ表の本体はCELL型ポインタの配列として実現している */ CELL table[BUCKET_SIZE]; /* init --ハッシュ表を初期化する ハッシュ表に含まれる全てのパケットにNULLをセット ハッシュ表を使う前に必ずセットしなければならない */ void init() { int i; /* BCKET_SIZEだけ繰り返して table[i]の中をNULLにして空にする */ for(i=0; i<BUCKET_SIZE; i++) table->next = NULL; } /* エラーメッセージをプリントしてexitする関数 */ /* ポインタ(アドレス)の先のデータを読み取り専用にする */ void fatal_error(char *s) { /* fprintf関数を使ってstderrで標準エラーを出力する*/ fprintf(stderr,"%s\n",s); exit(1); /* 異常終了 */ } /* ハッシュ値を計算する関数 パラメータとしてキーを与えると そのキーに対するハッシュ値(int型)を返す*/ int hash(int s) //修正 { /* キーの値を二乗してその中央値をとることで均等にしている */   return(s % BUCKET_SIZE); } /* find -- ハッシュ表を探索する 探したいキーの値をパラメータとして受け取る 成功したらキーを持つDATAへのポインタを返す (構造体CELL型のメンバdataへのポインタ) 見つからなければNULLを返す */ CELL *find(int key) { CELL *p; /* p=table[hash(key)]でそのキーが所属しているべきバケットから 連結リストへのポインタを取り出している for文本体では連結リストをたどりながら線形探索する */ for(p=&table[hash(key)]; p!=NULL; p=p->next) /* もし2つのキーが等しければ成功 */ if(key==p->key) /* キーを持つDATAへのポインタを返す */ return p;//&p->data; else /* 等しくなければ見つからないとしてNULLを返す*/ return NULL; } return NULL; } /* insert -- ハッシュ表にデータを挿入する 2つのパラメータを受け取る ①keyは挿入されるデータ持っているキーの値 ②dataはDATA *型で挿入されるデータへのポインタ データを登録する際に同じキーを持つデータがすでに登録されているかどうかをチェックする キーが重複していない場合、登録に成功したら1を返す 登録に失敗(すでに同じキーを持つデータがある) したら0を返す */ int insert(int key,double data) { CELL *p; int h; /* キーが重複していないか関数findを呼び出してチェックする 重複していたら0を返す もしNULLでないなら重複していない */ if(find(key) != NULL) return 0; /* もし重複していないなら関数mallocを呼び出し、 データを格納するセルを割り当てる */ if((p=malloc(sizeof(CELL))) == NULL){ /* もしセルの割り当てに失敗したらプログラムの実行を中止する */ fprintf(stderr,"out of momory\n"); exit(2); } /* セルを割り当てたらセルにキーとデータをセットして キーの値に対応するバケットに連結する*/ h=hash(key); p->key=key; p->data=data;//*dataだった p->next=&table[h]; table[h]=*p; return 1; } /* delete -- ハッシュ表から削除する 削除したいキーを受け取る 該当するキーを持ったデータが存在し、 削除に成功したら1を返す 該当するキーを持ったデータが見つからなければ何もしないで、 0を返す */ /* 最初にバケットを決め、 そのバケットに属する連結リストに対して削除の処理を行う */ int delete(int key) { int h; CELL *p,*q; h=hash(key); /* そのバケットは空か */ if(&table[h] == NULL) return 0; /* リストの先頭のセルが削除すべきデータか? */ if(key==table[h].key){ p=&table[h]; table->next=p->next;//&table[h]=p->next; free(p); /* 削除に成功したら1を返す */ return 1; } //構造体配列の場合、ここからの文がなくても削除できる /* リストの二番目以降のセルについて順番にチェックする */ for(q=&table[h],p=q->next; p!=NULL; q=p,p=p->next){ if(key==p->key){ q->next=p->next; free(p); /* 削除に成功したら1を返す */ return 1; } } /* 該当するキーを持ったデータが見つからなければ 削除に失敗したとして0を返す */ return 0; } static void hash_print(void) { int i; CELL *current = NULL; /* バケットの数だけ繰り返す */ for(i = 0; i < BUCKET_SIZE; i++){ if(&table[i] != NULL){ printf("table[%d]",i); /* currentをi番目にしておく */ current = &table[i]; /* currentがNULLでない間、次々表示させる*/ for(; current != NULL; current = current->next){ printf(" key=%d", (current->key)); printf(" data=%f", (current->data)); } printf("\n"); } } } int main(void) { /* ハッシュ表を初期化する */ init(); int key; /* 数字を入力するための配列変数 */ double data; int hashval; /* hash関数のハッシュ値を受け取る変数 */ int mn=0; /* メニュー選択の数字を入れる変数 */ int a; /* insert関数の戻り値を受け取る変数 */ int c; /* delete関数の戻り値を受け取る変数 */ CELL *fp; /* find関数の戻り値を受け取る変数 */ printf("チェイン法をします\n"); do{ printf("メニューを選んでください\n1=追加 2=検索 3=削除 4=ひょうじ 9=終了\n"); scanf("%d",&mn); switch(mn){ case 1: printf("8桁の数字を入力してください\n"); scanf("%d",&key); printf("データを入力してください\n"); scanf("%lf",&data); /* ハッシュ値を得る */ hashval=hash(key); printf("数字=%d ハッシュ値=%d\n",key,hashval); a=insert(key,data); if(a==1) printf("Done\n"); else printf("AlreadyExsits\n"); break; case 2: printf("検索する8桁の数字を入力してください\n"); scanf("%d",&key); fp=find(key); if(fp==NULL) printf("NotExsits\n"); else printf("key=%d 検索した値=%f\n",fp->key,fp->data); break; case 3: printf("削除する8桁数字を入力してください\n"); scanf("%d",&key); c=delete(key); if(c==1) printf("Done\n"); else printf("NotExsits\n"); break; case 4: printf("ひょうじします\n"); /* リストの要素の値を表示する */ hash_print(); break; case 9: printf("終了します\n"); break; default: printf("エラー:メニューの中の数字を入力してください\n"); } }while (mn !=9); return 0; }

3つの警告と1つのエラーが出ています

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hoshi-takanori

2021/01/08 08:39

fatal_error は引数 s に `%` が含まれていると問題が発生しますので、fprintf(stderr, "%s", s); とか fprintf(stderr, "Fatal Error: %s\n", s); のようにすると良いでしょう。 find は引数が int key なのに char の配列を渡してるところがあります。他にも hash の引数とかいろいろ怪しいですね…。
kyapi

2021/01/08 10:12

find の中は(char key)とかにした方が良いですか?? hashの引数とかは(p=table[hash(key)]の書き方がいけないということですか
tatsu99

2021/01/09 02:41 編集

ハッシュ値を作成する8桁の数字は、hashに文字列として渡すのですね。 これは、学籍番号ですか。 学籍番号は、00000000~99999999の数字を入力する前提で良いですか。 (学籍番号が123の場合は00000123と入力する) insertへdouble型のデータを渡すようになっていますが、main側ではそのデータをを渡してないですね。 このdouble型のデータは、どのような意味のデータですか?
kyapi

2021/01/09 06:51

はい!8桁の数字ならなんでも良いです!分かりにくかったので数字に直しました、 すみません、mainの中が消えていました、追加しました。 double型のデータはハッシュ表を理解するためなので特に意味は無く、とりあえずデータを格納して、 まだ不完全ですがcase4で全て表示したいです
tatsu99

2021/01/10 05:10

インデントがずれてますね。 ```ここに言語を入力 コード ``` が表示されたとき ```① ② ``` ①の個所にCと入力し ②の個所にあなたのソースを貼り付けます。 つまり、以下のようにします。 ```C あなたのソースをはりつけたもの ``` そうすると、きれいに、インデントがそろいます。
kyapi

2021/01/10 05:22

すみません、ここのソースコードの記載の仕方が中々慣れなくて、、 なおしました
tatsu99

2021/01/10 05:26

まだ、直ってませんが、とりあえず、回答欄のコメントにこれから回答します。
guest

回答5

0

find ですが、for文の中でキーが一致してもしなくても return すると
リストの先頭のキーしか見ていないことになります。

C

1CELL *table[BUCKET_SIZE]; 2 3CELL *find(int key) 4{ 5 for (CELL *p = table[hash(key)]; p != NULL; p = p->next) 6 if (key==p->key) return p; 7 return NULL; 8} 9 10int insert(int key, double data) 11{ 12 CELL *p = find(key); 13 if (p != NULL) return 0; 14 p = malloc(sizeof(CELL)); 15 if (p == NULL) { fprintf(stderr, "out of momory\n"); exit(2); } 16 int h = hash(key); 17 p->key = key; p->data = data; p->next = table[h]; 18 table[h] = p; 19 return 1; 20} 21 22int delete(int key) 23{ 24 int h = hash(key); 25 CELL *p, *q = table[h]; 26 if (q == NULL) return 0; 27 if (key == q->key) { p = q->next; free(q); table[h] = p; return 1; } 28 for (p = q->next; p != NULL; q = p, p = q->next) 29 if (key == p->key) { q->next = p->next; free(p); return 1; } 30 return 0; 31} 32 33void hash_print(void) 34{ 35 for (int i = 0; i < BUCKET_SIZE; i++) { 36 if (table[i] != NULL) { 37 printf("table[%d]", i); 38 for (CELL *p = table[i]; p != NULL; p = p->next) 39 printf(" key=%d data=%f", p->key, p->data); 40 printf("\n"); 41 } 42 } 43}

追記
table をポインタの配列にしたときに、
リストの先頭と 2番目以降を同等に扱うコードは書けます。

C

1CELL *table[BUCKET_SIZE]; 2 3int delete(int key) 4{ 5 for (CELL **p = &table[hash(key)], *q; q = *p; p = &q->next) 6 if (q->key == key) { *p = q->next; free(q); return 1; } 7 return 0; 8}

追記2
連結リストの先頭にダミーノードを置くと、確かに削除処理が簡単になります。
質問の現在のコードを次のように修正すると、
ポインタの配列ではなく構造体の配列でできます。

diff

1 for(i=0; i<BUCKET_SIZE; i++) 2- table->next = NULL; 3+ table[i].next = NULL; 4 } 5 6 /* キーの値を二乗してその中央値をとることで均等にしている */ 7-  return(s % BUCKET_SIZE); 8+ return(s % BUCKET_SIZE); 9 } 10 11- for(p=&table[hash(key)]; p!=NULL; p=p->next) 12+ for (p = table[hash(key)].next; p!=NULL; p=p->next) 13 /* キーを持つDATAへのポインタを返す */ 14 return p;//&p->data; 15- else 16- /* 等しくなければ見つからないとしてNULLを返す*/ 17- return NULL; 18- } 19+ /* 等しくなければ見つからないとしてNULLを返す*/ 20 return NULL; 21 } 22 23 p->data=data;//*dataだった 24- p->next=&table[h]; 25- table[h]=*p; 26+ p->next = table[h].next; 27+ table[h].next = p; 28 return 1; 29 } 30 31 32 h=hash(key); 33- /* そのバケットは空か */ 34- if(&table[h] == NULL) 35- return 0; 36- /* リストの先頭のセルが削除すべきデータか? */ 37- if(key==table[h].key){ 38- p=&table[h]; 39- table->next=p->next;//&table[h]=p->next; 40- free(p); 41- /* 削除に成功したら1を返す */ 42- return 1; 43- } 44-//構造体配列の場合、ここからの文がなくても削除できる 45- /* リストの二番目以降のセルについて順番にチェックする */ 46 for(q=&table[h],p=q->next; p!=NULL; q=p,p=p->next){ 47 if(key==p->key){ 48 q->next=p->next; 49 50 for(i = 0; i < BUCKET_SIZE; i++){ 51- if(&table[i] != NULL){ 52+ if(table[i].next != NULL){ 53 printf("table[%d]",i); 54 /* currentをi番目にしておく */ 55- current = &table[i]; 56+ current = table[i].next;

  return(s % BUCKET_SIZE); は return の前が全角スペースでした。
本当にコンパイルできたコードを貼り付けていますか?
また、コメントが嘘になっています。

find の中の else の部分は削除しました。
delete の中の不要な部分を大きく削除しました。
hash_print は、ダミーノードの次からを表示します。

投稿2021/01/12 13:54

編集2021/01/13 00:43
kazuma-s

総合スコア8224

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kyapi

2021/01/13 02:58 編集

丁寧にありがとうございます!!実行できました、とても助かります! 申し訳ございません。貼り付けた後にコメントを消したりしたので全角スペースが入ったようです、以後気を付けます コメントが大嘘で申し訳ないです、理解しながら書き換えていきます >hash_print は、ダミーノードの次からを表示 なるほど、そういうことだったのですね!!ありがとうございます!
guest

0

ベストアンサー

>Main.c:72:1:警告:非void関数がすべての制御パスで値を返すわけではありません
インデントを修正し、{}を付加すると以下のようになります。

C

1double *find(int key) 2{ 3CELL *p; 4 /* p=table[hash(key)]でそのキーが所属しているべきバケットから 5 連結リストへのポインタを取り出している 6 for文本体では連結リストをたどりながら線形探索する */ 7 for(p=table[hash(key)]; p!=NULL; p=p->next){ 8 /* もし2つのキーが等しければ成功 */ 9 if(key==p->key) 10 /* キーを持つDATAへのポインタを返す */ 11 return &p->data; 12 else 13 /* 等しくなければ見つからないとしてNULLを返す*/ 14 return NULL; 15 } 16 //コンパイラはここにreturnがないと言ってます。・・・① 17} 18

①の個所は、for(p=table[hash(key)]; p!=NULL; p=p->next){で
p=NULLとなったときに、①に遷移しますので、
このケースのことを考慮しなさい、とコンパイラは言っています。
但し、ワーニングなので、「そんなケースは発生しない」と断言できるなら無視しても構いません。

投稿2021/01/10 05:35

編集2021/01/10 05:37
tatsu99

総合スコア5493

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kyapi

2021/01/10 15:34

インデントが直らなくて申し訳ありません なるほど、そのような意味だったのですね、ありがとうございます! 断言できないのでつけるべきなのですね、 詳しく解説ありがとうございます また質問するかもしれませんが何卒よろしくお願いいたします
kazuma-s

2021/01/10 15:59

インデントが直らないのは「```」の使い方が無茶苦茶だからです。 エラーメッセージ `Main.c:72:1: warning: non-void function does not return a value in all control paths [-Wreturn-type] 3 warnings and 1 error generated. `` なぜ、1個の「`」や、2個の「``」を書くんですか? ```c ```c ```#include <stdio.h> なぜ、「```c」を 2つも書くんですか? それも全角の「c」で。 なぜ、「#include」の行に「```」を書くんですか? コード ```c コード ``` これは何ですか? 書くべき「```」は次の4つだけです。 エラーメッセージ ``` Main.c:72:1: warning: non-void function does not return a value in all control paths [-Wreturn-type] 3 warnings and 1 error generated. ``` ```C #include <stdio.h>  ...  return 0; } ``` 今すぐ直してください。
kyapi

2021/01/12 10:42

申し訳ございません、直しました
guest

0

paizaコンパイルし、エラーがないことを確認しました。実際の動作確認はしていません。
(参考にしてください)

C

1#include <stdio.h> 2#include <stdlib.h> 3 4/* ハッシュ法の定義 */ 5#define BUCKET_SIZE 10 /* ハッシュ表の大きさ */ 6 7typedef struct cell{ 8 int key; 9 double data; 10 struct cell *next; 11} CELL; 12/* ハッシュ表の本体はCELL型ポインタの配列として実現している */ 13CELL *table[BUCKET_SIZE]; 14 15/* init --ハッシュ表を初期化する 16 ハッシュ表に含まれる全てのパケットにNULLをセット 17 ハッシュ表を使う前に必ずセットしなければならない */ 18void init() 19{ 20 int i; 21 /* BCKET_SIZEだけ繰り返して 22 table[i]の中をNULLにして空にする */ 23 for(i=0; i<BUCKET_SIZE; i++) 24 table[i]=NULL; 25} 26 27/* エラーメッセージをプリントしてexitする関数 */ 28/* ポインタ(アドレス)の先のデータを読み取り専用にする */ 29void fatal_error(char *s) 30{ 31 /* fprintf関数を使ってstderrで標準エラーを出力する*/ 32 fprintf(stderr,"%s\n",s); 33 exit(1); /* 異常終了 */ 34 35} 36/* ハッシュ値を計算する関数 37 パラメータとしてキーを与えると 38 そのキーに対するハッシュ値(int型)を返す*/ 39int hash(int s) //修正 40{ 41 /* キーの値を二乗してその中央値をとることで均等にしている */ 42 return(s % BUCKET_SIZE); 43} 44 45/* find -- ハッシュ表を探索する 46 探したいキーの値をパラメータとして受け取る 47 成功したらキーを持つDATAへのポインタを返す 48 (構造体CELL型のメンバdataへのポインタ) 49 見つからなければNULLを返す */ 50 51CELL *find(int key) //修正 52{ 53 CELL *p; 54 /* p=table[hash(key)]でそのキーが所属しているべきバケットから 55 連結リストへのポインタを取り出している 56 for文本体では連結リストをたどりながら線形探索する */ 57 for(p=table[hash(key)]; p!=NULL; p=p->next){ 58 /* もし2つのキーが等しければ成功 */ 59 if(key==p->key) 60 /* キーを持つDATAへのポインタを返す */ 61 return p; 62 else 63 /* 等しくなければ見つからないとしてNULLを返す*/ 64 return NULL; 65 } 66 return NULL; 67} 68 69/* insert -- ハッシュ表にデータを挿入する 70 2つのパラメータを受け取る 71 ①keyは挿入されるデータ持っているキーの値 72 ②dataはDATA *型で挿入されるデータへのポインタ 73 データを登録する際に同じキーを持つデータがすでに登録されているかどうかをチェックする 74 キーが重複していない場合、登録に成功したら1を返す 75 登録に失敗(すでに同じキーを持つデータがある) 76 したら0を返す */ 77 78int insert(int key,double data) 79{ 80 CELL *p; 81 int h; 82 83 /* キーが重複していないか関数findを呼び出してチェックする 84 重複していたら0を返す 85 もしNULLでないなら重複していない */ 86 if(find(key) != NULL) 87 return 0; 88 /* もし重複していないなら関数mallocを呼び出し、 89 データを格納するセルを割り当てる */ 90 if((p=malloc(sizeof(CELL))) == NULL){ 91 /* もしセルの割り当てに失敗したらプログラムの実行を中止する */ 92 fprintf(stderr,"out of momory\n"); 93 exit(2); 94 } 95 /* セルを割り当てたらセルにキーとデータをセットして 96 キーの値に対応するバケットに連結する*/ 97 h=hash(key); 98 p->key=key; 99 p->data=data; 100 p->next=table[h]; 101 table[h]=p; 102 return 1; 103} 104 105/* delete -- ハッシュ表から削除する 106 削除したいキーを受け取る 107 該当するキーを持ったデータが存在し、 108 削除に成功したら1を返す 109 該当するキーを持ったデータが見つからなければ何もしないで、 110 0を返す */ 111 /* 最初にバケットを決め、 112 そのバケットに属する連結リストに対して削除の処理を行う */ 113int delete(int key) 114{ 115 int h; 116 CELL *p,*q; 117 118 h=hash(key); 119 /* そのバケットは空か */ 120 if(table[h] == NULL) 121 return 0; 122 /* リストの先頭のセルが削除すべきデータか? */ 123 if(key==table[h]->key){ 124 p=table[h]; 125 table[h]=p->next; 126 free(p); 127 /* 削除に成功したら1を返す */ 128 return 1; 129 } 130 /* リストの二番目以降のセルについて順番にチェックする */ 131 for(q=table[h],p=q->next; p!=NULL; q=p,p=p->next){ 132 if(key==p->key){ 133 q->next=p->next; 134 free(p); 135 /* 削除に成功したら1を返す */ 136 return 1; 137 } 138 } 139 /* 該当するキーを持ったデータが見つからなければ 140 削除に失敗したとして0を返す */ 141 return 0; 142} 143 144 145 146static void hash_print(void) 147{ 148 int i; 149 CELL *current = NULL; 150 /* バケットの数だけ繰り返す */ 151 for(i = 0; i < BUCKET_SIZE; i++){ 152 if(table[i] != NULL){ 153 printf("table[%d]:{",i); 154 /* currentをi番目にしておく */ 155 current = table[i]; 156 /* currentがNULLでない間、次々表示させる*/ 157 for(; current != NULL; current = current->next){ 158 printf("{%d:", (current->key)); 159 printf("%f}", (current->data)); 160 } 161 printf("}\n"); 162 } 163 } 164} 165 166int main(void) 167{ 168 /* ハッシュ表を初期化する */ 169 init(); 170 int n; /* 数字を入力するための配列変数 */ 171 double data; 172 int hashval; /* hash関数のハッシュ値を受け取る変数 */ 173 int mn=0; /* メニュー選択の数字を入れる変数 */ 174 int a; /* insert関数の戻り値を受け取る変数 */ 175 int c; /* delete関数の戻り値を受け取る変数 */ 176 CELL *fp; /* find関数の戻り値を受け取る変数 */ 177 178 printf("チェイン法をします\n"); 179 do{ 180 printf("メニューを選んでください\n1=追加 2=検索 3=削除 4=ひょうじ 9=終了\n"); 181 scanf("%d",&mn); 182 switch(mn){ 183 184 case 1: 185 printf("8桁の数字を入力してください\n"); 186 scanf("%d",&n); 187 printf("データをを入力してください\n"); 188 scanf("%lf",&data); 189 /* ハッシュ値を得る */ 190 hashval=hash(n); 191 printf("数字=%d ハッシュ値=%d\n",n,hashval); 192 a=insert(n,data); 193 if(a==1) 194 printf("Done\n"); 195 else 196 printf("AlreadyExsits\n"); 197 break; 198 199 case 2: 200 printf("検索する8桁の数字を入力してください\n"); 201 scanf("%d",&n); 202 fp=find(n); 203 if(fp==NULL) 204 printf("NotExsits\n"); 205 else 206 printf("key=%d 検索した値=%f\n",fp->key,fp->data); 207 break; 208 209 case 3: 210 printf("削除する8桁数字を入力してください\n"); 211 scanf("%d",&n); 212 c=delete(n); 213 if(c==1) 214 printf("Done\n"); 215 else 216 printf("NotExsits\n"); 217 break; 218 219 case 4: 220 printf("ひょうじします\n"); 221 /* リストの要素の値を表示する */ 222 hash_print(); 223 break; 224 225 case 9: 226 printf("終了します\n"); 227 break; 228 229 default: 230 printf("エラー:メニューの中の数字を入力してください\n"); 231 } 232 }while (mn !=9); 233 return 0; 234} 235

投稿2021/01/10 03:44

tatsu99

総合スコア5493

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kyapi

2021/01/10 15:21

参考にさせていただきます! ありがとうございます!!
kyapi

2021/01/12 14:47 編集

CELL型ポインタの配列としては完璧に動くようになりました!! しかし構造体配列のCELL table[BUCKET_SIZE];にして、&をつけたり変更したのですが、2つの箇所だけなぜか同じように変更してもエラーが出てしまいます ソースコードも編集いたしました Main.c:24:19:エラー:式を割り当てることができません &table [i] = NULL; ~~~~~~~~~ ^ Main.c:130:18:エラー:式を割り当てることができません &table [h] = p-> next; ~~~~~~~~~ ^ 2つのエラーが生成されました。 式が割り当てられないのはどういうことなのでしょうか、
tatsu99

2021/01/12 11:36

>CELL型ポインタの配列としては完璧に動くようになりました!! >しかし構造体配列のCELL table[BUCKET_SIZE];にして なぜ、CELL table[BUCKET_SIZE];にしたいのかが、よくわかりませませんが、どうしても そのようにして、実装したいということでしょうか。
kazuma-s

2021/01/12 13:44

> 式が割り当てられないのはどういうことなのでしょうか、 「代入する」の assign を「割り当てる」と誤訳しているのでしょう。 「&table[i] という式に NULL を代入することができません」という意味です。 &table[i] は式であり、値です。変数ではありません。
kyapi

2021/01/12 14:55 編集

tastsu99さん 何度も編集してしまったので通知がたくさん来ていたら申し訳ございません。 はい、連結リストのときに*をつけて宣言したときに削除の仕方がリストの先頭と、それ以外で異なりますが構造体の変数にしたときにこの境界条件をしなくても削除できるようになったので実装したいと思っています。 上のソースコードを直しました。一応、上のプログラムでエラーは出ずに、追加、削除、検索はできるのですが、 なぜかcase4の表示でバグってしまいます
kyapi

2021/01/12 14:55 編集

kazuma-sさん 何度も編集してしまったので通知がたくさん来ていたら申し訳ございません。 そのような意味だったのですね、ありがとうございます &table[i] は式、値なのですね、ではNULLを代入するためには&table[i]は使えないということになり、 一つ目のエラーを void init() { int i; /* BCKET_SIZEだけ繰り返して table[i]の中をNULLにして空にする */ for(i=0; i<BUCKET_SIZE; i++)   &table [i] = NULL; //table->next = NULL;として次々NULLにしていく } table->next = NULL;にすることでもとのプログラムとあまり意味を変えずに変更できていますか?一応エラーはでていませんが、、
guest

0

ソースをコピペしてこちらでコンパイルしてみました。
かなりエラーがでたので、その個所について指摘します。
32行  fprintf(stderr,%s,s);
fprintf(stderr,"%s\n",s);
に変更する。

39行 int hash(int *s)
int hash(int s)に変更する。
どのようなハッシュ値を生成したいのかが不明なので、
とりあえず、以下のような値を返すようにしておく。
while(*s)
i += *s++;
上記2行をコメントにし、
return(s % BUCKET_SIZE);
に変更する。

上記の変更により、hashの呼び出し側も変更する。
文字列で渡すのではなく、int型のデータを渡すにする。
char n[9];ではなく
int n;にして
scanf("%d",&n);(3か所)
にする。

58行 double data *find(int key)
double *find(int key)
に変更する。
私は
CELL *find(int key)
のほうが良いと思う。
そうすれば、dataだけでなく、keyの情報なども呼び出し側で表示できるため。

そのほかにもかなりエラーがでます。
一旦、上記を修正して、エラーをとれるところまで、とったソースを
アップし直してください。
どうしても取れないエラーがあれば、再度、そのエラーも提示してください。

投稿2021/01/10 00:18

tatsu99

総合スコア5493

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kyapi

2021/01/10 05:08

詳しくありがとうございます、 エラーがたくさん出てしまい申し訳ありません、 なんとか3つの警告と1つのエラーまで修正することができました。 日本語にすると Main.c:72:1:警告:非void関数がすべての制御パスで値を返すわけではありません[-Wreturn-type] } ^ {}の数は合っているはずなのですが、なぜでしょうか Main.c:104:10:エラー:間接参照にはポインタオペランドが必要です(「double」は無効です) p-> data = * data; ^ ~~~~ doubleが無効の意味が理解できません Main.c:210:14:警告:「double *」から「int」に割り当てられている整数変換への互換性のないポインター[-Wint-conversion] f = find(key); ^ ~~~~~~~~~ Main.c:211:17:警告:ポインターと整数の比較(「int」と「void *」)[-Wpointer-integer-compare] if(f == NULL) 〜^ ~~~~ ここら辺は関数の戻り値の代入の仕方が違うのでしょうか
tatsu99

2021/01/10 06:00 編集

>Main.c:72:1:警告:非void関数がすべての制御パスで値を返すわけではありません 別途、新規回答欄に書きます。 >Main.c:104:10:エラー:間接参照にはポインタオペランドが必要です(「double」は無効です) int insert(int key,double data)により dataはdouble型です。 int insert(int key,double *data)なら話はべつですが、 p-> data = data; にしてください。 >Main.c:210:14:警告:「double *」から「int」に割り当てられている整数変換への互換性のないポインター これは、 double *find(int key) により、double型へのポインターが返ります。 よって、 int f; /* find関数の戻り値を受け取る変数 */ ではなく、 double *f; にしなさいといっています。 >Main.c:211:17:警告:ポインターと整数の比較(「int」と「void *」) 前のint f;を修正すれば、ここは直ります。 int f;と定義して if(f == NULL)と書くのは、変です。
guest

0

エラーが出ているのは、

Main.c:58:12: error: expected ';' after top level declarator

double data *find(int key)

これですんで、ここんところのコードを提示しましょう

Main.c:32:20: warning: format string is not a string literal (potentially insecure) [-Wformat-security]

これはワーニングです。無視しても構いません


double data *find(int key)

data というのはナニモノでしょうか。
C言語のコードとして解釈不能なのでエラーが出てますね

投稿2021/01/08 08:13

編集2021/01/10 00:24
y_waiwai

総合スコア88038

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kyapi

2021/01/10 03:52

エラー関数は無視して良いのですね、 入力するデータのことなのですがこの書き方が間違っているんですね、直します ありがとうございます
y_waiwai

2021/01/10 04:13

error じゃなくて、warningと書いてあるメッセージは、警告、です。 文法に間違いはなく、正常にコンパイルできる、んだけど、バグの可能性がある記述、というふうに受け取りましょう 実際にバグの場合もあるし、プログラマが承知の上で記述した余計なお世話の場合もあります。 まあ、この場所でなぜ警告が出たのか、は理解しておいたほうがいいかと思いますが。
kyapi

2021/01/10 05:05

なるほど、そうだったのですね、 エラー関数は警告がでないようにできました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問