#include <iostream>

using namespace std;

 

// 디자인의 대전제: 모든 코드는 유지보수와 기능확장이 쉽도록 유연하게 설계되어야 한다.

 

// OCP : Open Closed Principle

//       기능확장에 열려있고 코드변경에 닫혀 있어야 한다.

 

// 생각해 볼 만한 문제.. 오목게임을 만들고 싶다. - 1인용.

// 다음 수를 예측하는 알고리즘은 자주 변경 될 수 있을 거 같다.

 

// 1. 변하는 것은 따로 캡슐화를 해라. - 오목과 다음 수 예측알고리즘을 분리한다.

// 2. 상속 대신에 포함을 사용하라. ( 상속은 너무 경직 되어 있다. 떼어다 붙여다가 안된다. )

// 3. 구현이 아닌 인터페이스를 사용해서 객체와 통신해라.( Loosely Coupling )

 

// 결국 아래코드가 GOF의 디자인패턴에 나오는 "전략패턴" 이다.

// 알고리즘(변하는요소를) 캡슐화

// 인터페이스를 먼저 설계한다.

struct IStrategy

{

public:

        virtual void NextPos( int(*p)[19], int* px, int* py ) = 0;

};

 

// 다음 수만 예측하는 알고리즘

class Level1 : public IStrategy

{

public:

        virtual void NextPos( int* px, int* py )

        {

        }

};

 

class Omok

{

        int board[19][19];

        IStrategy* pComputer;  // Composition( 포함, 구성)

public:

        void Run()

        {

               // 컴퓨터에게 다음 수를 두게 한다.

               int x, y;

 

               // Delegation(위임)이라고 부른다.

               pComputer->NextPos( board, &x, &y );

        }

 

        // 동적으로 알고리즘을 변경할 수 있게 한다.

        void SetStrategy( IStrategy* p ) { pComputer = p; }

};

 

void main()

{

}

 

 

/*

// 잘못된 방식

class Omok

{

public:

        virtual void NextPos( int* px, int* py )

        {

        }

};

 

class Level1 : public Omok

{

        virtual void NextPos( int* px, int* py )

        {

        }

};

 

void main()

{

        Omok* p = new Level1;

        p->NextPos();

}

*/

Tag | ,

8.6(월) C++ - STL 알고리즘의 종류

from Study/C++ 2007/08/08 17:29 view 12227

#include <iostream>

#include <algorithm>

#include <numeric>

#include <vector>

#include <functional>

#include <string>

using namespace std;

 

// 알고리즘의종류

// **. 알고림즘의 기본 구성

int foo( int a, int b ); 

 

int main()

{

        int x[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

        int y[10];

 

        int* p1 = remove( x, x+10, 3 );         // 알고리즘의 in place 버전

        int* p2 = remove_copy( x, x+10, y, 3 ); // 알고리즘의 copy 버전

       

        int* p3 = remove_if( x, x+10, foo );  // 알고리즘의 조건자 버전.

        int* p4 = remove_copy_if( x, x+10, y, foo );

 

// sort의 조건자버전- 조건자이름구별..

// sort 같은 알고리즘은 조건자 버전은 인자가 3개이고 조건자를 사용하지 않은 버전은
// 인자가 2개이다. 그러므로 sort함수는 조건자 버전과 그렇지 않은 버전을 명확이 구분
// 할 수 있으므로 _if 가 붙지 않는다!!!
       
sort( x, x+10 );

        sort( x, x+10, foo );

}

 

// sort에사용하는조건자함수규칙

// 아래함수를평가해보세요.

int foo( int a, int b )

{

        //return a <= b;       // 같을때바꾼다는건말도안됨. 1번에어긋남

        return a < b;          // ok.

}

// Strict Weak Ordering ( sort의조건의원칙?? )

// 1) f(a, a)는반드시false여야한다.

// 2) f(a, b)가참이면f(b, a)는거짓이다.

// 3) f(a, b)가참이고f(b, c)가참이면f(a, c)도참이다.

/////////////////////////////////////////////////

// 1. accumulate

void main()

{

        int x[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

 

        // 기본연산자버전+ 버전

        int n1 = accumulate( x, x+10, 0 );

        cout << n1 << endl;

 

        int n2 = accumulate( x, x+10, 1, multiplies<int>() );

        cout << n2 << endl;

}
/////////////////////////////////////////////////

void main()

{

        int x[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

 

        int* p1 = find( x, x+10, 3 );      // 변경불가sequence 알고리즘

        int* p2 = remove( x, x+10, 3 );    // 변경가능sequence 알고리즘

 

        sort( x, x+10 );    // 정렬 관련 알고리즘

 

        int n = accumulate( x, x+10, 0 ); // 범용수치알고리즘     "numeric"

        cout << n << endl;

}

// 2. 구간삭제 erase

void main()

{

        int x[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

        vector<int> v( x, x+10 );

 

        vector<int>::iterator p = remove( v.begin(), v.end(), 5 );

 

        // v.begin() ~ p까지가 유효한 구간이다. 나머지 유효하지 않은 구간을 지우자!

        v.erase( p, v.end() );

        int n = accumulate( v.begin(), v.end(), 0 );

 

        cout << n << endl;

}

  

// 3. copy, copy_backward

void main()

{

        string s1 = "ABCDE";

 

        // left shift

        //copy( s1.begin() + 1, s1.end(), s1.begin() );

 

        // right shift

        //copy( s1.begin(), s1.end() - 1, s1.begin() + 1 );
        // AAAAA가 출력
뒤에서 부터 copy해야 한다.

 

        copy_backward( s1.begin(), s1.end() - 1, s1.end() );

 

        int x[5] = { 1, 2, 3, 4, 5 };

        int y[5];

 

        //int* p = copy_if( x, x+5, y, foo ); // copy_if가없다. 짜보자!!

 

        cout << s1 << endl;

}

 

// 4. partial_sum

void main()

{

        int x[10] = { 1, 2, 3, 4, 5, -6, 7, 8, 9, 10 };

        int y[10];

 

        // x, x+10 까지의_부분합을구해라.

        partial_sum( x, x+10, y );

        copy( y, y+10, ostream_iterator<int>(cout, " ") );

}

Tag |

#include <fstream>

#include <sstream>

using namespace std;

 

void foo( pair<string, list<int> > p )

{

        cout << p.first << endl;

}

 

void main()

{

        map<string, list<int> > cross_index; // 이 자료구조를 생각해보자.

 

        //map<string, list<list<int> > >;    // 2차원 배열도 받아서 할 수 있다.

 

        ifstream f("a.cpp");   // 현재 파일이름 넣으세요.

        int line = 0;          // line no 관리

        string temp;

 

        // file에서 한 줄씩 읽어 들인다.

        while( getline( f, temp ) )     // 주의 f >> temp; 한 단어 입력

        {

               ++line; // 라인 no++

 

               istringstream iss( temp );

               string word;

 

               while( iss >> word )          // 한 문장을 단어별로 분리해 낸다.

               {

                       cross_index[ word ].push_back(line);

               }

        }

        //------------------------------------

        // 이제 map을 출력한다.

 

        // print_word_list

        for_each( cross_index.begin(), cross_index.end(), foo );

 

        // print_word_line_list

        map<string, list<int> >::iterator p = cross_index.begin();

       

        ostream_iterator<int> out( cout, " " );

 

        while ( p != cross_index.end() )

        {

               cout << p->first << " : "; // 단어출력

               copy( p->second.begin(), p->second.end(), out );

               cout << endl;

 

               ++p;

        }

}

 

// 응용비디오샵!!!

//map<Customer, list<VideoTape> > retal_list

//copy( cross_index["홍길동"].begin(), cross_index["홍길동"].end(), out );

 

 

Tag |

8.3(금) C++ - stringstream

from Study/C++ 2007/08/08 11:49 view 13285

#include <sstream>

#include <fstream>

 

// stringstream 에 대해서

// stream3개로 구분 할 수 있다. istream, ostream, stringstream

 

void main()

{

        char buf [256];

        cin >> buf;    // 표준입력에서 입력

 

        ifstream f("a.txt");

        f >> buf;      // 화일에서 입력

 

        //////////////////////////////////////////////////////

        string s = "I am a boy";

        istringstream iss(s);

 

        // 하나의 문장을 단어별로 분리하는 기법

        while( iss >> buf )

        {

               cout << buf << endl;

        }

}

//////////////////////////////////////////////////////
void
main()

{

        ofstream f("a.txt");

        ostringstream oss;

 

        cout << "A";   // 표준출력으로 출력

        f       << "A";       // 화일로 출력(a.txt 파일)

        oss     << "A";

 

        string s = oss.str();  // oss 가 내부적으로 가진 string 꺼낸다.

        cout << s << endl;

}

Tag |

8.3(금) C++ - 연관 컨테이너의 종류

from Study/C++ 2007/08/08 11:47 view 11450

// 연관 Container( Associative Container )


// 1. set: 순서를 가지고 값을 저장한다. 중복을 허용하지 않는다.

void main()

{

        // 트리!! 완전이진트리,  AVL, 레드블랙!!

        // 들어올때마다 sort를 하기 때문에  빠르다.

        // 두번째 인자로 단위전략을 쓰게되면 정렬방식을 바꿀 수 있다.

        typedef set<int, greater<int> > SET;

        set<int, greater<int> > s;

       

        s.insert(10);

        s.insert(20);

        s.insert(15);

        s.insert(100);

 

        SET::iterator p = s.begin();

        *p = 100;      // 성공은 하지만 정렬관계가 망가진다. 하지말자.

 

        //pair<set<int, greater<int> >::iterator, bool> ret = s.insert(15);

        pair<SET::iterator, bool> ret = s.insert(15);

        // insert가 실패 하면 ret에 fasle가 리턴된다. 중복된 것이므로 실패
       
if ( ret.second == false )

        {

               cout << "실패" << endl;

        } 

        copy( s.begin(), s.end(), ostream_iterator<int>(cout, " ") );

}



// 2. pair 에대해서

// 서로 다른 type 2개를 보관 할 수 있는 자료구조.


pair
<int, double> foo()

{

        return pair<int, double>(3, 3.4);

}

 

template<typename T1, typename T2> struct pair

{

        T1 first;

        T2 second;

        //- zero initialize

        //T b = T(); // built in type이면으로

        //           // User type이면default 생성자호출

        pair( T1 a = T1(), T2 b = T2() ) : first(a), second(b) {}
};

 

void main()

{

        pair<int, pair<int, double> > p2;     // 3개의 인자를 받고 싶을때!!

 

        // BOOST 안에는 pair를 개선한 tuple이 있습니다.

        //tuple<int> one;

        //tuple<int, int> two;

        //tuple<int, int, int> three;

 

        pair<int, double> p;

 

        cout << sizeof(p) << endl;

}


// 3. map : pair를 저장하는 set. key를 가지고 data를 저장.

void main()

{

        map<string, string> m;

 

        // map에 요소를 넣는방법1. insert 사용

        pair<string, string> p("mon", "월요일");

 

        m.insert(p);

 

        // 2. [] 연산자 사용

        m["tue"] = "화요일";

 

        cout << m["mon"] << endl;     // 월요일

        cout << m["web"] << endl;

}


// 4. stringstream

#include <sstream>

#include <fstream>

 

int main()

{

        int n = 10;

        ostringstream oss;

 

        // n을 문자열로 바꾸고 싶다.

        oss << "n = " << n;           // C라면 sprintf( buf, "n = %d", n );

        string s = oss.str();  // oss가 가진 string을 꺼낸다.

        cout << s << endl;

 

        char buf[256];

        //cin >> buf;

        //ifstream f( "a.cpp" );

        //f >> buf;

 

        // Cstrtok()STL style로 구현한 기법.

        istringstream iss( "I am a boy" );

 

        while( iss >> buf ) cout << buf << endl;

}

Tag |

8.3(금) C++ - queue에서의 단위전략

from Study/C++ 2007/08/07 21:26 view 10796

#include <queue>       // Q 또는우선순위Q를사용.

                       // 내부적으로 사용 할 container의 헤더도include 해야 한다.

#include <functional>

 

 

template<typename T, typename Cont = vector<T>, typename Pred = less<T> >

class priority_queue

{

        Pred f; // 조건자함수 객체생성

public:

        void foo()

        {

               // 크기비교가 필요하다면

               bool b = f(1, 2);

        }

};

 

// 절대값으로 크기를 비교하는 함수객체

template<typename T> struct abs_less

{

        bool operator()( T a, T b )

        {

               return abs(a) < abs(b);

        }

};

 

void main()

{

// greater<int> 는 템플릿 인자를 넘기기 때문에 타입을 넘긴다. , () 를 쓰지 않는다.!!!

// 결국 단위전략의 크기 비교객체를 다양하게 활용 할 수 있다.

        // 디폴트로 vector를 사용.
       
priority_queue<int, vector<int>, abs_less<int> > pq;
 

        pq.push(10);

        pq.push(20);

        pq.push(-50);

        pq.push(40);

        pq.push(30);

 

        cout << pq.top() << endl;
}

Tag |

8.3(금) C++ - stack에서의 단위전략

from Study/C++ 2007/08/07 21:22 view 10560

// 어답터 디자인패턴 기존의 있던 것을 이름만 바꿔서 새롭게 구성.

// Container 어답터

// list가있다. 그런데stack이필요하다.

 

template<typename T, typename Cont = deque<T> > class stack

{

        Cont st;

public:

        void push( T a ) { st.push_back(a); }

        void pop()       { st.pop_back(); }

        T&   top()       { return st.back(); }

};

 

#include <stack>

 

void main()

{

        stack<int, list<int> > st;

        stack<int> s; 

}

Tag |

// using namespace std::rel_ops;

// std::rel_ops 이름 공간안에는 아래 함수가 있다.

// < == 연산자를 정의해두면 다른연산자를 지원할 수 있다.!!!!!!!!!!

template<typename T> bool operator>( const T& a, const T& b)

{

        return !( a == b || a < b );

}

 

struct Point

{

        int x;

        int y;

public:

        Point( int a = 0, int b = 0 ) : x(a), y(b) {}

 

        bool operator==( const Point& p ) const

        {

               return true;

        }

        bool operator<( const Point& p ) const       // less than

        {

               return true;

        }

};

 

void main()

{

        Point p1, p2;

 

        bool b = p1 > p2;      // greater than

}

Tag |

8.3(금) C++ - 단위전략의 기본

from Study/C++ 2007/08/07 21:12 view 11083

// STLstring이 가지고 있는 단위전략패턴의 개념

// STLstring은 문자열의 비교를 위해 단위전략클래스를 사용하고 있다.

// 사용자가 만들어서 전달할수도있다.

 

struct my_traits : public char_traits<char>

{

        // 두문자가 같은 지를 비교하기 위해 아래함수를 호출한다.

        static bool eq(char c1, char c2)
        {
               return toupper(c1) == toupper(c2);
        }

        static bool lt(char c1, char c2)
        {
               return toupper(c1) < toupper(c2);
        }

        static int  compare( const char* s1, const char* s2, size_t n )

        {

               return memicmp( s1, s2, n );

        }

 

        // 그 외의 몇개의 함수를 더 제공해야 한다.

        // 하지만 상속 받았으므로 부모 것을 그냥 사용 할 수도 있다.

};

 

typedef basic_string<char, my_traits, allocator<char> > ci_string;

 

void main()

{

        // 템플릿 인자를 사용하는 단위전략, 함수 단위전략보다 다양한 작업가능.

        // , 컴파일시간에 결정되므로 오버헤드도 줄인다.

        // basic_string<char, my_traits, allocator<char> > s1 = "AA"; 
        //
유니코드, 단위전략, 할당

        ci_string s1 = "hello";

        ci_string s2 = "HELLO";

 

        //string s1 = "hello";

        //string s2 = "HELLO";

 

        if( s1 == s2 )

        {

               cout << "same" << endl;

 

        }

        else

        {

               cout << "NotSame" << endl;

        }

}

Tag | ,

8.3(금) C++ - 다형성의 기본

from Study/C++ 2007/08/07 20:54 view 11143

// C++에서다형성을지원하기위해있는문법

// 1. 가상함수- 실행시간다형성

// 2. 템플릿  - 컴파일시간다형성

// 3. 오버로딩- 컴파일시간


class Animal

{

public:

        virtual void Cry() {}  // 1

};

 

class Dog : public Animal

{

public:

        virtual void Cry() {}  // 2

};

 

template<typename T> void foo( T a )  // Cry라는함수가없다면에러가나온다.

{

        a.Cry();       // 다형성-> 컴파일타임에결정된다. ( type을알고있다. )

}

 

 

void foo( Animal* p )  // Animal의자식들만받는다.

{

        p->Cry();      // 1 ? 2 다형성-> 실행시간다형성( 메모리를찾아간다. )

}

 

 

Tag |