음악, 삶, 개발

10. Input and Output Streams 본문

개발 공부/Principles And Practice Using C++

10. Input and Output Streams

Lee_____ 2020. 7. 19. 04:20

< C++ 의 input 과 outpt 을 이해하기위해, 먼저 알아야할것 >

 

stream buffer 이다.

다른 블로그들 의 설명들을 먼저 읽고 오도록 한다.

 

스트림과 버퍼

C++ 의 입출력

stream 이란 ?

stream 이란?

stream 에 대한 이해

스트림(Stream) 이란?

Stream

버퍼(위키피디아)

[개념정리] 버퍼(Buffer)란?

(Term)버퍼(Buffer)란?


< 목차 >

 

10.1 Input and output

10.2 The I/O stream model

10.3 Files

10.4 Opening a file

10.5 Reading and writing a file

10.6 I/O error handling

10.7 Reading a single value (생략)

10.7.1 Breaking the problem into manageable parts (생략)

10.7.2 Separating dialog from function (생략)

10.8 User-defined output operators

10.9 User-defined input operators (생략)

10.10 A standard input loop (생략)

10.11 Reading a structured file (생략)

10.11.1 In-memory representation (생략)

10.11.2 Reading structured values (생략)

10.11.3 Changing representations (생략)


10.1 Input and output

 

현대 os 시스템은 I/O device 의 handling 을 device driver 로 분리한다.

프로그램은 I/O library 를 통해 device driver 로 접근한다.

I/O library 는 다른 source 의 input 과 output 을 가능한한 비슷하게 만들어준다. 

device driver 는 사용자가 볼수없는 os 의 깊은 곳에 위치해있다.

따라서 프로그래머는 이런 device 나 device driver 에 대해 생각할 필요없이,

I/O library 가 제공하는 I/O 의 abstraction 을 사용하면 된다.

 

I/O Model

input 과 ouput 은 library 에 의해 handle 되는 byte (문자열) 의 stream 으로 볼수있다.

프로그래머로써의 우리가 해야할일은 아래와같다.

  1. 적절한 data source 와 목적지로 I/O stream 을 셋업하는것.
  2. 저 stream 들로부터(from/to)  읽고 (read) 쓰는것 (read)

우리의 문자열이 어떻게 device 로 , 혹은 device 로부터 송신되는지는 

I/O library 와 device driver 가 알아서 한다.

프로그래머의 관점에서, input 과 ouput 의 종류는 매우 많고 다양한데,

아래와 같이 분류한다.

  • 많은 data items 의 streams (to/from file, network connection, recording device, display device)
  • keyboard 를 통한 사용자와의 interaction
  • graphical interface (마우스 click 을 받는등) 를 통한 사용자와의 interfaction

10.2 The I/O stream model

 

  • istream : input 의 stream 들을 다루기위한 type
  • ostream : output 의 stream 들을 다루기휘한 type

우리가 자주 사용했던 cin 은 istream 에, cout 은 ostream 에 속해있다.

istream 과 ostream 이 하는 역할을 각각 배워보자.

 

ostream

  • 다양한 type 의 값을 문자 sequence 로 변환한다.
  • 이 문자들을 "어딘가"로 보낸다 (console, file, main memory, 다른 computer 등등으로..)

ostream 의 작동 시각화

buffer : 운영 체제(os)와 통신하는 동안 ostream이 사용자가 제공한 데이터를 저장하기 위해 내부적으로 사용하는 데이터 구조다.

istream

  • 문자 sequence 를 다양한 type 의 값으로 변환한다.
  • 이 문자들을 "어딘가"로부터 받는다. (console, file, main memory, 다른 computer 등등으로부터...)

istream 작동 시각화

istream 역시 buffer 를 운영체제와 상호작용하기위하여 사용하는데,

istream 에서의 buffering 이 더 사용자에게 잘 느껴진다.

예를 들어, keyboard 에 연결된 istream 을 사용할때,

사용자가 타이핑한것들은 enter 를 치기전까지 buffer 에 남겨져있다.

 

ostream 의 주요 사용 목적은, 인간이 읽을수있도록 data 를 생산하는것이다. (e-mail, 웹페이지, 연락처등등)

따라서, ostream 은 text 를 formatting 하는 다양한 기능들을 제공한다. (11.2 에서 자세히)

input 과 관련된 복잡성은 어떻게 error 에 대응하냐이다.

파일과 관련된 iostream mode 에 대해서 이야기해보자.


10.3 Files

 

file 은 0 부터 위로 번호가 매겨진 bytes 의 sequence 이다.

각 파일은 규격이 있으며, bytes 가 의미하는것이 무언지를 결정한다.

예를 들어, .txt 파일은, 첫번째 4 bytes 가 첫번째 4개의 문자이다.

파일을 위해서, ostream 은 아래와 같은 일을 한다.

  1. memory 에 있는 객체를 bytes 의 stream 들로 변환한다.
  2. 이 stream 들을 disk 에 write 한다

istream 은 반대이다.

  1. disk 로부터 bytes 의 strea들을 받는다.
  2. 이 stream 들로부터 객체를 생성한다.

iostream between disk and memory


10.4 Opening a file

 

파일을 읽거나, 쓰기위해서는 파일을 위한 stream 을 열어야한다.

  • ifstream : 파일을 읽는 (read)  istream 
  • ofstream : 파일을 쓰는 (write) ofstream
  • fstream : read, write 둘다 가능한 iostream

파일 stream 은, 사용되기전에 먼저 file 에 attach 되어야한다.

예를 보자.

std::cout << "Please enter input file name: ";
string iName;
std::cin >> iName;
std::ifstream ist {iName}; // ist is an input stream for the file named name
if(!ist) error ("can't open input file ", iName);

string name 으로 정의된 ifstream 은 그 name 의 파일을 읽기위해(to read) open 한다.

!ist 는 파일을 잘 열렸는지 check 한다.

위와 같이 한 후에, 우리는 비로써 파일을 read 할수있다.

(일단 open 후에 read임, open 이 read 가 아님)

 

파일을 쓰기위해(to read) open 하는 것은 ofstream 을 사용한다.

std::cout << "Please enter name of output file : ";
string oName;
std::cin >> oName;
ofstream ost { oName }; // ost is an ouput stream for a file named oName
if (!ost) error ("can't open output file ", oName);

 

파일 stream이 코드의 scope { } 를 벗어나는 순간, 파일은 닫힌다 (closed).

파일이 닫히는 순간, buffer속 문자는 file 로 write 되고, buffer 는 비워진다 (flushed)

프로그램상에서, 파일은 다른 계산들이 시작되기전에 빨리 open 되는것이 best practice 다.

파일을, ostream 이나 istream 을 초기화 함으로써 열고, 

scope { } 를 통해 파일을 받는것이 이상적이다.

 

void fillFromFile(vector<Point>& points, string& name) {
	
	ifstream ist {name};
    
    if(!ist) error ("can't open input file ", name);

	// 파일은 암시적으로 이 함수가 끝났을때 닫힌다.

}

 

파일 stream 의 메소드로 open(), close() 가 있긴하지만,

scope 에 의지하여 파일을 닫는것이 가장 좋은 방법이다.

파일에 stream 이 attach 되기전에 누군가가 사용하려할수도있기때문이다.

파일 stream 객체의 초기화, scope 를 통해 open 하고 close 하도록 하자.

 

파일은 debugging 을 하기위해 아주 좋은 도구이기도하다.


10.5 Reading and writing a file

 

시간과, 온도를 나타낸 파일이 있다고 가정해보자.

0 60.7
1 60.6
2 60.3
3 59.22
...

이 파일을 읽고, 고대로 다른 파일로 만드는 코드를 작서해보자.

 

#include <iostream>

struct Reading {
	
	int hour;
    double temperature;

}

int main() {

	std::cout << "Please enter input file name: "; 
	std::string inputFileName;
    std::cin >> inputFileName;
    std::ifstream inputFileStream { inputFileName }; 
    if(!inputFileStream) { error("can't open input file ", inputFileName) };
    
    std::string outputFileName;
    std::cout << "Please enter name of output file: ";
    std::cin >> outputFileName;
	std::ofstream outputFileStream { outputFileName }; 
    if (!outputFileStream){ error ("can't open ouput file ", outputFileName);
    
    // read 한 data 를 저장하기.
    vector<Reading> temps; 
    
    int hour;
    double temperature;
    
    while (inputFileStream >> hour >> temperature) {
    	
        if (hour < 0 || 23 < hour) error ("hour out of range");
        temps.push_back(Reading{hour, temperature});
    	
    }

	for (int i = 0; i < temps.size(); ++i) {
    	
        outputFileStream << '(' << temps[i].hour << ',' << temps[i].temperature <<std::endl;
    
    }

}

10.6 I/O error handling

 

istream 의 error 를 확인할때 Stream state 라는 4가지 경우로 나눌수있다.

  • good() : 연산이 성공했다.
  • eof() : end of file 에서, end 를 hit 했다.
  • fail() : 예상못한 무언가가 일어났다. 
  • bad() : 예상못한 심각한 무언가가 일어났다. ex) disk 읽기 error

fail() 과 bad() 의 경계는 모호하다.

아래를 통해 구분할수있다.

  • input 연산이 우리가 해결할수있는 단순한 format error 를 만난 경우 : fail()
  • 위와 달리, bad disk 를 읽을려고했다던가 했다면  : bad()
  • bad() 는 또한 fail() 이다.

예를 보자.

int i = 0;
std::cin >> i;

// input 연산이 fail 했을경우
if(!std::cin) {

    if (std::cin.bad())  { error("cin is bad"); }
    if (std::cin.efo()) { }
    if (std::cin.fail()) { std::cin.clear(); } 		
    
}

10.7 Reading a single value 

10.7.1 Breaking the problem into manageable parts

10.7.2 Separating dialog from function

 

너무 지루한 부분이라, 생략. 추후 

내 마음이 괜찮아졌을때 읽고 요약할것... (247p ~ 251p)


10.8 User-defined output operators

 

bullt-in type 이 아닌, 사용자 정의 type (class, struct) 을 위해

<< operator 를 정의해주는것이 best practice 이다.

바로 debugging 을 위해서이다.

아래와 같이 정의하고 사용할수있다.

 

내가 직접 작성한 코드

Juce 에서 DBG 가 있긴하지만,

나만의 class 를 위해 customized 된 형태로 console 에 출력할수있어서, 매우 중요한 기능같다.

Peter 말에 의하면, 이 기능은 매우 유용한 기능이고,

ostream 은 text formatting 을 해주는 다양한 함수들을 제공한다고 하니 추후 공부해보자.


10.9 User-defined input operators

10.10 A standard input loop

10.11 Reading a structured file

10.11.1 In-memory representation

10.11.2 Reading structured values

10.11.3 Changing representations

 

일단 생략.


Review

 

  1. When dealing with input and ouput, how is the variety of devices dealt with in most modern computers?
  2. What, fundamentally, does an istream do?
  3. What, fundamentally, does an ostream do?
  4. What, fundamentally, is a file?
  5. What is a file format?
  6. Name four different types of devices that can require I/O for a program.
  7. What are the four steps for reading a file?
  8. What are the four steps for writing a file?
  9. Name and define the four stream states.
  10. 생략
  11. In what way is input usally harder than ouput?
  12. In what way is ouput usually harder than input?
  13. Why do we often want to separate input and ouput from computation?
  14. What are the two most common uses of the istream member function clear()?
  15. What are the usual function declarations for << and >> for a user-defined type X?

Terms

 

  • bad()
  • buffer
  • clear()
  • close()
  • device driver
  • eof()
  • fail()
  • file
  • good()
  • ifstream
  • input device
  • input operator
  • iostream
  • istream
  • ofstream
  • open()
  • ostream
  • output device
  • output operator
  • stream state
  • structured file
  • terminator
  • unget()

소감

 

이 chapter 는 개인적으로 너무 재미가 없었다...

절반 가까이 안읽고 생략했음에도..

2틀이나 시간이 걸렸다..

너무 재미없거나, 이해 안되거나, 내가 안쓸거같다거나(지금 알수없지만)

하는 내용들은 미래를 위해 일단 생략했다..

언젠가는 분명히 알아야할 내용일것이다..

그때 돌아와서 하면 된다..