½ºÄ«À̶óÀΠã±â

°ú¸ñ: Programming Language
±³¼ö: ÇÑ»ó¿µ
Á¦ÃâÀÏ: 29-Sep-97
Á¦ÃâÀÚ: ±è±â¿ë, 93208-002, Áö¸®Çаú

  • Tuple

    ¹®ÀÚ Çϳª°¡ ÀÔ·ÂÀ¸·Î µé¾î¿À¸é tuple ¿¡°Ô º¸³½´Ù. °è¼ÓÇؼ­ º¸³»´Ù°¡ (AddChar()) ÇϳªÀÇ tuple ÀÌ ¿Ï¼ºµÇ¾î »ç¿ëÇÒ ¼ö ÀÖ°Ô µÇ¸é (IsValid()) ±× tuple À» »ç¿ëÇÑ µÚ ÃʱâÈ­¸¦ ÇÑ´Ù (Clear()).

    while ((ch = getchar()) != EOF) {
        tuple.AddChar(ch);
        if (tuple.IsValid()) {
            skyline += tuple;
            tuple.Clear();
        }
    }
        

  • Exception Handling

    ÇÁ·Î±×·¥ ÁøÇà Áß¿¡ ¸î °¡Áö Exception ÀÌ ¹ß»ýÇÒ ¼ö Àִµ¥, ¿©±â¼­´Â ¼¼ °¡Áö°¡ °¡´ÉÇÏ´Ù°í º¸¾Ò´Ù. try-catch-throw ¸¦ »ç¿ëÇÏ¿´±â ¶§¹®¿¡, g++ ¿¡¼­ -fhandle-exceptions ¿É¼ÇÀ» ÄÑ¾ß ÇÑ´Ù.

    1. ErrInvalidFormat : ÀÔ·ÂÀÌ À߸øµÇ¾ú´Ù. ÀÌ ÇÁ·Î±×·¥¿¡¼­´Â [0-9\+\-\(\,\.\)] °¡ ¾Æ´Ñ ¹®ÀÚ´Â ¸ðµÎ ¹«½ÃÇÑ »óÅ¿¡¼­ scanf°¡ "(%f,%f,%f)" ¸¦ format À¸·Î ÇÏ¿© Àб⸦ ½ÃµµÇßÀ» ¶§ 3À» returnÇÏ´Â(3°³¸¦ ÀдÂ) °ÍÀ» ¿Ã¹Ù¸¥ ÀÔ·ÂÀ¸·Î °£ÁÖÇÏ¿´´Ù.

    2. ErrTooLongTuple : ÀԷµǴ Tuple ÀÌ ³Ê¹« ±æ´Ù. ÀÌ ÇÁ·Î±×·¥¿¡¼­ »ç¿ëÇÑ buffer ÀÇ Å©±â´Â 256 À¸·Î #define ÇÑ MAXCHAR Àε¥, tuple Çϳª°¡ MAXCHAR ¸¦ ³Ñ°Ô µÇ¸é ÀÌ Exception ÀÌ ¹ß»ýÇÑ´Ù.

    3. ErrNoSpace : skyline ¿¡ »õ·Î¿î tuple À» ´õÇÒ ¶§ µÎ °³ÀÇ Á¡À» À§ÇÑ Node ¸¦ Allocation ¹Þ°Ô µÇ´Âµ¥, ÀÌ°ÍÀÌ ¸¸¿¡Çϳª ½ÇÆÐÇÒ °æ¿ì ¹ß»ýÇÑ´Ù.

  • Misc.

    1. PrintDouble() : ÁÂÇ¥¿¡ ½Ç¼ö°¡ Çã¿ëµÇµµ·Ï Ç϶ó´Â Áö½Ã°¡ ÀÖ¾ú´Âµ¥ ¿ä±¸µÈ Ãâ·Â¿¡´Â ½Ç¼öÀÇ ÇüÅ°¡ ¾Æ´Ï´Ù. µû¶ó¼­ ¼Ò¼öÁ¡ µÚ¿¡ ÀÖ´Â 0Àº Ãâ·ÂÇÏÁö ¾Ê´Â 󸮰¡ ¿ä±¸µÇ¾ú´Ù.

    2. Comments : ÀԷ¿¡¼­ # À» ¸¸³ª¸é newline À» ¸¸³¯ ¶§±îÁö ÀÔ·ÂÀ» ¹«½ÃÇϵµ·Ï ÇÏ¿´´Ù.

    3. Debugging Tool : ÀԷ°ú Ãâ·ÂÀ» °¢°¢ stdin °ú stdout À¸·Î Ç߱⠶§¹®¿¡ ´Ù¾çÇÑ ÀԷ¿¡ ´ëÇØ ¿Ã¹Ù¸¥ °á°ú¸¦ º¸¿© ÁÖ´ÂÁö È®ÀÎÇϱâ À§ÇØ SkyLine.cpp »Ó ¾Æ´Ï¶ó Win32 ¿Í MFC ¸¦ ÀÌ¿ëÇÏ¿© ½Ã°¢ÀûÀ¸·Î º¸¿© ÁÖ´Â ÇÁ·Î±×·¥À» ÀÛ¼ºÇÏ¿´´Ù. ´ÙÀ½Àº ±× ½ÇÇà ¿¹ÀÌ´Ù.

  • ½ÇÇà ¿¹


    #cat input2.txt
    (2.6,4.8,7.4)(7.5,7.0,9.3)(5.6,5.7,6.0)(2.1,5.1,2.4)(5.8,3.1,9.6)

    #a.out < input2.txt
    (2.1,5.1)(2.4,0)(2.6,4.8)(5.6,5.7)(6,4.8)(7.4,3.1)(7.5,7)(9.3,3.1)(9.6,0)

    #cat input.txt
    (1,5,3)(4,3,5)(2,7,6)(7,1,9)

    #a.out < input.txt
    (1,5)(2,7)(6,0)(7,1)(9,0)

    #cat errin1.txt
    (1,2,3)(1.2,3.2,3.4)(3,12345567,3.44444,4.0000000000002)(2.4.5)

    #a.out < errin1.txt
    Error: Invalid tuple input:
    (2.4.5)

    #cat errin2.txt
    (1.01234567890123456789<200ÀÚ »ý·«>012345678901234567890123456789,1,2)

    #a.out < errin2.txt
    Error: Too long tuple input:
    (1.01234567890123456789<200ÀÚ »ý·«>012345678901234567890123456789,

    * ErrNoSpace ´Â ½ÇÇèÇØ º¼ ¼ö ¾ø¾ú´Ù

  • Source Files

    SkyLine.h
    //
    // SkyLine.h
    //
    
    #define MAXCHAR 256
    
    #define max(a, b) ((a) > (b) ? (a) : (b))
    #define min(a, b) ((a) < (b) ? (a) : (b))
    
    // enum BOOL { FALSE, TRUE };
    typedef int BOOL;
    
    class CoordNode {
    public:
        double x, y;
        CoordNode *next;
    
        CoordNode() { x = 0; y = 0; next = NULL; }
        CoordNode(double sx, double sy) { x = sx; y = sy; next = NULL; }
        void DeleteNextNode();
    };
    
    class Tuple {
    protected:
        char   str[MAXCHAR];
        int    cur;
        BOOL   bValid;
        BOOL   bComment;
    
        BOOL   isUseful(char ch);
        void   verify();
    
    public:
        double x1, y, x2;
    
        Tuple();
    
        BOOL   AddChar(char ch);
    
        BOOL   IsValid() { return bValid; }
    
        void   Clear() { cur = 0; bValid = FALSE; bComment = FALSE; }
        void   Print();
    };
    
    class SkyLine {
    protected:
    
        CoordNode *insert(CoordNode *pNode);
        void compact();
        void pullHeight(Tuple &t);
    
    public:
        CoordNode coordHead;
    
        SkyLine() {}
        ~SkyLine();
    
        SkyLine &operator +=(Tuple &t);
        void     Print();
    };
    
    class Exception {
    public:
        enum ErrType {
            NoError, ErrNoSpace, ErrTooLongTuple, ErrInvalidFormat
        } err;
    
        void *param;
    
        Exception() { err = NoError; param = NULL; }
        Exception(ErrType etype, void *p) { err = etype; param = p; }
        BOOL Handle();
    };
    
    
    SkyLine.cpp
    //
    // SkyLine.cpp
    //
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <ctype.h>
    
    #include "SkyLine.h"
    
    void CoordNode::DeleteNextNode()
    {
        CoordNode *pFree;
    
        pFree = next;
        if (!pFree)
            return;
    
        next = pFree->next;
    
        delete pFree;
    }
    
    Tuple::Tuple()
    {
        x1  = 0;
        x2  = 0;
        y   = 0;
    
        cur = 0;
        bValid = FALSE;
        str[MAXCHAR-1] = '\0';
    
        bComment = FALSE;
    }
    
    BOOL Tuple::isUseful(char ch)
    {
        if (!bComment && ch == '#') {
            bComment = TRUE;
            return FALSE;
        }
    
        if (bComment) {
            if (ch == '\n')
                bComment = FALSE;
            return FALSE;
        }
    
        if (isdigit(ch) || ch == '.' || ch == '+' || ch == '-')
            return TRUE;
    
        if (ch == '(' || ch == ',' || ch == ')')
            return TRUE;
    
        return FALSE;
    }
    
    void Tuple::verify()
    {
        int nGet;
    
        nGet = sscanf(str, "(%lf,%lf,%lf)", &x1, &y, &x2);
    
        bValid = (nGet == 3) ? TRUE : FALSE;
    
        if (!bValid) {
            Exception e(Exception::ErrInvalidFormat, this);
            throw e;
        }
    }
    
    
    BOOL Tuple::AddChar(char ch)
    {
        if (!isUseful(ch))
            return FALSE;
    
        str[cur++] = ch;
    
        if (ch == ')') {
            str[cur] = '\0';
            verify();
            return TRUE;
        }
    
        if (cur >= MAXCHAR - 2) {
            Exception e(Exception::ErrTooLongTuple, this);
            throw e;
        }
    
        return FALSE;
    }
    
    void Tuple::Print()
    {
        str[cur] = '\0';
        printf("%s", str);
    }
    
    SkyLine::~SkyLine()
    {
        while (coordHead.next) {
            coordHead.DeleteNextNode();
        }
    }
    
    SkyLine &SkyLine::operator +=(Tuple &t)
    {
        CoordNode *pLeft, *pRight, *pPrev;
    
        pLeft = new CoordNode(t.x1, t.y);
        pRight = new CoordNode(t.x2, 0);
    
        if (!pLeft || !pRight) {
            Exception e(Exception::ErrNoSpace, NULL);
            throw e;
        }
    
    
        pPrev = insert(pRight);
        if (pRight->y < pPrev->y) {
            pRight->y = pPrev->y;
        }
    
        pPrev = insert(pLeft);
        if (pLeft->y < pPrev->y) {
            pLeft->y = pPrev->y;
        }
    
        pullHeight(t);
        compact();
    
        return *this;
    }
    
    CoordNode *SkyLine::insert(CoordNode *pNode)
    {
        CoordNode *pPrev = &coordHead;
    
        while (pPrev->next) {
            if (pPrev->next->x >= pNode->x) {
                break;
            }
            pPrev = pPrev->next;
        }
    
        pNode->next = pPrev->next;
        pPrev->next = pNode;
    
        return pPrev;
    }
    
    
    void SkyLine::pullHeight(Tuple &t)
    {
        CoordNode *pNode = coordHead.next;
    
        while (pNode) {
            if (pNode->x >= t.x2)
                return;
            if (pNode->x > t.x1 && pNode->y < t.y)
                pNode->y = t.y;
    
            pNode = pNode->next;
        }
    }
    
    void SkyLine::compact()
    {
        CoordNode *pNode = coordHead.next;
    
        while (pNode) {
            if (!pNode->next)
                break;
            if (pNode->x == pNode->next->x) {
                pNode->y = max(pNode->y, pNode->next->y);
                pNode->DeleteNextNode();
                continue;
            }
            if (pNode->y == pNode->next->y) {
                pNode->x = min(pNode->x, pNode->next->x);
                pNode->DeleteNextNode();
                continue;
            }
    
            pNode = pNode->next;
        }
    }
    
    void PrintDouble(double num)
    {
        static const int MAXDECIMAL = 6;
    
        if ((double)(int)num == num) {
            printf("%d", (int)num);
            return;
        }
    
        int    n;
        int    m;
        double mul;
    
        for (n = 1, m = 10; n < MAXDECIMAL; n++, m *= 10) {
            mul = num * m;
            if ((double)(int)mul == mul) {
                break;
            }
        }
    
        printf("%.*f", n, num);
    }
    
    void SkyLine::Print()
    {
        CoordNode *pNode = coordHead.next;
    
        while (pNode) {
            putchar('(');
            PrintDouble(pNode->x);
            putchar(',');
            PrintDouble(pNode->y);
            putchar(')');
            pNode = pNode->next;
        }
    
        putchar('\n');
    }
    
    BOOL Exception::Handle()
    {
        switch (err) {
        case ErrInvalidFormat:
            printf("%s", "Error: Invalid tuple input:\n");
            ((Tuple *)param)->Print();
            putchar('\n');
            return TRUE;
    
        case ErrTooLongTuple:
            printf("%s", "Error: Too long tuple input:\n");
            ((Tuple *)param)->Print();
            putchar('\n');
            return TRUE;
    
        case ErrNoSpace:
            printf("%s", "Error: Memory allocation failed.\n");
            return TRUE;
    
        default:
            return FALSE;
        }
    }
    
    int main(void)
    {
        int     ch;
        Tuple   tuple;
        SkyLine skyline;
    
        while ((ch = getchar()) != EOF) {
            try {
                tuple.AddChar(ch);
                if (tuple.IsValid()) {
                    skyline += tuple;
                    tuple.Clear();
                }
            } catch (Exception e) {
                e.Handle();
                exit(1);
            }
        }
    
        skyline.Print();
    
        return 0;
    }