C++ Chapter 18.4 : 흐름 상태와 입력 유효성의 검증
카테고리: Cpp
태그: Cpp Programming
인프런에 있는 홍정모 교수님의 홍정모의 따라 하며 배우는 C++ 강의를 듣고 정리한 필기입니다. 😀
🌜 [홍정모의 따라 하며 배우는 C++]강의 들으러 가기!
chapter 18. 입력과 출력
흐름 상태와 입력 유효성의 검증
🔔 문자열 스트림의 현재 상태 확인하기
첫 번째 방법 👉 ios의 함수들 사용
std::ios
: 가장 높은 조상 입출력 클래스다.
const std::ios & stream
일 때- stream.
good()
- std::ios::good
- 스트림의 현재 상태가 좋으면 true 안좋으면 false 리턴
- 모든 error state flag가 0일 때 flag가 true가 된다.
- stream.
- stream.eof()
- std::ios::eof
- eof 즉 end of file 에 도달했다면 true 리턴 아니면 false 리턴
- 파일을 끝까지 다 읽었는지
- stream.fail()
- std::ios::fail
- 스트림 현재 상태가 실패면 true 성공이면 false 리턴.
- good()의 반대
- error state flag가 하나라도 1일 경우 flag가 true가 된다.
- stream.bad()
- std::ios::bad
- 데이터를 읽거나 쓸 때 에러가 발생할 때 flag가 true가 된다.
#include <iostream>
#include <string>
using namespace std;
void printStates(const std::ios& stream)
{
cout << std::boolalpha; // boolalpha option ON
cout << "Good() = " << stream.good() << '\n'; // 모든 error state flag가 0일 때 flag가 true가 된다.
cout << "eof() = " << stream.eof() << '\n'; // stream의 end of file에 도달하면 flag가 true가 된다.
cout << "fail() = " << stream.fail() << '\n'; // error state flag가 하나라도 1일 경우 flag가 true가 된다.
cout << "bad() = " << stream.bad() << '\n'; // 데이터를 읽거나 쓸 때 에러가 발생할 때 flag가 true가 된다.
}
int main()
{
while(true)
{
int i;
cin >> i;
printStates(cin);
cin.clear();
cin.ignore(1024, '\n');
cout << endl;
}
return 0;
}
💎입력💎
123
abc
123.456
💎출력💎
good() = true
eof() = false
fail() = false
bad() = false
good() = false
eof() = false
fail() = true
bad() = false
good() = true
eof() = false
fail() = false
bad() = false
printStates(cin)
- cin 스트림을 넘겨 줌.
iostream
의 부모클래스인ios
타입의 참조 변수로cin
객체를 참조 - 123 입력
- int i 에 123이 잘 들어갔다.
- good() = true. 이상 없음
- 버퍼가 비워지고 이제 다시 while 반복
- abc 입력
- abc는 문자열이므로 int i에 들어갈 수 없다.
- 논리적 오류 fail() = true
- good() = false
- 버퍼가 지워지고 이제 다시 while 반복
- 123.456 입력
- 123.456은 double형인데 int i에 123으로 들어갈 수 있음
- good() = true 이상 없음
- 버퍼가 지워지고 이제 다시 while 반복
- cin 스트림을 넘겨 줌.
두 번째 방법 👉 bitmask와 rdstate을 사용하여 비트로 흐름 상태 확인
#include <bitset>
#include <iostream>
#include <string>
#include <bitset>
using namespace std;
int main()
{
while (true)
{
int i;
cin >> i;
printStates(cin); // 1️⃣ 스트림 상태를 알 수 있는 첫번째 방법 -> ios의 good(), bad(), fail(), eof() 사용
/* 2️⃣ 스트림 상태를 알 수 있는 두번째 방법 -> 직접 goodbit, failbit 등등 bit를 사용 */
cout << boolalpha;
cout << std::bitset<8>(cin.rdstate()) << endl;
cout << std::bitset<8>(std::istream::goodbit) << endl;
cout << std::bitset<8>(std::istream::failbit) << endl;
cout << !bool((cin.rdstate() & std::istream::failbit) != 0) << endl;
cin.clear();
cin.ignore(1024, '\n'); // 버퍼에 남은거 지우기
cout << endl;
}
}
- 비트를 이용하므로 성능이 좋고 빠르지만 가독성이 떨어진다.
std::bitset<8>(cin.rdstate())
cin.rdstate()
ios
의 함수이다.- 현재의 에러 상태의 flag 상태를 리턴한다.
- 이 때의 flag 는 비트 마스크 방식 (bitmask)
std::bitset<8>(std::istream::goodbit)
- good bitmask = 00000000std::bitset<8>(std::istream::failbit)
- fail bitmask = 00000010!bool((cin.rdstate() & std::istream::failbit) != 0)
- goodbit가 아닌 failbit로&
연산 하는 이유 - goodbit는 00000000 이라서.. 에러가 난적이 없으므로 그냥 00000000이다. -rdstate
가 fail비트를 가지고 있지 않다면 성공인 상태. - good 상태. -&
연산 결과0
이 나올 것. - 0 = 0 이므로cin.rdstate() & std::istream::failbit) != 0
결과는 false - 성공인 상태 즉 true로 리턴해주어야 하니까 앞에 ! 붙이는 것이다. -!
bool((cin.rdstate() & std::istream::failbit) != 0) -rdstate
가 fail비트를 가지고 있지 않다면 실패인 상태 - fail인 상태. - 0이 아닌 수가 나올 것.&
연산 결과가 fail 비트로 나올 것이다. - 0 ≠ 0 이므로 결과는 true - 실패인 상태 즉 false로 리턴해주어야 하니까 앞에!
붙이기 - 이 비트 연산 결과를 bool로 형변환 -cin.rdstate() == std::istream::goodbit;
이렇게 하는 방법도 있음.
🔔 입력 유효성 검증
#include <cctype> 헤더 파일로부터
isalpha
,isalnum
,isblank
등드으이 함수를 사용하여 내가 원하는대로 입력이 잘 들어갔는지를 검증
#include <cctype>
isalpha
,isalnum
,isblank
, 등등…- 리턴값이 integer 정수다.
- 0이 아닌 정수면 true로 간주
- 0이면 false로 간주
예제 1
void printCaracterClassification(const char& input)
{
cout << std::boolalpha;
cout << "isalpha = " << bool(std::isalpha(input)) << '\n'; // 입력받은 게 문자인지?
cout << "isalnum = " << bool(std::isalnum(input)) << '\n'; // 입력받은 게 문자 또는 숫자인지?
cout << "isblank = " << bool(std::isblank(input)) << '\n'; // 입력받은 게 공백인지?
cout << "isdigit = " << bool(std::isdigit(input)) << '\n'; // 입력받은 게 숫자인지?
cout << "islower = " << bool(std::islower(input)) << '\n'; // 입력받은 게 소문자인지?
cout << "isupper = " << bool(std::isupper(input)) << '\n'; // 입력받은 게 대문자인지?
}
- 결과를 정수로 리턴하므로
bool
로 형변환 하여 출력하였다.
예제 2
bool isAllDigit(const string& str)
{
bool ok_flag = true;
for (auto e : str)
if (!bool(std::isdigit(e)))
{
ok_flag = false;
break;
}
return ok_flag;
}
int main()
{
cout << std::boolalpha;
cout << bool(isAllDigit("12345")) << '\n'; // true 출력
cout << bool(isAllDigit("12a34")) << '\n'; // false 출력
}
isAlldigit
👉 입력 받은 문자열이 모두 숫자냐- bool isAllDigit(const string& str)
- 입력받은 문자열 str을 한문자씩 다 뜯어서 문자인지 확인
🌜 개인 공부 기록용 블로그입니다. 오류나 틀린 부분이 있을 경우
언제든지 댓글 혹은 메일로 지적해주시면 감사하겠습니다! 😄
댓글 남기기