13. C++ Library 1편 : IO Classes가 궁금해

2021. 12. 1. 01:39c++/기초

1.The IO Classes

 

IO Class를 잘 알려면 우선 stream을 알아야 한다.

stream은 여러 프로그램과 Input/ output 장치들이 서로 문자들을 주고 받을 때 사용된다.

즉 키보드나 마우스, 모니터의 입력이 stream에 입력이 되고 프로그램에 나타나는 것이다.

이 stream을 작업하기 위해선 라이브러리를 가져와야 한다.

 

<iostream>은 객체 지향 라이브러리로 스트림을 이용해 입출력 기능을 제공한다.

<fstream>파일을 읽어들이거나 쓸 수 있는 기능을 제공한다.

<sstream>스트림에 들어있는 문자열 객체들에 대한 입출력 기능을 제공한다.

 

위 IO 타입의 관계는 상속을 사용해서 다른 종류의 stream의 차이를 무시하고 사용할 수 있다.

이것이 iosteream 라이브러리.

 

IO type의 객체는 복사하거나 값을 할당할 수 없다. 그래서 함수의 parameter나 return으로 사용할수도 없음.

IO library는 iostate라는 이름을 가진 기계에 종속된 타입을 정의할 수 있다.

bit들로 stream의 상태를 표현함.

batbit, failbit,eofbit 라면 stream은 fail이 될 것이라고 평가됨.

아래 함수들로 stream의 state를 정의한다.

 

 

Managing the Condition State

위 이미지는 전 state를 유지하며 유효한 cin을 사용하는 예이다. 어디에 사용하는겨;

위 이미지는 failbit 과 badbit일 경우  cin을 끄는 것. (eofbit일 경우 제외)

 

Managing the Output Buffer

 

각 프로그램을 읽고 쓴 데이터를 담고 있는 버퍼로 output 스트림은 작동된다.

운영체제는 데이터를 버퍼안에 저장한 이후에 그것에 대해 출력 명령을 함. .

때문에 자주 출력 명령을 하면 시간이 많이 소비된다.

 

버퍼를 아웃풋 장치에 flush되게 하는 조건이 있다. (flush는 버퍼에 담긴 데이터가 쏟아지는 것)

1. 모든 아웃풋 버퍼는 main이 return 되고 flush되기 때문에 일반적으로 프로그램이 완료됬을 때.

2. 버퍼가 가득차게 된다면 다음 값이 출력되기 전에 flush됨.

3.  endl 같은 조정자(manipulator)를 통해 버퍼를 flush할 수 있다.

4. 각 출력 명령이 실행된 후에 버퍼를 비우기 위해 스트림 내부를 설정하기 위해 unitbuf 조정자를 사용할 수 있다.

- cerr을 통해 unitbuf를 설정할 수 있다. cerr로 출력을 하면 즉시 flush가 된다.

5. 출력 스트림이 다른 스트림과 연결된다면 출력 스트림은 입출력이 실행될 때 마다 flush된다.

- 기본적으로 cin과 cerr은 cout과 묶여 있다. 이 경우에 cin으로 입력을 받거나 cerr을 출력하면 cout의 버퍼가 flush가 된다.

 

Output Buffer를 flush하기

endl 조정자를 사용 - 최근 line을 끝내면 버퍼를 flush한다.

flush 조정자를 사용 - 스트림을 flush한다. 그러나 출력에 어떤 character도 추가하지 않는다.

ends 조정자를 사용 - 버퍼에 null을 추가하고 이를 flush 한다.

 

 unitbuf 조정자

너가 모든 출력후에 flush하고 싶다면, unitbuf 조정자를 사용해라.

- 그러면 스트림은 매 출력마다 flush가 된다.

- nounitbu 조정자는 저장한다. 버퍼 flushing을 사용하는 스트림을 저장한다.

입출력 스트림이 서로 함께 묶기

입력 스트림이 출력 스트림과 묶였을 때 입력 스트림의 입력을 하는 시도보다 출력 스트림과 연관된 buffer가 먼저 flush된다. 

library는 cout과 cin을 tie 합니다. 시발 먼소리지

위는 cout의 버퍼가 flush가 되는 원인이다.

그래서 우리는 모든 출력이 끝난 후에 무언가를 입력받기를 요청할 수 있다.

 

오버로드(overload)된 tie의 두가지 버젼

1. first 버젼

argument를 가지지 않음. 이 객체와 최근에 묶인 출력 스트림의 포인터를 리턴한다.

2. second 버젼 (cin과 cout을 untie 하기 위해)

ostream의 포인터를 argument를 가진다. 그리고 그 ostream을 tie한다.

그 stream을 untie하기 위해 null pointer를 넣어준다.

 

2. file input/ouput

fstream은 파일 입출력을 지원하는 세 가지 타입으로 정의 되어야 한다.

 

1. ifstream은 파일을 읽어온다. (read)

2. ofstream은 파일을 작성한다. (write)

3. fstream은 파일을 읽거나 작성한다.

 

이들은 iostream을 상속한다. 이들은 파일과 관련된 스트림을 처리하는 멤버를 가지고 있다.

파일을 읽고 써보자 (파일 스트림 객체 사용법)

1. 파일 스트림 객체를 정의 해라.

2. 객체와 파일을 연결해라.

 

각 파일 스트림 클래스는 open이라는 함수를 멤버로 가진다.

open 함수는 파일을 불러와 읽거나 작성한다.

너가 파일 스트림을 만들었다면 선택적으로 파일 이름을 argument로 줄 수 있다. 그러면 자동으로 open이 실행됨

파일 이름은 C 양식의 char 배열.

그러나 C++ 11 은 파일 이름으로 string을 사용하는 것을 허락한다.

 

iostream& 대신 fstream을 사용하자.

원래 사용되어야 하는 타입의 객체가 있어야 하는 곳에 상속된 유형의 객체의 타입을 사용할 수 있다.

iostream의 레퍼런스나 포인터가 사용되어야 하는 함수에 fstream(sstream)을 사용할 수 있다.

위는 read 함수에 fstream 객체를 넣어주는 모습.

 

open과 close 함수의 사용

빈 파일 스트림과 open으로 불러온 파일을 연결할 수 있다.

파일을 불러오는 것에 실패할 경우 failbit이 설정된다.

open이 성공적이라면 open은 스트림의 상태를 good()으로 true로 세팅한다.

 

파일 스트림과 다른 파일이 연결될 경우 반드시 먼저 존재하는 파일을 닫고 새로운 것을 open해야한다.

fstream 객체가 범위를 벗어나면 자동으로 close가 된다. 그래서 그 객체는 destroy된다.

 

file modes

파일을 열 때 다양한 모드를 제공할 수 있다.

Out : 오직 ofstream과 fstream객체에서 사용 가능

In : ifstream과 fstream 객체에서 사용 가능

trunc : 오직 out으로 지정된 경우에만 사용 가능

app : app으로 지정되면 항상 파일은 output 모드로 열린다. out으로 지정되지 않더라도!

ate, binary : 임의의 파일 스트림을 다른 파일 모드들과 결합하여 사용할 수 있다.

out 모드로 파일을 열게 되면 기존에 존재하는 데이터는 삭제된다.

기본적으로 out 모드로 열면 기존의 파일을 버려지지만 trunc 모드로 지정하지 않는다면!!

out 모드로 열게 된 파일을 보존하기 위해서는 반드시 app 모드로 지정해야 한다. (오직 파일 끝까지 파일을 write할 수 있다.)

ofstream으로 연다면 out mode가 기본모드이다.

파일의 모드는 open함수를 부를 때 결정 된다.

3. string Streams

sstream은 인메모리 방식의 입출력을 지원하는 세가지 타입으로 정의 된다.

이러한 타입은 IO 스트림의 string처럼 string 타입으로 읽히거나 작성된다.istringstream, ostringstream, stringstreamfstream 처럼 이 타입들 또한 iostream의 헤더가 사용된다.string을 처리하기 위한 멤버가 존재.

istringstream은 우리가 전체 문장이나 문장 속 각 단어들을 처리할 때 자주 사용된다.

예를 들어서 한 사람이 여러 번호를 가지고 있을 경우

위 클래스를 정의 하면 해결할 수 있다.

이렇게 전화번호부를 쉽게 만들 수 있다!

 

ostringstream은 한번에 출력을 조금씩 생성하고 나중에 출력을 원하지 않을 때 유용하다 . ??

위의 예시를 다시 가져와서 우리가 저 다시 파일들을 읽고 이름과 번호 데이터를 평가하고 reformat하기를 원한다.

모든 번호가 유효하다면 리포맷된 번호를 포함한 새로운 파일을 작성하기를 원함.

만일 유효하지 않은 번호가 있다면 새로운 파일에 담지 않고 그 사람의 이름과 유효하지 않은 번호의 리스트를 포함한 에러메시지를 출력한다.

아 씹 어려워

반응형