본문 바로가기

고급C,C++

표준 템플릿 라이브러리(STL-Standard Template Library)

표준 템플릿 라이브러리(STL-Standard Template Library)는 컨테이너, 이터레이터, 함수 객체, 알고리즘을 나타내는 탬플릿들의 집합을 제공한다. 컨테이너는, 배열과 같이, 여러 개의 값을 저장할 수 있는 구성 단위이다. STL 컨테이너는 동질적(homogeneous)이다. 즉, 그들은 같은 종류의 값들을 저장한다. 알고리즘은, 배열을 소트하거나 리스트에서 특정 값을 검색하는 것과 같은, 특별한 작업들을 수행하기 위해 사용하는 방법이다. 이터레이터는, 배열 안에서 포인터를 사용하여 위치를 옮기듯이, 컨테이너 안에서 위치를 옮길수 있도록 도와주는 객체들이다. 즉, 이터레이터는 포인터의 일반화이다. 함수 객체는 함수와 비슷한 역할을 하는 객체이다. 함수 객체는 클래스 객체일 수도 있고, 함수 포인터일 수도 있다.(함수 이름은 포인터의 역할을 하기 때문에 함수 이름도 여기에 포함된다). STL을 사용하여 배열, 큐, 리스트와 같은 다양한 컨테이너들을 생성할 수 있다. 또한 STL은 검색, 소팅, 무작위화 등 다양한 작업을 수행할 수 있게 해준다.




  • vector 템플릿 클래스
    • vector 헤더파일
    • #include <vector>
      using namespace std;
      vector<int> ratings(5); //5개의 int형 값을 가진 벡터
      int n;
      cin>>n;
      vector<double> scores(n); //n개의 double형 값을 가진 벡터
  • vector에서 할 수 있는 것
    • 모든 STL 컨테이너들은 컨테이너에 있는 원소들의 개수를 리턴하는 size()
    • 두 컨테이너의 내용을 교환하는 swap()
    • 컨테이너에 있는 첫 번째 원소를 참조하는 이터레이터를 리턴하는 begin()
    • 컨테이너에 있는 마지막 원소 바로 다음(past-the-end)을 참조하는 이터레이터를 리턴하는 end()
    • 이터레이터
      • 포인터의 일반화이다.
      • 각 컨테이너 클래스는 하나의 적절한 이터레이터를 정의한다. 그 이터레이터의 데이터형 이름은 iterator인데, 클래스 사용 범위는 가지는 typedef이다.
      • 예를 들어, vetcor의 double형 특수화를 위한 이터레이터를 선언하려면 다음과 같이 한다.
        • vector<double>::iterator pd; //pd는 이터레이터
          vector<double> scores;
          pd = scores.begin();
          *pd = 22.3;
          ++pd;
    • past-the-end : 컨테이너에 있는 마지막 원소 바로 다음에 있는 원소를 참조하는 이터레이터
      • for(pd = scores.begin(); pd!= scores.end(); pd++)
             cout<<*pd<<endl;
    • 벡터의 끝에 하나의 원소를 추하가는 push_back()
      • vector<double> scores;
        double temp;
        while(cin>>temp && temp>=0)
             scores.push_back(temp);
        cout<<scores.size()<<"개의 점수가 입력되었습니다.\n";
    • 지정된 범위의 벡터를 삭제하는 erase() 
      • 이 메서드는 삭제할 범위를 정의하는 2개의 이터레이터를 전달인자로 사용한다. STL이 2개의 이터레이터로 어떻게 범위를 지정하는지를 이해하는 것이 중요하다. 첫 번째 이터레이터는 범위의 시작을 참조하고, 두 번째 이터레이터는 범위의 끝 바로 다음을 참조한다.
      • scores.erase(scores.begin(), scores.begin() + 2); //begin()과 begin() + 1에 의해 참조되는 첫 번째 원소와 두 번째 원소를 삭제한다.
    • insert()
      • 첫 번째 이터레이터 전달인자는 새로운 원소들이 삽입될 위치 바로 앞의 위치를 제공한다. 두 번째와 세 번째 이터레이터 전달인자는 삽인에 사용할 범위를 정의한다.
      • vector<int> old;
        vector<int> new;
        ...
        old.insert(old.begin(), new.begin() + 1, new.end()); //  new 벡터의 첫 번재 원소를 제외한 모든 원소를 old 벡터의 첫 번째 원소 앞에 삽입한다.
      • old.insert(old.end(), new.begin() + 1, new.end()); //새로 삽입되는 원소들은 old.end() 앞에 삽입된다. 그 위치는 old 벡터의 마지막 원소 바로 다음을 의미한다.

//vect2.cpp -- 메서드와 이터레이터
#include <iostream>
#include <string>
#include <vector>

struct Review
{
std::string title;
int rating;
};
bool FillReview(Review & rr);
void ShowReview(const Review & rr);

int main()
{
using std::cout;
using std::vector;
vector<Review> books;
Review temp;
while(FillReview(temp))
books.push_back(temp);
int num = books.size();
if(num>0)
{
cout<<"감사합니다. 당신은 다음과 같이 입력하셨습니다.\n"
<<"등급\t제목\n";
for(int i = 0; i< num; i++)
{
ShowReview(books[i]);
}
cout<<"한 번 더 출력한다.\n"
<<"등급\t제목\n";
vector<Review>::iterator pr;
for(pr = books.begin(); pr!=books.end(); pr++)
ShowReview(*pr);
vector<Review> oldList(books); //복사 생성자를 사용한다.
if(num>3)
{
//원소 2개를 삭제한다.
books.erase(books.begin() + 1, books.begin()+3);
cout<<"삭제한 후:\n";
for(pr = books.begin(); pr!=books.end(); pr++)
ShowReview(*pr);

//원소 1개를 삽입한다.
books.insert(books.begin(), oldList.begin() + 1, oldList.begin() + 2);
cout<<"삽입한 수:\n";
for(pr = books.begin(); pr!=books.end(); pr++)
ShowReview(*pr);

}
books.swap(oldList);
cout<<"oldList와 books을 교환한 후: \n";
for(pr = books.begin(); pr!=books.end(); pr++)
ShowReview(*pr);
}
else
cout<<"입력한 것이 없어, 얻은 것이 없습니다.\n";
return 0;
}



bool FillReview(Review & rr)
{
std::cout<<"책 제목을 입력하십시오(끝내려면 quit를 입력): ";
std::getline(std::cin,rr.title);
if(rr.title == "quit")
return false;
std::cout<<"책 등급(0~10)을 입력하십시오: ";
std::cin>>rr.rating;
if(!std::cin)
return false;
std::cin.get();
return true;

}

void ShowReview(const Review & rr)
{
std::cout<<rr.rating<<"\t"<<rr.title<<std::endl;
}

  • vector에서 할 수 있는 그 밖의 것
    • 대표적인 STL 함수 for_each(), random_suffle(), sort()
    • for_each()
      • 첫 번째와 두 번째 전달인자는 컨테이터의 범위를 정의하는 이터레이터이다. 세 번째 전달인자는 함수를 지시하는 포인터이다.
      • vector<Review>::iterator pr;
        for(pr = books.begin(); pr != books.end(), pr++)
              ShowReview(*pr);
      • for_each(books.begin(), books.end(), ShowReview);
    • random_shuffle()
      • 범위를 지정하는 두 개의 이터레이터를 사용하여, 그 범위 안에 있는 원소들을 무작위 순서로 재배치 한다.
      • random_shuffle(books.begin(), books.end());
    • sort()
      • 두가지 버전이 있다.
        • 첫 번째 버전은 범위를 지정하는 두 개의 이터레이터를 사용한다. 그것은 컨테이너에 저장되어 있는 데이터형의 원소에 맞게 정의된 < 연산자를 사용하여 그 범위를 소팅한다.
          • vector<int> coolstuff;
            ...
            sort(coolstuff.begin(), coolstuff.end());
          • 내장된 < 연산자를 사용하여 값을 비교하여 내용을 오른차순으로 소팅한다.
          • bool operator<(const Review & r1, const Review & r2)
            {
               if(r1.title<r2.title)
                 return true;
               else if(r1.title == r2.title && r1.rating < r2.rating)
                 return true;
               else
                 return false;
            } // 사용자정의 클래스 일 경우 구현 해줘야함
        • 두 번째 버전은 세번째 전달 인자로 값을 비교하기 위해 operator<() 대신에 사용할 함수를 지시하는 포인터이다. 리턴값은 bool형으로 변환할 수 있어야 한다.
          • bool WorseThan(const Review & r1, const Review & r2)
            {
               if(r1.rating<r2.rating)
                 return true;
               else
                 return false;
            }
          • sort(books.begin(), books.end(), WorseThan);