Ch 03. 입출력 - 03. cin

2025. 3. 29. 15:52Programming Language/C++

반응형

cin은 C++에서 표준 입력을 처리하는 객체로, 콘솔로 부터 데이터를 받아오는 역할을 한다.

std::istream 클래스의 전역 객체로 C++의 표준 라이브러리인 <iostream>에 정의되어 있다.

cin의 뜻은 Character Input으로 보통 키보드의 입력 값을 받아온다.

 

cout과는 반대로 <<가 아니라 >> 연산자를 사용하고 값을 넣어주는 용도이기에 보통 변수를 이용해서 값을 넣어준다.

이렇게 넣어주면 값을 터미널에서 커서가 깜빡거리면서 입력을 요구하고 

값을 넣어주면 a에 값이 들어가면서 

이렇게 입력한 값을 출력해준다.

scanf에서는(C언어에서) & 연산자를 넣어서 해당 변수의 주소값을 직접 전달해줘야만 외부의 변수인 a 값을 scanf함수내에서 넣어줄 수 있기 때문인데 C++에서는 참조라는 것을 사용해서 인자를 전달하면 밖의 변수도 함수 내부에서 변경이 가능하기 때문에 그냥 저렇게 넣기만 하면 되는 것이다.

 

그리고 scanf의 경우 %d로 값을 정수로 받고자 할때 

아래와 같이 정수값이 아니라 문자가 들어가게 되면 값이 들어가지 않고 쓰레기 값을 넣어줬었는데

cin을 사용하면

디폴트 값으로 0을 넣어준다

그리고 scanf를 사용할때랑 동일하게 if문 안에 넣어서 값을 받았는지 못받았는지를 확인할 수 도 있다.

 

여기서 cin도 scanf처럼 버퍼에 남는 현상은 동일하게 존재한다.

그러나 cin의 경우는 개행문자는 잘 처리해준다.

이렇게 입력을 두번 받아 출력을 한다면 

이렇게 잘 출력해주나

이렇게 다수의 값을 넣으면 입력을 추가로 받지 않고 버퍼에 있는걸 cin이 그냥 갖다가 쓴다.

 

이때는 cin의 ignore라는 함수를 사용해서 정리해줄 수 있다.

그런데 이것도 똑같이 하나의 문자만 ignore해주는 것이기 때문에 다수의 문자를 입력하면

이렇게 b만 뛰어 넘은 것을 볼 수 있다.

이럴 때는 ignore함수의 인자로 값을 추가해주면 된다.

 

- std::cin.ignore() : C++에서 표준 입력 스트림(std::cin)의 입력 버퍼에서 문자들을 무시(버림) 할 때 사용하는 함수

std::cin.ignore(스트림크기, 구분문자);

- 스트림크기 : 무시할 문자의 최대 갯수

- 구분 문자: 해당 문자를 만나면 무시를 멈춘다

 

 

그래서 스트림의 크기를 크게 잡아주고 구분문자를 개행문자인 '\n'을 설정해주면

이렇게 출력이 가능하다

여기서 스트림의 크기를 그냥 최대 값으로 넣어주기 위해서는 먼저 limits라는 표준 라이브러리를 추가해주고

스트림 사이즈부분에 std::numeric_limits<std::streamsize>의 max함수를 넣어주면

잘 작동되는 것을 볼 수 있다.

더보기

#include <limits>와 std::numeric_limits<std::streamsize>::max()

#include <limits>와 std::numeric_limits<std::streamsize>::max()는 C++에서 타입의 한계(최댓값, 최솟값 등)를 정확하게 알고 싶을 때 사용하는 기능이다.

 

1. #include <limits>

C++ 표준 라이브러리의 헤더파일로 다양한 기본 자료형(int, float, char, etc)의 최댓값, 최솟값, 특성들을 알 수 있게 해주는 기능이 정의되어 있음

 

이게 왜 필요하냐면 예를 들어 int의 최대값이 얼마인지 사람이 외우긴 어렵고 플랫폼마다 다를 수 있기에 C++이 직접 알려주게 해주기 위해 생성 및 제공되었다.

 

2. std::numeric_limits<T>

템플릿 클래스T로 전달되는 타입의 정보(한계값, 특성 등)를 제공해주는 클래스이다.

 

* 템플릿 클래스란? 

 자료형에 독립적인 클래스를 만들 수 있게 해주는 기능으로 같은 로직을 가지면서도 다양한 자료형에 대해 동작하는 클래스를 만들기 위해사용 하는 클래스를 지칭함, 다른 말로 말해서 다양한 타입으로 각각의 클래스를 만드는 대신 <T>로 전달되는 타입에 따라서 해당 타입의 클래스를 만들어주는 클래스를 말한다

 

3. std::streamsize

입출력 스트림에서 문자의 수를 표현하기 위한 타입으로 보통은 long long 또는 int64_t 정도 되는 큰 정수 타입을 의미한다.

C++의 <ios> 헤더에 정의되어 있는 typedef 또는 using alias로 

namespace std {
    using streamsize = std::streamoff; // 또는 std::common_type<std::streamoff>::type
}

 와 같이 정의되어 있다.

 

여기서 streamoff는 따로 정해져 있는 값은 아니고 OS나 컴파일러와 같은 플랫폼에 의해서 결정되는 최대 크기의 정수형이라고 보면된다.

 

결국 보통은 long long 타입이거나 int64_t 의 크기를 가진 큰 정수 타입이라는 의미는 이것 때문에 그런 것이다.

 

4. std::numeric_limits<T>::max()

타입 T가 표현할 수 있는 가장 큰 값을 반환하는 정적 함수

 

종합적으로 #include <limits>와 std::numeric_limits<std::streamsize>::max()에 대해서 한마디로 정하면

limits라는 표준 라이브러리(std)에서 가져온 numeric_limits라는 템플릿 클래스를 해당 플랫폼의 최대 크기의 정수 타입으로 구현한 다음에 이 최대 크기의 정수 타입의 최대 값을 출력해줘라 로 요약할 수 있다.

 

근데 여기서 만약 값의 형태가 변수에 맞지 않은 값을 넣어준다면 어떻게 될까? 

타입을 문자가 아니라 숫자로 변경해보고 

실행한 다음에 숫자가 아니라 문자를 넣어보면

한번에 그냥 값도 받지 못하고 종료돼버린다

 

입력이 실패되면 상태가 "실패"상태가 되어 버리기 때문에 그 이후의 함수를 무시하게 된다.

이때 cin의 fail이라는 함수를 확인하면 현재 cin의 상태를 확인할 수 있는데 

이렇게 추가해주면

이렇게 해당 값이 현재 실패 했다고 fail에 true값인 1을 던져준다.

이때 clear라는 함수를 사용하면 이 값을 초기화 시켜줄 수 있는데 

한번 다시 해보면

이렇게 clear 이후론 fail 함수가 false로 떨어지면서 실패 상태가 아님을 확인할 수 있다.

 

이제 이걸 if 문을 통해서 실패의 경우는 초기화해주자 라는 코드를 추가해주면

이렇게 정수 값을 넣을 값에 문자를 넣으려고 한다면 실패한 상태로 유지하지 않고 다음 값을 받으러 갈 수 도 있게 된다.

 

이렇게 입력의 문제에 대한 해결을 할 수 있다.

 

그리고 cin 또한 플래그를 지정해서 포멧 값을 변경할 수 도 있다.

예를 들어 가장 간단하게 true/false값은 기존에 그냥 출력하면 1 혹은 0으로 출력 되었는데 이걸 true/false로 출력할 수 있도록 했던게 boolalpha라는 플래그였다.

이렇게 1을 넣으면 true로써 적용이 될 것이다.

그런데 이렇게 숫자를 넣어서 다음이 1이 나오는건 정수로 하나 bool타입으로 하나 동일하니 우리가 원하는건 

이렇게 true를 입력하면 1로 출력되거나 false를 입력하면 0이 나오는 것을 말한다.

이렇게 하려면 cin을 실제로 사용하기 이전에 cin에 setf를 사용해서 boolalpha를 flag로 설정해주면 

 

true를 입력하면 값이 1이 나오게 된다 동일하게 false를 입력하면

0을 출력하는것을 볼 수 있다.

 

진법 변환을 하는것도 한번 보자면 값을 받으면 이걸 16진수로 변경하도록 한다면

이렇게 넣어주면

입력한 값을 16진수로 인식해서 입력한 값인 16진수를 10진수로 변경한 값을 출력한다.

 

여기서 

이렇게 사용하면 안되는 이유는 기본적으로 cin.setf의 진수 표기에는 10진수로 설정되어 있기에 그 값을 초기화해줄 마스크값이 필요하기 때문이다.

기존에 정렬과 같은건 따로 그런게 설정되어 있지 않기 때문에 할 필요가 없는데 진법의 경우는 추가적으로 마스크가 무조건 필요로 한것이다.

이것 또한 동일하게 cout 처럼 

이렇게 사용하는 것도 가능하다.

해제 또한 cout때와 동일하게 해주면 된다.

반응형