반응형

C++하면 가장 중요한 키워드가 하나 있다. 그건 바로 클래스(Class) 이다.

객체 지향 프로그래밍은 클래스에서 시작했다고 해도 과언이 아니며

오늘은 이 클래스란 것을 들여다볼 예정이다.

아시다시피 해당 내용은 다섯개 챕터로 나눠써도 부족한 만큼 크게크게 요약하여 작성하도록 하겠다.


1. 클래스(Class)?

클래스란 객체에서 불필요한 특성을 제거해 모델링해서 공통된 특성을 하나의 패키지안에 놓은 것이다.

맞다.. 이렇게 생각하면 어렵다. 쉽게 말해서 '구조체의 확장 버전'이라고 생각하면 편하다.

 

클래스는 구조체와 달리 각 타입별 변수의 집합 뿐만 아니라, 멤버 함수까지 포함되고

접근 제어 지정자를 선언하여 사용 가능하다.

 

여기서 클래스와 구조체에 차이점을 발견할 수 있는데 접근 제어 지정자를 따로 선언하지 않는다면

  • 구조체(struct)는 멤버변수가 public으로 선언되며,
  • 클래스(class)에선 멤버변수가 private으로 선언된다.

public과 private에 대해선 아래에서 설명하도록하겠다.

 

2. 클래스 선언

클래스 이용을 위해선 세가지 구역이 필요하다.

  • 클래스 선언 구역
  • 클래스 정의 구역
  • 클래스 사용 구역

클래스 사용을 위해선 클래스 선언부터 해주어야 한다.

 

우선 예제 코드를 보자.

class Friend {
//멤버 변수
private: //내부에서만 접근 가능(default라 생략 가능)
	int age;
	char *name;
//멤버 함수
public: //외부에서 접근 가능
	void printInfo(){}; 
	void printInfo2(); //내부 클래스 정의, 외부 클래스 정의 모두가능
};

void Friend::printInfo2() {
}

클래스는 다음과 같이 선언하게 된다. class <클래스명>으로 선언해준다.

이후 접근제어 지정자와 함께 멤버 변수나 멤버 함수를 사용해주면 된다.

 

멤버 함수는 위와 같이 내부 클래스에서 정의 가능하며 외부에서도 정의 가능하다.

여기에서 꼭 선언한 이후 세미콜론을 붙여주도록 한다.

 

잠깐, 접근제어 지정자에 대해 짚고 넘어가자.

  • public : 공개적 접근, 클래스 밖을 포함해 모든 곳에서 접근 가능하다.
  • protected : 클래스가 속한 클래스 내부나 해당 클래스로부터 파생한 클래스 내부에서만 접근 가능하다.
  • private (default) : 클래스가 속한 클래스의 내부만 접근 가능하며, 외부 접근 불가하다.

    *모든 멤버 변수는 꼭 필요한 경우가 아니면 protected나 private으로 외부 공개 안하는게 원칙이다.

    *일반적으로 멤버 변수는 private하며, 이에 안전하게 접근할 수 있는 멤버 함수는 public

 

 

3. 객체 생성

객체 생성을 위해선 다음과 같이 사용한다.

  • <클래스이름> <객체이름>;

 

멤버 사용을 위해선 다음과 같은 형태로 사용한다.

  • <객체이름>.<멤버변수>;
  • <객체이름>.<멤버함수()>;

 

당연히 초기화도 가능하며 예제로 살펴보자.

int main(void) {
	Friend kim;
	kim.age = 21; //멤버 변수 초기화, 해당 멤버 변수가 public이여야 직접 변경 가능
	kim.printInfo(); //멤버 함수 호출

	return 0;
}

 

Frient 클래스로 kim이란 객체를 생성하고, 안에 age를 초기화해주었다.

해당 부분처럼 age를 직접 초기화하기 위해선 클래스에서 int age가 public이어야 한다.

 

일반적으로 private에 선언하고 멤버함수로 setInfo()와 같은 함수를 만들어 변경해주는 것이 좋으며

본 예제에선 이해를 위해 위와 같이 작성하였다.

 

 

4. 생성자와 소멸자

생성자객체가 인스턴스화 될 때 컴파일러에 의해 호출되는 특수 메소드 함수이다.

디폴트 생성자, 매개변수 생성자, 복사 생성자가 존재하며 상황에 맞게 사용하게 된다.

특징은 다음과 같다.

  • 생성자는 클래스 이름과 반드시 같아야 함.
  • 생성자는 return을 가질 수 없음.

 

소멸자는 이와 반대로 객체 사용을 마쳤을 때 컴파일러에 의해 호출되는 특수 멤버 함수이다.

특징은 다음과 같다.

  • 객체가 유효 범위 벗어날 때 자동 호출
  • 클래스 이름 앞에 ~를 붙인다.

여기서 디폴트 생성자와 소멸자는 기본적으로 생성되며,

일반적으로 클래스 내부에서 동적할당 메모리를 할당, 해제할 때 사용된다.

 

예제를 보며 사용해보자.

#include <iostream>
using namespace std;

class Friend {
//멤버 변수
private:
	int age;
	const char* fname;
//멤버 함수
public:
	Friend(); //생성자
	~Friend(); //소멸자
	void printInfo(); //내부 클래스 정의, 외부 클래스 정의 모두가능
};
Friend::Friend() {
	cout << "생성자 호출" << endl;
	age = 24;
	fname = "KimJaeHo";
}
Friend::~Friend() {
	cout << "소멸자 호출" << endl;
}
void Friend::printInfo() {
	cout << "나이 : " << age << ", 이름 : " << fname << endl;
}

int main(void) {
	Friend kim;
	kim.printInfo(); //멤버 함수 호출

	return 0;
}

 

 

결과는 다음과 같다.


여기까지 클래스에 대한 공부를 마친다.

클래스에는 이외에도 오버로딩과 더불어 중요한 여러가지 개념들이 더 존재한다.

해당 포스팅에선 여기서 설명을 마치지만 함께 더 공부해봐야 할 것이다.

 

반응형

'Programming > Language' 카테고리의 다른 글

[Assembly] 파일 읽고 출력해보기  (0) 2020.06.06
[Assembly] 문자열 입력과 출력  (0) 2020.06.05
[Assembly] 1부터 10까지의 합 계산  (0) 2020.06.04
[C++] STL - multimap 공부  (0) 2020.05.24
[C++] STL - map 공부  (0) 2020.05.14
반응형

어셈블리어를 이용하여 파일을 읽고 출력하는 프로그램을 구현해보자.

필자는 Visual Studio 2017과 Irvine 라이브러리를 활용하여 개발할 예정이다.


1. 문제

  • 환경 : Visual Studio 2017, Irvine 라이브러리, x86 assembly
  • 디스크 파일을 읽어 읽은 결과를 메모리 덤프 및 화면 출력하는 프로그램을 작성
  • 디스크 파일은 c:\...\source\...\프로젝트\프로젝트\파일명에 위치

2. 문제 해결 방법

  1. 파일명과, 버퍼, 버퍼크기를 정의해준다(본 문제에선 버퍼 사이즈를 240이라 지정하였다.)
  2. 파일명 offset을 edx에 넣고, OpenInputFile을 call하여 파일 핸들값을 eax에 얻어온다.
  3. 정상적으로 파일이 열린경우 ReadFromFile을 이용하여 문자열을 읽어 버퍼에 넣는다.
  4. 정상적으로 읽었을 경우 버퍼 offset을 edx에 넣어 WriteString으로 문자열을 출력한다.
  5. ebx에 mov해둔 파일 핸들을 eax로 옮겨 CloseFile로 파일을 닫는다.

3. 코딩

TITLE Program asm4fileread(asm4fileread.asm)
; 프로그램 설명문 : 디스크의 파일을 읽고 출력하는 프로그램

INCLUDE c:\Irvine\Irvine32.inc
BUF_SIZE = 240

.data
filename		BYTE "sample.txt", 0
BUF			BYTE BUF_SIZE DUP(? )
good     		BYTE "Good processed !", 0dh, 0ah, 0
Nogood			BYTE "File open or write error !", 0dh, 0ah, 0

.code
main	PROC
	mov		edx, offset filename
	call		OpenInputFile			; 입력파일 열기
	mov		ebx, eax				; 핸들 ebx로 mov
	cmp		eax, 0					; 정상 오픈 확인
	jnz		good_open				; eax != 0 정상open
	call		WriteWindowsMsg			; open 오류
	jmp		terminate

good_open :
	mov		eax, ebx
	mov		edx, offset BUF
	mov		ecx, BUF_SIZE
	call		ReadFromFile			; 파일 내용 읽기
	jnc		good_read				; cf=0이면 jmp
	call		WriteWindowsMsg			; open 오류
	jmp		terminate

good_read :		
	mov		edx, offset BUF			; 버퍼내용 edx로 mov
	call		WriteString				; edx 출력
	call		Crlf
	jmp		good_end

good_end :								; 핸들 닫기
	mov		eax, ebx
	call		CloseFile
	mov		edx, offset good
	call		WriteString
	exit

terminate :
	mov		edx, offset nogood
	call		WriteString
	call		WaitMsg
	exit

main	ENDP
END	main

 

파일 내용과 실행 결과 사진은 다음과 같다.

 

 

 


계속해서 어셈블리를 통해 다양한 문제를 풀어볼 예정이다.

반응형

'Programming > Language' 카테고리의 다른 글

[C++] 클래스(Class) 공부  (0) 2022.06.06
[Assembly] 문자열 입력과 출력  (0) 2020.06.05
[Assembly] 1부터 10까지의 합 계산  (0) 2020.06.04
[C++] STL - multimap 공부  (0) 2020.05.24
[C++] STL - map 공부  (0) 2020.05.14
반응형

어셈블리어를 이용하여 문자열 입출력을 구현해보자.

필자는 Visual Studio 2017과 Irvine 라이브러리를 활용하여 개발할 예정이다.


1. 문제

  • 환경 : Visual Studio 2017, Irvine 라이브러리, x86 assembly
  • 키보드에서 문자열을 입력받아 그 문자열을 출력하고, 길이와 메모리 덤프된 결과역시 출력하라.


2. 문제 해결 방법

  1. 안내문 문자열을 출력한다.
  2. 문자열을 입력받는다. > ReadString 사용(edx에 offset 지정 및 ecx로 글자수 지정)
  3. 문자열 길이 계산 > StrLength 사용(edx에 문자열 offset 지정)
  4. 문자열 길이 0과 비교하여 0이 아닐경우 1번으로 돌아감
  5. 0이면 종료
  6. 메모리 덤프 결과 출력 > DumpMem 사용(ecx에 출력할 길이, esi에 시작주소, ebx는 단위 크기)

3. 코딩

 

TITLE Program asm3inputoutput(asm3inputoutput.asm)
; 프로그램 설명문 :	문자열 입력받고 출력하는 프로그램

INCLUDE c:\Irvine\Irvine32.inc

.data
Ask			BYTE "INPUT : ", 0
Len			BYTE "Length : ", 0
Output		BYTE "OUTPUT : ", 0
Answer		BYTE 50 DUP(?)

.code
main			PROC

START:
	mov 		edx, 0
	mov 		edx, OFFSET Ask
	call		WriteString				; ASK 안내문 출력
	mov 		edx, OFFSET Answer
	mov 		esi, edx
	mov 		ecx, SIZEOF Answer - 1
	call		ReadString				; 문자열 읽기
	call		Crlf
	mov 		edx, 0
	mov 		edx, OFFSET Len
	call		WriteString				; Len 안내문 출력
	mov 		edx, 0
	mov 		edx, OFFSET Answer
	call		StrLength				; 문자열 길이 계산
	call		WriteDec				; 문자열 길이 eax 출력
	call		Crlf
	call		Crlf
	cmp 		eax, 0					; 문자열 길이 0 비교
	jz  		LOUT					; 길이 0일 경우 프로그램 종료
	mov 		edx, 0
	mov 		edx, OFFSET Output
	call		WriteString				; OUTPUT 안내문 출력
	mov 		edx, 0
	mov 		edx, OFFSET Answer
	call		WriteString				; 입력한 문자열 출력
	call		Crlf
	mov 		ecx, eax				; 메모리 덤프 출력 길이 지정
	call		DumpMem					; 메모리 덤프 출력
	call		Crlf
	call		START					; 반복

LOUT:		exit					; 빠져나가기

main			ENDP
END			main

 

실행 결과는 다음과 같다.

 


어셈블리를 통해 다양한 문제를 풀어볼 예정이다.

반응형

'Programming > Language' 카테고리의 다른 글

[C++] 클래스(Class) 공부  (0) 2022.06.06
[Assembly] 파일 읽고 출력해보기  (0) 2020.06.06
[Assembly] 1부터 10까지의 합 계산  (0) 2020.06.04
[C++] STL - multimap 공부  (0) 2020.05.24
[C++] STL - map 공부  (0) 2020.05.14
반응형

어셈블리어를 이용하여 1부터 10까지의 합을 구하는 프로그램을 개발해보자.

본 필자는 Visual Studio 2017과 Irvine 라이브러리를 활용하여 개발할 예정이다.


1. 문제

  • 환경 : Visual Studio 2017, Irvine 라이브러리, x86 assembly
  • 1부터 10까지 합산 값을 출력하고 레지스터를 덤프하는 프로그램을 개발하라.


2. 문제 해결 방법

  1. 문자열을 출력한다.
  2. eax를 xor로 초기화 시킨다.
  3. ecx에 10을 mov 한다.
  4. loop를 돌며 eax에 ecx 값을 더한다.(지정된 위치로 넘어가고 ecx가 1씩 감소하며, ecx가 0이되면 빠져나온다.)
  5. 결과 값을 출력한다.
  6. 덤프된 레지스터를 출력한다.


3. 코딩

TITLE Program asm2sum.asm(asm2sum.asm)
; 프로그램 설명문 : 1부터 10까지의 합을 구해 출력하는 프로그램

INCLUDE c:\Irvine\Irvine32.inc

.data
str_data db "1 + 2 + 3 ... + 10 = ", 0	; 문자열 str_data db(1바이트)크기 선언

.code
main	PROC

mov 	ecx, 10					; ecx에 10을 mov
xor 	eax, eax				; eax는 0

LP:
add 	eax, ecx				; eax에 ecx를 더해 eax에 결과값 저장
loop	LP						; ecx가 0보다 크면 LP로 다시 돌아감, ecx 1 감소

mov 	edx, offset str_data	; str_data offset 주소 edx에 mov
call	writeString				; edx에 있는 값 문자열 출력

call	WriteDec				; eax에 있는 값 10진수 출력
call	Crlf					; 줄 바꿈
call	DumpRegs				; 덤프된 레지스터 출력

exit							; 종료
main	ENDP
END main

 

실행 결과는 다음과 같다.


어셈블리를 통해 다양한 문제를 풀어볼 예정이다.

반응형

'Programming > Language' 카테고리의 다른 글

[Assembly] 파일 읽고 출력해보기  (0) 2020.06.06
[Assembly] 문자열 입력과 출력  (0) 2020.06.05
[C++] STL - multimap 공부  (0) 2020.05.24
[C++] STL - map 공부  (0) 2020.05.14
[C++] STL - set 공부  (0) 2020.05.14
반응형

저번 시간은 map 컨테이너에 대해 알아보았다.

map은 key와 value를 함께 관리할 수 있는 연관 컨테이너였다.

단, key가 중복이 허용되지 않았다.

그럼 key를 중복으로 사용하고 싶다면 어떻게 해야할까?

그 해답인 multimap에 대해 알아보자.


1. multimap이란?

multimap은 map과 매우 유사한 연관 컨테이너이다.

균형 이진트리(중위순회)이며, key와 value의 쌍(pair)인 원소들의 집합으로 이루어져 있다.

multimap의 특징은 map과 달리 key값이 중복이 된다는 것이다.

key를 중복하여 사용하고자 할때 해당 컨테이너를 이용하면 프로그램을 유연하게 구현가능하므로 기억해두자.

 

map과 같이 원소 삽입시(insert) 자동 정렬되며, default 기준 오름차순정렬이다.

 

multimap을 사용하기 위해선 <map> 헤더파일을 include 해주어야하며(multimap이 아니다!!),

std::multimap<[key 데이터타입], [value 데이터타입]> [변수이름]; 형식으로 선언해 사용할 수 있다.

(using namespace std;로 std 생략하여 편하게 작성가능)

 

2. multimap - 생성자

multimap 생성자는 다음과 같이 사용 가능하다. 아래부터 key는 int, value는 char형이라 가정하고 작성하겠다.

  • multimap<int, char> mm;
    • 빈 multimap 컨테이너 mm을 생성
  • multimap<int, char, greater<int>> mm;
    • key를 내림차순으로 정렬하는 빈 multimap 컨테이너 mm을 생성
  • multimap<int, char> mm2(mm);
    • mm를 복사한 mm2 컨테이너 생성


3. multimap - 멤버 함수 및 접근 방식

다음은 multimap 멤버 함수와 접근 방식이다. (multimap<int, char> m 선언 기준)

 

- 멤버 함수

  • mm.begin();
    • mm의 맨 처음 원소를 가리키는 반복자 리턴
    • iterator = mm.begin();
  • mm.end();
    • mm의 마지막 원소를 가리키는 반복자 리턴
    • iterator = mm.end();
  • mm.clear();
    • mm의 모든 원소를 제거
  • mm.size(), mm.max_size();
    • mm의 원소 갯수를 반환
    • mm의 최대 사이즈 반환
  • mm.empty();
    • mm이 비어있는지 확인
  • mm.count(k);
    • mm에서 k(key) 원소의 갯수 반환
  • mm.insert(p), m.emplace(p);
    • mm에 p(pair)라는 객체 추가
    • insert 성공시 true 반환, key 이미 존재하여 실패한 경우는 false 반환
    • emplace로도 추가 가능
  • mm.insert(pair<int, char>(k, v)), m.emplace(pair<int, char>(k, v));
    • mm에 k(key), v(value) 값 삽입
    • insert 성공시 true 반환, key 이미 존재하여 실패한 경우는 false 반환
    • emplace로도 추가 가능
  • mm.erase(k);
    • mm에서 k(key) 값 해당 요소를 찾아 제거
  • mm.erase(start, end), mm.erase(iterator);
    • mm에서 start부터 end 범위 원소 모두 제거
    • iterator가 가리키는 key 제거
  • mm.find(k), mm.find(k)->second;
    • mm에서 k(key) 값을 찾아 반복자 형태로 반환
    • mm에서 k(key) 값을 찾아 value 출력
    • 못찾은경우 반복자 end 리턴
  • mm2.swap(mm);
    • mm과 mm2의 데이터를 바꿈
  • mm.upper_bound(k1), mm.lower_bound(k2);
    • k1(key) 값 해당되는 맨 마지막 원소의 다음을 가리키는 반복자 반환(폐구간 ")"로 사용)
    • k2(key) 값 해당하는 맨 첫번째 원소를 가리키는 반복자 반환(개구간 "["로 사용)
  • mm.equal_range(k);
    • k(key)이란 원소가 시작하는 구간과 끝나는 구간 반복자 pair 객체 반환
    • pair의 first는 lower_bound 반환값, second는 upper_bound 반환값
    • [ first, second )
  • mm.key_comp(), m.value_comp();
    • 정렬 기준 조건자 반환(key기준, value 기준 선택)

- 접근 방식

  • iterator를 통한 접근
    • multimap<int, char>::iterator mmit;
    • mmit->first(key), mmit->second(value) 형식으로 접근가능


4. multimap - 연산자

multimap의 연산자이다.

  • ==, != 
    • == : 두 multimap 컨테이너의 모든 원소가 같으면 참, 아니면 거짓
    • != : 두 multimap 컨테이너에서 하나라도 원소가 다르면 참, 아니면 거짓
  • <, >, <=, >=
    • multimap 컨테이너간 크기 비교


5. multimap 구조 및 실습

위에서 설명한 multimap의 구조는 균형 이진트리로 다음 그림과 같다.

계속해서 말하지만 key의 중복이 허용된다.



multimap 컨테이너를 이용하여 실습을 진행해보았다.

#include <iostream>
#include <map>
using namespace std;

int main(void) {
	multimap<int, char> mm;
	multimap<int, char>::iterator mmit;
	mm.insert(pair<int, char>(1, 'a')); //insert key 1, value 'a'
	mm.insert(pair<int, char>(2, 'b')); //insert key 2, value 'b'
	mm.insert(pair<int, char>(3, 'c')); //insert key 3, value 'c'
	mm.insert(pair<int, char>(4, 'd')); //insert key 4, value 'd'
	mm.insert(pair<int, char>(3, 'e')); //insert key 3, value 'e' > Allow!

	for (mmit = mm.begin(); mmit != mm.end(); mmit++) {
		cout << "key값 : " << mmit->first; //iterator->first는 key
		cout << ", value값 : "<< mmit->second << endl; //iterator->second는 value
	}

	cout << "mm.erase(1) 수행" << endl;
	mm.erase(1); //key가 1인값 제거

	for (mmit = mm.begin(); mmit != mm.end(); mmit++) {
		cout << "key값 : " << mmit->first; //iterator->first는 key
		cout << ", value값 : " << mmit->second << endl; //iterator->second는 value
	}

	cout << "mm.size : " << mm.size() << endl; //크기
	cout << "mm.max_size : " << mm.max_size() << endl; //최대 사이즈
	cout << "mm.count(3) : " << mm.count(3) << "개" << endl; //key가 3인 원소 갯수
	cout << "mm.find(2)->second : " << mm.find(2)->second << endl; //key가 2인 원소 value
	cout << "mm.lower_bound(3) : "<< mm.lower_bound(3)->first << ", " << mm.lower_bound(3)->second << endl;
	cout << "mm.upper_bound(3) : " << mm.upper_bound(3)->first << ", " << mm.upper_bound(3)->second << endl;

	return 0;
}

실행결과는 다음과 같다.

 


여기까지 multimap과 동시에 stl 파트를 마친다. 다음시간엔 클래스에 대해 알아볼 예정이다.

반응형

'Programming > Language' 카테고리의 다른 글

[Assembly] 문자열 입력과 출력  (0) 2020.06.05
[Assembly] 1부터 10까지의 합 계산  (0) 2020.06.04
[C++] STL - map 공부  (0) 2020.05.14
[C++] STL - set 공부  (0) 2020.05.14
[C++] STL - stack 공부  (0) 2020.05.11
반응형

저번 시간은 set 컨테이너에 대해 알아보았다.

set은 key만을 관리하는데 key와 value를 함께 관리할 수 있는 연관 컨테이너가 있다.

바로 map 컨테이너이다. 오늘은 map 컨테이너에 대해 알아보자.


1. map이란?

map은 set과 같은 연관 컨테이너로 노드 기반 컨테이너이다.

map 역시 균형 이진트리(중위순회)로 이루어져 있으며, key와 value의 쌍(pair)인 원소들의 집합으로 이루어져 있다.

여기서 key는 중복이 허용되지 않으며 중복을 허용하기 위해선 multimap을 사용하여야 한다.

 

원소 삽입시(insert) 자동 정렬되며, default 기준 오름차순정렬이다.

 

map을 사용하기 위해선 <map> 헤더파일을 include 해주어야하며,

std::map<[key 데이터타입], [value 데이터타입], [정렬 기준 조건자]> [변수이름]; 형식으로 선언해 사용할 수 있다.

정렬 기준 조건자는 greater<key 데이터타입> 형태로 선언하여 내림차순으로 변경가능하며, 생략 역시 가능하다.

(using namespace std;로 std 생략하여 편하게 작성가능)

 

 

2. map - 생성자

map 생성자는 다음과 같이 사용 가능하다. 아래부터 key는 int, value는 char형이라 가정하고 작성하겠다.

  • map<int, char> m;
    • 빈 map 컨테이너 m을 생성
  • map<int, char, greater<int>> m;
    • key를 내림차순으로 정렬하는 빈 map 컨테이너 m을 생성
  • map<int, char> m2(m);
    • m를 복사한 m2 컨테이너 생성


3. map - 멤버 함수 및 접근 방식

다음은 map 멤버 함수와 접근 방식이다. (map<int, char> m 선언 기준)

 

- 멤버 함수

  • m.begin();
    • m의 맨 처음 원소를 가리키는 반복자 리턴
    • iterator = m.begin();
  • m.end();
    • m의 마지막 원소를 가리키는 반복자 리턴
    • iterator = m.end();
  • m.clear();
    • m의 모든 원소를 제거
  • m.size(), m.max_size();
    • m의 원소 갯수를 반환
    • m의 최대 사이즈 반환
  • m.empty();
    • m이 비어있는지 확인
  • m.count(k);
    • m에서 k(key) 원소의 갯수 반환(중복안되므로 0 or 1)
  • m[k] = v;
    • m에 k(key)에 v(value)값 삽입
    • key 값 존재하는 경우 value 값 갱신, key 없는 경우엔 추가
  • m.insert(p), m.emplace(p);
    • m에 p(pair)라는 객체 추가
    • insert 성공시 true 반환, key 이미 존재하여 실패한 경우는 false 반환
    • emplace로도 추가 가능
  • m.insert(pair(k, v)), m.emplace(pair(k, v));
    • m에 k(key), v(value) 값 삽입
    • insert 성공시 true 반환, key 이미 존재하여 실패한 경우는 false 반환
    • emplace로도 추가 가능
  • m.insert(iterator, k);
    • m에서 iterator가 가리키는 위치부터 k(key)를 삽입할 위치 탐색하여 삽입(균형 이진트리)
  • m.erase(k);
    • m에서 k(key) 값 해당 요소를 찾아 제거
  • m.erase(start, end);
    • m에서 start부터 end 범위 원소 모두 제거
  • m.find(k);
    • m에서 k(key) 값을 찾아 반복자 형태로 반환
    • 못찾은경우 반복자 end 리턴
  • m2.swap(m);
    • m과 m2의 데이터를 바꿈
  • m.upper_bound(k1), m.lower_bound(k2);
    • k1(key)란 원소가 끝나는 구간 반복자
    • k2(key)란 원소가 시작하는 구간 반복자
  • m.equal_range(k);
    • k(key)이란 원소가 시작하는 구간과 끝나느 구간 반복자 pair 객체 반환
  • m.key_comp(), m.value_comp();
    • 정렬 기준 조건자 반환(key기준, value 기준 선택)

- 접근 방식

  • iterator를 통한 접근
    • map<int, char>::iterator mit;
    • mit->first(key), mit->second(value) 형식으로 접근가능
  • index 요소를 통한 접근
    • m[k](value) 형식 접근가능


4. map - 연산자

map의 연산자이다.

  • ==, != 
    • == : 두 map 컨테이너의 모든 원소가 같으면 참, 아니면 거짓
    • != : 두 map 컨테이너에서 하나라도 원소가 다르면 참, 아니면 거짓
  • <, >, <=, >=
    • map 컨테이너간 크기 비교


5. map 구조 및 실습

위에서 설명한 map의 구조는 균형 이진트리로 다음 그림과 같다.



map 컨테이너를 이용하여 실습을 진행해보았다.

#include <iostream>
#include <map>
using namespace std;

int main(void) {
	map<int, char> m;
	map<int, char>::iterator mit;
	m.insert(make_pair(3,'k')); //m에 3이란 key와, 'k'란 value 삽입
	m.insert(make_pair(1,'c')); //m에 1이란 key와, 'c'란 value 삽입
	m.insert(make_pair(2,'y')); //m에 2이란 key와, 'y'란 value 삽입

	cout << m[1] << endl; //첫번째 접근 방법

	mit = m.begin();
	cout << mit->first << ":" << mit->second << "\n" << endl; //두번째 접근 방법

	for (mit = m.begin(); mit != m.end(); mit++) {
		cout << mit->first << ":" << mit->second << endl; //모든 원소 key, value 출력
	}

	mit = m.find(3); //3이란 key 탐색
	if (mit != m.end()) { //m.end()가 아니면 출력 (find해서 없으면 m.end()반환하므로)
		cout << "\n 3이란 key를 찾았습니다. value 값은 " << mit->second << "입니다." << endl;
	}
	else {
		cout << "\n 3이란 key를 찾지 못했습니다." << endl;
	}
	return 0;
}

실행결과는 다음과 같다.


여기까지 map 공부를 마친다. 계속해서 stl에 대해 알아가볼 예정이다.

반응형

'Programming > Language' 카테고리의 다른 글

[Assembly] 1부터 10까지의 합 계산  (0) 2020.06.04
[C++] STL - multimap 공부  (0) 2020.05.24
[C++] STL - set 공부  (0) 2020.05.14
[C++] STL - stack 공부  (0) 2020.05.11
[C++] STL - list 공부  (0) 2020.05.07
반응형

이번 시간부터는 연관 컨테이너에 대해 알아보겠다.

연관 컨테이너는 일정 규칙에 따라 조직화하여 자료를 정렬하고 처리하는 컨테이너이다.

여기서 오늘 set 컨테이너에 대해 다뤄보려고 한다.


1. set이란?

set은 연관 컨테이너로 노드 기반 컨테이너이다.

균형 이진트리(중위순회)로 이루어져 있으며, key라고 하는 원소들의 집합으로 이루어져 있다.

여기서 key는 중복이 허용되지 않으며 중복이되는 key는 multiset으로 추후 설명할 예정이다.

 

원소 삽입시(insert) 자동 정렬되며, default 기준 오름차순정렬이다.

 

set을 사용하기 위해선 <set> 헤더파일을 include 해주어야하며,

std::set<[데이터타입]> [변수이름]; 형식으로 선언해 사용할 수 있다.

(using namespace std;로 std 생략하여 편하게 작성가능)

 

2. set - 생성자

set 생성자는 다음과 같이 사용 가능하다. 아래부터 데이터타입이 int라고 가정하고 작성하겠다.

  • set<int> s;
    • 빈 set 컨테이너 s 생성
  • set<int> s(predicate);
    • predicate 정렬 기준으로 빈 s 컨테이너 생성
  • set<int> s2(s);
    • s를 복사한 s2 컨테이너 생성

3. set - 멤버 함수

다음은 set 멤버 함수이다. (set<int> s 선언 기준)

 

- 멤버 함수

  • s.begin();
    • s의 맨 처음 원소를 가리키는 반복자 리턴
    • iterator = s.begin();
  • s.end();
    • s의 마지막 원소를 가리키는 반복자 리턴
    • iterator = s.end();
  • s.clear();
    • s의 모든 원소를 제거
  • s.size(), s.max_size();
    • s의 원소 갯수를 반환
    • s의 최대 사이즈 반환
  • s.empty();
    • s가 비어있는지 확인
  • s.count(3);
    • s에서 3이란 원소의 갯수 반환(중복안되므로 0 or 1)
  • s.insert(6);
    • s에 6이란 원소 삽입(자동 정렬)
    • 삽입 성공시 리턴값 pair<iterator, bool>에 pair.second 값으로 true, 삽입 실패시 false가 나옴(pair.first는 삽입한 원소 가리키는 반복자)
  • s.insert(iterator, 5);
    • s에서 iterator가 가리키는 위치부터 5를 삽입할 위치 탐색하여 삽입(균형 이진트리)
  • s.erase(iterator);
    • s에서 iterator가 가리키는 원소를 제거하고 다음 원소 가리키는 반복자 리턴
  • s.erase(start, end);
    • s에서 start부터 end 범위 원소 모두 제거
  • s.find(3);
    • s에서 3이란 원소 찾아 가리키는 반복자 반환, 없으면 s.end() 반환
  • s2.swap(s);
    • s와 s2 서로 데이터를 바꾼다.
  • s.upper_bound(4), s.lower_bound(5);
    • 4란 원소가 끝나는 구간 반복자
    • 5란 원소가 시작하는 구간 반복자
  • s.equal_range(3);
    • 3이란 원소가 시작하는 구간과 끝나느 구간 반복자 pair 객체 반환
  • s.key_comp(), s.value_comp();
    • 정렬 기준 조건자 반환(set에선 둘이 같음)

4. set - 연산자

set의 연산자이다.

  • ==, != 
    • == : 두 set 컨테이너의 모든 원소가 같으면 참, 아니면 거짓
    • != : 두 set 컨테이너에서 하나라도 원소가 다르면 참, 아니면 거짓
  • <, >, <=, >=
    • set 컨테이너간 크기 비교


5. set 구조 및 실습

위에서 설명한 set의 구조는 균형 이진트리로 다음 그림과 같다.



set 컨테이너를 이용하여 실습을 진행해보았다.

#include <iostream>
#include <set>
using namespace std;

int main(void) {
	set<int> s;
	set<int>::iterator sit;
	s.insert(3); cout << "3 원소 추가!" << endl;
	s.insert(7); cout << "7 원소 추가!" << endl;
	s.insert(2); cout << "2 원소 추가!" << endl;
	
	sit = s.begin();
	s.insert(sit, 6);
	cout << "s.begin()부터 탐색하여 6 원소 추가! \n" << endl;
	
	cout << "==========원소출력==========" << endl;
	for (sit = s.begin(); sit != s.end(); sit++) {
		cout << *sit << endl;
	}
	cout << "============================\n" << endl;

	s.erase(7); cout << "7 원소 삭제!" << endl;
	//s.erase(s.begin(), s.end()); // 모든 원소 삭제

	sit = s.upper_bound(3); cout << "3 원소 끝나는 구간에 반복자 지정" << endl;
	cout << "반복자가 가리키는 원소 : " << *sit << "\n" << endl;

	sit = s.find(6); cout << "6이라는 원소 찾기" << endl;
	if (sit != s.end()) {
		cout << *sit << " 원소가 존재 합니다." << endl;
	}
	else {
		cout << "해당 원소를 찾지 못했습니다." << endl;
	}
	
	return 0;
}

실행결과는 다음과 같다.


여기까지 set 공부를 마친다. 다음 시간엔 map에 대하여 알아보는 시간을 갖겠다.

반응형

'Programming > Language' 카테고리의 다른 글

[C++] STL - multimap 공부  (0) 2020.05.24
[C++] STL - map 공부  (0) 2020.05.14
[C++] STL - stack 공부  (0) 2020.05.11
[C++] STL - list 공부  (0) 2020.05.07
[C++] STL - vector 공부  (0) 2020.05.06
반응형

지난 시간에 STL의 시퀸스 컨테이너중 하나인 list에 대해 알아보았다.

연관 컨테이너로 넘어가기 전에 어댑터 컨테이너에 있는 몇몇 컨테이너들을 짚고 넘어가려고 한다.

이번 시간은 stack 컨테이너를 공부해볼 예정이다.


1. stack이란?

stack은 어댑터 컨테이너 중 하나로 vector, deque, list 구조와 같은 시퀸스 컨테이너를 변형한 것이다.

LIFO(Last In First Out) 방식이며 default로 deque 컨테이너를 기반으로 작동한다.

 

이를 사용하기 위해서 C언어에선 PUSH, POP과 같은 함수를 직접 만들어줘야하지만 C++에선 STL이 해결해준다.

<stack> 헤더파일을 include 해주어야하며,

std::stack<[데이터타입]> [변수이름]; 형식으로 선언해 사용할 수 있다.

(using namespace std;로 std 생략하여 편하게 작성가능)

 

*내부 컨테이너를 바꾸고 싶으면 std::stack<[데이터타입], [컨테이너타입]> [변수이름]; 형태로 선언하여 사용 가능하다.



2. stack - 생성자

stack 생성자는 다음과 같이 사용 가능하다. 아래부터 데이터타입이 int라고 가정하고 작성하겠다.

  • stack<int> stk;
    • 빈 stack 컨테이너 stk 생성(내부컨테이너 deque)
  • stack<int, vector<int>> stk;
    • 빈 stack 컨테이너 stk 생성(내부컨테이너 vector(int))


3. stack - 멤버 함수

다음은 stack 멤버 함수이다.

 

- 멤버 함수

  • stk.push(3);
    • stk에 3이란 데이터 삽입
  • stk.pop();
    • stk의 top이 가리키는 원소를 삭제
  • stk.top();
    • 맨위에 있는 데이터를 반환
  • stk.empty();
    • stk이 비어있는지 확인
  • stk.size();
    • stk의 사이즈 반환
  • stk.emplace(args);
    • C++11부터 지원
    • 특정 클래스의 stack이면 해당 인자를 해당 클래스 생성자로 넘겨 해당 클래스 객체 생성하여 Stack에 Push
  • stk.swap(stk2);
    • C++11부터 지원 
    • stk과 stk2의 데이터를 서로 바꿈


  •  

4. stack - 연산자

stack의 연산자이다.

  • ==, != 
    • == : 두 stack 컨테이너의 모든 원소가 같으면 참, 아니면 거짓
    • != : 두 stack 컨테이너에서 하나라도 원소가 다르면 참, 아니면 거짓
  • <, >, <=, >=
    • stack 컨테이너간 크기 비교


5. stack 구조 및 실습

위에서 설명한 stack의 구조는 다음 그림과 같다.



실습을 진행해보았다. stack 컨테이너를 이용해 원소를 추가, 삭제해보며 실습해보았다.

 

#include <iostream>
#include <stack>
using namespace std;

int main(void) {
	stack<int> stk;
	stk.push(10); cout << "stk 10 push" << endl;
	stk.push(20); cout << "stk 20 push" << endl;
	stk.push(30); cout << "stk 30 push" << endl;
	
	cout << "stk의 맨위 데이터 : " << stk.top() << endl;
	cout << "stk의 사이즈 : " << stk.size() << endl;
	cout << "stk이 비어있는가 : " << stk.empty() << endl;

	stk.pop(); cout << "stk pop > 30 out" << endl;
	stk.pop(); cout << "stk pop > 20 out" << endl;
	
	cout << "stk의 맨위 데이터 : " << stk.top() << endl;

	stk.pop(); cout << "stk pop > 10 out" << endl;

	cout << "stk의 사이즈 : " << stk.size() << endl;
	cout << "stk이 비어있는가 : " << stk.empty() << endl;
	return 0;
}

 

실행결과는 다음과 같다.

 


여기까지 stack 공부를 마친다. 슬슬 연관 컨테이너에 대해 공부해볼 계획이다.

반응형

'Programming > Language' 카테고리의 다른 글

[C++] STL - map 공부  (0) 2020.05.14
[C++] STL - set 공부  (0) 2020.05.14
[C++] STL - list 공부  (0) 2020.05.07
[C++] STL - vector 공부  (0) 2020.05.06
[C++] STL(Standard Template Library) 시작  (0) 2020.05.05

+ Recent posts