Chapter 15. C++ 입출력 시스템
Chapter 15. C++ 입출력 시스템
‘명품 C++Programming - 황기태’ 11장 학습 내용
1절. 스트림
스트림(stream)
- 데이터의 흐름
- 데이터를 전송하는 소프트웨어 모듈
- 흐르는 시내와 유사한 개념
- 스트림의 양 끝에는 프로그램과 장치 연결
- 보낸 순서대로 데이터 전달
- 입출력 기본 단위 : 바이트(byte)
- 스트림 종류
- 입력 스트림
- 입력 장치, 네트워크, 파일로부터 데이터를 프로그램으로 전달하는 스트림
- 출력 스트림
- 프로그램에서 출력되는 데이터를 출력 장치, 네트워크, 파일로 전달하는 스트림
- 입력 스트림
C++ 입출력 스트림
C++ 입출력 스트림 버퍼
- C++ 입출력 스트림은 버퍼를 가짐
- 키 입력 스트림의 버퍼
- 목적
- 입력장치로부터 입력된 데이터를 프로그램으로 전달하기 전에 일시 저장
- 키 입력 도중 수정 가능
-
키가 입력되면 이전 입력된 키를 버퍼에서 지움
-
- 프로그램은 사용자의 키 입력이 끝난 시점에서 읽음
-
키 : 키 입력의 끝 -
키가 입력된 시점부터 키 입력 버퍼에서 프로그램이 읽기 시작
-
- 목적
- 스크린 출력 스트림 버퍼
- 목적
- 프로그램에서 출력된 데이터를 출력 장치로 보내기 전에 일시 저장
- 출력 장치를 반복적으로 사용하는 비효율성 개선
- 버퍼가 꽉 차거나 강제 출력 명령 시에 출력 장치에 출력
- 목적
키 입력 스트림과 버퍼의 역할
스크린 출력 스트림과 버퍼의 역할
C++ 표준 : 스트림 입출력만 지원
- 입출력 방식 2가지
- 스트림 입출력 방식(stream I/O)
- 슽트림 버퍼를 이용한 입출력 방식
- 입력된 키는 버퍼에 저장
-
키가 입력되면 프로그램이 버퍼에서 읽어가는 방식
-
- 출력되는 데이터는 일차적으로 스트림 버퍼에 저장
- 특정한 경우에만 버퍼가 출력 장치에 출력
- 버퍼가 꽉 찼을 경우
- ‘\n’을 만난 경우
- 강제 출력 명령의 경우
- 특정한 경우에만 버퍼가 출력 장치에 출력
- 저 수준 입출력 방식(raw lever console I/O)
- 키가 입력되는 즉시 프로그램에게 키 값 전달
-
키 그 자체도 프로그램에 바로 전달 - 게임 등 키 입력이 즉각적으로 필요한 곳에 사용
-
- 프로그램이 출력하는 즉시 출력 장치에 출력
- 컴파일러마다 다른 라이브러리나 API 지원
- C++ 프로그램의 호환성 낮음
- 키가 입력되는 즉시 프로그램에게 키 값 전달
- 스트림 입출력 방식(stream I/O)
- C++ 표준은 스트림 방식만 지원
- 스트림 입출력은 모든 표준 C++ 컴파일러에 의해 컴파일
- 높은 호환성
2003년 이전의 C++ 입출력 라이브러리 약점
- 대표적인 구 표준(C++03) 입출력 라이브러리 클래스
- ios, istream, ostream, iostream, ifstream, ofstream, fstream
- 문자를 한 바이트의 char로 처리
- cin » 로 문자를 읽을 때, 한글 문자 읽기 불가능
- 영어나 기호 : 1 바이트
- 한글 문자 : 2 바이트
- cin » 로 문자를 읽을 때, 한글 문자 읽기 불가능
char ch;
cin >> ch;
// 키보드로 문자 입력
// 한글 문자는 읽을 수 없음
- 현재도 cin은 한글을 문자 단위로 읽을 수 없음
새 표준 C++ 입출력 라이브러리
- 다양한 크기의 다국어 문자를 수용하기 위해 입출력 라이브러리를 템플릿으로 작성
typedef로 선언된 ios, istream, ostream, iostream 클래스
입출력 클래스 소개
2절. 스트림 객체
표준 입출력 스트림 객체
- C++ 프로그램이 실행될 때 자동으로 생겨나는 스트림
- cin
- istream 타입의 스트림 객체
- 키보드 장치와 연결
- cout
- ostream 타입의 스트림 객체
- 스크린 장치와 연결
- cerr
- ostream 타입의 스트림 객체
- 스크린 장치와 연결
- 오류 메시지를 출력할 목적
- 스트림 내부 버퍼 거치지 않고 출력
- clog
- ostream 타입의 스트림 객체
- 스크린 장치와 연결
- 오류 메시지를 출력할 목적
- 스트림 내부 버퍼 거치지 않고 출력
- cin
iostream에 선언된 스트림 객체
ostream 멤버 함수
ostream& put(char ch);
// ch의 문자를 스트림에 출력
ostream& write(char *str, int n)
// str 배열에 있는 n개의 문자를 스트림에 출력
ostream& flush()
// 현재 스트림 버퍼에 있는 내용 강제 출력
- 예제 1. ostream 멤버 함수를 이용한 문자 출력 예제
SourceCodeChecking
istream 멤버 함수 : 문자 입력, get() 함수
int get()
// 입력 스트림에서 문자를 읽어 리턴
// 오류나 EOF를 만나면 -1(EOF) 리턴
istream& get(char& ch)
// 입력 스트림에서 문자를 읽어 ch에 저장
// 현재 입력 스트림 객체(*this)의 참조 리턴
// 오류나 EOF를 만나면 스트림 내부의 오류 플래그(failbit) 세팅 - (16장 참고)
- int get()을 이용하여 한 라인의 문자들을 읽는 코드
int ch;
while((ch = cin/get()) != EOF{
// EOF = -1 : 입력 스트림의 끝인지 비교
cout.put(ch);
// 읽은 문자 출력
if(ch == '\n') break;
// <Enter> 키가 입력되면 읽기 중단
- istream& get(char& ch)을 이용하여 한 라인의 문자들을 읽는 코드
char ch;
while(true){
cin.get(ch);
// 입력된 키를 ch에 저장하여 리턴
if(cin.eof()) break;
// EOF를 만나면 읽기 종료 : 입력 스트림의 끝인지 비교
cout.put(ch);
// ch의 문자 출력
if(ch == '\n') break;
// <Enter> 키가 입력되면 읽기 중단
}
ch = cin.get()의 실행 사례
- 예제 2. get()과 get(char&)을 이용한 한 줄의 문자를 읽는 예제
SourceCodeChecking
문자열 입력
istream& get(char *s, int n);
// 입력 스트림으로부터 n-1개의 문자를 읽어 배열 s에 저장
// 마지막에 '\0' 문자 삽입
// 입력 도중 '\n'을 만나면 '\0'을 삽입하고 리턴
- 사용 예시
char str[10];
cin.get(str, 10);
// 최대 9개의 문자를 읽고 끝에 '\0'을 붙여 str 배열에 저장
cout << str;
// str을 화면에 출력
입력 도중
키('\n')을 만날 때 - 읽기를 중단하고 리턴
-
키('\n')를 스트림 버퍼에 남김 - 다시 get()으로 문자열 읽기를 시도하면 입력 스트림에 남은 ‘\n’키를 읽게 되어 무한 루프에 빠짐
- cin.get()이나 cin.ignore(1);를 통해 문자 1개(‘\n’)를 스트림에서 읽어야 함
예제 3. get(char*, int)을 이용한 문자열 입력 예제
SourceCodeChecking
한 줄 읽기
istream& get(char *s, int n, char delim = '\n');
// 입력 스트림으로부터 최대 n-1개의 문자를 읽어 배열 s에 저장
// 마지막에 '\0' 문자 삽입
// 입력 도중 delim에 지정된 구분 문자를 만나면 지금까지 읽은 문자를 배열 s에 저장하고 리턴
istream& getline(char *s, int n, char delim = '\n');
// get()과 동일하지만 delim에 저장된 구분 문자를 스트림에서 제거
- 예제 4. getline()으로 한 줄 단위 문장 읽는 예제
SourceCodeChecking
입력 문자 건너뛰기와 문자 개수 알아내기
istream& ignore(int n = 1, int delime = EOF);
// 입력 스트림에서 n개 문자 제거
// 도중 delim 문자를 만나면 delim 문자를 제거하고 리턴
int gcount();
// 최근 입력 스트림에서 읽은 바이트 수(문자의 개수) 리턴
// <Enter> 키도 개수에 포함
- 입력 스트림에서 문자 건너뛰기
cin.ignore(10);
// 입력 스트림에 입력된 문자 중 10개 제거
cin.ignore(10, ';');
// 입력 스트림에서 10개의 문자 제거
// 제거 도중 ';' 을 만나면 종료
- 최근에 읽은 문자 개수 리턴
char line[80];
cin.getline(line, 80);
int n = cin.gcount();
// 최근 실행한 getline() 함수에서 읽은 문자의 개수 리턴
3절. 포맷
포맷 입출력
- 입출력 시 포맷 지정 가능
- C언어의 printf()와 유사
- 포맷 입출력 방법 3가지
- 포맷 플래그
- 포맷 함수
- 조작자
포맷 플래그
- 입출력 스트림에서 입출력 형식을 지정하기 위한 플래그
ios 클래스에 정의된 포맷 플래그
포맷 플래그를 세팅하는 멤버 함수
long setf(long flags);
// flags를 스트림의 포맷 플래그로 설정하고 이전 플래그 리턴
long unsetf(long flags);
// flags에 설정된 비트 값에 따라 스트림의 포맷 플래그를 해체하고 이전 플래그 리턴
- 10진수를 16진수로 출력 예시
cout.unsetf(iost::dec);
// 10진수 해제
cout.setf(ios::hex);
// 16진수 설정
cout << 30 << endl;
// 1e 출력
- 사용 예시 2
cout.setf(ios::dec | ios::showpoint);
// 10진수 표현, 실수에 소숫점 이하 나머지는 0으로 출력 설정
cout << 23.5 << endl;
// 23.5000으로 출력
- 예제 5. setf(), unsetf() 사용한 포맷 출력 예제
SourceCodeChecking
포맷 함수 활용
int width(int minWidth);
// 출력되는 필드의 최소 너비를 minWidth로 설정
//- 이전에 설정된 너비 값 리턴
char fill(char cFill);
// 필드의 빈칸을 cFill 문자로 채우도록 지정하고 이전 문자 값 리턴
int precision(int np);
// 출력되는 수의 유효 숫자 자리 수를 np개로 설정
// 정수 부분과 소수점 이하의 수의 자리를 모두 포함하고 소수점(.) 제외
- 너비 설정 예제 1
cout.width(10);
// 다음에 출력되는 "hello"를 10칸으로 지정
cout << "hello" << endl;
// 빈칸 5 + hello 5문자 출력
cout.width(5);
// 다음에 출력되는 12를 5칸으로 지정
cout << 12 << endl;
// 빈칸 3 + 12 2문자 출력
// 출력 예시
// hello
// 12
- 너비 설정 예제 2
cout << '%';
cout.width(10);
// 다음에 출력되는 "Korea/"만 10칸으로 지정
cout << "Korea/" << "Seoul/" << "City" << endl;
// 출력 예시
// % Korea/Seoul/City
- 빈칸 채우기 예제
cout.fill('^');
cout.width(10);
cout << "Hello" << endl;
// 출력 예시
// ^^^^^Hello
- 유효 숫자 자리 수 예제
cout.precision(5);
cout << 11./3.;
// 출력 예시
// 3.6667
- 예제 5. width(), fill(), precision() 사용한 포맷 출력 예제
SourceCodeChecking
4절. 조작자
조작자
- manipulator
- 스트림 조작자(stream manipulator)
- 조작자는 함수
- C++ 표준 라이브러리에 구현된 조작자 : 입출력 포맷 지정 목적
- 개발자만의 조작자 작성 가능 : 다양한 목적
- 매개 변수 없는 조작자와 매개 변수를 가진 조작자로 구분
- 조작자는 항상 « 나 » 연산자와 함께 사용
조작자의 종류
- 매개 변수 없는 조작자
cout << hex << showbase << 30 << endl;
cout << dex << showpos << 100 << endl;
// 출력 예시
// 0x1e
// +100
- 매개 변수 있는 조작자
- #include
필요
- #include
cout << setw(10) << setfill('^') << "Hello" << endl;
// 출력 예시
// ^^^^^Hello
매개 변수 없는 조작자
매개 변수 있는 조작자
예제 7. 매개 변수 없는 조작자 사용 예제
SourceCodeChecking예제 8. 매개 변수 있는 조작자 사용 예제
SourceCodeChecking
조작자 실행 과정
사용자 정의 조작자 함수 원형
- 매개 변수 없는 조작자
istream& manipulatorFuncion(istream& ins);
// 입력 스트림에 사용되는 조작자 원형
ostream& maniupularFunction(ostream& outs);
// 출력 스트림에 사용되는 조작자 원형
예제 9. 사용자 정의 조작자 예제 1
SourceCodeChecking예제 10. 사용자 정의 조작자 예제 2
SourceCodeChecking
5절. 연산자
삽입 연산자(«)
- insertion operator
- 삽입자라고 불림
- « 연산자는 C++의 기본 연산자 : 정수 shift 연산자
- ostream 클래스에 중복 작성
class ostream: virtual public ios{
...
public:
ostream& operator << (int n);
// 정수를 출력하는 << 연산자
ostream& operator << (char c);
// 문자를 출력하는 << 연산자
ostream& operator << (const char* s);
// 문자열를 출력하는 << 연산자
...
};
삽입 연산자의 실행 과정
사용자 삽입 연산자 만들기
- 개발자가 작성한 클래스의 객체에 « 연산자 출력 예제
#include <iostream>
using namespace std;
class Point{
int x, y;
public:
Point(int x = 0, int y = 0){ this->x = x; this->y = y; }
friend ostream& operator <<(ostream& stream, Point a);
};
ostream& operator <<(ostream& stream, Point a){
stream << "(" << a.x << ", " << a.y << ")";
return stream;
}
int main(){
Point p(3, 4);
// Point 객체 생성
cout << p << endl;
// Point 객체 화면 출력
Point q(1, 100), r(2, 200);
// Point 객체 생성
cout << q << r << endl;
// Point 객체 화면 출력
}
// 출력 예시
// (3, 4)
// (1, 100)(2, 200)
cout « p;를 위한 « 연산자 만들기
- 예제 11. Book 클래스 예제
SourceCodeChecking
추출 연산자(»)
- extraction operator
연산자는 C++의 기본 연산자 : 정수 shift 연산자
- ostream 클래스에 중복 작성
class istream : virtual public ios{
...
public:
istream& operator >> (int& n);
// 정수를 입력하는 >> 연산자
istream& operator >> (char& c);
// 문자를 입력하는 >> 연산자
istream& operator >> (const char* s);
// 문자열를 입력하는 >> 연산자
...
};
- 추출 연산자의 실행 과정
- 삽입 연산자의 실행 과정과 유사
사용자 추출 연산자 만들기
- 개발자가 작성한 클래스의 객체에 » 연산자 입력
#include <iostream>
using namespace std;
class Point { // 한 점을 표현하는 클래스
int x, y; // private 멤버
public:
Point(int x = 0, int y = 0) { this->x = x; this->y = y; }
friend istream& operator >> (istream& ins, Point &a); // friend 선언
friend ostream& operator << (ostream& stream, Point a); // friend 선언
};
istream& operator >> (istream& ins, Point &a){ // >> 연산자 함수
cout << "x 좌표 >> ";
ins >> a.x;
cout << "y 좌표 >> ";
ins >> a.y;
return ins;
}
ostream& operator << (ostream& stream, Point a){
stream << "(" << a.x << ", " << a.y << ")";
return stream;
}
int main() {
Point p;
// Point 객체 생성
cin >> p; // >> 연산자 호출하여 x 좌표와 y 좌표를
cout << p; // << 연산자 호출하여 객체 p 출력
}
// 출력 예시
// x 좌표 >> 100
// y 좌표 >> 200
// (100,200)
// 첫 줄부터 cin >> p, cout << p 실행
cin » p;를 위한 » 연산자 만들기
This post is licensed under CC BY 4.0 by the author.

