728x90

황기태 저자의 명품 C++ Programming 개정판을 읽고 학습한 내용을 정리한 포스트입니다!

https://search.shopping.naver.com/book/catalog/32436115747

 

C++ Programming : 네이버 도서

네이버 도서 상세정보를 제공합니다.

search.shopping.naver.com

 

ostream의 멤버 함수를 이용한 문자 출력

  • ostream 클래스는 << 연산자 외에 화면 출력을 위한 다른 멤버 함수를 제공한다.
ostream& put(char ch) // ch의 문자를 스트림에 출력
ostream& write(char* str, int n) // str 배열에 있는 n개의 문자를 스트림에 출력
ostream& flush() // 현재 스트림 버퍼에 있는 내용 강제 출력

 

  • put()은 문자 단위로 출력하는 함수이다.
cout.put('A');
cout.put(33); // ASCII 코드 33은 문자 '!'이므로 !가 출력됨

 

  • write()는 char 배열에 들어 있는 문자들을 출력하는 함수이다.
char str[] = "I love programming"; // char *str = "I love programming";과 동일하다.
cout.write(str, 6); // str에 있는 6개의 문자 "I love" 출력

 

  • flush()는 출력 버퍼에 있는 문자들을 모두 강제로 출력시킨다.
  • cout.put('A')에 의해 출력된 문자 'A'가 스트림 버퍼에 남아 있을 때, flush()에 의해 강제 출력된다.
  • 컴파일러에 따라 put(), write() 함수가 문자를 버퍼에 기록한 후 바로 버퍼를 출력하는 경우도 있기에, cout.flush() 호출이 필요 없는 경우도 있다.
cout.put('A');
cout.flush(); // 스트림 버퍼에 있는 문자 'A'를 화면에 강제 출력

 

istream의 멤버 함수를 이용한 문자 입력

  • istream 클래스도 >> 연산자 외에 다양한 입력 멤버 함수를  가지고 있다.
  • >> 연산자는 빈 칸, 탭, 뉴라인 등 공백 문자(white space) 키를 읽을 수 없지만, istream 멤버 함수를 사용하면 공백 문자를 읽을 수 있다.

 

문자 입력
  • 문자를 입력받는 get() 함수는 다음 2가지 종류가 있고, 이들은 2바이트로 구성되는 한글 문자를 읽을 수 없다.
int get()  // 입력 스트림에서 문자를 읽어 리턴. 오류나 EOF를 만나면 -1(EOF) 리턴

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

 

  • int get()은 입력 스트림에서 한 개의 문자를 읽어 리턴하며, <Enter> 키 등의 공백 문자도 읽어 리턴
  • get()의 리턴 타입이 char가 아닌 int 타입인 이유는 입력 스트림의 끝을 만나면 EOF를 리턴하는데, EOF는 C++ 표준 헤더 파일에 '#define EOF -1'로 int 타입으로 선언되어 있기 때문이다.
// <Enter> 키가 입력될 때까지 키보드에서 문자를 읽고 출력하는 코드
int ch;
while((ch=cin.get()) != EOF) { // 키보드에서 문자 읽기
    cout.put(ch); // 읽은 문자 출력
    if(ch == '\n') // <Enter> 키가 입력된 경우 읽기 중단
    	break;
}

  • istream& get(char& ch) 함수는 문자를 읽어 참조 매개 변수 ch에 저장하고 리턴
  • 마찬가지로 ' ', '\n' 등 공백 문자를 읽어 리턴할 수 있다.
char ch;
while (true) {
	cin.get(ch); // 키를 ch에 읽어옴
	if (cin.eof()) break; // EOF 문자 즉 ctrl-z 키가 입력된 경우, 읽기 종료
	cout.puth(ch);
	if (ch == '\n')
		break;
}
  • cin.get(ch)이 EOF를 만나면 cin 스트림 내부에 eofbit 플래그를 세팅하기 때문에, ch에 읽혀진 값이 정확한지 확인하기 위해 cin.eof()를 호출한다.
  • 아래는 get()과 get(char&)을 이용한 한 줄의 문자 읽기 예시이다.
#include <iostream>
using namespace std;

void get1() {
	cout << "cin.get()로 <Enter> 키까지 입력 받고 출력합니다>>";
	int ch; // EOF와의 비교를 위해 int 타입으로 선언
	while((ch = cin.get()) != EOF) { // 문자 읽기
		cout.put(ch); // 읽은 문자 출력
		if(ch == '\n')
			break; // <Enter> 키가 입력되면 읽기 중단
	}
}

void get2() {
	cout << "cin.get(char&)로 <Enter> 키까지 입력 받고 출력합니다>>";
	char ch;
	while(true) { 
		cin.get(ch); // 문자 읽기
		if(cin.eof()) break; // EOF를 만나면 읽기 종료
		cout.put(ch); // ch의 문자 출력
		if(ch == '\n')  
			break; // <Enter> 키가 입력되면 읽기 중단
	}
}

int main() {
	get1(); // cin.get()을 이용하는 사례
	get2(); // cin.get(char&)을 이용하는 사례
}

 

문자열 입력
  • 이 함수는 배열 끝에 '\0'을 삽입하여 문자열이 되도록 한다.
  • 사용자가 'Hello<Enter>'를 입력한다면 cin.get(str, 10)은 총 5개의 문자 'H', 'e', 'l', 'l', 'o'를 읽어 str 배열에 저장한 후 '\0'을 추가하고 리턴한다.
istream& get(char* s, int n) // 입력 스트림으로부터 n-1개의 문자를 읽어 배열 s에 저장하고 마지막에 '\0' 문자 삽입. 입력 도중 '\n'을 만나면 '\0'을 삽입하고 리턴
char str[10];
cin.get(str, 10); // 최대 9개의 문자를 읽고 끝에 '\0'를 붙여 str 배열에 저장
cout << str; // str을 화면에 출력

 

  • 입력 도중 '\n'을 만날 때는 주의해야 한다. '\n' 문자를 만나면 읽기를 중단하고 리턴하여, '\n'이 스트림 버퍼에 남아있다.
  • 만약 이 상태에서 다시 읽기를 하게 되면 '\n'부터 읽기 시작하게 되어 아무것도 읽지 않고 바로 리턴한다.
  • 이 문제로 프로그램은 무한 루프에 빠지게 되므로, '\n' 문자를 제거하기 위해 아래와 같이 해주어야 한다.
cin.get(); 혹은
cin.ignore(1); // cin 버퍼에서 문자 1개 삭제
#include <iostream>
#include <cstring>
using namespace std;

int main() {
	char cmd[80];
	cout << "cin.get(char*, int)로 문자열을 읽습니다." << endl;
	while(true) {
		cout << "종료하려면 exit을 입력하세요 >> ";
		cin.get(cmd, 80); // 79개까지의 문자 읽음
		if(strcmp(cmd, "exit") == 0) {
			cout << "프로그램을 종료합니다...."; 
			return 0;
		}
		else // else 블록을 제거하면 무한루프에 빠짐
			cin.ignore(1); // 버퍼에 남아 있는 <Enter> 키 ('\n') 제거
	}
}

 

get() 함수로 한글 문자와 한글 문자열 읽기
  • cin은 문자를 한 바이트로만 다루도록 작성되어 있기에, 2바이트로 구성되는 한글 문자를 읽을 수 없다.
  • 하지만, 한글 문자열의 경우 get(char* str, int n) 함수를 호출하고 읽을 문자 개수의 2배 크기의 배열을 str에 넘겨주면 한글 문자열을 읽어 들일 수 있다. 

한 줄 읽기

istream& get(char* s, int n, char delim='\n')
// 입력 스트림으로부터 최대 n-1개의 문자를 읽어 배열 s에 저장하고 마지막에 '\0' 문자 삽입. 입력 도중 delim에 지정된 구분 문자를 만나면 지금까지 읽은 문자를 배열 s에 저장하고 리턴
istream& getline(char* s, int n, char delim='\n')
// get()과 동일. 하지만 delim에 지정된 구분 문자를 스트림에서 제거
  • getline()은 delim에 지정된 구분 문자를 만날 때까지, 혹은 n-1개의 문자를 모두 읽을 때까지 배열 s에 문자를 읽어 들이는 함수
  • delim 매개 변수가 생략되면 <Enter> 키가 입력될 때까지 한 라인을 읽는다.

  • getline()이 delim 문자를 스트림 버퍼에서 제거하는 것과 달리, get()은 delim 문자를 버퍼에 그대로 남겨 둔다.
  • 따라서, get()으로 여러 라인을 연속하여 읽을 때 각 라인마다 스트림 버퍼에서 강제로 '\n'을 제거하지 않으면 무한 루프에 빠질 수 있다.
#include <iostream>
using namespace std;

int main() {
	char line[80];
	cout << "cin.getline() 함수로 라인을 읽습니다." << endl;
	cout << "exit을 입력하면 루프가 끝납니다." << endl;

	int no = 1; // 라인 번호
	while(true) {
		cout << "라인 " << no << " >> ";
		cin.getline(line, 80); // 79개까지의 문자 읽음
		if(strcmp(line, "exit") == 0)
			break;
		cout << "echo --> ";;		
		cout << line << endl; // 읽은 라인을 화면에 출력
		no++; // 라인 번호 증가
	}
}

 

입력 스트림의 문자 건너띄기 & 읽은 문자 개수 알아내기

istream& ignore(int n=1, int delim=EOF)
// 입력 스트림에서 n개 문자 제거. 도중에 delim 문자를 만나면 delim 문자를 제거하고 리턴

int gcount()
// 최근에 입력 스트림에서 읽은 바이트 수(문자의 개수) 리턴. <Enter> 키도 개수에 포함
char line[80];
cin.getline(line, 80);
int n = cin.gcout(); // cin.getline()에서 읽은 문자의 개수 리턴
  • 위의 코드에서 'Hello<Enter>'를 입력하면 cin.getline(line, 80)가 읽은 문자의 개수는 6이다. => 'Hello\0'
  • 아래와 같이 get으로 읽는 경우 5를 리턴하는데, getline()과 달리 get()은 '\n'을 cin의 스트림 버퍼에 그대로 남겨두기 때문이다.
char line[80];
cin.get(line, 80);
int n = cin.gcount();
728x90

'Programming Language > C++' 카테고리의 다른 글

[C++] 삽입 연산자(<<)와 추출 연산자(>>)  (0) 2023.12.21
[C++] 포맷  (1) 2023.12.21
[C++] 입출력 기초  (1) 2023.12.20
[C++] struct with Cpp  (3) 2023.12.20
[C++] queue, deque with Cpp  (1) 2023.12.20