[C++ I/O]ostream, istream 멤버 함수 그리고 '한 줄' 읽기

Jin Hur·2022년 6월 8일
0

C++

목록 보기
4/18

"명품 C++ 프로그래밍" / 황기태 / 생능출판

istream 멤버 함수

istream 클래스도 >> 연산자 외에도 다양한 입력 멤버 함수를 가지고 있다.
>> 연산자는 공백 문자(<space>, <Tab>, <Enter> 키 등 공백 문자 키를 읽을 수 없지만 다른 멤버 함수를 사용하면 공백 문자까지 읽을 수 있다.

/* 문자 입력 */
// 입력 스트림에서 문자를 읽어 리턴. 오류나 EOF를 만나면 -1(EOF) 리턴
int get()
// 입력 스트림에서 문자를 읽어 ch에 저장. 현재 입력 스트립 객체(*this)의 참조 리턴. 오류나 EOF를 만나면, 스트림 내부의 오류 플래그(failbit) 세팅
istream& get(char& ch)

/* 문자열 입력 */
// 입력 스트림으로부터 n-1개의 문자를 읽어 배열 s에 저장하고 마지막에 널문자를 삽입한다. 
// 입력 도중에 '\n'을 만나면 널문자를 삽입하고 리턴.
istream& get(char* s, int n)
// 입력 도중 delim에 지정된 구분 문자를 만나면 지금까지 읽은 문자를 배열 s에 저장하고 리턴
istream get(char* s, int n, char delim='\n')

/* 한 줄 읽기 */ 
// delim에 지정된 구분 문자를 만날 때까지, 혹은 n-1개의 문자를 모두 일을 떄까지 배열 s에 문자를 일어 들이는 함수. 
// get과 동일하지만 지정된 구분 문자를 스트림에서 제거한다는 것이 차이점이다.
istream& getline(char* s, int n, char delim='\n')

ostream 멤버 함수

ostream 클래스는 << 연산자 외에도 화면 출력을 위한 다른 멤버 함수를 제공한다.

// ch 문자를 스트림에 출력
ostream& put(char ch)

// str 배열에 있는 n개의 문자를 스트림에 출력
ostream& write(char* str, int n)

// 현재 스트림 버퍼에 있는 내용을 강제 출력
// 컴파일러에 따라 <<, put(), write() 함수가 문자를 버퍼에 기록한 후 바로 버퍼를 출력하기도 하기에, cout.flush() 호출이 필요없는 경우도 있다. 
ostream& flush()

한 줄 읽기

1. int get()을 활용한 한 줄 읽기

공백 문자를 포함한 한 개의 문자를 읽어 리턴한다.

// get()을 이용한 한 라인 읽기 코드
// (1)
int ch;
while ((ch = cin.get()) != EOF) {
	cout.put(ch);
	if (ch == '\n')	// 입력 스트림에서 개행 키('\n')가 변수에 들어오면 종료한다. => 한 줄 읽기
		break;
}

// (2)
char c;
string s = "";
while (true) {
	c = cin.get();
	
	if (c == EOF)
		break;
	if (c == '\n')
		break;

	s += c;
}
cout << s << endl;

2. string 라이브러리의 getline() 함수 사용

istream& getline(istream& is, string& str)
istream& getline(istream& is, string& str, char delim)

cin 객체의 멤버함수에 문자열을 전달할 때 string 인자로 넣으면 에러가 발생한다. 따라서 string 클래스의 getline 함수를 사용한다.

string s;
getline(cin, s);
cout << s << endl;

또한 이전에 cin 객체 버퍼에 남아있는 값이 있을 것이라 의심되는 경우 해당 버퍼를 비워야 한다.

원치 않은 결과가 나온 이유는 cin >> a; 과정에서 a에 숫자 키가 들어가고, <Enter> 키는 여전히 버퍼에 남아있다. getline()의 경우 공백 문자도 입력으로 허용하기에 이전 입력에서 남은 <Enter> 키가 들어온다. 다만 하나의 입력으로 받아들이고 들어온 <Enter>를 버린다. 이렇나 경우 getline() 이전에 cin.ignore() 함수를 사용해서 버퍼에 남은 개행 문자를 버려야 한다.

연속적인 getline() 사이에는 상관없다. 개행 문자를 버리기에 다음 getline()에 영향을 주지 않는다.

string s;
getline(cin, s);
cout << s << endl;

0개의 댓글