프로그래밍 이야기

A Tour of C++ : 10장 입력과 출력

원생계 2019. 11. 23. 21:51

.

10. 입력과 출력

10.1 소개

입출력 스트림 (I/O Stream)

텍스트와 수치 값에 대한 Formatted / Unformatted Buffered I/O 지원.

ostream / istream 타입 있는 값(‘c’, 123, (123,45)과 바이트 시퀀스 사이를 스트림 버퍼를 통해 변환.

타입 민감성 보장, 사용자 정의 타입에 맞게 확장 가능.

이러한 스트림 이용 std::string 의 입출력과 string 버퍼를 이용한 형식화, 파일 입출력 가능.

모든 입출력 스트림 클래스는 소유 자원(버퍼, 파일핸들 등)을 해제하는 소멸자를 포함. ‘자원 획득이 곧 초기화’(RAII)의 한 예.

10.2 출력

<ostream> 에서 모든 내장 타입 출력 연산 정의. << 연산자는 ostream타입의 객체 출력 연산자. cout 은 표준 출력 스트림, cerr 은 에러 보고 표준 스트림. cout 출력값은 기본적으로 문자 시퀀스.

cout << ‘Value of i=” << i << ‘\n’;

10.3 입력

<istream>

>> 연산은 입력 연산자, cin 은 표준 입력 스트림, >> 의 오른쪽 항은 어떤 입력이 허용되고 대상이 무엇인지 결정.

int i;

cin >> i; // 정수를 i에 읽음.

int i;

double d;

cin >> i >> d; // i와 d에 읽기

띄어쓰기와 개행 문자를 비롯한 공백 문자는 읽기를 종료시킴.

한 행 전체를 읽으려면 getline() 함수.

10.4 입출력 상태

iostream 연산의 성공 여부를 알 수 있는 상태.

vector<int> read_ints(istream& is)

{

vector<int> res;

for (int i; is>>i; )

res.push_back(i);

return res;

}

is>>i 연산이 true를 반환하는지 검사.

vector<int> read_ints(istream& is, const string& terminator)

{

vector<int> res;

for (int i; is >> i; )

res.push_back(i);

if (is.eof()) // 파일의 끝. 정상 종료.

return res;

if (is.fail()) { // 실패.

is.clear(); // 상태를 good()으로 리셋

is.unget(); // 숫자가 아닌 무언가를 스트림으로 되돌림.

string s;

if (cin>>s && s == terminstor)

return res;

cin.setstate(ios_base::failbit); // cin 상태에 fail() 추가.

}

return res;

}

auto v = read_ints(cin, “stop”);

10.5 사용자 정의 타입의 입출력

struct Entry {

string name;

int number;

}

ostream& operator<<(ostream& os, const Entry& e)

{

return cout << “{\”” << e.name << “\”, “ << e.number << “}”;

}

입력 연산자는 형식체크와 에러처리 따로 해야해서 더 복잡.

istream& operator>>(...)

{

// { 로 시작

// 문자를 모두 name 으로 저장

// {로 닫고, number 읽기.

// 첫 문자가 {가 아닌 경우 ios_base::failbit 를 기록하고(is.setstate(ios_base::failbit) ) return is;

10.6 형식화

iostream 입력과 출력의 형식을 제어하는 데 필요한 다양한 연산 제공. 조정자(manipulator). ios, istrea, ostream, iomanip 에서 찾을 수 있음.

ex)

cout << 1234 << ‘,’ << hex << 1234 << ‘,’ << oct << 1234 << ‘\n’; // 1234, 4d2, 2322 출력

cout << d << “; “ // 기본 형식 입력/저장

<< scientific << d << “; “ // 1.123e2 스타일

<< hexfloat << d << “; “ // 16진수

<< fixed << d << “; “ // 123.456 스타일

<< defaultfloat << d << ‘\n’; // 기본 형식

cout.precision( n ) 으로 전체 숫사 자릿수+소수점 자릿수를 설정.

10.7 파일 스트림

<fstream> ifstream(읽기), ofstream(쓰기), fstream(읽기/쓰기)

ofstream ofs {“target”};

if (!ofs)

error(“‘target’을 쓰기용으로 열 수 없음“);

ifstream ifs {“source’};

if (!ifs)

error(“‘source’를 읽기용으로 열 수 없음.”);

10.8 문자열 스트림

<sstream> 은 string 읽고 쓰기 스트림.

istringstream(읽기), ostringstream(쓰기), stringstream(읽고/쓰기)

void test()

{

ostringstream oss;

oss << “{temperature,” << scientific << 123.4567890 << “}”;

cout << oss.str() << ‘\n’;

}

istringstream 에서 읽어들인 결과는 str()로 확인.

10.9 C 스타일 입출력

표준 라이브러리 printf(), scanf(). 타입과 보안 측면에서 안전하지 않아 비추천. C스타일 입출력 사용하지 않는 상황에서 입출력 성능을 고려해야 한다면

ios_base::sync_with_stdio(false); // 큰 오버헤드 피할 수 있음

호출하지 않으면 C스타일 입출력 호환성 유지를 위해 iostream 이 매우 느려질 수 있음.

10.10 파일 시스템

파일 시스템 라이브러리, 일관된 인터페이스 제공 <filesystem>

- 파일 시스템 경로 표현과 파일 시스템 탐색

- 파일 타입과 권한 확인

유니코드도 지원. (자세한 정보= cppreference, 부스트 파일 시스템 문서 참고)

path f = “dir/hypotherical.cpp”;

assert( exists(f) );

if (is_regular_file(f))

cout << f << “ 는 파일. 크기는 “ << file_size(f) << ‘\n’;

path 클래스 = 다양한 운영체제 기본 문자 집합과 관례를 처리하는 복잡 클래스. 특히, main() 의 파일 이름 처리 가능.

int main( int argc, char* argv[] )

{

...

path p {argv[1]}; // 커맨드라인으로부터 path 생성

cout << p << “ “ << exists(p) << ‘\n’; .// path 는 문자열로 출력 가능.

}

void use(path p)

{

ofstream f {p};

if (!p) error(“잘못된 파일 이름: “, p);

}

파일 시스템 타입(일부)

path 디렉터리 경로

filesystem_error 파일 시스템 예외

directory_entry 디렉터리 항목

directory_iterator 디렉터리 순회

recursive_directory_iterator 디렉터리와 그 하위 디렉터리 순회

void print_directory(path p)

try {

if ( is_directory(p) ) {

cout << p << “:\n”;

for ( const directory_entry& x : directory_iterator{p} )

cout << “ “ << x.path() << ‘\n’;

}

}

catch ( const filesystem_error& ex ) {

cerr << ex.what() << ‘\n’;

}

void use()

{

print_directory(“.”); // 현재 디렉터리

print_directory(“..”); // 부모 디렉터리

print_directory(“/”); // 유닉스 루트 디렉터리

print_directory(“c:”); // 윈도우 볼륨 C

for ( string s; cin >> s; )

print_directory(s);

}

하위 디렉터리 나열 recursive_directory_iterator{p}

경로 연산(일부) (p, p2는 path)

value_type 파일 시스템의 기본 인코딩에 사용하는 문자 타입

string_type std::basic_string<value_type>

const_iterator path의 value_type에 대한 const 양방향 반복자.

iterator const_iterator의 별칭.

p=p2 p2를 p에 대입

p/=p2

p+=p2

p.native()

p.string()

p.generic_string()

p.filename() p의 파일 이름 부분.

p.stem() p의 꼬리(stem) 부분.

p.extension() p의 파일 확장자(.을 제외한 확장자)

p.begin()

p.end()

p==p2, p!=p2

p<p2, p<=p2, p>p2, p>=p2

is>>p, os<<p p에 스트림 입출력

u8path(s) UTF-8 인코딩된 s로부터 path 생성

파일 시스템 연산(일부)(p, p1, p2는 path)

exists(p)

copy(p1,p2)

copy(p1,p2,e)

b=copy_file(p1,p2)

b=create_directory(p)

b=create_directories(p)

p=current_path() // p에 현재 작업 디렉터리 대입

current_path(p) // p에 현재 작업 디렉터리 대입

s=file_size(p) // p의 포함 바이트 수

b=remove(p)

지정된 연산이 실패하면 함수는 filesystem_error 예외 던짐.

error_code 를 추가 인자로 받는 버전 exists(p,e)

질의함수(inquiry function) f는 path나 file_status

is_block_file(f) f가 블록 디바이스인가?

is_character_file(f) 문자 디바이스?

is_directory(f) 디렉터리?

is_empty(f) 빈 파일or빈 디렉터리?

is_fifo(f) 명명된 파이프(named pipe)인가?

is_other(f) 알 수 없는 종류의 파일인가?

is_regular_file(f)

is_socket(f) IPC 소켓인가?

is_symlink(f) 심볼릭 링크(symbolic link)인가?

status_known(f)

10.11 조언

[1] iostream 은 타입 안전성과 타입 민감성, 확장성을 제공\

[4] endl 을 피하라.

[6] 일반적 출력은 cout 을, 에러는 cerr 를.

[10,11] << 와 >> 는 연쇄적으로 사용하라.

.

.

.

728x90
반응형