掲示板ランキング  水着  着ぐるみ・コスチューム  雨具


掲示板利用宣言

 次のフォームをすべてチェックしてからご利用ください。

 私は

 題名と投稿者名は具体的に書きます。
 課題の丸投げはしません。
 ソースの添付は「HTML変換ツール」で字下げします。
 返信の引用は最小限にします。
 環境(OSとコンパイラ)や症状は具体的に詳しく書きます。
 返信の付いた投稿は削除しません。
 マルチポスト(多重投稿)はしません。

掲示板1

管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    記事検索    ログ    タグ一覧

No.6875

bsearch関数について
投稿者---yuki(2006/12/07 11:25:11)


以下のプログラムで解らないところが3箇所あります。どなたか御教示の程宜しくお願いします。

/*
    bsearch関数を利用して要素を探索
*/

#include <stdio.h>
#include <stdlib.h>

/*--- 整数を比較する関数 ---*/
int int_cmp(const int *a, const int *b)
{
    if (*a < *b)
        return (-1);
    else if (*a > *b)
        return (1);
    else
        return (0);
}

int main(void)
{
    int  i, ky, *p;
    int  x[7];
    int  nx = sizeof(x) / sizeof(x[0]);

    printf("%d個の整数を昇順に入力してください。\n", nx);

    printf("x[0] : ");        /* (1) */
    scanf("%d", &x[0]);           /* (1) */

    for (i = 1; i < nx; i++) {        /* (2) */
        do {
            printf("x[%d] : ", i);
            scanf("%d", &x[i]);
        } while (x[i] < x[i - 1]);   /* 一つ前の値よりも小さければ再入力 */
    }

    printf("探す値 : ");
    scanf("%d", &ky);

    p = bsearch(&ky,                             /* 探索値へのポインタ */
                x,                               /* 配列 */
                nx,                              /* 要素数 */
                sizeof(int),                     /* 要素の大きさ */
                (int (*)(const void *, const void *))int_cmp     /* 比較関数 */    /* (3) */
                );

    if (p == NULL)
        puts("探索に失敗しました。");
    else
        printf("%dは%d番目にあります。\n", ky, (int)(p - &x[0]) + 1);      /* (4) */

    return (0);
}



まず/*(1)*/の部分を独立させないで
削除して,
その下の/*(2)*/の部分のfor文の i = 1を i = 0 としてはいけないのでしょうか?
後コメント(3)(4)の部分の意味するところと機能が解りません。
どなたかお教え下さい。


この投稿にコメントする

削除パスワード

発言に関する情報 題名 投稿番号 投稿者名 投稿日時
<子記事> Re:bsearch関数について 6876 YuO 2006/12/07 11:53:01
<子記事> Re:bsearch関数について 6877 keichan 2006/12/07 11:57:19
<子記事> Re:bsearch関数について 6878 2006/12/07 11:58:40


No.6876

Re:bsearch関数について
投稿者---YuO(2006/12/07 11:53:01)


>まず/*(1)*/の部分を独立させないで
>削除して,
>その下の/*(2)*/の部分のfor文の i = 1を i = 0 としてはいけないのでしょうか?

iが0のとき,for文中のdo文の条件式が不正になることはわかりますか?
つまり,x[0] < x[-1]という条件式になりますが,x[-1]は正しくありません。


>後コメント(3)(4)の部分の意味するところと機能が解りません。

(3)はやってはいけない典型的なキャストです。
比較関数int_cmpの型が間違っているので,強引にキャストしているようです。
まず,int_cmpを
int int_cmp(const void *pa, const void *pb)
{
    int a = *(const int *)pa, b = *(const int *)pb;

    if (a < b)
        return -1;
    else if (a > b)
        return 1;
    else
        return 0;
}
のように変更後,(3)の行を
                int_cmp                          /* 比較関数 */
に置き換える必要があります。


(4)は特別なことがないような……。
pはサーチした結果で,見つかればその要素へのポインタ,なければNULLが返ります。
else節に来るのは見つかった場合ですから,N番目 (0起点) の要素が見つかった場合,pは&x[N]になります。
これで置き換えると,
(int)(&x[N] - &x[0]) + 1
となります。
ここで,ポインタの減算の定義より括弧内はN - 0となるので,この行は
        printf("%dは%d番目にあります。\n", ky, N + 1);
と同じ,ということになります。



この投稿にコメントする

削除パスワード

No.6877

Re:bsearch関数について
投稿者---keichan(2006/12/07 11:57:19)


>まず/*(1)*/の部分を独立させないで
>削除して,
>その下の/*(2)*/の部分のfor文の i = 1を i = 0 としてはいけないのでしょうか?
2分岐探索を行う前準備として、検索をかける配列は昇順または降順にソートされている必要があります。
その為、提示されているソースでは最初の値が入っていないと2回目以降の
入力で判定が出来ません。
"1回目の入力のみ例外的な動作"をしますのでわざとforスコープから外しているのではないですか?
forスコープの中に記述は可能ですが、if文で条件分岐をしないといけません。

>後コメント(3)(4)の部分の意味するところと機能が解りません。
>どなたかお教え下さい。
"関数ポインタ"で検索をかけてみてみるとよろしいかと思います。


この投稿にコメントする

削除パスワード

No.6878

Re:bsearch関数について
投稿者--- (2006/12/07 11:58:40)


こんな書き方もありかなぁ、などと思ったりします。

    for (i = 0; i < nx; i++) {
        printf("x[%d] : ", i);
        scanf("%d", &x[i]);
        if (i >= 1 && x[i] < x[i-1])
            i--;
    }





この投稿にコメントする

削除パスワード

管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    記事検索    ログ    タグ一覧





掲示板提供:(有)リアル・インテグリティ