\(\texttt{cin}\) Object
\(\texttt{cin}\) 객체 ("C-In" 혹은 "Console-Input" 이라 읽는다.)
- C++에서 제공하는 표준 입력 객체이다.
- <iostream>에 정의되어 있는 istream 클래스에 속해있는 객체이다.
- \(\texttt{cin}\)이 조건 검사식에 위치하게되면 Method(메서드)의 특성을 띄게 되는데, 입력이 성공할 경우 \(\texttt{cin}\) 구문은 \(\texttt{true}\)를, 입력에 실패할 경우 \(\texttt{false}\)를 리턴하게 된다.
(\(\texttt{cin}\) 객체의 리턴형은 \(\texttt{cin}\) 객체 그 자체이지만, 조건 검사식에 위치한 \(\texttt{cin}\) 구문은 리턴형을 Boolean으로 변환한다.)
입력의 끝을 구분짓는 방법
1. Sentinel Chracter (표지 문자)
- 임의의 특수 문자(Sentinel)를 선정해서 그 문자를 입력 중지 신호로 사용하는 방법이다.
* 데이터형 별 데이터 처리 방법
1. \(\texttt{char}\)형 : 입력 행에 있는 첫 문자를 읽는다.
2. \(\texttt{int}\)형 : 숫자가 아닌 첫 문자가 나오기 전까지 읽는다.
3. \(\texttt{double}\)형 : 부동소수점 수의 일부가 아닌 첫 문자가 나오기 전까지 읽는다.
4. \(\texttt{char}\)형 배열 : 빈칸 문자가 나올 때까지 읽는다.
(\(\texttt{cin.getline()}\) 메서드의 경우, 개행 문자가 나올 때까지 읽는다.)
\(\texttt{cin}\)을 이용한 입력
- \(\texttt{cin}\)은 char형 값을 입력받을 때, 공백 문자, 개행 문자 들을 무시하고 건너뛴다.
- \(\texttt{cin}\) 입력은 버퍼를 이용하기 때문에 Enter 키를 누르기 전까지는 프로그램에 전달되지 않는다.
Ex. 입력한 문자를 Echo하며 문자의 개수를 카운팅하는 프로그램 예시 (\(\texttt{cin}\)을 이용한 방법)
char ch;
int count = 0;
cout << "문자들을 입력하시오 (입력을 마치려면 #을 입력): " << endl;
cin >> ch; // cin 을 이용한 입력
while (ch != '#') {
cout << ch; // Echoes : 키보드에서 키를 눌렀을 때, 화면 상에 문자가 나타나게 하는 기능
++count;
cin >> ch;
}
cout << endl << count << " 개의 문자를 읽었습니다." << endl;
return 0;
}
* Echoes : 키보드에서 키를 눌렀을 때 화면 상에 문자가 나타나게 하는 기능이다.
\(\texttt{cin.get()}\) 멤버함수를 이용한 입력
- \(\texttt{cin}\)을 통한 방법과는 달리, \(\texttt{cin.get()}\) 멤버함수는 빈칸 문자와 공백 문자까지도 입력받아 변수 ch에 저장한다.
- Function Overloading(함수 오버로딩) 기법을 통해 \(\texttt{cin.get()}\)의 매개변수 가짓수는 0개 ~ 2개의 범위를 갖는다.
+ C Style의 문자 입출력 함수 \(\texttt{getchar()}\), \(\texttt{putchar()}\)는 <cstdio> 헤더파일 (구 버전 stdio.h)을 포함시키면 이용할 수 있다.
1. \(\texttt{cin.get()}\)
- 입력으로부터 그 다음 문자를 읽어 리턴한다.
- \(\texttt{get()}\)의 다른 버전들과 달리, 매개변수가 없는 버전에서 \(\texttt{get()}\)은 객체가 아닌 문자를 리턴한다.
ch = cin.get(); // cin.get()은 객체가 아닌 문자를 리턴하므로 이와 같은 구문이 가능하다.
- <cstdio>의 \(\texttt{getchar()}\), \(\texttt{putchar()}\) 함수를 <iostream>의 \(\texttt{cin.get()}\), \(\texttt{cout.put()}\) 메서드로 변환하는 데 주로 사용된다.
- \(\texttt{cin.get()}\)은 EOF가 감지되었을 때, <iostream> 헤더파일에 정의되어있는 기호 상수 "EOF"로 나타내는 특별한 값을 리턴한다.
* 일반적으로, EOF는 다른 문자들의 ASCII Code와 혼동되지 않도록 -1로 정의되어 있다.
2. \(\texttt{cin.get(char ch)}\)
- 입력을 수행하고 \(\texttt{cin}\) 객체를 리턴한다. (연속적인 입력을 가능하게 함)
cin.get(ch1).get(ch2);
// cin.get(ch1)은 결과적으로 cin객체를 리턴하여
// get(ch2)에 적용되는 cin객체로 다시 사용된다.
- 리턴값이 \(\texttt{istream}\) 객체이기 때문에, OOP적인 접근에 사용하는 것이 적당하다.
- 문자 코드를 \(\texttt{int}\)형으로 리턴한다.(C Style의 \(\texttt{getchar()}\) 함수와 유사하다.)
3. \(\texttt{cin.get(char* arrName, int ArSize)}\)
// Ex. cin.get(char* arrName, int ArSize) 함수 사용 예시
char temp[30];
cin.get(temp,30);
while (cin && cin.get != '\n')
continue;
Ex. 입력한 문자를 Echo하며 문자의 개수를 카운팅하는 프로그램 예시 (\(\texttt{cin.get(char)}\) 를 이용한 방법)
char ch;
int count = 0;
cout << "문자들을 입력하시오 (입력을 마치려면 #을 입력): " << endl;
cin.get(ch); // cin 을 이용한 입력
while (ch != '#') {
cout << ch; // Echoes : 키보드에서 키를 눌렀을 때, 화면 상에 문자가 나타나게 하는 기능
++count;
cin.get(ch);
}
cout << endl << count << " 개의 문자를 읽었습니다." << endl;
return 0;
}
- "\(\texttt{cin.get(ch)}\)" 구문에서 값을 변경(입력)할 목적으로 매개변수 "\(\texttt{ch}\)"를 Call by Value 타입으로 넘긴 것으로 착각할 수 있지만, \(\texttt{<iostream>}\)헤더 파일내에 \(\texttt{cin.get(ch)}\) 멤버함수의 매개변수는 Call by Reference 타입으로 정의되어 있기 때문에 내부적으로는 변수를 참조형으로 주고받고 있으므로 결과적으로 값의 변경이 가능하다.
특성 | \(\texttt{cin.get(ch)}\) | \(\texttt{ch = cin.get()}\) |
입력 문자 전달 방법 | 매개변수 ch에 대입 | 함수의 리턴값을 ch에 대입 |
문자가 입력되었을 때의 함수 리턴값 | istream 클래스의 객체 (bool 값으로 변환 후 True) |
int형으로 된 문자 코드 |
EOF에서의 함수 리턴값 | istream 클래스의 객체 (bool 값으로 변환 후 False) |
EOF |
\(\texttt{cin}\)과 EOF
- \(\texttt{cin}\) 객체는 EOF를 감지했을 때 두 개의 비트값을 (eofbit & failbit)를 1로 설정한다.
- eofbit, failbit 둘 다 가장 최근에 읽은 결과를 저장하고 있는 비트이며, 따라서 \(\texttt{cin.eof()}\)나 \(\texttt{cin.fail()}\) 검사는 언제나 읽기 시도 다음에 수행되어진다.
- \(\texttt{cin}\)의 Method는 EOF를 감지하면 cin 객체에서 EOF 조건을 나타내는 Flag를 설정하는데, 이 플래그가 설정되면 \(\texttt{cin}\)은 더 이상의 입력을 받아들이지 않는다.
* \(\texttt{cin.eof()}\) : 는 EOF가 탐지되었을 경우 True 값을 리턴하고, 그 이외에는 False 값을 리턴한다.
* \(\texttt{cin.fail()}\) : eofbit나 failbit 둘 중 하나라도 값이 1로 설정되어 있으면 True 값을, 그 이외에는 False 값을 리턴한다.
* \(\texttt{cin.clear()}\) : EOF 플래그를 지우고 다시 입력이 진행될 수 있도록 허용한다. (입력 Buffer를 초기화하는 역할을 한다.)
- 또한 \(\texttt{istream}\) 클래스는 \(\texttt{cin}\)과 같은 \(\texttt{istream}\) 객체를 Boolean값으로 변환하는 함수를 제공하는데, 이 덕분에 루프 조건 검사 부분과 같이 Boolean 타입의 값이 필요한 부분에서 \(\texttt{cin}\)을 활용할 수 있다.
(마지막으로 시도한 입력이 성공하면 True 값을, 그 이외에는 False 값을 리턴한다.)
while(cin); // 가장 최근에 입력이 성공했을 경우, 루프를 진행한다.
// 아래 두 구문은 EOF가 탐지되지 않았으면 루프를 진행시키는 구문들이다.
while(!cin.fail());
while(!cin.eof());
- 또한, \(\texttt{cin}\)을 통한 판별은 디스크 고장과 같은 다른 결함까지도 탐지하기 때문에
\(\texttt{!cin.fail()}\) 이나 \(\texttt{!cin.eof()}\)와 같은 구문보다 더 일반적으로 사용된다.
Ex. \(\texttt{cin}\)객체로 입력을 받을 때, 비정상적인 입력에 대한 대처방법 예시
while (!(cin >> arr[i])) {
// 입력에 성공할 경우, while 루프는 실행되지 않는다.
// = 부적절한 입력에 대처하는 루프
cin.clear(); // 입력을 초기화
while (cin.get() != '\n')
continue; // 불량 입력값을 제거 = 입력 큐에 남아있는 입력값을 그 줄의 끝('\n')까지 읽어 들인다.
cout << "올바른 값을 입력하세요 : ";
}