본문 바로가기
Topos Uranos

요약

입력은 세계가 프로그램으로 들어오는 경계이며, 세계는 명세를 지키지 않는다. 이 수업은 믿지 않고 읽는 법을 가르친다. 곧 std::getline 함수로 줄 전체를 읽고, 그것을 >> 연산자와 섞을 때 나타나는 빈 줄을 피하는 법, 스트림 상태를 조회하여 입력, 출력, 오류 수업에서는 뒤섞인 채로만 보았던 세 가지 상황(잘못된 데이터, 들어가지 않는 수, 데이터의 끝)을 구별하는 법, 실패한 읽기에서 clear 함수와 ignore 함수로 복구하는 법, 그리고 가장 안전한 방식으로서 각 데이터를 텍스트로 읽어 std::from_chars 함수로 변환하되 변환이 텍스트 전체를 소비한 경우에만 받아들이는 법이다. 마지막에는 계약을 갖춘 함수 readInt를 제시하며, 강좌의 나머지 부분에서 이것을 다시 쓸 수 있다.

학습 목표

  1. std::getline 함수로 줄 전체를 읽고, >> 연산자로 읽은 뒤에 오는 getline 호출이 왜 빈 줄을 돌려주는지 설명하며, 이를 std::ws 조작자로 피할 수 있다.
  2. 읽은 뒤에 fail() 함수와 eof() 함수로 스트림 상태를 조회하고, 이를 통해 잘못된 데이터, 자기 자료형에 들어가지 않는 수, 입력의 끝을 구별할 수 있다.
  3. 잘못된 입력에서 clear 함수와 ignore 함수로 복구하고, 입력이 끝나면 종료하는 읽기 반복문을 작성할 수 있다.
  4. 텍스트로 읽은 수를 std::from_chars 함수로 검증하되 오류가 없고 문자열 전체가 소비될 것을 요구하며, 그 검증을 계약을 갖춘 함수로 감쌀 수 있다.

다시, 경계

입력, 출력, 오류 수업은 std::cin >> n 문장에 관해 세 가지 사실을 확립했다. 읽기는 수를 이어 갈 수 없는 첫 문자에서, 그 문자를 소비하지 않고 멈춘다. 한 문자도 읽지 못하면 스트림은 오류 상태가 되고, 그 뒤의 모든 읽기는 아무것도 하지 않는다. 그리고 if (std::cin) 문장으로 무언가 실패했는지 알 수 있다. 반복문 수업은 조건 while (std::cin >> value) 문장이 입력이 끝날 때에도, 잘못된 데이터가 올 때에도 종료한다는 것을 덧붙였다. 그러나 이 도구들만으로는 프로그램이 무언가 잘못되었다는 것은 알아채지만 무엇이 잘못되었는지는 모르며, 포기하는 것 말고는 할 수 있는 일이 없다.

이 수업은 한 가지 설계 원리, 곧 경계에서의 방어적 프로그래밍에서 출발한다. 들어오는 모든 데이터는 쓰기 전에 검증하며, 그것을 검증하는 프로그램은 바로잡을 여지가 있는 잘못된 데이터(다시 요청하기, 건너뛰기, 보고하기)와 바로잡을 여지가 없는 데이터의 끝을 구별한다. 그렇다면 세 가지가 필요하다. 데이터를 쓰인 그대로, 곧 한 줄로 읽는 것, 읽기가 왜 실패했는지 아는 것, 그리고 스트림에 읽는 능력을 되돌려 주는 것이다.