[C++ 기초 문법] #1. #include, 표준 입출력

YUN·2026년 2월 14일

C++

목록 보기
15/82
post-thumbnail

1. C와 C++

C++은 역사적으로 C에서 출발했고, 그 결과 C++은 많은 C의 표준 문법을 포함한다.

입,출력을 예로 들었을때, C++ 에서는

  • C++ 스타일
  • C 스타일 (C 표준 라이브러리를 C++에 맞게 Wrapper 형태로 감싼 라이브러리 사용)

위와 같이 2가지 방법을 사용할 수 있다.

2. 프로그램 기본 구조

#include <iostream>    // 입출력 라이브러리
using namespace std;   // std:: 생략 가능하게

int main() {
    // 여기에 코드 작성
    return 0;
}
  • #include <헤더> : 컴파일 지시어로, 헤더 파일을 복붙해주는 기능을 수행한다
  • using namespace std : std::cout 대신 그냥 cout 으로 쓸 수 있게 해준다. (namespace 관련 개념으로, 뒤에서 다룰 것이다)
  • int main() : 프로그램의 시작점 (Entry Point)
  • return 0 : 함수의 반환 값으로, return 0은 관례적으로 프로그램의 정상 종료 를 의미한다.

3. 자주 사용되는 헤더 파일

// 방법 1: 필요한 것만 개별 include
#include <iostream>   // cin, cout
#include <vector>     // vector
#include <algorithm>  // sort, max, min
#include <string>     // string
#include <cmath>      // abs, sqrt, pow

// 방법 2: 한 방에 전부 포함 (코테 한정 추천 ✅)
#include <bits/stdc++.h>   // GCC 전용, 모든 표준 헤더 포함

위에 나와있는 헤더파일들은 전부 표준 헤더 파일로 개벼로 include도 가능하고, 한 번에 전체를 include 하는 방식도 존재한다.

4. 입출력

(1) <iostream> 과 운영체제 : ⌨️→💻 입력의 원리

(1) 사람이 키보드를 누름
(2) OS가 \n(엔터키)가 들어오기 전까지 눌린 키보드 정보를 OS Buffer에 저장
(3) \n(엔터키) 들어오면 C++ 표준 라이브러리인 iostream 내부의 C++ stream 버퍼 에 저장
(4) cin >> a; 하면 a에 눌린 키보드 정보가 저장됨

(2) <iostream> 과 운영체제 : 💻→🖥️ 출력의 원리

(1) cout << a + b << "\n" 실행
(2) iostream 내부의 C++ stream 버퍼 에 저장 (버퍼링 적용: Flush 되면 OS버퍼로 내보냄)
(3) flush 발생시 C++ stream 버퍼의 데이터를 OS Buffer로 전달
(4) OSTerminal 프로그램에 해당 데이터 전달하면 Terminal 프로그램이 전달받은 데이터의 픽셀 데이터를 생성하여 GPU로 전송
(5) GPU가 모니터에게 신호 주면, 모니터가 해당 픽셀에 빛을 쏨

이때 중요한 것이 flush가 발생하는 시점이다.

  • ✅ '\n'을 만났을 때 (보통 자동 flush)
  • ✅ 버퍼가 가득 찼을 때
  • ✅ endl을 쓰면 강제 flush
  • ✅ 프로그램 종료 시

위의 4가지 경우에 C++ stream 버퍼 에서 flush가 발생한다.


C++ 은 앞서 말했듯이 여러가지 방식으로 코딩이 가능하다.

입출력의 경우도 C++ 스타일, C 스타일 과 같이 2가지 방식으로 가능하다

(3) C++ 스타일 : cin / cout

#include <iostream>
using namespace std;

int main() {
    int a, b;
    cin >> a >> b;          // 공백, 탭, 엔터 기준으로 입력 받음
    cout << a + b << "\n";  // 출력 후 줄바꿈
    return 0;
}

위의 코드를 뜯어보자.

#include <iostream>

#include <iostream>   // Input/Output Stream (입출력 스트림)

<iostream> 은 cin, cout 이 정의된 헤더파일로, 이렇게 복붙해줘야 컴파일 과정에서 오류가 나지 않는다.

using namespace std

using namespace std;

이것을 이해하려면 namespace를 이해해야한다.

namespace는 왜 존재할까?

만약 두 회사가 각각 "print"라는 함수를 만들었다면?

회사A::print()   ← A의 print
회사B::print()   ← B의 print

print()를 사용자가 호출 시 이 중 어떤 함수인지 컴파일러는 알 수 없다.

이런 경우를 대비해 이름 충돌을 방지하기 위해 만들어진 "폴더" 같은 개념이 namespace 이다.

C++의 수많은 namespace 중에서 stdC++ 표준 라이브러리들이 모여있는 namespace이다.

원래대로라면, namespace명::함수명 으로 함수에 접근하는 것이 정석이다.

다시 본론으로 돌아가자.


cin, coutC++ 표준 라이브러리에 속하고, 따라서 std namespace에 속한다.

std::cin   // std라는 이름공간 안에 있는 cin
std::cout  // std라는 이름공간 안에 있는 cout

그래서 원래대로는 위와 같이 cincout에 접근해야한다.

그러나 매번 앞에다가std::를 붙이기는 매우 번거롭고 귀찮다.

using namespace std;   // "std:: 생략할게!"

이럴때 위와 같이 using namespace std 를 써주면 std::를 생략하고 cin이나 cout만 써도 인식이된다.

// ❌ using namespace std 없이
std::cin >> a >> b;
std::cout << a + b << std::endl;

// ✅ using namespace std 있으면
cin >> a >> b;
cout << a + b << endl;

추출 연산자(>>)와 삽입 연산자(<<)

>><<는 뭘까? >>는 데이터를 ->로 전달하고 <<는 데이터를 ->로 전달한다.

cin >> a >> b

C++ stream Buffer 에 값이 있으면 바로 변수에 집어넣고, 값이 없으면 표준 입력을 대기한다

cin >> a >> b;
  • cin : 키보드로부터 입력 받는 객체
  • a, b : 데이터가 저장될 변수
키보드 입력: 3 5↵(엔터)

cin >> a >> b;
      ↓     ↓
      a=3   b=5

(공백, 탭, 엔터를 기준으로 자동 분리!)

cin은 위와 같이 공백, , 엔터 기준으로 데이터를 자동으로 분리해서 변수에 저장한다.

또한 cin >>는 알아서 앞에 있는 공백/탭/개행(\n)을 전부 건너뛰고 다음 값을 읽는다.

cout << a + b << "\n"

C++ stream Buffer에 값을 집어넣는다 (C++ Stream Buffer는 flush 발생시 버퍼의 데이터를 OS Buffer로 전송한다)

cout << a + b << "\n";
  • cout : 화면에 출력하는 객체
  • a + b : 출력할 값
  • "\n" : 줄바꿈 문자

cout은 연속 출력(Chaining)이 가능하다

cout << "합: " << a + b << "\n";
//      첫번째    두번째    세번째  → 순서대로 출력
// 출력: 합: 8

위와 같이 <<를 연속으로 사용하면 사이에 공백을 넣어서 화면에 출력한다.

결론

표준입출력 사용하고 싶을때는 그냥 아래 코드 구조를 외워서 쓰면 된다.

#include <iostream>
using namespace std;

int main() {
    int a, b;
    cin >> a >> b;          // 공백, 탭, 엔터 기준으로 입력 받음
    cout << a + b << "\n";  // Buffer Flush + 마지막에 줄 바꿈 
    return 0;
}

한 줄 통째로 입력 받기 : getline(cin, string line)

// 한 줄 통째로 입력 (공백 포함)
string line;
getline(cin, line);   // 공백 포함해서 한 줄 전체를 읽음

만약 사용자 입력이 Hello World\n 이라면 line에는 string 타입의 Hello World가 저장된다. (즉, 공백을 포함하여 \n 만나기 전까지 저장한다)

getline() 사용시 버퍼에 남아있는 \n은 어떻게 될까?

line에는 \n이 들어가지않고, 자동으로 \n를 버퍼에서 삭제시켜버린다.

그러나 cin뒤에 getline을 사용할때는 주의해야한다.

자동으로 \n을 삭제하는 getline()과 달리, cin은 버퍼에 남은 \n을 자동으로 삭제하지 않고 C++ steram buffer에 그대로 남겨준다.

(cin이 변수에 값을넣을때 내부적으로 공백, 탭, 개행을 전부 무시하기때문에 cin입장에서는 굳이 버퍼에서 개행을 삭제할 필요가없다)

이는 cin뒤에 getline을 사용하는 경우 문제를 야기한다.

// 패턴 3: cin 뒤에 getline 쓸 때 주의!
int n;
cin >> n;

string line;
getline(cin, line);

이 코드에서

사용자 입력: 5↵(엔터)
            Hello World↵(엔터)

사용자가 위와 같이 입력하는 경우,

cin\n을 버퍼에서 자동으로 삭제하지 않기에 getline()이 남아있는 \n을 읽게되고, line에는 " "만 저장된다.

이를 막으려면 cingetline() 사이에 cin.ignore(); 를 넣어줘야한다.

// 패턴 3: cin 뒤에 getline 쓸 때 주의!
int n;
cin >> n;
cin.ignore();
string line;
getline(cin, line);

위와 같이 코드를 작성해주면 cin.ignore()C++ Streram Buffer에 남아있던 \n을 제거해줄 것이고 line에는 Hello World가 성공적으로 저장될 것이다.

(4) C 스타일 : scanf / printf

#include <cstdio>

int main() {
    int a, b;
    scanf("%d %d", &a, &b);    // 서식 지정자로 입력
    printf("%d\n", a + b);     // 서식 지정자로 출력
    return 0;
}
#include <cstdio>

<stdio>C에서 표준 입출력 라이브러리 이다. cstdio는 이를 C++에 맞게 감싼 Wrapper 이다.

scanf("%d %d", &a, &b);    // 서식 지정자로 입력
printf("%d\n", a + b);     // 서식 지정자로 출력

C에서와 동일하게 서식 지정자를 활용하여 scanfprintf를 수행해주면 된다.

까먹기 쉬운것이 입력에서는 입력 받을 변수의 주소를 넘겨줘야하고, 출력에서는 출력할 데이터 를 넘겨주면 된다.

자주 사용하는 서식 지정자

#include <cstdio>

int main() {
    int a = 42;
    double b = 3.14159;
    char c = 'A';
    char str[] = "Hello";

    printf("%d\n", a);       // 정수        → 42
    printf("%f\n", b);       // 실수(소수점) → 3.141590
    printf("%c\n", c);       // 문자        → A
    printf("%s\n", str);     // 문자열      → Hello
    printf("%%\n");          // % 자체 출력  → %
    return 0;
}

나는 C/C++을 제일 처음 배울때 와닿지 않았던 것이 자료형서식 지정자의 관계였다.

아니! 자료형이 이미 int고, float이고, char로 정해져있는데 서식 지정자가 왜 필요하냐?

하는 의문이 존재했다.

그런데 요즘은 '뭐, 정수 자료형이라도 소수로 표현하고 싶을때가 있는거고, 소수라도 소수점 날리고 정수로 표현하고 싶을때가 있지 않을까?' 하고 생각한다.

특히 char의 경우 자료형의 특성상 내부적으로 ASCII 코드로 저장되는 정수 자료형이기에 %dASCII 코드 그대로 출력하고 %cASCII 코드문자로 변환하여 출력한다는 점이 재미있다.

scnaf 사용시 주의할 점

int a;
double d;
char str[100];

scanf("%d", &a);       // int    → %d  + & 필수!
scanf("%lf", &d);      // double → %lf + & 필수! (%f 아님!)
scanf("%s", str);       // 문자열 → %s  + & 없음! (배열 이름이 이미 주소)
  • scanf의 인자로 항상 변수의 주소를 넘겨줘야한다.
  • scanf는 형식 지정자에 따라 공백/탭/개행(= whitespace)을 자동으로 건너뛴다.
    • %d, %lld, %f, %lf, %s 등은 공백/탭/개행(= whitespace)을 자동으로 건너뛴다.
    • %c 는 공백/탭/개행(= whitespace)을 건너뛰지않고 그대로 읽는다. (주의!)
  • double 사용시 : printf()면 서식 지정자를 %f로, scanf()면 서식 지정자를 %lf로 사용한다.
  • long long 사용시 : 서식 지정자를 %lld로 사용해야한다.
  • scnaf() 사용시 문자열을 <string>의 string 타입을 쓰면 안되고 char []로 써야한다.
  • 문자열=char [] 사용시 마찬가지로 변수의 주소를 넘겨줘야한다. 그런데 C/C++ 특성상 배열의 이름이 그 자체로 주소이므로, 주소 연산자(&)없이배열의 이름만 그대로 넘겨주면된다.
profile
안녕하세요. 전자공학부 학부생의 공부 기록입니다.

0개의 댓글