8.2(목) C++ - 삽입반복자

from Study/C++ 2007/08/02 20:05 view 17946

#include <list>

#include <algorithm>

#include <iostream>

using namespace std;

 

// 삽입반복자

// 3개의 삽입반복자가 있다.

 

// 삽입반복자 함수버전의 구현

template<typename T> back_insert_iterator<T> xback_inserter( T& c )

{

        // 후방 삽입반복자 객체를 만들어서 리턴해 준다.

        // 타입을 넘겨주면서 생성자를 호출하여 리턴!
       
return back_insert_iterator<T>(c);
   

}

 

void main()

{

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

 

        list<int> st(5, 1);

 

        // 삽입반복자의 객체를 만든 후 copy를 호출해도 되지만

        // 헬퍼함수를 사용해도 된다.

        copy( x, x+5, xback_inserter(st) );

 

        //front_insert_iterator<list<int> > p( st );

        //back_insert_iterator<list<int> > p( st );

        //insert_iterator<list<int> > p( st, st.begin() );

 

        //*p = 10;

        // 위코드대신push_front()를사용해도된다.

        //st.push_front( 10 );

 

        // 하지만여러개를계속넣고싶다면삽입반복자덕에copy()를사용할수있게된다.

        //copy( x, x+5, p );

 

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

 

        copy( st.begin(), st.end(), out );

}

Tag |

#include <iostream>

#include <iterator>

#include <algorithm>

using namespace std;


// 1. copy 알고리즘에 대해서

void main()

{

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

        int y[10];

 

        copy( x, x+10, y );

 

        for( int i = 0; i < 10; ++i )

        {

               cout << y[i] << endl;

        }

}

 

// 2. 출력반복자

void main()

{

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

 

        *p = 10;       // 10을 출력한후 자동으로 ++을 수행한다.

 

//      ++p;           // 실제로는 아무일도 하지 않는다.

        *p = 20;

 

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

 

        // 배열을 화면에 출력하는 방법.

        copy( x, x+10, p );

}


// 3. 출력반복자 와 파일

void main()

{

        ofstream f("a.txt");   // 출력전용 파일생성.

 

        // 리스코프의 치환법칙- 부모가 들어 갈 수 있다면 자식도 들어갈 수 있다.???

        ostream_iterator<int> p( f, " " ); // 화일스트림을 가르키는 출력반복자

 

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

        copy( x, x+10, p );    //!!!

}

// 4. 입력스트림 반복자
#include <fstream>

void main()

{

        ifstream f1("a.cpp"); // 현재 소스파일의 이름을 넣으세요.

        //istream_iterator<char> p1(f1), p2;  // 디폴트생성자는 EOF를 가르킨다.

        istreambuf_iterator<char> p1(f1), p2;

        ostream_iterator<char> p3(cout, "");

        copy( p1, p2, p3 );

}

Tag |

8.1(수) C++ - 반복자 분류

from Study/C++ 2007/08/02 19:09 view 17951
  1. 형태별 분류
    1. 일반 포인터
    2. Container Iterator
    3. Stream Iterator
    4. Inserter Iterator

  2. 기능별 분류
     

    =*i

    *i=

    ++i

    i++

    --i

    i--

    i[n]

    i+n

    i-n

    i+=n

    i-=n

    입력 반복자

    O

     

    O

    O

                 

    출력 반복자

     

    O

    O

    O

                 

    정방향 반복자

    O

    O

    O

    O

                 

    양방향 반복자

    O

    O

    O

    O

    O

    O

             

    임의 접근 반복자

    O

    O

    O

    O

    O

    O

    O

    O

    O

    O

    O


  3. 5가지 종류로 구분하는 이유
    1. 알고리즘 함수가 요구하는 반복자에 따라 알고리즘 함수를 구분하기 위해서이다.
    2. 프로그램 ? Container ( 출력 )
    3. Container ? 프로그램 ( 입력 )

  4. Example
    1. find( first, last, value );    // 최소한 입력 반복자
    2. reverse( first, last );       // 최소한 양방향 반복자
    3. sort( first, last );            // 퀵소트라면 최소한 임의접근 반복자. 
                                        // 입.출력,정.양방향 은 내부에 sort 함수를 가지고 있다.
Tag |

// 1. 개념. 용어

반복자는(Iterator)는 포인터와 유사한 객체로서 STL의 알고리즘 함수가 컨테이너에 저장된 객체들의 시퀀스를 순회 할 때 사용한다. 컨테이너와 알고리즘 함수의 사이를 연결해주는 중간자로서의 역할을 담당하기도 한다. 반복자 덕택에 저장방식(자료구조)에 관계없이 동일한 알고리즘 함수를 구현 할 수 있는 것이다.

 

STL의 각 컨테이너는 자신의 요소를 가르키는 반복자를 가지고 있다. 각 컨테이너의 begin(), end() 함수는 자신이 지닌 첫번째 요소와 마지막 다음(past-the-end) 요소를 가르키는 반복자를 리턴한다.

 

반복자 구간 ? 시퀀스의 시작을 가르키는 first, 마지막 다음을 가르키는 last의 반복자 한 쌍. 반복자 구간은 [first, last] 처럼 표기한다. 또한, first에서 시작해서 operator++ 연산으로 도달 가능한 경우 유효(Valid, 도달가능-reachable)한 구간이라고 한다. 모든 STL의 알고리즘은 넘겨 받은 구간이 유효하다는 가정하에 작업을 수행한다. 또한 아무 요소도 없는 구간은

first == last

가 되는데 이를 빈 구간(empty)라고 한다. 빈 구간도 유효한 구간이다.

Past the end ? Container end() 함수를 통해서 얻게 되는 iterator는 마지막 요소가 아니라 마지막 다음을 가르키는데 이를 보통 past-the-iterator라고 부른다. iterator를 참조하는 것은 오류이다.

 

// 2. 반복자의무효화

void main()

{

           vector<int> v(10);

 

           v[0] = 100;

 

           vector<int>::iterator p = v.begin();

 

           cout << *p << endl;

 

//        v.resize(20); // 반복자를 무효화 시킨다.p 가리키는 곳을 재할당

           v.resize(5); // 무효화 될 가능성이 있다. 메모리를 줄이기만 한다.

 

           cout << *p << endl;

}

 

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

// 3. 반복자의 활용

void main()

{

           list<int> s;

 

           s.push_back(10);

           s.push_back(20);

           s.push_back(30);

           s.push_back(40);

 

           slist<int>::iterator p1 = s.begin();

           cout << *p1 << endl;

 

           slsit<int>::iterator p2 = s.end();

 

           reverse( p1, p2 )

}

 

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

void main()

{

        vector<list<int> > st(10); // hash table

 

        st[0].push_back(10);

 

        vector<string> v(10);

 

        v[0][0] = 'a';

 

        string s = "ahfsdhksdfkshdfkjhsdkfhsdkfh";

 

        sort(s.begin(), s.end());

 

        reverse( s.begin(), s.end());

 

        replace( s.begin(), s.end(), 'f', '-');

 

        cout << s << endl;

}

 

 

// 반복자의분류- 5가지

int main()

{

        list<int> s;   // 양방향반복자

 

        sort( s.begin(), s.end());    // 임의접근이어야한다.

        s.sort(); // Quick 이아닌버블이나selection 으로구현됨.

       

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

        int y[10];

 

        copy( x, x+10, y); // x ~ x+10y로복사한다.

 

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

       

        int k = *x; // ok..

        *x = 20; // error

        slist<int> s;

 

        // s에요소추가...

        slist<int>::iterator p = s.begin();

 

        int k = *p; // 입력

        *p = 30;    // 출력

 

        ++p; // ok...

        --p; // 될까?? 안된다. single linked list는 전방향!!

}

 

Tag |

8.1(수) C++ - template 전문화

from Study/C++ 2007/08/02 18:05 view 19181

// template 전문화가 요즘들어 인기를 얻고 있는 이유. - 메타의 세계

// 컴파일시간에 어떤일을 수행하게 하는 기법. 컴파일시간은 오래 걸리지만

// 실행시간이 단축된다. 주로 전문화를 사용해서 컴파일 재귀호출을 사용한다.

// 하지만 컴파일 역량이 있기 때문에 9번이상?? 은 안된다. 왜그렇까..컴파일 하기 싫은가..


template
<int n> class Pow

{

public:

        enum { result = n * Pow<n-1>::result };

};

 

template<> class Pow<0>

{

public:

        enum { result = 1 };

};

 

void main()

{

        int n = Pow<5>::result;


       
cout << n << endl;

}

 

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

// Template 전문화( 특화, Specialization ).

template<typename T, typename T2> class Test {};     // 1

template<typename T> class Test<T, int> {};          // 2

 

Test<int, double> t1;  // 1

Test<int, int> t2;     // 2

 

// Primary Template

template<typename T> class Stack

{

        T* buf;

};

 

// 전문화 Template

template<> class Stack<int>

{

};

 

// 부분전문화- 모든 포인터는 이 클래스 사용

template<typename T> class Stack<T*>

{

        T* buf;

};

 

void main()

{

        Stack<int> s;

}

 

Tag |

8.1(수) C++ - typename

from Study/C++ 2007/08/02 17:17 view 18134

#include <iostream>

using namespace std;

 

// typename 문법이야기

// 1.2 의 중복문제가 발생해서 이를 해결하고자 typename 키워드를 만들었다.

// 그러고 보니 class T 라는 것의 의미가 명확하지가 않는 것을 알 수가 있었다.

// class Tint와 같은 타입도 받을 수 있기 때문에 typname으로 바뀌게 된 것이다.!!!

// 하지만 class는 여전히 지원된다.

 

template<typename T> void foo( T a )

{

        typename T::B* p;
        // 1. T
안에 내포클래스로 B가 있는데 그 포인터 p를 선언.

        // 2. T안에 B라는 static 변수가 있는데 곱하기 p를 한다.

}

 

class A

{

public:

        static int B;

 

        class B

        {

        };

};

 

void main()

{

        A a;

        foo( a );

}


//////////////////////////////////////////////////////////////////// 
// 디폴트 인자

template<typename T = int, int n = 10> class Stack

{

        T buf[n];

};

 

void main()

{

        Stack<int, 10> s;

        Stack<int> s2;

 

        stack<> s3;    // 모두 default 사용

}

Tag |

8.1(수) C++ - template 파라미터

from Study/C++ 2007/08/02 16:43 view 18087

#include <iostream>

#include <vector>

using namespace std;

 

// template 파라미터의종류

// 1. type

// 2. 상수( 정수와포인터상수만가능) 파라미터.

// 3. template temlpate 파라미터- template 이름을 넘긴다???

 

// vector는 디폴트 인자가3 개가 있으므로 넘기기 힘들다.

// 그래서 새롭게 만든 template를 넘겨보자!! VECTOR

template<typename T> class VECTOR

{

};


template
<template<typename> class A, typename T> class Stack

{

        A<T> v;

public:

};

 

int main()

{

        Stack<VECTOR, int> s;

 

        return 0;

}


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

template <typename T, int n, template<typename> class A> class Stack

{

        A<T> v;                // 결국 vector<int> v

        T buf[n];              // 배열첨자에 템플릿인자 상수는 가능하다.

};

 

void main()

{

        vector<int> a;

        vector b;

 

        Stack<int, 10, vector> s;

 

        int n = 10;

        //Stack<int, n> s2;    // error

}


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

// 클래스template 2 

typedef vector<vector<int> > Matrix;

 

void main()

{

        //vector<vector<int> > m(3, 3);

        Matrix m(3, 3);

       

        m[0][0] = 10;

       

        vector<int> v(10, 3);

 

        v[0] = 10;

}

 

//////////////////////////////////////////////////////////////////// 
template
<typename T> class Stack

{

};

void main()

{

        Stack<int> s;

        Stack<Stack<int> > s2; // >> 와 혼동 되지 않도록 해야 한다.

}

 

Tag |

// 클래스 template의 기본.
template
<typename T> class Stack

{

        T* buf;

public:

        Stack() {}             // 1. ok. 생성자이름은클래스이름

        //Stack<T>() {}        // 2. 에러

 

        // 복사생성자의모양

        Stack( const Stack<T>& ) {}

 

        void push ( T a );

};

 

// 클래스template의멤버함수를외부에구현하려면

template<typename T> void Stack<T>::push( T a )

{

}

 

void main()

{

        Stack<int> s1;

//      Stack      s2;  // error. Stack template의이름이지Type이아니다.

                        // typeStack<T> 이다.

}



// 멤버 함수 template를 활용해보자.!!! 

template<typename T> class Stack

{

public:

        Stack(){}

        template<typename U> explicit Stack(const Stack<U>&)

        {

        }

        explicit Stack(const Stack<T>&)

        {

        }

 

};

void main()

{

        Stack<int> s1;

        Stack<int> s2(s1);

 

        Stack<int> s3;

        Stack<double> s4(s3);

}

 

 

Tag |

8.1(수) C++ - 함수 template

from Study/C++ 2007/08/02 16:00 view 19901

#include <iostream>

using namespace std;

 

// 1. 함수template

// (1) instantiation : T -> 특정 type으로 변경되는 과정.

// (2) template 의원리: Code Generation ->
//      단점: Code Bloat(코드가커질수있다.),2번 컴파일 한다.

// (3) template 2번문법을 확인하게 된다.

// (4) internal linkage를가진다.(완전한 구현체를 가져야 한다.),다른파일에 정의하면 에러

//             클래스template를 만들때에서 선언과 구현 모두 헤더에 넣어야 한다.

// (5) 함수template overloading 된다.

 

template <typename T> T Max( T a, T b )  // 1

{

        return a < b ? b : a;

}

 

int Max( int a, int b )                  // 2

{

        return a < b ? b : a;

}

 

void main()

{

        cout << Max( 1, 2 ) << endl;     // 2

        cout << Max( 3.4, 3.2 ) << endl; // 1

        // 2. 6.0은에러.int버전이없다면Tambigous 하다는에러.
       
cout << Max( 65, 'B' ) << endl;

}

Tag |

7.31(화) C++ - Composite 패턴

from Study/C++ 2007/08/02 15:53 view 21900

#include <iostream>

#include <string>

#include <vector>

using namespace std;

 

// 폴더와File의공통의부모

class Item

{

        string name;

public:

        Item( string s ) : name ( s ) {}

     
        // 상수함수로만들어야상수함수에서불러올수있다.  

        string GetName() const { return name; }       

 

        virtual int GetSize() = 0;

 

       // Getname을상수함수로만들자!!
       
virtual void print( string prefix ) const
        {

               cout << prefix << GetName() << endl;

        }

};

 

class File : public Item

{

        int size;

public:

        // 부모클래스에디폴트생성자가없으므로명시적으로부모생성자를호출해줘야한다.

        File( string n, int s ) : Item(n), size(s) {}

 

        virtual int GetSize() { return size; }

};

 

class Folder : public Item

{

        vector<Item*> items;

public:

        Folder( string n ) : Item(n) {}

 

        void Add( Item* p ) { items.push_back(p); }

 

        virtual int GetSize()

        {

               int sz = 0;

               for ( int i = 0; i < items.size(); ++i )

               {

            // 다형성( Polymorphism ), 가상함수를통해객체에따라다른기능을제공한다.

                       sz += items[i]->GetSize();

               }

               return sz;

        }

 

        virtual void print( string prefix ) const

        {

               cout << prefix << GetName() << endl;  // 먼저자신의이름출력

               prefix = prefix + string("\t");

 

               for ( int i = 0; i < items.size(); ++i )

               {

                       items[i]->print( prefix );

               }

        }

};

 

void main()

{

        Folder* R = new Folder("ROOT");

        Folder* A = new Folder("A");

        Folder* B = new Folder("B");

 

        R->Add(A);

        R->Add(B);

 

        R->Add( new File( "a.txt", 10 ) );

        A->Add( new File( "b.txt", 20 ) );

        B->Add( new File( "c.txt", 30 ) );

 

        cout << R->GetSize() << endl;

 

        R->print("");

}

 

Tag | ,