[C++] 입출력 (printf(), scanf(), cout, cin)

2024. 3. 3. 18:07Programming Language/C++

아래 링크 클릭 시 해당 본문으로 이동

C의 입출력 방식

C++의 입출력 방식

C 입출력 방식 vs. C++ 입출력 방식


C의 입출력 방식

헤더 파일

// C 방식
#include <stdio.h>  // stdio.h => global namespace
// #include : 내가 원하는 다른 기능을 포함시킨다는 의미, 전처리기이다.
// stdio : standard input output (표준 입출력)
// .h : 헤더 파일(header file)을 의미하는 확장자

// C++ 방식
#include <cstdio>  // cstdio => std라는 namespace

printf()scanf()를 사용하려면 #include <stdio.h>라는 표준 입출력 헤더 파일이 필요하다.


printf()

• 출력(print) + 형식(formatted)

서식화된 출력을 지원한다는 의미이다.

• 표준 출력 함수

보통 문자열을 출력할 때 사용한다.

• 콘솔 창에 원하는 데이터를 서식 지정자에 맞게 출력할 수 있다.

• 첫 번째 인자 : printf()에 출력하고 싶은 자료형의 서식 지정자

• 두 번째 인자 : 첫 번째 인자로 넣은 서식 지정자에 해당하는 값 (넣고 싶은 값)

 

▷ 예시

#include <stdio.h>

int main()
{
	printf("abc %d\n", 10);  // abc 10
    printf("abc %f\n", 3.25f);  // abc 3.250000
    
    return 0;
}

 

%d 자리는 정수 10으로, %f 자리는 실수 3.250000으로 대체됐다.

콘솔(console) 창

 입출력할 수 있는 창

main()가 실행되면 콘솔 창이 나타난다.

이스케이프 시퀀스(\n), 형식 지정자(%d, %f)는 해당 본문 아래 페이지 참고
이스케이프 시퀀스
형식 지정자

scanf()

scan(데이터를 읽고 처리한다.) + 형식(formatted)

서식화된 입력을 받다는 의미이다.

• 콘솔 창으로부터 입력을 받아 지정한 변수에 저장하는 함수

scanf()를 쓸 때 scanf_s로 써야 한다. (safe 버전)

 

▷ 예시

#include <stdio.h>

int main()
{
    int k = 0;
    // 변수 k에 넣을 정수형 값 입력
    scanf_s("%d", &k);  // 정수형(%d)을 입력받아서 k에 저장한다.
    
    return 0;
}

scanf_s() 실행 결과 (입력 전)

콘솔 창이 입력한 내용을 받아와서 지정한 변수에 저장하는 것이 scanf()의 기능이다.

때문에 코드를 실행하면 콘솔 창이 입력을 기다린다.

 

콘솔 창에 50을 입력하고 엔터를 누르면 지정한 변수 k에 50이 저장된다.

콘솔 창에 50 입력

로컬 창 : k에 50이 들어가있음.

scanf_s()에서 변수의 주소로 접근한 이유

(scanf() 보다 좀 더 안전한 scanf_s()를 사용할 것이기 때문에 scanf_s()라고 표현하겠다.)

scanf_s() 콘솔 창에 입력한 데이터를 지정한 변수에 넣어주는 역할을 하는 함수이다.

다시 말해 콘솔 창으로부터 입력된 값을 전달해준 주소로 접근해서 넣어주는 함수이다.

#include <stdio.h>

void Test(int* a)
{
	*a = 500;  // a의 주소에 접근해서 값을 500으로 바꾼다.
}

int main()
{
	int a = 100;   
    Test(&a);  // a의 주소를 Test() 함수에 넣는다.
    
    printf("출력 : %d\n", a);  // 출력 : 500
    
    scanf_s("%d", &a);
    
    return 0;
}

scanf()_s가 변수 앞에 &를 붙여서 주소를 요구했던 이유도 이 때문이다.

값을 넣었을 때 a값이 500이 아닌 100이 나왔던 것처럼 변경된 값이 적용되지 않을 수도 있으므로 주소로 접근해서 확실하게 값을 넣어준다.

scanf_s()가 종료되면 그때 a값이 바뀐다.

scanf_s()에서 콘솔 창에 700을 입력하고 엔터를 누르면 a값이 700으로 변경된다.


이스케이프 시퀀스(escape sequence)

프로그램 결과가 화면에 출력될 때 사용할 특수한 문자를 위해 만들어졌다.

\' 작은 따옴표(')
\" 큰 따옴표(")
\? 물음표(?)
\\ 백슬래시(\)
\a 경고음 발생
\b 백 스페이스(backspace)
\n 줄 바꿈
\r 캐리지 리턴(carriage return)
\t 수평 탭(tab)
\v 수직 탭(tab)
\f 폼 피드(form feed)

형식 지정자

형식 지정자 자료형 의미
문자열
%c char 문자 하나
%s char*, char[ ] 문자열
정수
%hd
또는
%hi
short (부호 O) 10진 정수
%hu unsigned short (부호 X) 10진 정수
%ho unsigned short (부호 X) 8진 정수
%hx unsigned short (부호 X) 16진 정수 (소문자 표기)
%hX unsigned short (부호 X) 16진 정수 (대문자 표기)
%d int (부호 O) 10진 정수
%i int (부호 O) 10진 정수
%u unsigned int (부호 X) 10진 정수
%o unsigned int (부호 X) 8진 정수
%x unsigned int (부호 X) 16진 정수 (소문자 표기)
%X unsigned int (부호 X) 16진 정수 (대문자 표기)
%ld long (부호 O) 10진 정수
%li long (부호 O) 10진 정수
%lu unsigned long (부호 X) 10진 정수
%lo unsigned long (부호 X) 8진 정수
%lx unsigned long (부호 X) 16진 정수 (소문자 표기)
%lX unsigned long (부호 X) 16진 정수 (대문자 표기)
%lld long long (부호 O) 10진 정수
%lli long long (부호 O) 10진 정수
%llu unsigned long long (부호 X) 10진 정수
%llo unsigned long long (부호 X) 8진 정수
%llx unsigned long long (부호 X) 16진 정수 (소문자 표기)
%llX unsigned long long (부호 X) 16진 정수 (대문자 표기)
실수
%f float 실수 → 고정 소수점 표현 (10진수, 소문자 표기)
(소수점 아래 6자리까지)
%F float 실수 → 고정 소수점 표현 (10진수, 대문자 표기)
(소수점 아래 6자리까지)
%e float 실수 → 부동 소수점 표현 (10진수, e-표기법)
%E float 실수 → 부동 소수점 표현 (10진수, E-표기법)
%g float %f 또는 %e 중 짧은 것 사용 (소문자 표기)
%G float %F 또는 %E 중 짧은 것 사용 (대문자 표기)
%a float 실수 → 지수 표현 (16진수, 소문자 표기)
%A float 실수 → 지수 표현 (16진수, 대문자 표기)
%lf double 실수 → 소수점 표현 (10진수, 소문자 표기)
%le double 실수 → 지수 표현 (10진수, 소문자 표기)
#lE double 실수 → 지수 표현 (10진수, 대문자 표기)
%lg double %lf와 %le 둘 중 짧은 것 사용 (소문자 표기)
%lG double %lf와 %le 둘 중 짧은 것 사용 (대문자 표기)
%llf
또는
%Lf
long double 실수 → 소수점 표현 (10진수)
%Le long double 실수 → 지수 표현 (10진수, 소문자 표기)
%LE long double 실수 → 지수 표현 (10진수, 대문자 표기)
%La long double 실수 → 지수 표현 (16진수, 소문자 표기)
%LA long double 실수 → 지수 표현 (16진수, 대문자 표기)
포인터
%p - 포인터(pointer) 메모리 주소
% 기호
%% - 퍼센트(%) 기호 출력
플래그
%숫자 - • 숫자만큼의 폭을 출력
• 오른쪽 정렬(기본)
%.숫자 - • 온점(.) 뒤의 숫자만큼 소숫점 자릿수 조절
• 나머지는 반올림
%- - 왼쪽 정렬
%+ - • 음수일 때만 표현되던 부호 → 양수에서도 표현
• 양수일 경우 ➜ '+' 부호
%# - • 출력되는 숫자 앞 → 진법 표기
• 실수일 경우 ➜ 소수점을 강제로 붙임.
(%#o, %#x, %#X, %#f, %#F, %#e, %#E, %#g, %#G)
%0숫자 - • 숫자만큼의 폭을 지정
• 빈칸 ➜ 0으로 채움.

C++의 입출력 방식

헤더 파일

#include <iostream>

+) 디스어셈블리 - cin, cout

// _PURE_APPDOMAIN_GLOBAL extern _CRDATA2_IMPORT istream cin;
// _PURE_APPDOMAIN_GLOBAL extern _CRDATA2_IMPORT ostream cout;
	// extern 키워드가 붙은 이유 : iostream이라는 헤더 파일을 참조하면 모든 파일은 해당 변수를 알게 된다.

cin, cout 기본 형식

std::cin
std::cout

cout

• 데이터를 출력하는 데 사용되며, 출력 스트림을 나타내는 객체

• istream 클래스의 전역 변수명(객체명)

cout 문법

cout << 출력할데이터;

삽입 연산자(<<)는 출력할 데이터를 출력 스트림에 삽입하고, 출력 스트림에 삽입된 데이터는 스트림을 통해 출력 장치로 전달되어 출력된다.


cin

• 데이터를 입력받는 데 사용되며, 입력 스트림을 나타내는 객체

• cin 객체는 자동으로 사용자가 입력한 데이터를 변수의 타입과 동일하게 변환시켜 준다.

• ostream 클래스의 전역 변수명(객체명)

cin 문법

cin >> 입력데이터를저장할변수;

추출 연산자(>>)로 사용자가 입력한 데이터를 입력 스트림에서 추출하여 변수에 저장한다.

※ >> 방향 주의
변수에 데이터를 집어넣는 모습을 생각하면 쉽다.

 


C 표준 입출력(printf(), scanf()) vs C++ 표준 입출력(cin, cout)

특징 C 표준 입출력
printf(), scanf()
C++ 표준 입출력
cin, cout
라이브러리 C 표준 라이브러리
(stdio.h)
C++ 표준 라이브러리
(iostream)
형태 함수 객체
C 및 C++에서의
사용 가능 여부
C, C++에서 사용 가능 C에서는 사용 불가능하고, C++에서만 사용할 수 있다.
구문 형식 지정자 사용
(ex. %d, %f)
연산자 오버로딩 사용
(>>, <<)
입출력 스트림 표준 스트림(stdin, stdout)과 함께 작동한다. 입출력 스트림 객체(cin, cout, cerr 등)를 사용한다.
확장성 사전에 정의된 형식에만 제한된다. 연산자 오버로딩을 통한 사용자 정의 타입을 지원한다.
처리 속도 최소한의 오버헤드로 인해 일반적으로 더 빠르다. 추가적인 안전성과 기능으로 인해 printf(), scanf()에 비해 느리다.
컴파일러 검사 데이터의 자료형을 검파일러가 검사할 수 없어서 버그가 발생할 확률이 높다. 데이터의 자료형을 컴파일러가 검사한다.
오류 처리 오류를 확인하기 위해 반환값을 제공한다. 스트림 상태(cin.fail() 등)를 직접 확인할 수 있다.

printf(), scanf()는 형식화된 입출력에 효율적이지만 형식 지정자를 신중히 정해야 한다.

cin, cout은 속도는 느리지만 비교적 최근에 나와 안전성과 확장성 면에서 더 뛰어나다.

cin, cout 속도 향상 시키는 법

• 불필요한 flush가 호출되지 않게 endl보다 \n을 사용한다.

• flush
출력 스트림 맨 뒤에 줄 바꿈 문자를 추가하지 않고 출력 스트림 내부 버퍼에 있는 데이터를 모두 비우는 동작

• C 표준 입출력 방식 사용하기

• 버퍼 동기화 끊기

일종의 편법으로 아래 코드를 main()에 추가함으로써 버퍼 동기화를 끊고 tie를 풀어주면 된다.

• tie
서로의 I/O 작업 전에 버퍼를 자동으로 비운다.

단, 버퍼 동기화를 끊으면 cin, cout를 쓰면서 printf(), scanf()를 같이 쓸 수 없고, 이 방식이 통하지 않는 경우도 발생할 수 있기 때문에 추천하지는 않는다.

// main() 맨 윗줄에 추가하기
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);