태터데스크 관리자

도움말
닫기
적용하기   첫페이지 만들기

태터데스크 메시지

저장하였습니다.


* 이전글

2016/05/06 - [C++ 기본] Hello World 시작

2016/05/10 - [C++ 기본] 클래스와 상속, friend, virtual, template 키워드 등

2016/05/13 - [C++ 응용] 퀵, 머지, 힙, 버블, 선택, 삽입 정렬 알고리즘 구현



* 이번에는 변수형과 기본 함수들에 대해서 간단하게 살펴볼 것이다. 기본적인 내용이므로 레퍼런스로만 봐도 되도록 정리할 것이다.



* 변수형

: 각 변수형의 크기는 처음에는 크게 신경쓰지 않아도 되지만, 나중에 TCP 연동을 하거나 메모리 취적화가 필요할 때에는 조금씩 신경을 써야할 것이다.


- char: 1byte=8bit 크기의 문자를 하나 저장

- short: 2byte=16bit 크기의 정수를 저장

- int: 4byte=32bit 크기의 정수를 저장

- long: 8byte=64bit 크기의 정수를 저장

- float: 4byte=32bit 크기의 실수를 저장

- double: 8byte=64bit 크기의 실수를 저장

- bool: true 또는 false 값을 저장

- void: 형 없음을 표시

- NULL: 0 또는 \0을 의미


* 변수 정의

: 변수는 간단하게 변수형, 변수명, 그리고 초기화 값으로 정의할 수 있다. 초기화 값은 반드시 넣을 필요는 없지만, 프로그래밍 실수를 방지하기 위하여 기본값을 항상 염두에 두고 프로그래밍하면 좋다.
char a = 'c';
short b = 1;
int c = 100;
long d = 10000;
float e = 1.5;
double f = 3.5;


* 변수 값 대입

: 변수 대입은 = 연산자를 통해서 할 수 있다. 클래스의 operator=를 오버라이딩한 것처럼 오른쪽에 하나의 인자를 받는 연산자이고, 왼쪽에는 수식이나 변수와 동일한 형태를 리턴하는 함수나 표현식이 올 수 있다.
int a = 1;
int b = 2;
int c = a;
b = c;
int d = c * b;
int e = sum(a, b);

int sum(int x, int y) {
    return x+y;
}


* 문자열: string

: 기존 일반 C와 달라진 가장 대표적인 것이라면 기본 모듈로 <string>을 가지고 있어서 char*로 처리해야 했던 문자열을 조금 더 편리하게 사용할 수 있다. string이 기본적으로 사용하게 되는 함수들을 간단하게 살펴보면 아래와 같다. 


- string::begin() = 시작 iterator

- string::end() = 종료 iterator

- string::size() = 문자열 길이

- string::length() = 문자열 길이

- string::clear() = 문자열 삭제

- string::empty() = 빈 문자열 여부 확인

- string::operator[int] = 해당 index의 문자 접근

- string::at(int) = 해당 index의 문자 접근

- string::operator+= = 문자열 추가

- string::append(string) = 문자열 추가

- string::push_back(char) = 문자 추가

- string_c_str() = 동일한 문자열을 char*로 받기

string str = "My String";
str = str + " has changed";
cout << str << endl; // == "My String has changed\n"
str[0] = 'm';
cout << str << endl; // == my String has changed\n"


* 배열 []

: 배열은 특정 형식이 여러 개 연속해서 있는 것을 배열이라고 하며, 기본적으로 [] 연산자를 사용하거나 * 포인터를 사용한다.

int arr[3];
arr[0] = 1;
arr[1] = 2;
arr[2] = 3;
int initArr[] = {1,2,3};
int zeroArr[5] = {}; // zeroArr[0] == 0 ... zeroArr[4] == 0
int* pArr = arr;
cout << pArr[0]; // == 1
cout << *(pArr+1); // == 2

: 다중배열은 아래와 같이 [][]를 연달아서 사용하면 된다. 필요한만큼 다차원 배열을 정의할 수 있다. 초기화할 때에는 다중 배열이 나란히 하나의 배열로 정의된 것처럼 쭉 초기화할 수 있다.

int multidimensionArray[2][3] = { 1,2,3,4,5,6};
for (int i = 0 ; i < 2 ; i++) {
    for (int j = 0 ; j < 3 ; j++) {
        cout << multidimensionArray[i][j] << ", ";
    }
    cout << endl;
}
// Result
// 1, 2, 3,
// 4, 5, 6,

: 함수 인자로 전달시에는 아래와 같이 전달하면 된다. 하지만 이 때에 배열의 크기는 따로 알 수 없기 때문에, C++에서는 일반적으로 배열의 길이도 함께 전달한다.

int arr[] = {6,3,4,3,2,1};
int length = sizeof(arr) / sizeof(arr[0]);
sort(arr, length);

void sort(int sortingArray[], int length) {
    /* ... */
}

: 위와 같이 [] 연산자로 배열을 정의하게 되면 길이를 따로 관리해야 하는데, 그러한 것이 아니라 배열에 대한 길이 정보 등을 함께 가지고 있고자 한다면, 내장 배열 모듈을 사용하는 경우도 있다.


* std::array

: 내장 배열 모듈은 #include <array>를 include 해야 하고, 정의할 때 어떠한 형식의 배열인지와 배열 크기를 함께 정의해야 한다. array 모듈에서 많이 사용하는 함수 레퍼런스는 아래와 같다.


- array::begin() = 시작 iterator

- array::end() = 끝 iterator

- array::size() = 배열 크기

- array::operator[int] = 해당 index 위치의 element 접근

- array::at(int) = 해당 index 위치의 element 접근

#include <array>

std::array<int, 3=""> arr = {1,2,3};
cout << arr[0]; // == 1
arr[2] = 4;
cout << arr[2]; // == 4



* std::vector

: 그리고 조금 유사한 vector 모듈은 기존의 배열을 동적으로 크기도 변경하고자 할 때 많이 사용하곤한다. array는 고정된 배열이라 일반 []연산자를 이용해서 배열을 사용하는 것과 큰 차이가 없다면, vector 모듈은 사용하고자 동적으로 변경 가능한 다양한 배열의 기능들을 제공해주기 때문에 더 다양한 방법으로 활용이 가능하다. 사용하려면 #include <vector>를 include 해야 하고, 어떠한 형태의 배열을 사용할 것인지 명시해야 한다. vector에서 많이 사용하는 레퍼런스는 아래와 같다.


- vector::begin() = 시작 iterator

- vector::end() = 끝 iterator

- vector::size() = 현재 크기

- vector::resize(int) = 배열 크기 변경

- vector::empty() = 배열이 비어있는지 여부 리턴

- vector::operator[int] = 해당 index 위치의 element 접근

- vector::at(int) = 해당 index 위치의 element 접근

- vector::push_back(T) = 배열의 뒤에 element 삽입

- vector::pop_back() =  배열의 뒤에 있는 element를 삭제

- vector::insert(iter, T) = 특정 위치에 element를 삽입

- vector::erase(iter) = 특정 위치의 element를 삭제


: 간단한 사용예는 아래와 같다.

#include <vector>

std::vector<int> arr = {1,2,3};
cout << arr[0]; // == 0
arr[1] = 5;
cout << arr[1]; // == 5
arr.insert(arr.begin()+1, 8); // 인덱스 1의 위치에 8 삽입
cout << arr[1]; // == 8
cout << arr.pop_back(); // == 3


* std::unordered_map, std::map

: unordered_map은 알고리즘 문제를 풀 때 사용하기 편한 해쉬맵으로 사용 가능하다. 일반 map은 BST 등과 같은 탐색 알고리즘을 사용하는데 비해 unordered_map은 해쉬 함수를 이용해서 키를 생성하는 것이 다르다. 내장되어있는 함수는 비슷한데, 아래와 같은 대표 함수들이 있다. unordere_map과 map을 언제 사용하느냐는, 전체 map을 순서대로 탐색할 필요성이 있느냐, 또는 전체 탐색을 하더라도 순서는 상관없고, 개별 값들에 대한 접근만 중요하느냐에 따라서 달라진다.


- std::unordered_map.begin() = 시작 iterator

- std::unordered_map::end() = 끝 iterator

- std::unordered_map::size() = 현재 크기

- std::unordered_map::empty() = 현재 map이 비어있는지 확인

- std::unordered_map::operator[T] = 해당 키T에 해당하는 값 접근

- std::unordered_map::at(T) = 해당 키T에 해당하는 값 접근


: 해쉬맵으로 사용하는 경우 아래와 같은 예로 사용할 수 있다.

#include <unordered_map>

std::unordered_map<string, string> myMap;
myMap["hello"] = "World";
cout << myMap.at("hello") << endl; // == "World"
cout << myMap.at("World") << endl; // == "" 키가 없으니 기본 값 "" 출력



* std::unordered_set, std::set

: unordered_set은 하나의 집합을 설정하는 라이브러리로 특정 항목에 대한 unique 성을 체크 하는 등의 기능을 수행할 때 사용하면 좋다. 나중에 unique한 집합을 순서대로 출력해야 할 필요성이 있다면 그냥 set을 사용하고, unique 함 만을 체크해야 한다면 unordered_set을 사용하면 된다.


- std::unordered_map.begin() = 시작 iterator

- std::unordered_map::end() = 끝 iterator

- std::unordered_map::size() = 현재 크기

- std::unordered_map::empty() = 현재 map이 비어있는지 확인

- std::unordered_map::insert(T) = 해당 키T를 설정

- std::unordered_map::find(T) = 해당 키T가 있으면 해당 위치의 iterator 리턴, 없으면 end() 리턴


: 해쉬맵으로 사용하는 경우 아래와 같은 예로 사용할 수 있다.

#include <unordered_set>

unordered_set<string> mySet;

cout << (mySet.find("1") == mySet.end()) << endl; // == 1 (true)
mySet.insert("1");;
cout << (mySet.begin() == mySet.find("1")) << endl; // == 1 (true)


* 끝


* 다음편 예고

: 일단 C++을 통한 코딩 인터뷰를 보기 위해서는 위의 데이터 구조들만 사용해도 충분히 원하는 알고리즘을 구현하는데 문제가 없을 것이다. 특히 vector, map, unordered_map, set이 아마 가장 많이 사용하게 되는 자료 구조가 아닐까 생각한다. 다음에는 C++을 통해서 기본적인 데이터 구조들을 구현해보도록 하겠다.

저작자 표시 비영리 동일 조건 변경 허락
신고

이 글을 공유하세요.

질문이나 의견을 댓글로 달아 주세요

티스토리 툴바