[C++] cin.fail(), cin.clear(), cin.ignore() 함수, getline() 함수, cin

visualnnz·2024년 2월 17일

Cpp

목록 보기
1/7

1. cin.fail()

  • cin.fail() 함수는 숫자형 변수에 문자를 넣으려는 코드와 같이 올바르지 않은 시도가 이루어 질 때 failbit를 set(설정)하며 참(=1)을 반환하게 된다.

    반환값 : 정수형 변수에 문자를 입력할 경우 true


2. cin.clear()

  • cin.clear() 함수는 내부상태플러그를 초기화 시켜 cin이 올바른 동작을 이어가게 한다.


3. cin.ignore()

  • 인자(argument)를 2개 넣을 수 있다.

    1. 첫 번째 인자로는 읽어들일 문자의 개수
    2. 두 번째 인자로는 읽어들이면 종료할 문자

    • 입력버퍼에 있는 문자를 최대 첫 번째 인자로 지정한 수만큼 읽어들인 후 버리게 되고 또는 두 번째 인자로 지정한 문자를 만나면 그 문자를 마지막으로 읽어들인 후 버리게 된다. (둘 중 먼저 만족하는 조건을 따르게 된다.)

  • C언어의 fflush(stdin)처럼 작동한다.

  • 인자를 안넣고 cin.ignore()로 사용하면 문자 한 개만큼 버퍼를 비운다.


4. getline()


  • cin은 공백 입력시 공백을 구분자로 인식하고 입력을 받지 않는다.
    └ e.g.) "a b c"를 입력했다면 a만 입력된다.

  • getline(string)을 사용하면 \n을 구분자로 사용하여 문자열을 입력받고 이후 \n을 버퍼에서 지운다. 즉, \n을 받아들인다.

  • 이와 반대로 cin\n, '띄어쓰기', 'tab'를 구분자로 사용하며 버퍼를 지우지 않기 때문에, cin 이후 getline을 사용한다면 cin,ignore()과 같은 함수를 사용하여 버퍼를 비워주어야된다. (아니면 엔터를 입력값으로 받는다.)

  • getline은 2가지의 형태가 있다.
    └ 1. std::istream::getline의 cin.getline()
    └ 2. std::getline(string)

std::istream::getline의 cin.getline()


char* 타입의 문자열을 받을경우 사용할 수 있다.

  • 프로토타입 : itream& getline(char* s, streamsize n, char delim);
    s : 문자열을 받을 배열을 가리키는 포인터
    n : 저장할 문자의 최대 갯수
    delim : '제한자'이며, 지정한 문자가 나타나면 입력을 멈춘다. 대신 제한자는 저장하지 않는다.
    └ 제한자를 지정하지 않을 수도 있는데, 그렇다면 개행문자\n로 자동 설정 된다.

참고로 cin.getline()의 첫 인자는 문자열을 받을 배열의 포인터이기에 string타입을 입력하려고 하면 안된다.

std::getline(string)


String 타입을 받을 경우 사용한다.

  • 프로토타입 : istream& getline(istream& is, string& str, char delim);
    is : 문자들이 추출될 istream(입력 스트림)오브젝트(키보드 입력을 받을거면 cin 쓰면 된다.)
    str : 입력받은 문자열들이 저장될 string 오브젝트
    delim : '제한자'이며, 지정한 문자가 나타나면 입력을 멈춘다. 대신 제한자는 저장하지 않는다.
    └ 제한자를 지정하지 않을 수도 있는데, 그렇다면 개행문자\n로 자동 설정 된다.

4-1. cin 팁


  • cin으로 입력받을 경우, 버퍼에 \n이 남는다.
  • cin다음 입력을 cin으로 받을 경우, 전 버퍼에 있던 공백 및 개행문자(\n)를 무시하기 때문에 버퍼를 굳이 비워줄 필요가 없다.
  • cin다음 입력을 getline으로 받을 경우, 전 버퍼에 있던 공백 및 개행문자를 포함해서 입력받기 때문에 버퍼를 지워주는 작업 cin.ignore()이 필요하다.
  • getline 다음 입력을 getline으로 받을 경우, getline\n문자를 버퍼에 포함시키지 않기 때문에 버퍼를 비워줄 필요가 없다.
  • Windows와 Linux의 개행 문자 차이, 컴파일러의 차이 등에 따라 실행 결과가 일치하지 않을 수 있다.

예제코드

#include <iostream>
int main()
{
	int a;
	while (1)
	{
		std::cin >> a;
		if (cin.fail())
		{
			std::cout << "비정상" << std::endl;
			std::cin.clear();
			std::cin.ignore(5, '\n');
		}
	}
}
  • ⌨️ 입력
  1. 1
  2. 2
  3. abcde
  4. abcdef
  • 🖥️ 출력
  1. 비정상
  2. 비정상
    비정상

    위 예제코드를 살펴보면 1번째와 2번째 입력으로 정수형 변수 a의 값으로 1과 2를 입력했을 땐 정상 실행된다.


    하지만 3번째에 abcde를 입력했을 땐(실제로는 변수 a의 값에 'a'를 입력하려는 시도) std::cin.fail()이 참값을 반환해서 아래 조건문이 실행된다.
    "비정상"이라는 문장을 출력한 후, 내부상태플러그를 초기화 시키고, 입력버퍼에서 abcde를 지워준다.
    이때 살펴볼 것은 cin.ignore(5, '\n'); 가 n의 값으로 5를 설정했기 때문에
    "abcde"는 한 번에 입력버퍼에서 비워지며 조건문이 한 번만 실행되지만


    4번째 입력 "abcdef"는 "abcde"가 한 번에 입력버퍼에서 비워져도 6번째 문자 'f'가 아직 입력버퍼에 남아있게 되어서 정수형 변수 a에 'f'가 입력되려는 잘못된 시도를 하게 되고 조건문이 한 번 더 실행된다.





출처 : 티스토리, "[C++] std::cin.ignore(), std::cin.clear(), std::cin.fail() 함수", https://dntworry-behappy.tistory.com/2, (2020. 2. 11.)

0개의 댓글