'language/C|C++'에 해당되는 글 11건

336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

21-1. 스트림과 데이터의 전송


스트림(stream):    프로그램과 하드웨어(키보드, 모니터,..)를 연결해주는 소프트웨어적으로 구현된 다리

 연속된 데이터의 열(line)


표준 스트림(standard stream): 표준 입출력 스트림. 기본적으로 제공되는 스트림


stdin      : 표준 입력 스트림

stdout    : 표준 출력 스트림



21-2. 문자 단위 입출력 함수


putchar

fputc


getchar

fgetc


EOF: 오류발생 및 파일의 끝에 도달한 경우 호출되는 반환 값(-1). Ctrl+Z


21-3. 문자열 단위 입출력 함수


puts: 자동 개행

fputs


gets: Overflow 발생 가능성

fgets: 문자열 마지막에 NULL 삽입



21-4. 표준 입출력 버퍼


버퍼(buffer): 여분의 임시 메모리 공간

버퍼링(buffering): (성능 향상의 목적으로) 버퍼(임시 저장소)에 데이터를 임시 저장해 두는 것.


fflush: 버퍼를 비우는 작업을 하는 함수.



21-5. 문자열 조작 함수





'language > C|C++' 카테고리의 다른 글

typedef  (0) 2016.08.06
FILE* fopen  (0) 2016.07.26
데이터 상수화, 포인터 상수화  (0) 2016.07.21
SwitchViewDemo  (0) 2016.06.06
디폴트 대입연산자에 의한 문제점  (0) 2016.05.07
블로그 이미지

saylin

,
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.


const int* n : 데이터 상수화(n이 가르키는 데이터 값 변경 불가)


int* const n : 포인터 상수화(n이 가르킬 변수 변경 불가)



'language > C|C++' 카테고리의 다른 글

FILE* fopen  (0) 2016.07.26
문자와 문자열 처리 함수  (0) 2016.07.25
SwitchViewDemo  (0) 2016.06.06
디폴트 대입연산자에 의한 문제점  (0) 2016.05.07
#pragma  (0) 2016.05.02
블로그 이미지

saylin

,

SwitchViewDemo

language/C|C++ 2016. 6. 6. 01:30
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

1. CMyHtmlView, CMyEditView, CMyListView Class 추가


2. CMainFrame 헤더 파일에 다음과 같이 각각의 클래스 헤더 파일들 추가


 

// MainFrm.h : CMainFrame 클래스의 인터페이스

//

 

#pragma once

 

#include "MyEditView.h"

#include "MyHtmlView.h"

#include "MyListView.h"

 

class CMainFrame : public CFrameWnd

{



3. 추가한 클래스의 객체들에 대한 포인터 변수를 CMainFrame 클래스의 멤버로 등록


 

protected// 컨트롤 모음이 포함된 멤버입니다.

                  CToolBar          m_wndToolBar;

                  CStatusBar        m_wndStatusBar;

 

// 생성된 메시지 함수

protected:

                  afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);

                  DECLARE_MESSAGE_MAP()

 

                  CMyHtmlView* m_pwndHtmlView;

                  CMyEditView* m_pwndEditView;

                  CMyListView* m_pwndListView;

};

 


4. CMainFrame 클래스의 OnCreateClient 가상 함수를 재정의하여 다음과 같이 뷰 윈도우를 new 연산을 통해 생성하는 코드를 작성


OnCreateClient() 함수를 호출하면 내부적으로 new 연산 후 CreateWindow() 함수가 호출된다.


이 과정에서 RUNTIME_CLASS 매크로가 사용되는데, 

MFC에서는 이를 통해 임의로 정의되는 하위 클래스의 동적 생성을 지원한다.



BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)

{

                  // TODO: 여기에 특수화된 코드를 추가 /또는 기본 클래스를 호출합니다.

 

                  m_pwndHtmlView = new CMyHtmlView;

                  m_pwndEditView = new CMyEditView;

                  m_pwndListView = new CMyListView;

 

                  return CFrameWnd::OnCreateClient(lpcs, pContext);

}

 


다만, 위 과정에서 CMyHtmlView, CMyEditView, CMyListView 클래스의 생성자는 

protected에 의해서 접근이 제한되어 있기 때문에 이를 public 멤버로 수정해준다.



// CMyEditView 뷰입니다.

 

class CMyEditView : public CEditView

{

                  DECLARE_DYNCREATE(CMyEditView)



// protected 멤버를 다음과 같이 public으로 수정

 

public:

                  CMyEditView();           // 동적 만들기에 사용되는 protected 생성자입니다.

                  virtual ~CMyEditView();

 

public:

#ifdef _DEBUG

                  virtual void AssertValid() const;

#ifndef _WIN32_WCE

                  virtual void Dump(CDumpContext& dc) const;

#endif

#endif

 

protected:

                  DECLARE_MESSAGE_MAP()

};

 

 


5. CMainFrame의 헤더 파일에 다음과 같은 상수를 정의


이 상수들은 생성될 뷰 윈도우의 ID가 된다.


 

// MainFrm.h : CMainFrame 클래스의 인터페이스

//

 

#pragma once

 

#include "MyEditView.h"

#include "MyHtmlView.h"

#include "MyListView.h"

 

#define VIEWID_DEFAULT AFX_IDW_PANE_FIRST

#define VIEWID_HTML    AFX_IDW_PANE_FIRST      + 10         

#define VIEWID_EDIT    AFX_IDW_PANE_FIRST      + 20         

#define VIEWID_LIST    AFX_IDW_PANE_FIRST      + 30




6. CMainFrame Class의 OnCreateClient() 함수에 뷰 윈도우를 생성하는 코드들을 추가


BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)

{

                  // TODO: 여기에 특수화된 코드를 추가 /또는 기본 클래스를 호출합니다.

 

                  m_pwndHtmlView = new CMyHtmlView;

                  m_pwndEditView = new CMyEditView;

                  m_pwndListView = new CMyListView;

 

                  m_pwndHtmlView->Create(NULL, NULL, WS_CHILD , CFrameWnd::rectDefault, this, VIEWID_HTML, pContext);

                  m_pwndEditView->Create(NULL, NULL, WS_CHILD , CFrameWnd::rectDefault, this, VIEWID_EDIT, pContext);

                  m_pwndListView->Create(NULL, NULL, WS_CHILD , CFrameWnd::rectDefault, this, VIEWID_LIST, pContext);

 

                  return CFrameWnd::OnCreateClient(lpcs, pContext);

}



7, CMyHtmlView Class에 OnInitialUpdate() 가상 함수를 재정의하고 다음과 같은 코드를 추가


void CMyHtmlView::OnInitialUpdate()

{

                  CHtmlView::OnInitialUpdate();

 

                  Navigate2(_T("C:\\"));

}

 


8. CMyListView Class에 WM_CREATE 메세지 핸들러 함수를 등록하고 리스트 컨트롤을 초기화하는 코드를 추가


 

int CMyListView::OnCreate(LPCREATESTRUCT lpCreateStruct)

{

                  if (CListView::OnCreate(lpCreateStruct) == -1)

                                   return -1;

 

                  CListCtrl& List = GetListCtrl();

 

                  List.InsertColumn(0, _T("Name"), LVCFMT_LEFT, 200);

                  List.InsertItem(0, _T("SwitchViewDemo"));

 

                  List.ModifyStyle(LVS_TYPEMASK, LVS_REPORT);

 

                                   return 0;

}

 


9. CMainFrame Class에 SwitchView(int nID) 함수를 멤버로 등록하여 다음과 같은 코드를 추가


void CMainFrame::SwitchView(int nID)

{

                  // CFrameWnd::GetActiveView 함수.

                  // 현재 활성화된  윈도우의 포인터를 반환하는 기능

                  CView* pOldView = GetActiveView();

                  CView* pNewView = NULL;

 

                  switch(nID)

                  {

                  case VIEWID_HTML:

                                   pNewView = (CView*)m_pwndHtmlView;

                                   break;

 

                  case VIEWID_EDIT:

                                   pNewView = (CView*)m_pwndEditView;

                                   break;

 

                  case VIEWID_LIST:

                                   pNewView = (CView*)m_pwndListView;

                                   break;

                  }

 

                  if(pNewView)

                  {

                                   if(pOldView == pNewView)                      return;

 

                                   pOldView->ShowWindow(SW_HIDE);

                                   pOldView->SetDlgCtrlID(nID);

 

                                   // 활성화된 윈도우의 ID 반드시 AFX_IDW_PANE_FIRST 되어야 한다.

                                   pNewView->SetDlgCtrlID(AFX_IDW_PANE_FIRST);

                                   pNewView->ShowWindow(SW_SHOW);

 

                                   // 특정 윈도우를 활성화된 클라이언트 윈도우로 설정하는 기능을 수행

                                   SetActiveView(pNewView);

                                  

                                   // CFrameWnd::RecalcLayout 함수. 

   //  메인프레임 윈도우와 관련된 각종 컨트롤과 클라이언트 윈도우를 적절히 재배치

                                   RecalcLayout();

                  }

}

 


10. 다음과 같이 메뉴 리소스를 편집하고 각각의 메뉴에 대한 이벤트 처리기를 추가





11. 추가한 이벤트 처리기 함수에 다음과 같은 코드를 입력


 

void CMainFrame::OnSwitchviewSwitcheditview()

{

                  SwitchView(VIEWID_EDIT);

}

 

void CMainFrame::OnSwitchviewSwitchhtmlclass()

{

                  SwitchView(VIEWID_HTML);

}

 

void CMainFrame::OnSwitchviewSwitchlistview()

{

                  SwitchView(VIEWID_LIST);

}

 



'language > C|C++' 카테고리의 다른 글

문자와 문자열 처리 함수  (0) 2016.07.25
데이터 상수화, 포인터 상수화  (0) 2016.07.21
디폴트 대입연산자에 의한 문제점  (0) 2016.05.07
#pragma  (0) 2016.05.02
인라인(Inline) 함수  (0) 2016.05.02
블로그 이미지

saylin

,
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

아래 코드와 같이 객체 간 (디폴트 대입연산자를 통한) 대입연산을 시행하는 경우, 

소멸자의 호출과정에서 문제가 발생한다. 즉, 두 개의 객체를 생성했지만 소멸자는 한번 밖에 호출되지 않는다.


이는 디폴트 대입연산자를 통한 대입연산은 얕은 복사를 수행하기 때문에 생기는 문제다.

얕은 복사(Shallow Copy)는 객체의 멤버변수를 단순 복사해서 다른 객체의 멤버 변수에 옮기는 역할만을 수행한다.


문자열과 같은 포인터 변수를 복사하는 경우, 포인터 변수가 참조하는 주소값을 복사하게 되고 

따라서 얕은 복사가 수행된 후 두 객체는 하나의 같은 문자열 데이터를 참조하게 된다.


한 객체가 소멸자를 호출하여 소멸하면 그 객체가 가지고 있던 문자열 데이터 또한 소멸하게 된다.

이후 다른 객체가 소멸자를 호출할 때, 그 객체의 포인터 변수가 가리키는 문자열 데이터는 이미 소멸한 상태이므로

이미 지워진 문자열을 중복 소멸하는 문제가 발생하게 된다.


아래 코드를 컴파일하면 정상적으로 수행되긴 하지만 종료 과정에서 에러가 발생한다.





에러가 발생한 지점이 debug_heap.cpp의 _CtrIsValidHeapPointer(block)에서 발생한 것으로 보아 

현재로선 정확한 현상 진단을 하기는 어렵지만 정상적으로 메모리 해제가 이루어지지 않음으로써 발생하는 문제로 추정한다.


이는 얕은 복사를 수행하는 디폴트 대입연산자 대신 깊은 복사(Deep Copy)를 수행하는 직접 대입 연산자를 정의하면 해결된다. (주석 부분)


#define _CRT_SECURE_NO_WARNINGS


#include <iostream>

#include <cstring>


using namespace std;


class Person

{

private:

char *name;

int age;

public:

Person(char *myname, int myage)

{

int len = strlen(myname) + 1;

name = new char[len];

strcpy(name, myname);

age = myage;

}

void ShowPersonInfo() const

{

cout << "이름: " << name << endl;

cout << "나이: " << age << endl;

}

~Person()

{

delete[]name;

cout << "called destructor!" << endl;

getchar();

}

// Person& operator=(const Person& ref)

// {

//  delete[]name;

//  int len = strlen(ref.name) + 1;

//  name = new char[len];

//  strcpy(name, ref.name);

//  age = ref.age;

//  return *this;

// } 

};


int main(void)

{

Person man1("Lee Dong woo", 29);

Person man2("Yoon ji yul", 22);

man2 = man1;


man1.ShowPersonInfo();

man2.ShowPersonInfo();


return 0;

}



'language > C|C++' 카테고리의 다른 글

데이터 상수화, 포인터 상수화  (0) 2016.07.21
SwitchViewDemo  (0) 2016.06.06
#pragma  (0) 2016.05.02
인라인(Inline) 함수  (0) 2016.05.02
#ifdef, #endif,.. Preprocessor  (0) 2016.05.01
블로그 이미지

saylin

,