본 내용은 POCU COMP3200: C++ 언매니지드 프로그래밍 강의를 토대로 작성하였습니다.
1. 입력 스트림(Input Stream)
키보드에서 읽기
scanf는 왜 위험한가?
scanf()는 경계검사를 하지 않는다!
경계검사 : 내가 사용하는, 쓸 메모리가 실제 내가 가진 메모리 내부에 들어가니? 들지 않으면 안전하게 연산을 하겠다. exception 등을 던진다.
C 스타일의 문자열은 Character Array, 바꿔 말하면 Character Pointer임. 그래서 어느 정도의 메모리가 할당되어 있는지 실행 중에는 알 수 없음. 그래서 string 제일 뒤에 특수한 Character을 넣어서 string이 끝나는 것을 표시함. 이게 NULL Character Stream.
위 예제에서 문자 끝에 NULL 캐릭터가 있어야 하는데 NULL 캐릭터를 넣으려 하니까 빨간색 부분이 우리가 소유하지 않은 메모리임. 따라서 우리가 소유하지 않은 메모리를 덮어 쓰는 문제가 생김.
scanf는 char*를 받음. character array는 char pointer. char*를 받는데 그것의 길이를 알 수 없으니 무조건 읽음. 이걸 해결하려면?
5개로 잡아주면 됨. 하지만 이게 범용적인 솔루션은 아님. 다른 이름이 긴 글자가 들어간다면?
cin은 같은 문제가 있을까?
똑같은 문제가 있음. 이유 ? char 배열과 char 포인터는 같음
C++에서 쓸 수 있는 더 안전한 방법 - setw()
내가 가진 버퍼 사이즈가 4글자 밖에 없으니 알아서 읽어오라고 하면 세 글자만 읽어오고 NULL 캐릭터를 붙여줌
2. 스트림 상태 (Stream States)
cin, cout은 스트림. 이 스트림에서 뭔가를 읽어 왔는데 가끔은 읽어올 때 실패할 때가 있을 것.
그럼 실패 했다는 것을 어떻게 확인? 성공, 실패 여부 찾기 위해 상태가 자동적으로 저장됨
file의 마지막(end-of-file)을 만나지 않았으면 진행해라 / NULL은 직관적이지 않음
1) 456까지 읽고 a에서 멈춤. 456까지 무사히 읽었기 때문에 eof는 아니고(a가 eof가 아니니까) 실제 숫자 읽었으니 failbit set가 안됨
2) 456 넣었을 때 제대로 읽고(failbit == unset) 커서가 6 다음에 와있는건데 set이 될 수도 있고 안될수도 있음
언제 set이 안돼?
콘솔에서 데이터 입력할 때 456하고 엔터 치면 뒤에 뉴라인 캐릭터가 있기 때문에 무사히 읽고 뉴라인 캐릭터는 eof가 아니기 때문에 unset.
언제 set이 됨?
input을 콘솔에서 하는 게 아니라 텍스트파일로 저장해두고 콘솔에서 치는 것 처럼 리디렉션을 할 수 있음.
이렇게 하면 456뒤에 엔터 안치고 저장할 수 있어서 마지막 캐릭터가 eof가 되기 때문에 set이 됨
그래서 eof 처리하는 코드 쓸 때 이 두가지 경우를 모두 테스트 해봐야 함.
3) abc를 숫자로 읽을 방법은 없으니 failbit가 set이 되고 실패를 하고 아직도 포인터는 a를 가리키고 있음. 따라서 eofbit은 set이 안됨
4) eof를 넣었을 땐 eof니까 set 되고 숫자가 아니니까 failbit도 set
//알파벳 e o f가 아니라 eof 입력하는 방법 있음. 구글에 쳐보기
3. 입력 버리기(Discarding Input) : clear(), ignore()
clear()
스트림을 좋은 상태(good state)로 돌려 줌
cin.clear();
언제 써?
스트림이 좋지 않은 상태가 되었을 때. failbit이 들어왔다거나 eof가 들어왔을 때 다시 스트림을 아무 문제 없는 상태(문제 있는 bit가 설정되었을 때 그걸 그냥 지워줄 때)로 만들어줌
댓글