본문 바로가기
SW/C,C++

[C++] std::cin 타입 불일치

by FastBench 2024. 5. 2.

[C++] std::cin 사용 시 주의점

cin 변수의 타입불일치

코드를 짜다가 정수 값을 입력받을 일이 있었는데, 예상치 못한 에러가 나와서 당황했다.

 

아래와 같은 코드가 있다고 해보자.

#include <iostream>

int main(){
    int index;
    std::cout << "Enter index   : ";
    std::cin >> index;
    std::cout << "index is " << index << std::endl;

    int num;
    std::cout << "Enter num     : ";
    std::cin >> num;
    std::cout << "num is " << num << std::endl;

    return 0;
}

올바른 정수값을 넣어 줄 경우 출력은 생각하는 대로다.

만약 문자를 입력한다면 어떻게 될까

두번째 입력을 받기도 전에 채워지고 이상한 값이 num 에 할당된다.

 

문제의 원인

  1. 타입 불일치: int 변수에 문자를 입력하면, 입력 스트림은 실패 상태로 설정된다. 이 때문에 변수 index는 초기화되지 않거나 기본값인 0으로 설정된다.
  2. 스트림의 실패 상태: 입력이 실패하면 스트림이 실패 상태에 머물게 된다. 이 상태에서는 더 이상의 입력을 받지 않으며, 스트림을 명시적으로 클리어하지 않는 한 이 상태가 유지된다.
  3. 버퍼 내 데이터: 문자 데이터가 입력 버퍼에 남아 있어 다음 입력 호출에 영향을 준다.

해결방법

먼저 올바르지 않은 cin 이 입력되는 상황이 예상되는 부분마다 검사를 해준다.

    while ( std::cin.fail() ){	// If wrong cin
        std::cin.clear; 		// clear the error status flag
        std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // clear the buffer
        std::cout << "Enter index	: ";
        std::cin >> index;
    }
  • std::cin.fail() 함수는 입력이 실패했을 때 true를 반환한다.
  • std::cin.clear() 함수로 오류 상태 플래그를 clear 한다.
  • std::cin.ignore() 함수는 두개의 매개변수를 받는다
    • 최대 문자 수 (기본값: 1): 스트림에서 무시할 최대 문자 수를 지정한다. 타입은 std::streamsize 다.
      • climits 헤더를 사용할 경우, INT_MAX 를 사용하도 되는데 (int 의 최대값), 플랫폼에 따라 타입 불일치 문제가 발생할 수 있으므로 limits 헤더의 std::numeric_limits<std::streamsize>::max() 를 쓰는 것이 안전하다.
    • 구분자 (기본값: EOF): 이 구분자를 만날 때까지 문자를 무시하고, 구분자 자체도 무시한다.

 

결과

 

댓글