• ベストアンサー

線形探索のエラーがでて困っています

線形探索を用いて表を作るプログラムを作ったのですが、データの数が10000ならば作動するのですが、それ以上になってしまうとセグメントエラーが起こります。なぜだが教えていただけないでしょうか? #include <stdio.h> #include <stdlib.h> #include <time.h> #define N 1000000 #define M 10 typedef int Key; typedef struct item{ Key key; }Item; struct table { int n; Item item[N]; }; typedef struct table *Table; Item *lookup_item(Table table ,Key key){ int i=0; while(1){ if(i==table->n) return (0); if(table->item[i].key==key) return &(table->item[i]); i++; } return 0; } int add_item(Table table, Item item){ int i; int n=table->n; if(lookup_item(table ,item.key)!=0) return (0); else { table->item[n].key=item.key; table->n++; return (1); } } Table new_table(){ Table table; table = (Table)malloc(sizeof(table)); return table; } int remove_item(Table table, Key key){ int i=0; int n=table->n; if(lookup_item(table,key)!=0) { while(1){ if(table->item[i].key==key){ table->item[i].key=table->item[n-1].key; table->n--; return 1; } i++; } } else return (0); } Key keys[N]; int main() { Table table; Item item; clock_t t1, t2; char buff[128]; int i, j, n; /* ファイルからキーを読み込み keys[] に格納する。*/ for (n=0; n<N && fgets(buff, 128, stdin)!=NULL; n++) { keys[n] = atoi(buff); } /* 表を用意する。*/ table = new_table(); /* 追加項目数と全項目の追加に必要な時間(秒単位)を印字する。*/ t1 = clock(); for (i=j=0; i<n; i++) { item.key = keys[i]; j += add_item(table, item); } t2 = clock(); printf("%d %.3f\n", j, (double)(t2-t1)/CLOCKS_PER_SEC); /* 探索成功数と全項目の探索に必要な時間(秒単位)を印字する。*/ t1 = clock(); for (i=j=0; i<n; i++) { if (lookup_item(table, keys[i])!=NULL) j++; } t2 = clock(); printf("%d %.3f\n", j, (double)(t2-t1)/CLOCKS_PER_SEC); /* 削除項目数と全項目の削除に必要な時間(秒単位)を印字する。*/ t1 = clock(); for (i=j=0; i<n; i++) { j += remove_item(table, keys[i]); } t2 = clock(); printf("%d %.3f\n", j, (double)(t2-t1)/CLOCKS_PER_SEC); return 0; } よろしくお願いします。

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

  • ベストアンサー
  • buriburi3
  • ベストアンサー率44% (353/792)
回答No.3

int add_item(Table table, Item item){ int i; int n=table->n; // ★★ ← ココで参照されているtable->nは値が初期化されていない。 if(lookup_item(table ,item.key)!=0) return (0); else { table->item[n].key=item.key; table->n++; return (1); } } typedef struct table *Table; Item *lookup_item(Table table ,Key key){ int i=0; while(1){ if(i==table->n) // ★★ ← 初期化していないからどんな値が入っているのかドキドキ return (0); if(table->item[i].key==key) return &(table->item[i]); i++; } return 0; } Table new_table(){ Table table; table = (Table)malloc(sizeof(table)); // ★★ ←領域を取っているが初期化していない table->n = 0 ; // ●● 思うにコレが抜けてるんじゃ… return table; }

sin1224
質問者

お礼

ありがとうございます! 指摘していただいたところを直したらプログラムが動きました。 自分はもう少しポインタを勉強すべきですね。

その他の回答 (2)

  • noocyte
  • ベストアンサー率58% (171/291)
回答No.2

> typedef struct table *Table; > (中略) > table = (Table)malloc(sizeof(table)); この2行しか見てませんが…(笑), 上の2行目の左辺は struct table の配列を期待しているのに, malloc() の引数はポインタのサイズになってます. まぎらわしいので1行目は typedef struct table Table; とした方がいいと思います.

sin1224
質問者

お礼

ご意見ありがとうございました。 やはりみなさん指摘したとおりこの初期化が間違ってるようですね。 プログラムは動きました。本当にありがとうございます。

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

できればOSとかコンパイラ含めた環境も書いて欲しいのですが、 table = (Table)malloc(sizeof(table)); return table; とりあえずここでメモリ確保に失敗してたりしませんか? この関数でもその上でも tableが有効なポインタであるか チェックしてませんよね。

sin1224
質問者

お礼

確保に失敗していました・・ ご指摘ありがとうございます。プログラムは動きました。やはりほかの関数でもチェックを入れたほうがいいのですね。

関連するQ&A

  • 線形探索について

    C言語の線形探索の課題なんですが 5つの整数を入力して その入力した値からみつけたい値を探索する課題なのですが #include <stdio.h> /*--- 要素数nの配列aからkeyと一致する要素を線形探索 ---*/ int search(const int a[], int n, int key) { int i = 0; while (1) { if (i == n) return (-1); /* 探索失敗 */ if (a[i] == key) return (i); /* 探索成功 */ i++; } } int main(void) { int i, ky, idx; int x[4]; int nx = sizeof(x) / sizeof(x[0]); printf("%d個の整数を入力してください。\n", nx); for (i = 0; i < nx; i++) { printf("x[%d]:", i); scanf("%d", &x[i]); } printf("探す値:"); scanf("%d", &ky); idx = search(x, nx, ky); /* 配列xから値がkyである要素を線形探索 */ if (idx == -1) puts("探索に失敗しました。"); else printf("%dは%d番目にあります。\n", ky, idx + 1); return (0); } ここまではわかるのですが、 x[0]=99 x[1]=99 x[2]=88 x[3]=99 x[4]=22 と入力したときに 99は 1番目に見つかりました 2番目に見つかりました 4番目に見つかりました と出力したいのですがうまくいきません 線形探索で同じ数値を探索するにはどうすればよいのですか?

  • 線形探索(番兵法)のプログラムについて。

    線形探索(番兵法)のプログラムについて考えています。 メイン関数からsearch関数に値を渡してそこで探索させるのですが、 int search(int a[], int n, int key) { int i = 0; a[n] = key; while (1) { if (a[i] == key) break; i++; } return (i == n ? -1 : i); } のwhileを使ったやり方からfor文を使ったやり方に変更したいと思っています。 色々な方法でプログラムを考えてみたいので。 そうすると、なんかうまくいきません。 for文だとどのように考えたらいいのでしょうか?

  • C言語<素数を求めるプログラム>

    #include<stdio.h> int j; int prime(int n) { int i; if(n < 2) return 0; if(n == 2) return 1; if(n%2 == 0) return 0; for(i = 3; i*i<= n; i += 2){ if(n%i == 0) return 0; } return 1; } int main(void) { int n; for(n=1; n <= 1000; n++) { if(prime(n)){ printf("%d\n",n); j++; } } printf("素数の個数は全部で %d 件見つかりました。\n",j); return 0; } このプログラムは1から1000までの素数のみを表示させるプログラムでありますが、このアルゴリズムが全くわかりません。 int prime(int n)の中身のアルゴリズムがどういう仕組みになっているのかお分かりになりますでしょうか?

  • クイックソートについて

    クイックソートのプログラムなんですが、 セグメンテーション違反で実行出来ません。 どこがおかしいのでしょうか? int main(void) { FILE *fp; int a[10],b=0,n; clock_t start; double jikan; if( (fp = fopen ("quicksort.txt","r") ) == NULL ) { printf("ファイルが見つかりません : quicksort.txt\n"); exit(1); } while( fscanf(fp, "%d", &a[b]) != EOF ) { b++; } start = clock(); quick_sort(a,n); jikan = clock() - start; for(n = 0; n < b ; ++n) { printf("%d ",a[n]); } printf("計算時間 %.3f 秒 \n", jikan/CLOCKS_PER_SEC); return 0; } int partition(int a[], int l, int r) { int i,j,pivot,t; i = l-1; j = r; pivot = a[r]; for(;;) { while( a[++i] < pivot ) ; while( i < --j && pivot < a[j] ) ; if( i >= j ) break; t=a[i]; a[i]=a[j]; a[j]=t; } t=a[i]; a[i]=a[r];a[r]=t; return i; } void quick_sort_1(int a[],int l,int r) { int v; if( l >= r ) return; v = partition( a, l, r); if( l < v-1 ) quick_sort_1( a, l, v-1); if( v+1 < r ) quick_sort_1( a, v+1, r); } void quick_sort(int a[],int n) { quick_sort_1( a, 0, n-1); }

  • 線形探索法のプログラムについて

    配列Aに格納されている数字を検索するプログラムより、 Aのプログラムでは配列Aに格納されている数字を検索(scanf("%d" , j)で入力)した にもかかわらず、「該当するデータがありませんでした」と表示されてしまいます。 Bのプログラムでは、配列Bに格納されている数字を検索(scanf("%d" , j)で入力)すると 「該当するデータがありました」と表示されます。 Aのプログラムで、------でかこってある部分に問題があると思われ、 いろいろと試してみましたが、未だにその理由をつかむことができません。 その理由を知りたく、書き込みを致しました。 ご教授の程宜しくお願い致します。 A. main(){ int i , j; int k = 0; int A[5] = {4 , 1 , 3 , 4 , 5}; printf("検索する数値を入力してください > "); scanf("%d" , j); --------------------------------------------------------------- for(i=0 ; i<5 ; i++){ if(A[i] == j){ printf("該当するデータはあります"); k++; } } --------------------------------------------------------------- if(k <= 0){ printf("該当するデータがありませんでした\n"); } return; } B #include<stdio.h> main(){ int i , j , k; int A[5] = {4 , 1 , 3 , 4 , 5}; printf("検索する数値を入力してください > "); scanf("%d" , j); for(i=0 ; i<5 ; i++){ if(A[i] == j){ k++; } } if(k>0){ printf("該当するデータはありました"); }else{ printf("該当するデータはありませんでした"); } return; }

  • 線形探索と二分探索

    線形探索と二分探索のプログラムを作成中です。 自力(本やwebに落ちているサンプルを参考にして)でここまで作りましたが正直自信がありません。どうかお願いします。 #include <stdio.h> #define ARRAYI1_MAX sizeof(array1) #define ARRAYI2_MAX sizeof(array2) //int binary_search(int*,int,int); //二分探索関数のプロトタイプ宣言 int liner_search(int*,int,int); //線形探索関数のプロトタイプ宣言 void main(void) { int array1[]={2,3,5,8,12,20,32,52}; int array2[]={22,34,65,66,12,33,43,5,1}; int result,key; printf("探す文字を入力して下さい。\n"); sacnf("%d",&key); result=liner_search(array1,ARRAYI1_MAX,key); if(result<0){ printf("見つかりませんでした\n");} else{ printf("%d番目に見つかりました\n",result);} } //線形探索 int liner_search(int*array,int num_array,int key) { int i=0; for(i=0;i<result;i++) } /*二分探索 int binary_search(int*array,int num_array,int key) { }*/

  • ヒープの探索の再帰 改め

    前回の質問は↓ http://oshiete1.goo.ne.jp/kotaeru.php3?q=658496 です。 前回の質問は何とか自己解決できました。 int find(int x, int *A, int i, int n) { if(A[i] == x)return 1; if(i>n)return 0; if(A[i]>x)return 0; if(A[i]<x){ i = i*2 + 1; if(find(x, A, i, n))return 1; i++; if(find(x, A, i, n))return 1; } return 0; } そして関数呼び出しの際に、 find(x, A, 0, n); とすることにより、探索が可能になりました。ただやはりもっと簡単にできそうな気がするのですが、思いつきません。もっと綺麗に書けるのならその書き方を教えて欲しいです。

  • 配列のエラーに関して

    java言語を用いて,Householder変換を用いた固有値の数値計算に挑戦してみました.しかし,次のようなエラーが発生し上手くいきません.どなたかこの問題を解決するためにお力をかしていただけないでしょうか. ----------エラー内容-------------------------------------------------------------------------------- Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 0 out of bounds for length 0 at Out.Mhouse(House.java:90) at House.main(House.java:10) ---------------------------------------------------------------------------------------------------- //Householder変換 public class House{ public static void main(String[] args){ double[][] A = new double[3][3]; int n = A.length; Out out = new Out(); for(int i = 0;i < n;i++){ for(int j = 0;j < n;j++){ if(j < n-1){ System.out.print(out.Mhouse(A)[i][j] + " "); }else if (j == n-1) System.out.println(out.Mhouse(A)[i][j]); }; }; }; }; class Out{ double[][] outpro(double[] x){ int n; n = x.length; double[][] A = new double[n][n]; for(int i = 0;i < n;i++ ){ for(int j = 0;j < n;j++){ A[i][j] = x[i] * x[j]; } } return A; }; double[][] Msca(double a,double[][] A){ int n = A.length; for(int i = 0;i < n; i++){ for(int j = 0;j < n;j++){ A[i][j] = a * A[i][j]; } } return A; }; double selfpro(double[] x){ double a = 0; int n = x.length; for(int i = 0;i < n; i++){ a = a + x[i] * x[i]; }; return a; }; double[] minus(double[] x, double[] y){ int n = x.length; double[] z = new double[n]; for(int i = 0;i < n;i++){ z[i] = x[i] - y[i]; }; return z; }; double[][] house_1(double[] x){ int n = x.length; double[][] A = new double[n][n]; for(int i=0;i < n;i++){ for(int j = 0;j < n;j++){ if(i == j){ A[i][j] = 1 - Msca(2/selfpro(x),outpro(x))[i][j]; }else{ A[i][j] = - Msca(2/selfpro(x),outpro(x))[i][j]; }; }; }; return A; }; double[][] house_2(double[] x){ double[][] z = new double[1][1]; z[1][1] = 1 - 2; return z; }; double[][] Mhouse(double[][] A){ int n = A.length; double[][] H = new double[n][n]; for(int i = 0;i < n;i++){ double[] x = new double[n-i]; double[] y = new double[n-i]; double[][][] L = new double[i][n-i][n-i]; for(int j = 0;j < n-i;j++){ x[j] = A[i][i+j]; if(j == 0){ y[j] = 1; }else{ y[j] = 0; }; x[j] = y[j] - x[j]; }; if(i < n-1){ L[i] = house_1(x); for(int k = 0;k < n-i;k++){ for(int l = 0;l < n-i;l++){ H[i+k][i+l] = L[i][k][l]; }; }; }else if(i == n-1){ L[i] = house_2(x); for(int k = 0;k < n-i;k++){ for(int l = 0;l < n-i;l++){ H[i+k][i+l] = L[i][k][l]; }; }; }; }; double[][] B = new double[n][n]; for(int i = 0;i < n;i++){ for(int j = 0;j < n;j++){ for(int k = 0;k < n;k++){ B[i][j] = H[i][k] * A[k][j]; }; }; }; return A; }; };

    • ベストアンサー
    • Java
  • 多分探索木の昇順出力

    多分探索木の昇順出力する。関数を作っています。以下の関数が、多分木を出力関数ですが 途中でセグメントエラーが起きてしまいます。 void out_MS(NODE *p){ int i,n=0 ; for(i = 0; i <= p->nkeys; ++i) if (p->refs[i] != NULL) out_MS(p->refs[i]) ; while(p->keys[n+1]!='\0'){ printf("No:%3d \"%s\"\n",count,p->keys[n]) ; count++; n++; } } この、多分木に使われている、構造体は以下のとおりです #define KK 16 typedef struct node{ // 多分探索木、B(B*)木構造体 char *keys[KK] ; // キー配列 int nkeys ; // キーの個数(実際の) struct node *refs[KK + 1] ; // 子への参照欄 } NODE ; この構造体に以下の関数で、10万要素の単語(ランダム)に追加していきます。 int add(NODE *root, char *inv) { NODE *now , // 当該節 *prnt ; // nowの親節 int pos ; // 節内のキーの追加位置 prnt = now = root ; while(now != NULL) { // キーの探索 pos = binsearch(now->keys, now->nkeys, inv) ; // 二分探索 if (pos < now->nkeys && strcmp(inv,now->keys[pos])==0) // 探索値はある return FLS ; // 追加の必要なし if (now->nkeys == KK) { // 当該節に無い、節内に空きが無い prnt = now ; now = now->refs[pos] ; // 子の節へ }else if (pos <= now->nkeys) // 当該節に無い-追加位置が範囲内 break ; } if (now != NULL) // 当該節は在る store_key(now, inv, pos, &(now->nkeys)) ; // 当該節にキーを追加格納 else { // 当該節は無い-新規生成 if (now != root) { // nowは根ではない now = set_key(KK, inv) ; // キーを新節に格納 prnt->refs[pos] = now ; // 親節の参照欄に新節の番地を格納 }else return FLS ; } return 1 ; } 上記の関数で使われている、store_key set_key binserch の関数は以下のとおりです void store_key(NODE *trgt, char *inv, int pos, int *nkeys) { if (trgt->keys[pos] == INTV) // 当該位置は空 trgt->keys[pos] = strdup(inv) ; // 当該位置に格納 else { // 当該位置に入っている shift_element(trgt, 'R', pos, *nkeys) ; // 要素を移動 trgt->keys[pos] = strdup(inv) ; // 当該位置に格納 } ++*nkeys ; return ; } int binsearch(char *array[], int size, char *inv){ // 二分探索 int mid, // 当該位置 low, // 探索範囲の下限 high ; // 探索範囲の下限 if (size == 0) // キーは格納されていない return 0 ; if (strcmp(inv,array[0])<0) // 探索範囲以下 return 0 ; if (0 < strcmp(inv,array[size - 1] )) // 探索範囲以上 return size ; low = 0 ; // 下限設定 high= size - 1 ; // 上限設定 while(0 <= high - low) { // 二分探索本体 mid = (high + low) >> 1 ; // 中間位置を調べる if (strcmp(inv,array[mid])==0) // 入力値が一致したとき return mid ; if (strcmp(inv,array[mid])<0) // 入力値が小さいとき high = mid - 1; else // 入力値が大きいとき low = mid + 1 ; } return low ; } NODE *set_key(int size, char *key) { NODE *new ; new = crt_node(size) ; // 節の生成 new->keys[0] = strdup(key) ; // 配列の先頭に入力値を格納 new->nkeys = 1 ; // 節内の実際の要素数 return new ; } ぜひ、お力をお貸しください。よろしくお願いします。

  • Cygwinでの実行時に生じるエラーの原因を教えてください!

    以下は2次元の配列を左に90度回転させるのにかかるサイクルカウントを計測するプログラムです。 --------------------------------------------------- #include "clock.h" #define N 512 typedef int matrix_t[N][N]; void naive_rotate(matrix_t src, matrix_t dst){ int i, j; double d; start_counter(); for(i=0; i < N; i++){ for(j=0; j < N; j++){ dst[N-1-j][i] = src[i][j]; } } d = get_counter(); printf("CycleCount:%f\n",d); return; } int main(){ int i,j; matrix_t a,b; for(i=0; i < N; i++){ for(j=0; j < N; j++){ a[i][j] = j; } } naive_rotate(a,b); return 0; } ------------------------------------------------- Nを64,128・・・,2048のそれぞれでこいつをコンパイル、 $ gcc -O2 -I../include L_rotate.c ../lib/libcsapp.a 実行すると、Nが512以上のときは $ ./a.exe 45 [main] a 8024 _cygtls::handle_exceptions: Error while dumping state (probably corrupted stack) Segmentation fault (core dumped) と表示されてしまいます。libcsapp.aには問題はないので、このプログラム中のどこをどう直せばよいのでしょうか?