'C++프로그래밍'에 해당되는 글 45건

#define MAX_ELEMENT 200
#define HEAP_FULL(n) (n == MAX_ELEMENT-1)
#define HEAP_EMPTY(n) (!n)
typedef struct{
 int key;
}element;

element heap[MAX_ELEMENT];
int n=0;

//최대 히프에 삽입
void insert_max_heap(element item, int* n){
 int i;
 if(HEAP_FULL(*n)){
  fprintf(stderr,"the heap is FULL\n");
  exit(1);
 }
 i=++(*n);
 while((i != 1) && (item.key > heap[i/2].key)){
  heap[i] = heap[i/2];
  i/=2;
 }
 heap[i] =item;
}

element delete_max_heap(int* n){
 int parent,child;
 element item,temp;
 if(HEAP_EMPTY(*n)){
  fprintf(stderr,"the heap is EMPTY\n");
  exit(1);
 }

 item=heap[1];
 temp=heap[(*n)--];
 parent = 1;
 child = 2;
 while(child <= *n){
  if(child< *n) && (heap[child].key) < heap[child+1].key
   child++;
  if(temp.key >= heap[child.key) break;

  heap[parent] =heap[child];
  parent=child;
  child* = 2;
 }
 heap[parent] = temp;
 return item;
}

블로그 이미지

百見 이 不如一打 요 , 百打 가 不如一作 이다.

,

11장정리

C++프로그래밍/C++ 2007. 7. 26. 10:12

int main(){
 string str1="Good";
 string str2="Morning";
 string str3=str1+str2;

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

 str1+=str2;
 if(str1==str3)
  cout<<"equal"<<endl;

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

 return 0;
}

 
이 메인 함수에 대한 string 클래스를 디자인 해라.
블로그 이미지

百見 이 不如一打 요 , 百打 가 不如一作 이다.

,

typedef struct TreeNode{
 int key;
 struct TreeNode *left,*right;
}TreeNode;

//삭제
void delete_node(TreeNode** root, int key){
 TreeNode *p,*child,*succ,*succ_p,*t;

 p = NULL;
 t= *root;

 while(t != NULL && t->key != key){
  p=t;
  t=(key < t->key) ? t->left : t->right;
 }
 if( t== NULL){
  printf("Key is not in the tree");
  return ;
 }
 // 단말노드인 경우
 if((t->left == NULL) && (t->right == NULL)){
  if(p != NULL){
   if(p->left == t)
    p-left = NULL;
  }
  else
   *root = NULL;
 }
 //하나의 자식만 가지는 경우
 else if((t->left == NULL) || (t->right == NULL)){
  child = (t->left != NULL) ? t->left : t->right;
  if(p != NULL){
   if(p->left == t)
    p->left = child;
   else p->right = child;
  }
  else
   *root = child;
 }
 else{
  succ_p = t;
  succ = t->right;
  while(succ->left != NULL){
   succ_p = succ;
   succ = succ->left;
  }
  if(succ_p-<left == succ)
   succ_p->left = succ->right;
  else succ_p->right = succ->right;

  t->key = succ->key;
  t=succ;
 }
 free(t);
}

블로그 이미지

百見 이 不如一打 요 , 百打 가 不如一作 이다.

,

typedef struct node* tree_pointer;
typedef struct node{
 int data;
 tree_pointer left_child,right_child;
};
//이진 탐색 트리의 순환적 탐색
tree_pointer search(tree_pointer root, int key){
 if(!root) return NULL;
 if(key == root->data) return root;
 if(key < root->data)
  return search(tree_pointer left_child,int key);
 return search(tree_pointer right_child,int key);
}
//이진 탐색 트리의 반복적 탐색
tree_pointer search(tree_pointer tree,int key){
 while(tree){
  if( key == tree->data) return tree;
  if( key < tree->data)
   tree=tree->lefe_child;
  else
   tree=tree->right_child;
 }
 return NULL;
}
//반복적 탐색의 변형
void modified_search(tree_pointer node2,int num){
 tree_pointer temp;
 if(!node2) return NULL;
 while(node2 !=NULL ){
  if(num == node2->data) return node2;
  temp=node2;
  if(num < temp->data)
   temp = temp->left;
  else temp=temp->right;
 }
}


//이진 탐색 트리에 원소를 삽입
void insert_node(tree_pointer* node,int num){
 tree_pointer ptr;
 temp=modified_search(*node,num);
 if( temp || !(*node)){
  ptr = (tree_pointer)malloc(sizeof(node));
  if(IS_FULL(ptr)){
   fprintf(stderr,"The memory is FULL\n");
   exit(1);
  }
  ptr->data = num;
  prt->left_child = prt->right_child = NULL;
  if(*node)
   if(num < temp->data)
    temp->left_child = ptr;
   else temp->right_child =ptr;
  else *node =ptr;
 }
}


블로그 이미지

百見 이 不如一打 요 , 百打 가 不如一作 이다.

,

10장정리

C++프로그래밍/C++ 2007. 7. 24. 21:13

1. 연산자 오버로딩의 의미

#include <iostream>

using std::cout;
using std::endl;

class Point{
private:
 int x,y;
public:
 Point(int _x=0, int _y=0) :x(_x),y(_y){}
 void ShowPosition();
 void operator+(int val);
};

void Point::ShowPosition(){
 cout<<x<<' '<<y<<endl;
}

void Point::operator+(int val){
 x+=val;
 y+=val;
}

int main(){
 Point p(3,4);
 p.ShowPosition();
 p.operator+(10);  // p+10;
 p.ShowPosition();

 return 0;
}

p객체를 생성하면서 3.4로 초기화 시켜주고 p의 멤버함수 operator+를 호출하면서 10을
인자로 전달해주고있다. operator+함수는 클래스 멤버변수의 값에 매개변수를 더해주고있다.

C++의 연산자 오버로딩은 하나의 약속일뿐이다.p+10 <-이것은 원래대로 라면 객체와 정수를 더하는 연산인데 이게 가능한가? 불가능하다.그래서 정한 약속에 불과할 뿐이다.
+기호 앞에operator이라는 이름을 붙여서 일반의 +와 오버로딩을 시키는 것이다.
결국 p+10 이란 문장은 p.operator+(10) 해석이 된다.이것은 곧 멤버함수에 의한 연산자 오버로딩에 해당된다.

2. 연산자를 오버로딩 하는 두가지 방법
멤버함수에 의한 연산자 오버로딩

class Point{
private:
 int x,y;
public:
 Point(int _x=0, int _y=0) :x(_x),y(_y){}
 void ShowPosition();
};

void Point::ShowPosition(){
 cout<<x<<' '<<y<<endl;
}

이러한 함수로 객체와 객체를 더해서 객체에 대입해 주고자 한다..무슨말이냐면 ㅋㅋ

int main(){
 Point p1(1,2);
 Point p2(2,3);
 Point p3=p1+p2;
 p3.ShowPosition();
 return 0;
}


이런 연산을 하고 싶단말이지..그럼 저건 어떤식으로 해야 가능할까?
함수를 정의해 보자고..우선 두개다 객체야..그럼 인자로 객체를 받아야할테고..
자 써보자고 operator+(Point& P) 이렇게 받는 객체를 생성해야지..
그리고 몸체부분에서 새로운 객체를 하나 생성해주고 temp로 그 temp생성할때
매개변수를 p1.p2의 x,y를 더한값을 주고 temp를 리턴해.

Point operator+(Point& p){ //(Point p)로넘겨주어도 되나 메모리의 사용에 효율을위해
   Point temp(x+p.x,y+p.y);
   return temp;
}


전역함수에 의한 오버로딩
위의 Point p3=p1+p2; 이 연산을 전역함수로 선언할 경우는 위의 멤버함수의 연산자 오버로딩과 형태가 달라진다.
사용자 삽입 이미지
<내가 돈주고산 열혈강의C++ ppt에서 캡춰>

이렇다는것을 알아두길 바라고..그럼 전역함수로 연산자 오버로딩을 하려면?
일단 저거 보면 연산자오버로딩 함수가 객체 두개를 인자로 받고 있다..그럼
operator+(Point& p1,Point& p2) 로 전달을 해줘야 하겠지..그럼 전체적으로 써볼까..
Point operator+(Point& p1,Point& p2){
   Point temp(p1.x+p2.x , p1.y+p2.y);
   return temp;
}

이렇게 해줘야..된닷!! 그런데 여기서..전역함수 이니까..멤버함수에 접근할려면
객체 내에서 friend선언 을 해줘야 하는것을 잊지 말라규~~

위와같이 멤버함수에서의 사용법과 전역함수에서의 사용법중 어떤게 좋을까.



객체지향에는 전역이라는 개념이 존재하지 않는다.




오버로딩이 불가능한 연산자의종류

.         .*         ::         ?:         sizeof


연산자 오버로딩에 있어서의 주의사항
첫째.본 의도를 벗어난 연산자 오버로딩은 좋지않다.
둘째.연산자 우선순위와 결합성을 바꿀수는 없다.
셋째.디폴트 매개변수 설정이 불가능하다.
넷째.디폴트 연산자들의 기본 기능까지 빼앗을 수는 없다.

3.단항연산자의 오버로딩
증가 감소 연산자의 오버로딩

사용자 삽입 이미지

<내가 돈주고산 열혈강의C++ ppt에서 캡춰>


이 소스를 보고 이해해라 어려운건 아니니..그런데 ++(++p)나 --(--p)연산의 함수를 보면
리턴타입이 레퍼런스 인 이유는 레퍼런스로 리턴받지 않으면 리턴값이 그냥 복사만 되기때문에 p의 값은 한번밖에 연산이 되지않고 나머지 한번의 연산은 복사본을 가지고 하는 연산이다. 그렇기때문에 레퍼런스로 넘겨주어야 p를 두번 연산할수 있는것이다.

선 연산과 후 연산의 구분
 
사용자 삽입 이미지
<내가 돈주고산 열혈강의C++ ppt에서 캡춰>

위와 같이 연산 할때와 연산 할때의 연산자 오버로딩의 매개변수가 다르다.
연산을 위한 함수를 오버로딩 할경우 키워드int를 매개변수로 선언하면 이것은 연산을
뜻하는 것으로 해석함. 여기서 int는 키워드 이다.

Point& Point::operator++(){
 ++x;
 ++y;
 return *this;
}
Point Point::operator++(int){
 Point temp(x,y); //point temp(*this);
 x++;
 y++;
 return temp; //여기서는 레퍼런스로 넘기면 안된다 왜냐면 temp객체는 함수지역객체이
}                 //기 때문에 함수가 종료됨과 동시에 사라지게 된다..그래서 복사로넘겨야
                  //한다. 이런 자질구레한 것까지 신경써야 좋은프로그래밍을 할수있겠지?

4. 교환법칙 해결하기
int a=3+4; 의 경우 3과4는 변경되지 않고 3+4의 값만이 a에 대입이 되는것이다.그런데
맨위의 예제에서 보면

Point p(3,4);
p+10;


이 operator+함수는 분명 p를 변경시키고 있다.제대로 표현하기 위해서는
operator+함수 안에서 새로운 객체를 생성후 그 객체의 인자로 val값과 x,y값을 더한값을 주어 그 객체를 리턴하면 된다. 그럼p를 변경시키지 않고 원하는 결과를 얻을수 있다.

만약에 위의 문장 p+10; 이것이 10+p; 가 된다면 어떻게 될까? 10은 분명히 객체가 아닌데...
이것도 따로 정의 해주어야 한다..;;이럴경우는 전역함수로 하는 수 밖에 없다.
operator+(int val,Point& p) 이렇게 넘겨 주어서 함수내에서 연산후 리턴해줘야 한다.
그냥 리턴값을 단순히 위치만 바꿔서 p+10을 리턴해주어도 되고 함수내에서 객체 생성후 인자로 멤버변수값과 val값을 전달한 객체를 리턴해주어도 되고..방법은 여러가지!

임시 객체의 생성..(나..원 -_-;;별...)
임시객체 생성문법
Point(3.4);
이름이 없다..생성되고 바로 다음줄에서 소멸된다.
임시객체를 사용할경우 컴파일러에 따라서 프로그램 최적화가 진행된다.

5. cin.cout.endl의 비밀

#include <stdio.h>

namespace mystd{
 char* endl="\n";
 class ostream
 {
 public:
  ostream& operator<<(char* str){
   printf("%s",str);
   return *this;
  }
  ostream& operator<<(int i){
   printf("%d",i);
   return *this;
  }
  ostream& operator<<(double i){
   printf("%e",i);
   return *this;
  }
 };
 ostream cout;
}

using mystd::cout;
using mystd::endl;

int main(){
 cout<<"hello world"<<100<<endl;
 cout<<100;
 return 0;
}

this포인터의 값을 넘겨주고 레퍼런스로 받는 이유는 다음연산을 위해서 이다.

<< , >> 연산자 오버로딩

ostream& operator<<(ostream& a,Point& p){
 a<<p.x<<' '<<p.y<<endl;
 return a;
}

int main(){
 Point p(1,3);
 cout<<p;
 return 0;
}


이거보고 알아서 파악해..힘들다.
메인함수의 cout<<p는 cout.operator<<(p) 인데 객체 p는 우리가 정의해준거다 .그러므로 표준에는 들어있지 않기때문에 멤버함수에선 불가능 하고 전역함수로 우리가 선언해주자
operator<<(cout,p)이걸 받을수 있게 해주면 될거 아니야 리턴은 꼭 레퍼런스로..또써먹을려면..

6. 배열의 인덱스 연산자 오버로딩의 예
기본자료형 데이터를 저장할수 있는 배열 클래스

arr[i] = arr.operator[](i)
객체를 저장할수 있는 배열 클래스

7.반드시 해야만 하는 대입연산자의 오버로딩

#include <iostream>

using std::cout;
using std::endl;
using std::ostream;

class Point{
 int x,y;
public:
 Point(int _x=0,int _y=0) : x(_x),y(_y){}
 friend ostream& operator<<(ostream& os,const Point& p);
};

ostream& operator<<(ostream& os, const Point& p){
 os<<"["<<p.x<<","<<p.y<<"]";
 return os;
}

int main(){
 Point p1(1,3);
 Point p2(10,30);
 cout<<p1<<endl;
 cout<<p2<<endl;

 p1=p2;
//p1=p2=p3; 이런 문장이 있을경우를 생각해보자 분명 연산자를 오버로딩
시켜서 해결해야만 할것이다..
 cout<<p1<<endl;
 return 0;
}

p1=p2;의 경우 디폴트 대인연산자가 제공이 된다(프로그래머가 대입 연산자를 정의해 주지 않으면) 디폴트 대입 연산자의 기능은 멤버대 멤버변수의 복사가 이루어진다.
이것은 디폴트복사 생성자와 비슷하다. 가지고 있는 문제점도 디폴트 복사생성자와 거의 같다...예제를 보며 알아서 찾아내라 오늘은 영..~~기분이 안나네 ㅋㅋ

1번소스는 문제 있는 코드
2번소스는 문제 고친 코드
사용자 삽입 이미지
<내가 돈주고산 열혈강의C++ ppt에서 캡춰>

이것도 동적할당을 할땐 문제가 되지..알아서 잘 해결해 언제까지 내가 이렇게 알려줄순
없잔아.ㅋㅋ  hint 깊은복사
ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ
블로그 이미지

百見 이 不如一打 요 , 百打 가 不如一作 이다.

,

typedef struct threaded_tree *threaded_pointer;
typedef struct threaded_tree{
 short int left_thread;
 threaded_pointer left_child;
 char data;
 threaded_pointer right_child;
 short int right_child;
};

//한노드의 중위 후속자를 찾는 함수
threaded_pointer insucc(threaded_pointer tree){
 threaded_pointer temp;
 temp=tree->right_child;
 if(!tree->right_thread)
  while(!temp->left_thread)
   temp=temp->left_child;
 return temp;
}
//스레드이진트리의 중위순회
void tinorder(threaded_pointer tree){
 threaded_pointer temp=tree;
 for( ; ; ){
  temp = insucc(temp);
  if(temp = tree) break;
  printf("%3c",temp->data);
 }
}
//스레드 이진 트리에서의 오른쪽삽입
void insert_right(threaded_pointer parent, threaded_pointer child){
 threaded_pointer temp;
 child->right_child=parent->right_child;
 child->right_thread=parent->right_thread;
 child->left_child=parent;
 child->left_thread=TRUE;
 parent->right_child = child;
 parent->right_thread = FALSE;
 if(!child->right_thread){
  temp=insucc(child);
  temp->left_child=child;
 }
}

블로그 이미지

百見 이 不如一打 요 , 百打 가 不如一作 이다.

,