CPP/Cpp module

[Cpp 개념공부]__cin에서 endof 를 쏴줄 때 cin이 다시 사용하지 못하는 이슈__

뜨거운 개발자 2023. 1. 13. 01:44

나의 궁금증을 한줄로 요약하자면

안녕하세요 혹시 cin을 입력 받을 때 유닉스의 경우 ctrl+d 윈도우의 경우 ctrl+z를 입력하면 endof를 입력이 되는걸로 알고 있는데 이렇게 입력을 받고나면은 다른 cin은 전부 실행이 되지 않고, 끝나게 됩니다. cin이 endof를 받게되면 endofbit를 초기화해서 stdin을 사용하지 못하게 하는 것 같은데, 이것을 혹시 되돌려서 다시 cin 즉 stdin을 받는 방법을 아실까 싶어서 댓글 남겨봅니다. 감사합니다!

cin에서 endof 를 쏴줄 때 cin이 다시 사용하지 못하도록 변하는 것 같다.

이 문제를 어떻게 해결 할 수 있을까?

완전히 고장나는 것일까? try catch를 하는 것 말고 cin을 고치는 방법은 없는 걸까?

window와 unix에서의 eof입력

EOF가 Windows와 Linux에서 다르게 트리거된다는 점에 유의하는 것이 중요합니다. 

unix의 경우 CTRL + D, Windows의 경우 CTRL+ Z를 사용해서 eof를 사용합니다.

ctrl d까지 입력을 받는 코드 예시

std::string line;
while (std::getline(std::cin, line))
{
    std::cout << line << std::endl;
}

#include <iostream>

int main()
{
	using namespace std;

	int a, b;

	while(true) {
		cin >> a >> b;
		if (cin.eof()) break;
		cout << a + b << "\n";
	}

	return 0;
}

이 코드를 사용해도 사실 저 if (cin.endof()) break;사용하나 사용하지 않나 결과 같은 똑같았다.

#include <iostream>

int main()
{
	std::string command;
	while (true) {
		getline(std::cin,command);
		if (std::cin.eof()==1) {
			std::cin.clear();
			std::cin.ignore();
			continue;
			}
		cout << command << endl;
	}
}

이렇게 코드를 짜면 실제로 종료가 되지는 않는다. 다만, cin이 더이상 입력을 받지 않고 그냥 고장난 cin을 계속해서 사용하는샘이다.

이슈 해결

슬랙에 있는 글을 찾아보니 나보다 먼저 이 부분에 대해서 궁금해한 카댓이 있었다.

여기서 너무 토론을 잘 해주셨는데, ctrl + d를 쏴주는 것이 나는 당연히 그냥 평범하게 프로그램에 012이런식으로 입력하듯이 프로그램에 endof를 입력하는 것이라고 생각했는데, ctrl+d를 사용하는 건 터미널에서 실행되기 때문에 어플리케이션의 stdin을 받아버리는 것이라고 한다.

따라서 내가 처음에 하고 싶었던 방법은 cleareer함수를 사용해서 해결 할 수 있을 것이다.

clearerr
아직 C 언어와 친숙하지 않다면, 씹어먹는 C 언어 강좌 를 보는 것이 어떻까요? 오류 표시자를 초기화(clear) 한다. 스트림의 EOF 표시자와 오류 표시자를 모두 재설정(reset) 한다. 만일 스트림 함수가 오류 혹은 파일끝에 도달하였기 때문에 실패한다면, 이 두 개의 표시자들 중 하나가 설정된다. 이 표시자들은 rewind, fseek, fsetpos 함수 들 중 어느 하나가 호출 되기 전 까지 변경되지 않는다.
https://modoocode.com/50
ios::eof
이 레퍼런스의 모든 내용은 여기 를 기초로 하여 작성하였습니다. 아직 C++ 에 친숙하지 않다면 씹어먹는 C++ 은 어때요? eofbit 이 설정되었는지 확인한다. 이 함수는 스트림의 eofbit 오류 상태 플래그가 이전의 입출력 작업으로 인해 설정되었을 때 true 를 리턴한다. eofbit 플래그는 입력 작업 중 파일 끝(End Of File) 에 도달하였을 때 설정되는 플래그 이다.
https://modoocode.com/167

clearerr함수는오류와 스트림의 endof 표시자를 재설정 한다고 한다.

다만 file스트림으로 줘야하는 인수가 무엇인지 모르겠어서 문제가 생긴다.

따라서 내가 생각했던 이슈를 해결하려면, 이 글에도 내가 원하는 내용은 나와있지 않고

C++언어 정리하기 - cout과 cin
이번 내용을 시작하기 전에안녕하세요 루벤딕스입니다. 저번 포스팅에서는 main() 진입 전의 초기화를 알아...
https://m.blog.naver.com/ruvendix/220953194013

미해결… 아마도 그냥 endof에 도달하면 그냥 끝내는 식으로 타협을 봐야 할 것 같다라고 생각했으나 내 생각을 부셔줬다.

진짜 해결

위와 같이 ft_cin함수를 사용해서 입력을 해줬다.

void	Contact ::ft_cin(std::string &s)
{
	fflush(stdin);
	std::cin.clear();
	clearerr(stdin);
	getline(std::cin,first_name);
}

해결 코드

cin을 command +d 를 했을 때 생기는 문제는 clearerr함수를 사용해서 해결 할 수 있었다.

위 코드를 통해서 printable하지 않은 입력이 들어왔을 때 해결 뿐 아니라, ctrl+d로 eofbit를 true로 초기화되어있는 경우 다시 원상태로 복구하여서 프로그램이 바로 종료되는 것을 막아주었다.

bool	check_printable(std ::string s)
{
	int	size(s.size());
	for (int i=0;i < size;i++)
	{
		if (!(std:: isprint(s[i])))
			return (1);
	}
	return (0);
}
void	print_if_non_printable(void)
{
	std:: cout << "!!Please provide valid input!!\n";
}
void	Contact ::ft_cin(std::string &s)
{
	fflush(stdin);
	std::cin.clear();
	clearerr(stdin);
	getline(std::cin,s);
}

void	Contact ::add_contact(void)
{
	std ::cout << "please input first name\n";
	ft_cin(first_name);
	while (std::cin.eof() || check_printable(first_name))
	{
		print_if_non_printable();
		std ::cout << "please input first name\n";
		ft_cin(first_name);
	}
...
}

Uploaded by N2T

728x90