• ベストアンサー

bsearch関数

エラー 関数 `typespec' 内: 警告: 互換性のないポインタ型からの引数 5 個の `bsearch' を渡しますです int typespec(void) { static char *types[] = { "char", "int", "void" }; char *pt = token; if (bsearch(&pt, types, sizeof(types)/sizeof(char *), sizeof(char *), compare) == NULL) return NO; else return YES; } int compare(char **s, char **t) { return strcmp(*s, *t); } サイトや教科書を見たり読んだりして、標準ヘッダとも被らないように試みてみたのですが、余計エラーが増えてしまいます。「引数 5 個」ということは、全部アウトなんでしょうか? 過去の質問を見てみてもピンときません。暇な方がいるなら是非初心者にもわかりやすいアドバイスください。 (OSはLINUX。端末はGNOMEです)

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

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

bsearchの最後の引数の型は int (*)(const void *, const void *) です。constがないと型が違うとなります。 参考: http://www.linux.or.jp/JM/html/LDP_man-pages/man3/bsearch.3.html

p_hetare
質問者

補足

int typespec(void) { static char *types[] = { "char", "int", "void" }; char *pt = token; if (bsearch(&pt, types, sizeof(types)/sizeof(char *), sizeof(char *), compare) == NULL) return NO; else return YES; } static int compare(const void **s, const void **t) { return strcmp(*s, *t); } これでいいのでしょうか?参考のサイトをみてみましたが、エラーは同じでした。どこか自分が見落としてる所があるからかも知れませんが・・・。

その他の回答 (3)

  • tatsu99
  • ベストアンサー率52% (391/751)
回答No.4

まず、#1の方の参考URLをみると、 #include <stdlib.h>となっています。 これが、指定されていることが前提です。 void *bsearch(const void *key, const void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *)); のint (*compar)(const void *, const void *) の部分は、 compareという関数の引数が、 (const void *, const void *)で、戻り値がint型であることを要求しています。 つまり int compar(const void *, const void *)のような関数であれば 良いわけです。(実際の関数名はcomparなくてもよいです。何でも良いです) そうすると、あなたが最初にかかれた int compare(char **s, char **t) は、引数の型が合っていませんのでNGです。 そこで、引数を合わせるために、強引に int compare(const void *, const void *) とします。 型はこれで、良いのですが、実際にあなたが渡して欲しいのは、 char **s, char **tの型です。 それで、強引にキャストして char **s0 = (char**)s; char **t0 = (char**)t; のように設定し直します。 あとは、変数名がs0,t0になってしまったので、 return strcmp(*s0, *t0); とします。

p_hetare
質問者

お礼

解説ありがとうございます。 是非メモして、何回も見直したいと思います。 教科書・サイトなどに載っていない部分を解説してもらうのは、本当に助けられます。

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

日本語のメッセージはアホなので英語にすべきだと思うけどそれはさておき, 警告が出ている行はどこですか? compare のプロトタイプ宣言がないとかいうオチはありませんよね?

p_hetare
質問者

補足

今回はさすがにそういう事はありませんでした^^; No.2さんのアドバイスでコンパイルはいきました。

  • tatsu99
  • ベストアンサー率52% (391/751)
回答No.2

理由は#1のかたの言われるとおりです。 compareを以下のように修正して下さい。 int compare(const void *s, const void *t) { char **s0 = (char**)s; char **t0 = (char**)t; return strcmp(*s0, *t0); } たぶん、これでわかるかと思いますが、この理由がわからない場合は、 再度説明しますので、その旨補足して下さい。

p_hetare
質問者

補足

コンパイルは成功しました、でも理由がわかりません。 説明してくださるなら この機会に知っておきたいので是非お願いします。

関連するQ&A

  • qsortの引数について

    以下のプログラムがあります。 int compare( const char **name1, const char **name2 ) { return strcmp( *name1, *name2 ); } int main( void ) { char *names[] = { "rand", "calloc", "malloc" }; int num = sizeof names / sizeof names[0]; qsort( names, num, sizeof( names[0] ), (int (*)(const void *, const void * ))compare ); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~この部分 return 0; } 上の「~~~」の上の部分のqsort関数の第4引数のキャストの意味が 分かりません。なぜ関数の前に引数が書かれるのでしょうか? またintの後にある(*)は「int型のポインタ」と言う意味なのか、 compare関数のポインタなのかも分かりません。 ご回答よろしくおねがいします。

  • 昇順ソート

    sort.txtから読み込んだ値を 昇順でソートして出力するにはどうしたらよいでしょうか? #include <stdio.h> #include <stdlib.h> #include <string.h> #include <search.h> /* 比較関数 */ int strcmp_asc(const void *, const void *); int main(void) { FILE *fin, *fout; int i; int length; char s[256], s2[256]; if( (fin=fopen("sort.txt","r"))==NULL) { printf("入力ファイルがオープンできません\n"); exit(EXIT_FAILURE); } if( (fout=fopen("file2.txt","w"))==NULL) { printf("出力ファイルがオープンできません\n"); exit(EXIT_FAILURE); } while(fgets(s, 256, fin) != NULL) { /* 要素数を求める */ length = sizeof(s) / 256; /* 昇順でソート */ qsort(s, length, 256, strcmp_asc); /* memset(s2, NULL, sizeof(s2)); for (i = 0; i < length; i++) { } */ fprintf(fout,"%s\n",s2); } fclose(fin); fclose(fout); return 0; } int strcmp_asc(const void *sa, const void *sb) { return strcmp((char *)sa, (char *)sb); } sort.txt 50 45 35 25 15 10 5 1 32 46 8 7 9 19 18 14 16 13 12 17 11 20 40 30 31 3 2 37 38 36 33 39 34 49 47 48 4 6 44 42 43 41 21 22 26 24 28 29 27 23

  • プログラミング(配列と関数の引数)

    a : ABCDE a : ABCDEFGH Len : 8 a : FGHIJ a : FGH a : FGH, c : FGH 上記のように表示されるプログラムを作りたいのですが、なかなかできません。下記のようなプログラムを作ったのですがどこが間違っているのかよくわかりません。分かる方、指摘をお願いします。 #include <stdio.h> void my_strcpy(char s[], char t[]); int my_strlen(char s[]); void my_strcat(char s[], char t[]); int main(){ char a[10]; char b[10] = "ABCDE"; char c[] = "FGH"; int len; my_strcpy(a, b); printf("a : %s\n", a); my_strcat(a, c); printf("a : %s\n", a); len = my_strlen(a); printf("Len : %d\n", len); my_strcpy(a, "FGHIJ"); printf("a : %s\n", a); a[3] = '\0'; printf("a : %s\n", a); if(strcmp(a, c) == 0){ printf("a : %s, c : %s\n", a, c); } int i, s, t; my_strcpy(a, b + 2); printf("a : %s\n", a); void my_strcpy(char s[], char t[]){ for (i = 0; t[i] != '\0'; i++){ s[i] = t[i]; } s[i] = '\0'; } int my_strlen(char s[]){ int i; for (i = 0; s[i] != '\0'; i++); return i; } void my_strcat(char s[], char t[]){ int i, j; for (i = 0; s[i] != '\0'; i++); for (j = 0; t[j] != '\0'; i++, j++){ s[i] = t[j]; } s[i] = '\0'; } }

  • この関数がどのような計算を行うものか教えて下さい。

    #define NULLC(char) 0 #define YES 1 #define NO 0 int string_compare(char *s1, char*s2){ while(*s1==*s2) if(*s1==NULLC) if(*s2==NULLC) return YES; else return NO; else if(*s2==NULLC) return NO; else{++s1;++s2;} return NO; }

  • Cのポインタについて

    int howiwork(char *s, char **tab) { int i; if( s == NULL ) return ERROR; for ( i = 0;*tab;tab++,i++) if(! strcmp(s,*tab)) return i; return ERROR; } このプログラミングの機能を教えていただきたいのですがお願いします。

  • ポインタにによる値の表現と文字列の表現について

    ◎1------------------------------ #include<stdio.h> int main(void) { char *pt="ABC"; printf("pt=%s\n",pt); char dt[10]="ABCDE"; char *pp; pp=dt; printf("pp=%s\n",pp); return 0; } -------------------------------------- ◎2---------------------------------- #include<stdio.h> int main(void) { char *pt="ABC"; printf("*pt=%s\n",*pt); char dt[10]="ABCDE"; char *pp; pp=dt; printf("*pp=%s\n",*pp); return 0; } ----------------------------------- ◎3--------------------------------------- #include<stdio.h> int main(void) { int ary[5]={111,222,333,444,-1}; int* pt=ary; while(1){ printf("%d ",*pt); ++pt; if(*pt==-1){ break; } } puts(""); return 0; } ----------------------------------------------- 以上3つのプログラムで、◎1はprintfで「*」が付いてなく、正常に実行出来ました。 ◎2はprintfで「*」が付いてなく、エラーは出ませんが、文字列が表示されませんでした。 ◎3は文字列ではなく値ですが、printfで「*」が付いていて正常に実行できます。 これは、値の場合は「*pt」とすることで、ptのアドレスに値を代入しているという事で、「printf("%d ",*pt);」で実行できたということですかね? 文字列の場合は、先頭のアドレスを渡すだけなので、「printf("pt=%s\n",pt);」のようにしてアドレスを参照しないとダメであるということですか? ◎2で「printf("*pt=%s\n",*pt);」としてしまうと、何が起きてしまうのかわかりません。 以上、教えていただけると嬉しいです。

  • C言語のqsortについて

    現在、qsortのコードに取り組んでいます。 if (strcmp(ad, "ASC") == 0) { qsort(sin, sizeof(cnt), sizeof(sin[0]), cmp_u); } else { qsort(sin, sizeof(cnt), sizeof(sin[0]), cmp_d); } 恐らくこちらのqsortでの第二引数が書き方を間違えていると思うのですが、修正の方法が分からず、どなたか教えて頂けないでしょうか? #include <stdio.h> #include <time.h> #include <string.h> #include <stdlib.h> static char ad[10]; int cmp_u(const void* a, const void* d) { return strcmp((char*)a, (char*)d); } int cmp_d(const void* a, const void* d) { return strcmp((char*)d, (char*)a); } int main() { int num1, num2; char op; float answer; int r,i; FILE* fp; char c[11]; char sin[1000][1000]; char ad[8]; fp = fopen("log.txt", "a+"); if (fp == NULL) { printf("ファイルオープン失敗\n"); return -1; } while (1) { r = scanf("%d%c%d", &num1, &op, &num2); if (r != 3) { puts("input error"); return 1; } if (op == '+') { answer = num1 + num2; } else if (op == '-') { answer = num1 - num2; } else if (op == '*') { answer = num1 * num2; } else if (op == '/') { answer = (float)num1 / num2; } time_t t = time(NULL); struct tm* tm = localtime(&t); printf("%d/%02d/%02d ", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday); printf("%02d:%02d:%02d ", tm->tm_hour, tm->tm_min, tm->tm_sec); printf("%d%c%d,%f\n", num1, op, num2, answer); fprintf(fp, "%d/%02d/%02d ", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday); fprintf(fp, "%02d:%02d:%02d ", tm->tm_hour, tm->tm_min, tm->tm_sec); fprintf(fp, "%d%c%d,%f\n", num1, op, num2, answer); printf("計算を続けますか?"); scanf("%s\n", &c); if (strcmp(c, "no") == 0) { break ; } } fclose(fp); fp = fopen("log.txt", "r"); int cnt = 0; for (i = 0;i < 1000;i = i + 1) { if (fgets(sin[i], sizeof(sin[0]), fp)) ++cnt; else break; } fclose(fp); printf("ASC or DESC: "); scanf("%s", ad); if (strcmp(ad, "ASC") == 0) { qsort(sin, sizeof(cnt), sizeof(sin[0]), cmp_u); } else { qsort(sin, sizeof(cnt), sizeof(sin[0]), cmp_d); } for (i = 0;i < cnt;i = i + 1) { printf("%s", sin[i]); } return 0; }

  • 関数のポインタ

    char* check(int a,int b,int c) { return(\"yes\"); とした場合char* checkは何を表しているのでしょうか。 また、 char *str_copy(char d[], char s[]) { char *t=d; while(*d++ = *s++) ; return t; とした場合との違いはあるのでしょうか。 ポインタを返すときに*をつけると教わったのですがいまいち理解できなかったのですがどのような処理が行われているのでしょうか、お願いします。

  • 関数の引数をvoid*でキャストする

    最近見かけたCのプログラムで、関数の引数の型は void* なのですが、その関数を使うときに 引数をvoid*でキャストしていました。 例えば、 func ( (void*) p ); こういうことです。 私の知っている知識では、 void* と 任意の型のポインタは キャストなしに相互に代入可能です。 関数の引数でも、キャストは要らないものだと思っていました。 そうすると、引数を void* でキャストするのは無意味だと思うのですが、・・・ 違うのでしょうか。処理系によるとか。 逆に、関数の引数の型がchar*などで、渡すものが void* のときはどうなのでしょうか。 下のプログラムは、関数byte_orderの引数の型はvoid*ですが、int型へのポインタ( &a )を設定しています。私の環境では、コンパイルエラーも警告もないし、動作も正常です。 #include <stdio.h> #include <string.h> void byte_order(void *vp) { char char_array[4]; strncpy(char_array, vp, 4); printf("出力します:%x %x %x %x\n", char_array[0], char_array[1], char_array[2], char_array[3]); } int main(void) { int a = 0x12345678; byte_order(&a); return 0; } このプログラムは単なる一例であって、質問はバイトオーダに関するものではありません。 また、C言語の質問であって、C++ではありません。

  • 「動的確保した2次元配列のメモリ解放」を関数化したい

    質問タイトルの通りですが、 「動的確保した2次元配列のメモリ解放」をC言語で関数化したいと思っています。しかし、関数の引数には動的確保した配列の先頭アドレスのみ渡す形にしたいです。そのような場合の関数化は可能ですか? どうもうまくいかず、困っています。 以下、具体的に、サンプルソースを記述します。 わかる方、よろしくお願いします。 //====================================================// #include<stdio.h> unsigned char** AllocByteArray2d(int column, int row); void FreeByteArray2d(unsigned char** box); int main(voidls){ unsigned char array**; array = AllocByteArray2d(2, 3); FreeByteArray2d(array); return 0; } unsigned char** AllocByteArray2d(int column, int row){ unsigned char* box; box = (unsigned char**)malloc( sizeof(unsigned char*)*column ) int i; for(i=0; i<column; i++){ box[i] = (unsigned char*)calloc( row, sizeof(unsigned char)); if(box[i] == NULL) exit(EXIT_FAILURE); } return box; } //引数では配列の先頭アドレスだけ渡す形にしたい void FreeByteArray2d(unsigned char** box){ //ここをどう書いたらいいかわからない }

専門家に質問してみよう