C言語関係掲示板

過去ログ

No849 3つの正整数の中央値を取得するマクロ

[戻る] [ホームページ]
No.10939

よろしゅー
投稿者---中央値取得のマクロ化(2003/12/07 11:35:20)


はじめまして。
C言語でプログラムを組はじめて間もない素人同然の者です。
自分で考えてもうまくいかず、行き詰まってしまったので投稿しました。

早速ですが、悩んでいる点についてのアドバイスをお願いしたいと思います。

今、正整数が3つあるとします。(それぞれn1, n2, n3)
これらの中から中央の値を取得する関数を作りました。以下の通りです。
int Mid(int n1, int n2, int n3)
{
  if (n1 <= n2) {
    if (n2 <= n3) {
      return n2;
    } else if (n1 <= n3) {
      return n3;
    } else {
      return n1;
    }
  } else if (n1 <= n3){
    return n1;
  } else{
    return n3;
  }
}

この関数をマクロ化したく、以下の通りにしたのですがうまくいきません。
#define Mid(n1, n2, n3) (n1 <= n2) ? ((n2 <= n3) ? n2 : ((n1 <= n3) ? n1 : n3)) : (n1 <= n3) ? n1 : n3

どこに問題があるのでしょうか?
ご存じの方、ご教授お願い親します。

No.10941

Re:よろしゅー
投稿者---ともじ(2003/12/07 12:27:59)


>この関数をマクロ化したく、以下の通りにしたのですがうまくいきません。
>#define Mid(n1, n2, n3) (n1 <= n2) ? ((n2 <= n3) ? n2 : ((n1 <= n3) ? n1 : n3)) : (n1 <= n3) ? n1 : n3

#define Mid(n1, n2, n3) (n1 <= n2) ? ((n2 <= n3) ? n2 : ((n1 <= n3) ? n3 : n1)) : ((n1 <= n3) ? n1 : n3)

    if (n1 <= n2) {
        if (n2 <= n3) {
            return n2;
        } 
        else {
            if (n1 <= n3) {
                return n3;
            } 
            else {
                return n1;
            }
        }
    } 
    else {
        if (n1 <= n3){
            return n1;
        }
        else{
            return n3;
        }
    }
を展開するとわかりやすいのではないでしょうか。



No.10942

Re:よろしゅー
投稿者---かずま(2003/12/07 13:55:01)


> どこに問題があるのでしょうか?

関数で、n1 > n2 かつ n1 > n3 のとき、結果が n3 とは限りません。
マクロ化するとき、n1 <= n3 の結果を逆にしています。


関数なら、
int Mid(int a, int b, int c)
{
    if (a < b) {
        if (c < a) return a;
        if (b < c) return b;
        return c;
    } else {
        if (a < c) return a;
        if (c < b) return b;
        return c;
    }
}

マクロなら、
#define Mid(a, b, c) \
    ((a)<(b)?(c)<(a)?(a):(b)<(c)?(b):(c):(a)<(c)?(a):(c)<(b)?(b):(c))

次の 6とおりのテストをしてみること。
    Mid(1, 2, 3)
    Mid(1, 3, 2)
    Mid(2, 1, 3)
    Mid(2, 3, 1)
    Mid(3, 1, 2)
    Mid(3, 2, 1)

題名が不適切です。投稿者名の「中央値取得のマクロ化」を題名にすべきです。


No.10949

Re:よろしゅー
投稿者---ともじ(2003/12/07 18:33:31)


>#define Mid(n1, n2, n3) (n1 <= n2) ? ((n2 <= n3) ? n2 : ((n1 <= n3) ? n3 : n1)) : ((n1 <= n3) ? n1 : n3)

かずまさんがご指摘の通り、元の関数が違っていますね。検証しませんでした。すみません。
加えて、() の囲み方も足りませんでした。これでは、マクロの副作用を
引き起こす可能性があります。

マクロの副作用というのは、以下のmax1で、
2 * (5 > 10) ? 5 : 10
と展開されて正しい結果が得られないような場合をいいます。
ですから、マクロを使う場合、max2のように厳重に()で囲む必要があります。
#include <stdio.h>

#define max1(X, Y) (X > Y) ? X : Y 
#define max2(X,Y) (((X) > (Y)) ? (X) : (Y))

int main(void)
{
    printf("%d\n", 2 * max1(5, 10)); 
    printf("%d\n", 2 * max2(5, 10)); 

    return;
}

No.10950

中央値取得のマクロ化
投稿者---Re:よろしゅー(2003/12/07 19:36:51)


ともじさん、かずまさん、返信ありがとうございます。

かずまさんの言われるとおり、関数の段階で間違っていました。
申し訳ございません。

以下の内容を、テストしてみたいと思います。
>次の 6とおりのテストをしてみること。
Mid(1, 2, 3)
Mid(1, 3, 2)
Mid(2, 1, 3)
Mid(2, 3, 1)
Mid(3, 1, 2)
Mid(3, 2, 1)

>題名が不適切です。投稿者名の「中央値取得のマクロ化」を題名にすべきです。

すいません。
名前と題名を間違えてしまいました。
ご迷惑をおかけいたしました。