Manipulator
cout 키워드를 통한 피연산자의 출력 형식(8진수, 16진수, 문자...)을 결정하는 키워드.
// In C Language...
int Number = 10;
printf("%x\n", Number);
// number를 16진수 출력형식으로 출력.
// In C++ Language...
int Number = 10;
std::cout << std::showbase << std::hex << Number << std::endl;
// base는 진법. showbase는 진법 표시을 생략하지 말고 표기하라.
std::cout << std::showpos << Number; // +123 (양수에 + 붙임)
std::cout << std::noshowpos << Number; // 123 (+ 없앰, 기본값)
std::cout << std::dec << Number; // 123 (10진수, 기본값)
std::cout << std::hex << Number; // 7b (16진수)
std::cout << std::oct << Number; // 173 (8진수)
std::cout << std::uppercase << std::hex << Number; // 7B (16진수 대문자)
std::cout << std::nouppercase << std::hex << Number; // 7b (16진수 소문자)
std::cout << std::showbase << std::oct << Number; // 0173 (진수 표시, 8진수는 0, 16진수는 0x)
std::cout << std::noshowbase << std::oct << Number; // 173 (진수 표시 없앰)
std::cout << std::dec; // 다시 10진수로 리셋
// MinusNumber = -123, setw(6) = 6칸 확보
std::cout << '[' << std::setw(6) << MinusNumber << ']';
// [-123] → 오른쪽 정렬 (기본값), 공백으로 채움
// [ -123] 이 아니라 [ -123] (6칸)
std::cout << '[' << std::setw(6) << std::left << MinusNumber << ']';
// [-123 ] → 왼쪽 정렬
std::cout << '[' << std::setw(6) << std::internal << MinusNumber << ']';
// [- 123] → 부호는 왼쪽, 숫자는 오른쪽
std::cout << '[' << std::setw(6) << std::right << MinusNumber << ']';
// [ -123] → 오른쪽 정렬 (기본값)
std::cout << '[' << std::setw(6) << std::setfill('0') << MinusNumber << ']';
// [-00123] → 빈칸을 0으로 채움
// Number01 = 123.0, Number02 = 123.456
std::cout << std::showpoint << Number01 << ' ' << Number02;
// 123.000 123.456 → 소수점 아래 무조건 표시 (기본 6자리)
std::cout << std::noshowpoint << Number01 << ' ' << Number02;
// 123 123.456 → 의미없는 소수점 생략
std::cout << std::fixed << Number02;
// 123.456001 → 고정 소수점 표기
std::cout << std::scientific << Number02;
// 1.234560e+02 → 과학적 표기법
// IsReady = true
std::cout << std::boolalpha << IsReady; // true (문자로 출력)
std::cout << std::noboolalpha << IsReady; // 1 (숫자로 출력, 기본값)
std::cout << std::fixed << std::setprecision(2) << Number02;
// 123.46 → 소수점 2자리까지만
- pos는 positive의 약자로 양수를 의미
- setw() 빼고 나머지는 한번 설정하면 계속 유지
분할 컴파일의 필요성
선언과 구현을 분리해놓는 이유: 컴파일 때문
기존 컴파일 내용은 빌드했을 때 저장이 되는데, 수정 후 재컴파일할 때는 수정된 부분만 재컴파일된다. 그런데...
- 헤더 바꿈 → 그 헤더 include한 모든 .cpp 재컴파일
- .cpp 바꿈 → 그 .cpp 하나만 재컴파일
파일이 100개인 프로젝트에서 헤더 건드리면 100개 다 다시 컴파일해야 한다. 구현만 분리하면 바뀐 파일 하나만 다시 컴파일한다.
컴파일 단계 후에 링크 단계가 실행되므로, 변경된 부분 연결은 기존과 동일하게 작동한다.
순환 참조 방지
// ❌ 헤더에 구현까지 있으면
// Monster.h 가 Player.h 포함
// Player.h 가 Monster.h 포함
// → 무한루프!
// ✅ 분리하면
// Monster.h 에는 선언만
// Monster.cpp 에서 Player.h 포함
// → 문제없음
JAVA는 구현 위치 상관 없이 JVM이 알아서 처리해주는데, C++은 컴파일러가 직접 다 하기 때문에 분리가 중요
C++은 파일 단위로 컴파일.
Monster.cpp → 컴파일 → Monster.o
Player.cpp → 컴파일 → Player.o
main.cpp → 컴파일 → main.o
↓
합치기 (링크)
↓
game.exe
헤더를 include 하면 어떻게 되냐면
// main.cpp
#include "Monster.h" // Monster.h 내용을 main.cpp에 그대로 복붙하는 것과 같음
#include 는 사실상 복붙.
헤더에 구현까지 있으면
// Monster.h 에 구현까지 있을 때
class Monster {
public:
void Attack() { cout << "공격!"; } // 구현이 헤더에 있음
};
// 이 헤더를 10개 파일이 include 하면
// Attack() 구현 코드가 10개 파일에 복붙됨
// Monster.h 조금만 바꿔도 10개 전부 재컴파일!
구현을 .cpp로 분리하면
// Monster.h → 선언만
class Monster {
public:
void Attack(); // 선언만
};
// Monster.cpp → 구현만
void Monster::Attack() { cout << "공격!"; }
```
```
Monster.h 바뀜 → 10개 파일 재컴파일 😢
Monster.cpp 바뀜 → Monster.cpp 하나만 재컴파일 😊
한 줄 요약
#include는 복붙이라서, 헤더에 구현까지 있으면 수정할 때마다 그 헤더 포함한 파일 전부 다시 컴파일
네임스페이스
전역변수/전역함수/클래스 등의 이름 충돌을 피하기 위해서 사용하는 키워드
범위 지정 연산자 ::
어디에 소속되어 있는지 명시하기 위해 사용하는 연산자
// Main.cpp
#include <iostream>
namespace hello
{
char String[32] = "Hello, Namespace!";
}
namespace hi
{
char String[32] = "Hi, Namespace!";
}
int main(void)
{
std::cout << "hello's String: " << hello::String << std::endl
<< "hi's String: " << hi::String << std::endl;
return 0;
}
namespace 쓰는 예
// Hello.h
#pragma once
namespace hello
{
void Greet();
}
// Hello.cpp
#include <iostream>
#include "Hello.h"
void hello::Greet()
{
std::cout << "Hello, Namespace!" << std::endl;
}
// Main.cpp
#include <iostream>
#include "Hello.h"
#include "Hi.h"
using namespace hello;
int main(void)
{
Greet();
hi::Greet();
return 0;
}
실제로 std가 이렇게 되어있음
namespace std {
class string { ... };
class vector { ... };
class cout { ... };
}
// 그래서 이렇게 쓰는 거임
std::string name;
std::vector<int> list;
using 키워드
타이핑 양을 줄이기 위해 사용하는 키워드
COUT
스트림 상태에 문제가 있다면 어떻게 될까요?
유효하지 않은 데이터를 읽으려 해서 스트림 상태가 망가졌다면 다시 해당 스트림으로 읽으려 할 때 우리가 원하는 대로 동작하지 않는 모습을 볼 수 있습니다. 그 이유는 유효하지 않은 값이 스트림에 남아 있을 수도 있기 때문입니다. 이 유효하지 않은 값을 버리고 싶다면 어떻게 해야할까요?

cin의 상태 종류
goodbit :“아무 문제 없음”, “기본 상태”
eofbit: “더이상 읽을 입력 데이터가 없음”
failbit: “읽고자 하는 입력 데이터의 자료형이나 형식이 맞지 않음”
badbit: “입력 장치의 심각한 오류”, 거의 일어나지 않음."
cin.clear() 함수
eofbit, failbit, badbit을 unset 시켜주는 함수. 즉, good state가 됩니다
cin.ignore() 함수
파일 끝에 도달하거나 지정한 수 만큼 문자를 버리면 멈춥니다.
cin.ignore(); // 문자 1개를 버림.
cin.ignore(10, '\\n'); // 문자 10개를 버림. 단, 그 전에 '\\n' 문자를 버리면 곧바로 버리는 걸 멈춤.
cin.ignore(LLONG_MAX, '\\n'); // 최대 문자 수를 버림. 단
스트림 상태 되돌리기
// Main.cpp
#include <iostream>
int main(void)
{
int Number;
std::cin >> Number;
std::cout << "Number: " << Number
<< " // eof bit: " << std::cin.eof()
<< " // fail bit: " << std::cin.fail() << std::endl;
std::cin.clear();
std::cin.ignore(LLONG_MAX, '\n');
std::cin >> Number;
std::cout << "Number: " << Number
<< " // eof bit: " << std::cin.eof()
<< " // fail bit: " << std::cin.fail() << std::endl;
std::cin.clear();
std::cin.ignore(LLONG_MAX, '\n');
std::cin >> Number;
std::cout << "Number: " << Number
<< " // eof bit: " << std::cin.eof()
<< " // fail bit: " << std::cin.fail() << std::endl;
return 0;
}'코딩 학습 > C와 C++' 카테고리의 다른 글
| C++ 기초 - 생성자와 소멸자 (0) | 2026.04.06 |
|---|---|
| C++ 배치고사 선택 문제 (0) | 2026.04.03 |
| C++ 배치고사 필수 문제 (0) | 2026.04.02 |
| C++ 팀프로젝트 - 텍스트 RPG 게임 만들기(4) (0) | 2026.03.31 |
| C++ 팀프로젝트 - 텍스트 RPG 게임 만들기(2) (0) | 2026.03.27 |