Ch17 stream
표준입출력(standard input output)
CLI 에서 보통 쓰는게 표준 입출력. stdio 인 이유가 standard input output 임.
알고리즘 문제 풀 때 가끔 표준출력으로 제출하시오 이렇게 나옴.
C/C++ 은 표준입출력이 언어에 내장 안됨
많은 언어들이 내부에 입출력 기능을 언어 자체에 내장하고 있으나 c, c++ 은 없음.
그래서 우리는 <stdio.h> 같은걸 Include 하는 것.
이는 컴파일러 설계자가 입출력 함수를 하드웨어에 가장 적합하게 설계할 수 있게하기 위해서임.
C 에서
우리가 자주 쓰는 <stdio.h> 같이 Unix 환경에서 개발된 몇몇라이브러리는 __ANSI C__에서 표준 입출력(standard input output) 패키지로 구성해놔서 간단히 가져다 쓸 수 있음.
C++에서
<iostream> 이 ANSI/ISO C++ 에서 STL(Standard Template Libray) 이랑 같이 C++ Standard Libary(std namespace 에 있음) 로 들어감.
Stream
어떤 장치/프로그램에서 입출력을 해도 C++ 이 같은 방법으로 처리할 수 있게 하는 매개체
이때 보통 임시 저장용 버퍼를 만들어서 장치 간 정보전송률 차이를 줄임
- 예를들어 CPU 는 명령어당 처리할 수 있는 단위가 작지만 데이터 이동속도가 빠름
- 근데 HDD 는 느리니까 한번에 여러바이트를 RAM 에 보냄
스트림 = 버퍼 + 추가기능 대충 이렇게 보면 됨
C++ 의 스트림
stl 에서 stream 은 cout, cin, ofstream, ifstream sstream 등이 있고 아래에서 살짝 다룰 것임.
지금 주목할 것은 이런 stream 은 모두 ios_base 를 부모로 둔 <iostream> 에 있는 쓰는 ostream(out), istream(in) 중 하나를 상속 받는 다는 것
-
C++ 에서 stl 에 cout, iostream 같은 stream 을 만들어 줬고
-
애네들은 ostream, istream 를 상속 받으며
-
얘내로 만든 stream 객체가 안에 소숫점 아래 자리수, 10진법이냐 16진법이냐, 입력이 제대로 되었냐 같은 정보를 담아서 입출력 데이터를 제어하게 됨.(사용해봤을거임) => 기능
-
그리고 그 안에서 streambuf 객체를 사용함. => 버퍼
즉 앞에서 말한 Buffer 와 추가기능 이 C++ STL 의 Stream 에서 이렇게 적용이 되는 거임.
참고
<iostream> 에서 표준입출력 장치 와 연결을 보여주는 부분. (뭔 장치인지는 변수명곧내)
cin, cout 이런 애들이 ios_base(왜냐면 i,o,stream 이니까) 을 왜 상속받는지 보여줌
참고로 wchar_t 버전도 그 밑에줄에 있음
밑에서 4번째 줄을 보면 알 수 있 듯 이러한 스트림은 streambuf 객체를 이용함.
istream 도 찾아보면 비슷하게 나옴.
참고. stdio
를 이용해서 buffer 와 표준입출력(저기선 stdin) 을 직접 연결하면 위와같은 코드가 됨.(PS 풀 때 대용량 인풋에서 종종 괜찮음)
Redirection
표준입력과 표준출력이 대부분의 OS 에서 키보드와 화면임
이러한 표준입출력을 다른쪽으로 옮겨주는게 리디렉션
cmd<Test.txt
길이는 7
cmd>String2Count <Test.txt >Ans.txt
Window CMD 에선 <
랑 >
으로 Redirection 을 함.
Redirection 명령인 <Test.txt
으로 Test.txt 의 텍스트(위에선 “abcdefg” 넣음) 를 String2Cout.cpp 의 cin 으로 넣게 됨. 그럼 cout 에 버퍼엔 “길이는 7” 이 들어갈 거임.
표준출력을 Redirection 을 안하면 cout 이 그대로 CLI(커맨드 그거) 에 출력함
>Ans.txt
로 Redirection 을 하면 cout 이 Ans.txt 로 가서 “길이는 7” 이라고 적음
이걸 내가 쓸 일이 있을까? 쓰는 예
cout, cin (표준입출력)
연산자 Overloading
기본적인 자료형은 위처럼 ostream, istream 내부에서 Overloading 되어 있음.
type 이 char* 같은거면 끝에 Null 문자 넣어야 정상작동하고 입력인 경우 알아서 결과값에 넣어줌.
이건 우리가 커스터마이즈 할 때 하는거.
함수의 리턴값 덕분에 cout << "1" << "b"
이렇게 연달아서 가능하단건 다들 알거임
cout (표준 출력)
cout 은 코테용으로도 알아두면 좋은게 있음.
cout 의 버퍼는 일반적으로 512 byte 나 그 배수임.
그리고 std::endl
은 출력과 동시에 버퍼를 비움(flush).
그래서 버퍼가 꽉차기를 기다리지 않고 바로 출력을 원하면 std::endl
이 좋은데 코테에서 속도를 중시해서 cout << asdf << '\n'
이런식으로 많이 씀
아님 printf 쓰던가 힘.
Ios_base::boolapha
같이 cout.setf()
로 출력형식 설정할 때 쓰는 위와 같은 애들은 비트마스크로 저장되어서 각 비트가 켜져있으면 그에 맞는 처리를 해줌
근데 저런거 하나하나 다 못외우므로 __Manipulators(조정자) __ 라고 매크로도 만들어놓음. 예를들어
cout << cout.setf(ios::boolalpha);
=> cout << boolalpha;
이렇게.
특이점은 얘는 <<
이거로 처리함.
cin (표준 입력)
- cin 은
>>
이 연산자를 쓰면 whitespace(‘ ‘, ‘\n’, ‘\t’) 을 다 무시함. - ‘\n’ 나올 때 까지 버퍼에 값을 넣으며 대기하고 ‘\n’ 이 나오면 다음 명령을 실행함.
clear()
는 버퍼를 비우는게 아니고 eofbit, badbit, failbit 같이 입력이 오류없이 제대로 들어왔는지 파악하는 상태( 스트림 비트상태 )를 초기화 (잘못된 입력으로부터 복구하는 용)- 이러한 스트림 비트상태가 하나라도 on 이면 stream 이 닫히고 이후의 cin 을 호출해도 아무일도 안함.
- 스트림 비트상태를 on 시킨 데이터는 그대로 버퍼에 남아있음.
- 버퍼 비우려면 어디 빈곳에 while 문 돌리면서 출력함.
- 잘못된 입력에 대해 try-catch 문이 가능하도록 exception 을 발생하도록 설정할 수 있음
- get, getchar 이런건 지금봐도 헷갈리므로 필요할 때 검색
fstream
- 어차피 필요할 때 검색하면서 사용할거라 대부분 생략
- close() 해도 파일과의 연결만 끊어지고 버퍼는 객체가 소멸될 때 해체됨에 주의
- 얘도 마찬가지로 clear() 가 버퍼 초기화가 아니라 스트림 상태 초기화임. (사실 버퍼 cursor 만 조정하면 되지 초기화할 이유가 없다.)
- 스트림상태는
is_open
,![객체]
등으로 가능. - 한 객체로 동시에 여러개의 파일도 열 수 있음(최대 갯수는 운영체제 나름)
위는 컴파일러가 자동으로 생성하는 임시파일명 생성( sjgw.0 이런식으로 나옴.)
sstream
- string stream 을 줄여서 sstream
- 실제로 정의하는 클래스는 istringstream, ostringstream 으로 줄여부르지 않음(?!)
- cout 이 표준출력, ofstream 이 파일출력이었다면 이건 string 이 출력대상
- cout 에 있는 웬맨한 기능은 다 적용이 됨.
- 정수를 hex 로 바꿔서 string 에 넣는다던지 하는 필요가 있을 때 사용하면 좋음
[객체].str()
하면 버퍼가 닫히고 완성된 string 이 리턴됨
댓글남기기