본문 바로가기

C++

c++ 15 ( 기본 자료구조 - STL 기초 자료구조 활용 )

std::vector<T>

std::vector<T>는 vector 헤더파일에 작성되어 있다.

이 std::vector를 활용하게 되면

유동적인 배열을 편안하게 활용할 수 있다. 

 

std::vector<T>는 우리가 일반적으로 배열을 사용하듯 사용할 수 있으며

std::vector는 iterator(순회자)를 통해 각각의 원소를 순회할 수 있고

이 순회자를 이용해

algorithm에 작성되어 있는 sort( ... ) 함수를 이용해 값을 정렬할 수 있다.

 

#define _CRT_SECURE_NO_WARNINGS
#include <cstdio>
#include <vector>


int main() {
    
    std::vector<int> myvec = {10, 20, 30}; // 초깃값 설정 가능
    
    myvec.push_back(100);
    myvec.push_back(200);
    myvec.push_back(300);

    //myvec에는 10, 20, 30, 100, 200, 300이 들어가있다.
    
    myvec[2] = 55; // 2번째 배열 값 바꾸기
    
    for(int i = 0; i < myvec.size(); i++) {  // myvec.size()로 원소가 몇 개 들어가는지 알 수 있다

        printf("%d ", myvec[i]);
        // std::vector라고 하는 자료구조 stl클래스가 []을 오버로딩 했기때문에 가능
        
    }
    return 0;
}

 

 

 

순회자 (interator)

순회자는 기본 자료구조들이 갖고있는 원소 탐색 객체이다.

이 탐색 객체를 이용하면 원소들을 차례대로 가져올 수 있고

물론 이 순회자를 이용해 for 루프를 돌 수도 있다.

순회자의 값을 가져올 때에는 포인터의 값을 가져오는 것 처럼

* (에스터리스크) 연산자를 활용한다.

 

for ( auto it = v.begin(); it != v.end(); it++) { ... }

 

순회자는 이 순회자가 하나씩 하나씩 다음 원소를 탐색하게 해주는 개체

즉, for loop 돌 듯이 돌게 해주는 개체

 

#define _CRT_SECURE_NO_WARNINGS
#include <cstdio>
#include <vector>
#include <algorithm>


int main() {
    
    std::vector<int> myvec = {40, 1, 5};
    
    myvec.push_back(4);
    myvec.push_back(10);
    myvec.push_back(7);


    // 정렬
    std::sort(myvec.begin(), myvec.end());
    
    
    // 순회자 (iterator)
    for(std::vector<int>::const_iterator it = myvec.begin(); it!= myvec.end(); it++) {
        printf(" %d  ", *it);
    }
        
    return 0;
}

 

 

auto

auto 키워드는 컴파일러가 추론 가능한 데이터 타입을 

자동으로 지정해줄 수 있다.

auto를 이용해 굉장히 긴 클래스명이나 데이터타입을 짧게 줄일 수 있어 많이 사용된다.

 

auto 다음 쓰는 타입이 오른쪽에 assign되는 초기값에 의해서 자동으로 타입 결정

 

myvec.begin()이라 했을 때 리턴되는 값이 std::vector<int>에 const iterator 타입 

이런식으로 순회가 가능하다.

 

#define _CRT_SECURE_NO_WARNINGS
#include <cstdio>
#include <vector>
#include <algorithm>


int main() {
    
    std::vector<int> myvec = {40, 1, 5};
    
    myvec.push_back(4);
    myvec.push_back(10);
    myvec.push_back(7);


    
    // 순회자 (iterator)
    for(auto it = myvec.begin(); it != myvec.end(); it++) {
        printf(" %d  ", *it);
    }
        
    return 0;
}

 

 

std::map< K, V >

: string을 인덱스로 갖는 배열

std::map은 map 헤더파일에 작성되어 있다.

std::map은 배열과 비슷하지만 좀 더 확장성이 있는 배열로

키와 그에 맞는 값 쌍을 저장할 수 있다 

키는 배열처럼 연속적이지 않아도 되며 std::string 등

꼭 integer 가 아니더라도 키값을 가질 수 있다는 것이 가장 큰 장점이다.

 

map은 원소 삽입과 동시에 자동으로 값이 정렬되는 특징이 있다.

 

 

#define _CRT_SECURE_NO_WARNINGS
#include <cstdio>
#include <vector>
#include <map>
#include <string>
#include <algorithm>


int main() {
    
    std::map<std::string, std::string> capitals; // vector, map 둘 다 생성자 호출 필요없음
        
    capitals["korea"] = "seoul"; // capitals라는 map의 korea라는 문자열에 seoul이 대응되어 들어가있다.
    capitals["usa"] = "washington";
    
    printf("%s\n ", capitals["korea"].c_str()); // seoul이 출력됨
    
    
    // erase 멤버함수 : key 값을 집어 넣어주면 해당 key 값을 지워준다.
    capitals.erase("korea");
   
    
    
    // count 멤버함수 : key를 가지고 key에 해당하는 값의 존재 유무에 대한 값을 리턴
    if (capitals.count("korea") == 1) {
        printf("korea가 존재합니다."); 
    }
    else {
        printf("korea가 존재하지 않습니다..");
    }
    
    
    return 0;
}

 

 

std::map의 순회

std::map은 순회를 하기 위해 일반적인 for 루프를 활용할 수 없고,

iterator (순회자)를 활용한 순회만 가능하다.

 

for (auto it = m.begin(); it != m.end(); it++) {

      it->first;       // map의 각각 키

      it->second;  // map의 각각 값

}

 

map에 들어가있는 인덱스는 넣은 순서가 아니라

tree라는 자료구조를 통해서 만들어지게 된다.

자동으로 정렬이 됨

 

 

#define _CRT_SECURE_NO_WARNINGS
#include <cstdio>
#include <vector>
#include <map>
#include <string>
#include <algorithm>


int main() {
    
    std::map<std::string, std::string> capitals;
        
    capitals["korea"] = "seoul";
    capitals["china"] = "beijing";
    capitals["usa"] = "washington";
    
    
    for(auto it = capitals.begin(); it != capitals.end(); it++) {

        printf("first : %s\n", it->first.c_str()); // first는 key
        printf("second : %s\n", it->second .c_str()); // second는 value
        
        printf("capitals[ %s ] = %s\n", it->first.c_str(), it->second.c_str()); // 위와 같은 의미
    }
    
    
    return 0;
}

 

 

 

연습 프로그래밍

 

1번 선택시 회원가입, 2번 선택시 회원의 리스트 출력, 3번 선택시 종료되는 프로그램

 

#define _CRT_SECURE_NO_WARNINGS
#include <cstdio>
#include <vector>
#include <map>
#include <string>
#include <algorithm>


int getInteger(const char* prompt) {
    
    printf("%s", prompt);
    int input;
    fseek(stdin, 0, SEEK_END);
    scanf("%d", &input);
    
    return input;
}


// std string을 리턴해주는 getString 함수
std::string getString(const char* prompt) {
    
    printf(prompt);
    char str[100] = { 0, }; // 초기화
    fseek(stdin, 0, SEEK_END);
    scanf("%99[^\n]s", str);
    
    return str; // =이라는 operator가 오버로딩 되어있어 자동으로 캐스팅해서 리턴해준다.
    
}


int main() {
    
    std::map<std::string, std::string> member;
    
    for(;;) { // 무한루프
        printf("1. 회원가입\n");
        printf("2. 회원출력\n");
        printf("3. 프로그램 종료\n");
        
        int menu = getInteger("번호를 입력하세요 : ");
        
        if (menu == 1) {
            std::string id = getString("아이디를 입력해주세요 : ");
            std::string pwd = getString("비밀번호를 입력해주세요 : ");
            
            if (member.count(id)) { // 아이디 중복 여부 판단
                printf("중복된 아이디 입니다.\n");
            }
            else {
                member[id] = pwd;
                printf("회원가입이 완료되었습니다.\n");
            }
        }
        
        else if (menu == 2) {
            for(auto it = member.begin(); it != member.end(); it++) {
                printf("%s\n", it->first.c_str());
            }
        }
        
        else if (menu == 3) {
            printf("프로그램 종료");
            break;
        }
        
        else {
            printf("잘못된 입력 입니다..\n");
        }
    }
    
    
    return 0;
}

 

 

과제형 연습 프로그래밍

 

 

Headerf.h

#ifndef __HEADERF_H__
#define __HEADERF_H__


#define _CRT_SECURE_NO_WARNINGS
#include <cstdio>
#include <map>
#include <string>


int getInt(const char* prompt);
std::string getString(const char* prompt);


class Dictionary {
private:
    std::map<std::string, std::string> words; // 단어와 매칭되는 뜻
    
public:
    void insertWorld(const std::string& word, const std::string& meaning);
    bool exists(const std::string& word);
    std::string getMean(const std::string& word);
};




#endif 

 

Source.cpp

#include "Headerf.h"


int main() {
    
    Dictionary* dict = new Dictionary;
    
    for (;;) {
        printf("1. 단어 등록\n");
        printf("2. 단어 찾기\n");
        printf("3. 프로그램 종료\n");
        int input = getInt("메뉴 번호를 입력하세요 : ");
        if (input == 1) {
            // 단어등록
            std::string word = getString("단어를 입력하세요 : ");
            std::string mean = getString("뜻을 입력하세요 : ");
            dict->insertWorld(word, mean);
            printf("정상적으로 등록이 되었습니다\n\n");
        }
        else if (input == 2) {
            // 단어찾기
            std::string word = getString("찾을 단어 : ");
            if (dict->exists(word)) {
                printf("단어 뜻 : %s\n", dict->getMean(word).c_str());
            }
            else {
                printf("없는 단어 입니다.\n");
            }
        
        }
        else if (input == 3) {
            // 프로그램 종료
            printf("프로그램을 종료합니다.\n");
            break;
        
        }
        else {
            printf("잘못 입력하셨습니다.\n");
        }
    }
    return 0;
}


int getInt(const char* prompt){
    
    int input;
    printf(prompt);
    fseek(stdin, 0, SEEK_END);
    scanf("%d", &input);
        
    return input;
}


std::string getString(const char* prompt){
    
    char input[100] = { 0, };
    printf(prompt);
    fseek(stdin, 0, SEEK_END);
    scanf("%99[^\n]s", input);
    
    return input;
}


void Dictionary::insertWorld(const std::string& word, const std::string& meaning){ // 단어 입력
    // 변수를 그대로 가져오기 때문에 값복사가 일어나지 않는다.
    words[word] = meaning;
}
bool Dictionary::exists(const std::string& word){ // 단어 존재유무
    return words.count(word) == 1;
}
std::string Dictionary::getMean(const std::string& word){ // 단어를 통해 뜻을 가져오기
    return words[word];
}