달력

52024  이전 다음

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

 

C++이 어려워지므로, 수업시간에 공부한 예제 중심으로 설명하겠습니다.

아래 순서이며 전부 열혈강의 책에 있습니다.

1. 스마트 포인터 (두 예제 중에 첫 번째 꺼)

2. 펑터 (첫 번째 예제)

3. 스트링연산자 (역시 첫 번째 예제)

 

 

1. 스마트 포인터

: 클래스 객체를 포인터 문법처럼 쓸 수 있는 것입니다.

어떻게? 포인터 문법에 사용되는 각종의 연산자를 오버로딩 해서요.

왜 쓰냐? 아래처럼 소멸자를 이용하여, 프로그램 종료 시에 동적할당 된 주소를 소멸시켜 주려구요.

 ~SmartPtr()

 {  

delete posptr;

 }

스마트한 발상이네요.

 

나머지는 아래 코드의 주석을 참조하세요.

=====================

#include <iostream>

using namespace std;


class Point

{

private: 

int xpos, ypos;


public: 

Point(int x=0, int y=0) : xpos(x), ypos(y)  

{  cout<<"Point 객체 생성"<<endl; }


~Point()

  

cout<<"Point 객체 소멸"<<endl; 

} 


void SetPos(int x, int y)

 {  xpos=x;  ypos=y; }


 friend ostream& operator<<(ostream& os, const Point& pos);

};


ostream& operator<<(ostream& os, const Point& pos)

{ 

os<<'['<<pos.xpos<<", "<<pos.ypos<<']'<<endl;

 return os;

}



class SmartPtr{

private: 

Point * posptr;


public: SmartPtr(Point * ptr) :

posptr(ptr) //처음 객체 생성 시에, 객체(Point형 포인터ptr)하게 

  {  }             //되면, 그 객체의 posptr 값은 ptr 값이 됩니다.

                    //왜 이러느냐? 나중에 이 객체 sptr 자신이 ptr을 대체하려고 ptr 값을

                   //자신의 몸 안 (posptr)에 복사해 놓는 것입니다. 저그 같습니다.

 

 Point& operator*() const //코드에서 ‘*(객체)’하면 호출되고, 그 객체 몸 안에 있는 

{                                              //*posptr 값을 Point형으로 토해 냅니다. 그럼 ‘*(객체)’  

return *posptr;                //*posptr , ‘Point형 객체로 대변신!!

 } 


Point* operator->() const //역시 위와 같은 연산자 오버로딩. 반환형을 유심히 보세요.

 { 

 return posptr;

 } 


~SmartPtr() 

 {  

delete posptr; //이 부분이 없으면 동적할당 해제가 안됩니다. 안 스마트 하지요.

 }

};


int main(void)

{

 SmartPtr sptr1(new Point(1, 2)); 

SmartPtr sptr2(new Point(2, 3)); 

SmartPtr sptr3(new Point(4, 5));

 cout<<*sptr1; //위 연산자 오버로딩에 의해 *sptr1*ptr1로 되고, 

cout<<*sptr2; cout<<*sptr3;

 sptr1->SetPos(10, 20); //연산자 오버로딩에 의해 ptr ->setpos(10, 20)이 되죠.

 sptr2->SetPos(30, 40); 

sptr3->SetPos(50, 60);

 cout<<*sptr1;  

cout<<*sptr2; 

cout<<*sptr3; 

return 0;

}

 

이상 스마트하게 설명을 마쳤습니다.

목 운동 좀 하고, 아래 펑터 예제로 들어가 봅시다

 

2. 펑터

스마트 포인터가 객체를 포인터처럼 쓰게 하는 거고, 이를 위해 포인터 관련 연산자를 오버로딩 합니다. 마찬가지로,

펑터는 객체를 함수처럼 쓸 수 있게 하는 것이며, 이를 위해 함수 관련 연산자 즉, () 연산자를 오버로딩 합니다.

아래 코드 중에서,,,

====================================

#include <iostream>

using namespace std;


class Point

{

private: int xpos, ypos;public: 

Point(int x=0, int y=0) : xpos(x), ypos(y)  {  }


Point operator+(const Point &pos) const  

{  

return Point(xpos+pos.xpos, ypos+pos.ypos); 

} 


friend ostream& operator<<(ostream& os, const Point& pos);

};


ostream& operator<<(ostream& os, const Point& pos)

{ 

os<<'['<<pos.xpos<<", "<<pos.ypos<<']'<<endl; return os;

}


class Adder //아래 부분에서 () 연산자를 인수의 자료형별로 3가지로 오버로딩 하네요.

{

 public int operator()(const int &n1, const int &n2) //int 관련한 이 부분을 지워봅시다. 

{  

return n1+n2;

 }


 double operator()(const double &e1, const double &e2) 

{  

return e1+e2; 

}


 Point operator()(const Point &pos1, const Point &pos2)

 {  

return pos1+pos2;

 }

};



int main(void)

{

 Adder adder; 

cout<<adder(1, 3)<<endl; //그러면 이 코드는 어떻게 될까요?? 

cout<<adder(1.5, 3.7)<<endl; //double관련 연산자 오버로딩을 지우면 얘는 어케될까요? 

cout<<adder(Point(3, 4), Point(7, 9)); //Point관련 연산자 오버로딩을 지우면?? 

 return 0;                                                            //결과와 이유를 설명하세요. 숙제입니다. 

}

 


 3. String 클래스 만들기

C언어에서 char*를 썼던 곳에, C++에서 우리는 string을 씁니다. 용법이 비슷해서 stringchar*와 같이 기본자료형 비스무리한 걸로 알고 쉽습니다. 하지만, char*는 기본자료형 포인터 이며, string은 사용자정의 자료형입니다.

따라서 String str1 하면, char*와 닮은 string형 변수 str1이 생기는 것이 아니라,

string형 클래스 객체 str1이 생기는 것이죠.


그리고 이 string형 객체 str1char형 포인터 변수 Pchar처럼 동작하게끔 string 클래스에 연산자 오버로딩을 시켜놓은 것이며, 우리는 이 클래스를 가져다 쓰는 것입니다.

, 그럼 어떤 연산자를 오버로딩 해야 할까요?

=============

#include <iostream>

#include <string>

using namespace std;


int main(void)

{ 

string str1="I like "; //일단 문자열이 들어가야 하므로 = 연산자에 대해 대입이  

string str2="string class"; //되게끔 오버로딩 시켜 놓아야 합니다. 

string str3=str1+str2; //char*와는 다르게 +기능이 있으며, 이 역시 +연산자에 대한

                               //오버로딩으로 가능해 진 것입니다.

cout<<str1<<endl; //<<연산자에 대해 ‘operator<< (const String str)' 이렇게   

cout<<str2<<endl; //오버로딩 되어 있을까요?? 그럴까요?? 숙제입니다. 맞추면 

cout<<str3<<endl; //소개팅 나가 드립니다.

 str1+=str2; //+= 연산자에 대해서도 오버로딩 해야 하고, 

if(str1==str3)   //비교 연산자 ===에 대해서도 오버로딩 해야 하고 

cout<<"동일 문자열!"<<endl; else  cout<<"동일하지 않은 문자열!"<<endl;

 string str4; cout<<"문자열 입력: "; cin>>str4; //cout에 쓰인 <<처럼, cin에 쓰인 >> 연산자도 오버로딩 해야 함. 

cout<<"입력한 문자열: "<<str4<<endl; 

return 0;

}

 

 

 

 


Posted by C언어 보이
|

#include <iostream>
using namespace std;

class Point
{
private:
 int xpos, ypos;
public:
 Point(int x=0, int y=0) : xpos(x), ypos(y)
 {
  cout<<"Point 객체 생성"<<endl;
 }
 ~Point()
 {
  cout<<"Point 객체 소멸"<<endl;
 }
 void SetPos(int x, int y)
 {
  xpos=x;
  ypos=y;
 }
 friend ostream& operator<<(ostream& os, const Point& pos);
};
ostream& operator<<(ostream& os, const Point& pos)
{
 os<<'['<<pos.xpos<<", "<<pos.ypos<<']'<<endl;
 return os;
}

class SmartPtr
{
private:
 Point * posptr;
public:
 SmartPtr(Point * ptr) : posptr(ptr)
 {  }

 Point& operator*() const
 {
  return *posptr;
 }
 Point* operator->() const
 {
  return posptr;
 }
 ~SmartPtr()
 {
  delete posptr;
 }
};

int main(void)
{
 SmartPtr sptr1(new Point(1, 2));
 SmartPtr sptr2(new Point(2, 3));
 SmartPtr sptr3(new Point(4, 5));
 cout<<*sptr1;
 cout<<*sptr2;
 cout<<*sptr3;

 sptr1->SetPos(10, 20);
 sptr2->SetPos(30, 40);
 sptr3->SetPos(50, 60);
 cout<<*sptr1;
 cout<<*sptr2;
 cout<<*sptr3;
 return 0;
}

 

====================================

 

 

#include <iostream>
using namespace std;

class Point
{
private:
 int xpos, ypos;
public:
 Point(int x=0, int y=0) : xpos(x), ypos(y)
 {  }
 Point operator+(const Point & pos) const
 {
  return Point(xpos+pos.xpos, ypos+pos.ypos);
 }
 friend ostream& operator<<(ostream& os, const Point& pos);
};

ostream& operator<<(ostream& os, const Point& pos)
{
 os<<'['<<pos.xpos<<", "<<pos.ypos<<']'<<endl;
 return os;
}

class Adder
{
public:
 int operator()(const int &n1, const int &n2)
 {
  return n1+n2;
 }
 double operator()(const double &e1, const double &e2)
 {
  return e1+e2;
 }
 Point operator()(const Point &pos1, const Point &pos2)
 {
  return pos1+pos2;
 }
};

int main(void)
{
 Adder adder;
 cout<<adder(1, 3)<<endl;
 cout<<adder(1.5, 3.7)<<endl;
 cout<<adder(Point(3, 4), Point(7, 9));
 return 0;
}

 

 

=============

 

#include <iostream>
#include <string>
using namespace std;

int main(void)
{
 string str1="I like ";
 string str2="string class";
 string str3=str1+str2;

 cout<<str1<<endl;
 cout<<str2<<endl;
 cout<<str3<<endl;

 str1+=str2;
 if(str1==str3)  
  cout<<"동일 문자열!"<<endl;
 else
  cout<<"동일하지 않은 문자열!"<<endl;

 string str4;
 cout<<"문자열 입력: ";
 cin>>str4;
 cout<<"입력한 문자열: "<<str4<<endl;
 return 0;
}

 

 

 

 

 

Posted by C언어 보이
|

오전) 아트메가 각 버스별 비트숫자가 의미하는 명령어

 

오후) 링크드 리스트

 

핵심 : 중간삽입은...

삽입할 구조체가 stpnew라 카므는..

조건 만족시에,

stpfront->next=stpnew;

stpnew-next=rear;

즉 stpnew가 앞 놈의 next고, 자신의 next는 뒷 놈으로 넣는다.

 

 

 

 

조건 식은... stpnew->data가 stprear->데이타 보다 작다는 것.

 

아, 열 핵심스러운 설명이네요. 감탄감탄+_+;

 

 

 

위 코드는 아래와 같습니다.

 

void Node_Insert(Node * head,char Cdata)
{
 Node* stpfront=head;
 Node* stprear=head;
 
 Node* stpnew=malloc(sizeof(Node));
 stpnew->data=Cdata;
 stpnew->next=0;
 

 while(stprear->next!=0)
 {
  stpfront=stprear;
  stprear=stprear->next;
  if(stprear->data>stpnew->data)
  {
   stpfront->next=stpnew;
   stpnew->next=stprear;
   
   break;
  }
 }

}

 

이상으로,

링크드리스트 중간삽입에 대하여 알아보았습니다.

 

 

Posted by C언어 보이
|

문제 연결리스트 삽입.

: 연결리스트코드로  'a->b->c->null'로 출력되게 되어 있는데, 여기서 z를 삽입하여  'a->b->z->c->null'로 되게 하라.

 

조건1. 추가 변수 선언하지 말 것.

조건2. 삽입되는 z를 사용자 입력을 받아서 하면 더 칭찬해 줌. 

 

 

 

 

고친 부분은 30~38행 이다.

처음에 생각하기는 어려울 수도 쉬울 수도 있으나,

해석은 무지 쉽다.

 

특히 31행을 보라.

아주 쉽다.

 

 

 

 

 

 

 

 

 

이상 연결리스트의 삽입에 대해 알아보았습니다~

 

 

 

 

 

 

Posted by C언어 보이
|

[오전] 분할컴파일

#if a : a가 0이 아닌 경우 endif가 나올 때 까지 아래 실행문을 실행하라는 말.

(실행문)

#endif

 

[오후]

- 소스인사이트 툴 사용법.

- 전날 오후 수업 복습

- 기타 개인용무 (개인송사)

Posted by C언어 보이
|

아트메가 밝히기 : volatile, 반복문

문제 : LED 8개를 이용하여 불을 하나씩 오른쪽으로~왼쪽으로~  움직여 보시오.

풀이 :

-          Volatile 쓰는 이유 : for ~넘어가게 하지 않기 위해서. Cpu 최적화를 하기 때문에 volatile 써주면..for문이 하는 일이 없다고 보고 uicnt=65000 바로 넣어버려, 반복문을 넘어가게 된다.

 

 

참고로 16 Mhz이기 때문에..6 오천이면… 6.5/16 만에 반복문 하나를 수행하는 .

그래서 4개를 써주면  6.5*4해서 1.3 만에 움직이게 있다.

그럼..얼마나 움직이게 것인가..

Led 개의 주소는 2 뛰므로 곱하기 2 것이다.

 

 

그리고 중요한 조건식.

본인은..’dir’라는 변수를 이용했다.

변수로 불빛이 움직여야 방향 (, 불이 들어와야 led 주소값) 판별해 준다.

그리고 범위는 128(1 led) 0(8  led)으로 지정해 준다.

 

이상으로 아트메가 밝히기 : volatile, 반복문

보았다.

 

Posted by C언어 보이
|

[오전]

아트메가용 컴파일러의 이해와 설치

 

[오후]

- 구조체 멤버변수의 주소접근 (void 포인터의 사용)

- 구조체 typedef

 

 

Posted by C언어 보이
|

20140409 mcu 구조와 구조체 사용 시 주의점

 

[오전]

1. MCU

risc : 쪼개놓은 명령어. 복잡다양.

cisc : 뭉쳐놓은 명령어. 심플단순.

 

ALU

CU

Reg - 메모리

       - 기능 + 메모리

 

[오후]

구조체 : 저장방식이 4바이트 씩. 따라서 넘치지 않게.

또..2바이트 자료형 (short)은 ..중간에 저장되지 않음.

이 때 pragma pack 을 적절히 사용.

 

 

 

Posted by C언어 보이
|

가산기회로의 구조, strcpy 함수, 구조체 배열

 

1. 오전

- 가산기회로의 구조

- 발진회로에 대한 내용 대략 읽어봄

 

2. 오후

c언어

 

(1) strcpy 함수의 테스트 (두번 째 인자에 포인터 상수 대신 다른 걸로)

: 문제없음. 다만 문자열 복사함수의 특징상 문자열 상수 포인터로 쓰는 경우가 많아서 const 임을 '상정'하는 것일 뿐, const를 '써야만' 한다는 문법적 제약은 아님을 발견하였음. 뭐 별 가치없는 발견으로 보임.

 

 

 

(2) 구조체 배열 실습한 것임

 

 

Posted by C언어 보이
|

putchar 함수의 활용 : 문자열의 주소접근과 포인터

 

 

putchar함수는 하나의 문자를 출력하는 함수이다.

용법은

putchar('출력문자 변수명');

와 같이 쓴다.

 

 

자 아닥하고 문제!

아래 반복문을 이용하여 testprogram을 출력하라.

 

 

즉, 아래처럼 하라.

단, 변수는 추가로 쓰지 말고, 출력함수도 putchar만 쓰라.

오로지 조건식과 실행식만 추가해라.

힌트 : 문자열의 각 글자와 그 주소값을 이용하라.

5분 주께..

1분..

2분..

 

정답은 아래와 같다.

 

이상으로 'putchar 함수의 활용'에 대하여 알아보았다.

아래 손가락! 눌러주시고 좋은 하루 보내세요~*

 

Posted by C언어 보이
|