科目: 程式設計
學號: 考試日期 2024.6.14
期末考 姓名:
考試時間 08:10-11:00
Open book; turn off computer & mobile phone
1
2
3
4
5
6


7
8
9
10

  1. (10%) Suppose you compile and run the following code on a x86 host (e.g., lilina) which stores data in Little Endian. What will be the output?
    // Little Endian, void*
    #include <iostream>
    using std::cout;
    using std::endl;
    int main()
    {
       char school[] = "NCNU";     // ASCII code of 'A' is 65.
       void* p = school;
       char*  p1 = reinterpret_cast<char*>(p);
       short* p2 = reinterpret_cast<short*>(p);
       cout << *reinterpret_cast<short*>(p1 + 1) << '\t';
       cout << *(p2 + 1) << endl;
       return 0;
    }


  2. (10%) If we expect the output of this program to be a sorted sequence 1, 2, 3, 4, 5, 6, 7, what should be the statement in (2)?
    // Doubly Linked-List
    #include <iostream>

    class CNode {
    public:
        CNode* prev;
        CNode* next;
        int    data;
        CNode(int v=0): prev(nullptr), next(nullptr), data(v) {}
        // Be aware of the order.  The initialization list should not be
        // data(v), prev(nullptr), next(nullptr)
    };

    class CList {
    public:
        CNode* head;
        CNode* tail;
        CList() { head = tail = nullptr; }

        void insertAfter(int v, CNode* p) {
            CNode* pNewNode = new CNode(v);
            if (p == tail) {        // p->next == nullptr
                tail = pNewNode;
            } else {
                pNewNode->next = p->next;
                p->next->prev = pNewNode;
            }
            pNewNode->prev = p;
            p->next = pNewNode;
        }

        void insertBeginning(int v) {
            // It assumes head is not null.
            // Is this assumption safe?
            CNode* pNewNode = new CNode(v);
            head->prev = pNewNode;
            pNewNode->next = head;
            head = pNewNode;
        }

        void append(int v) {
            if (head == nullptr) {
                CNode* pNewNode = new CNode(v);
                head = tail = pNewNode;
            } else {
                if (v < head->data) {
                    insertBeginning(v);
                } else {
                    CNode* p;
                    // Find the node whose value is greater than v
                    for (p=head; p->data <= v && p->next != nullptr;
                            p=p->next);
                    if (v < p->data)
                                (2)    
                    else    // p == tail, i.e., p->next == nullptr
                        insertAfter(v, p);
                }
            }
        }

        void show() {
            for (CNode* p = head; p != nullptr; p=p->next)
                std::cout << p->data << ' ';
            std::cout << std::endl;
        }
    };

    int main() {

        int A[] = {  2, 4, 6, 1, 3, 5, 7 };
        CList aList;
        for (size_t i=0; i<sizeof(A)/sizeof(A[0]); ++i)
           aList.append(A[i]);
        aList.show();
        return 0;
    }


  3. (10%) Determine whether the following code has syntax errors or not.  If it is correct, predict its output.  If it is incorrect, point out the line(s) with syntax mistake(s).

    // operator--()
    #include <iostream>
    #include <string>
    #include <cstring>
    using std::string;
    using std::ostream;

    class CTime {
    friend ostream& operator<<(ostream& o, CTime t) {
        o << t.to_str();
        return o;
    }
    public:
        CTime(short h = 0, short m = 0):
            hour(h), minute(m) { }
        string to_str() {
            char result[6];
            sprintf(result, "%02d:%02d", hour, minute);
            return string(result);
        }
        CTime& operator--() {
            --hour;
            return *this;
        }
        CTime operator--(int n) {
            if (--minute < 0) {
                minute += 60;
                if (--hour < 0) hour+=24;
            }
            return *this;
        }
    private:
        short hour;
        short minute;
    };

    int main() {
        CTime t1(0, 0);
        CTime t2(0, 0);
        std::cout << --t1 << ' ' << t2-- << '\n';
        return 0;
    }


  4. (10%) Determine whether the following code has syntax errors or not.  If it is correct, predict its output.  If it is incorrect, point out the line(s) with syntax mistake(s).

    // Return by Reference
    #include <iostream>
    #include <string>
    #include <cstring>
    using std::string;
    using std::ostream;

    class CTime {
    friend ostream& operator<<(ostream& o, CTime t) {
        o << t.to_str();
        return o;
    }
    public:
        CTime(short h = 0, short m = 0):
            hour(h), minute(m) { }
        string to_str() {
            char result[6];
            sprintf(result, "%02d:%02d", hour, minute);
            return string(result);
        }
        CTime& operator--() {
            --hour;
            return *this;
        }
        CTime operator--(int n) {
            if (--minute < 0) {
                minute += 60;
                if (--hour < 0) hour+=24;
            }
            return *this;
        }
    private:
        short hour;
        short minute;
    };

    int main() {
        CTime t0(0);
        CTime t1(1);
        CTime t2(6, 12);
        --t0 = t2;
        t1-- = t2;
        std::cout << t0 << ' ' << t1 << ' ' << t2 << '\n';
        return 0;
    }


  5. (10%) If the contents of your CView::OnDraw() function are as below, what result will be shown on the screen after you run the program?  Please specify the coordinates of the endpoints.

    // Rectangle()
    for (int i = 0; i < 5; ++i) {
        int x = 50 - i * 10;
        pDC->Rectangle(x, x, 110 - x, 110 - x);
    }


  6. (10%) If the contents of your CView::OnDraw() function are as below, what result will be shown on the screen after you run the program?  Please specify the coordinates of the endpoints.

    // MoveTo(), LineTo()

    const double PI = 3.14159;
    int r = 100;
    int x0 = r;
    int y0 = r;
    CPoint points[5];
    int degree;
    double theta;
    for (int i = 0; i < 5; ++i) {
        degree = 360 / 5 * i + 90;
        theta = degree * PI / 180;
        points[i] = CPoint(x0 + r * cos(theta), y0-r*sin(theta));
    }
    pDC->MoveTo(points[0]);
    for (int i = 0; i < 5; ++i)
        pDC->LineTo(points[(i + 1) * 2 % 5]);


  7. (10%) Suppose you prepared a message handler in your CView as below:

    // Timer
    void CYourView::OnTimer(UINT_PTR nIDEvent)
    {
        static int n = 0;
        int x = ++n * 10;
        CClientDC aDC(this);
        aDC.Rectangle(x + 1, 11, x + 9, 19);
        if (n >= 40) KillTimer(1);

        CView::OnTimer(nIDEvent);
    }

    In your CView::OnDraw() function, you start the timer by

    SetTimer(1, 500, NULL);

    Suppose the size of your client window is greater than 800x600. Then, after starting the program for 30 seconds, how many rectangles will be drawn on the screen?
    [Timer]

  8. (10%) Suppose we want to develop an MFC application for Caesar Cipher as below. The text typed by the user will be automatically converted to uppercase. What should be the Boolean values of the following properties of the plaintext edit box?
    1. Border
    2. Multiline
    3. Read-Only
    4. Uppercase
    5. Want Return
    [Caesar Cipher]


  9. (10%) When we create the event handler of a menu item, under which class should we place the event handler?
    1. CAboutDlg
    2. CApp
    3. CDoc
    4. CView
    5. CMainFrame
    [Event Handler]

  10. (10%) There are four steps when we create a dialog:
    1. Insert Dialog
    2. Associate the Dialog with a Class
    3. Add a member variable in the Dialog class as a "Control Variable"
    4. Activate the dialog from a menu item handler

    Take the example of Line Width Dialog for example. In Step 4 the code would be
    void CMenuView::OnLineWidth()
    {
    CLineWidthDialog DialogWindow;
    DialogWindow.m_DialogWidth = m_Width;
    if (DialogWindow.DoModal() == IDOK) {
    m_Width = DialogWindow.m_DialogWidth;
    m_SolidPen.DeleteObject();
    m_SolidPen.CreatePen(PS_SOLID, m_Width, m_Color);

    CMenuDoc* pDoc = GetDocument();
    pDoc->UpdateAllViews(NULL);
    }
    }
    If we omit the statement to initialize the data member m_DialogWidth before we activate the dialog, how will the program behave differently?  Can we still draw lines with different widths?
    void CMenuDrawView::OnLineWidth()
    {
    CLineWidthDialog DialogWindow;
    // DialogWindow.m_DialogWidth = m_Width;
    if (DialogWindow.DoModal() == IDOK) {
    m_Width = DialogWindow.m_DialogWidth;
    m_SolidPen.DeleteObject();
    m_SolidPen.CreatePen(PS_SOLID, m_Width, m_Color);

    CMenuDrawDoc* pDoc = GetDocument();
    pDoc->UpdateAllViews(NULL);
    }
    }

    [Dialog]