Skip to content

Latest commit

 

History

History
148 lines (109 loc) · 4.51 KB

15_입출력.md

File metadata and controls

148 lines (109 loc) · 4.51 KB

입출력

다음은 c++의 입출력 라이브러리의 클래스 구조를 나타낸 것입니다.

  • ios_base

    • c++의 모든 입출력 클래스의 기반입니다.
    • 실수를 출력할 때 어떤 식으로 할지, 정수를 10진수 또는 16진수로 할지 등을 처리합니다.
  • ios

    • ios_base를 상속 받습니다.
    • 스트림 버퍼를 초기화합니다.
      • 스트림 버퍼는 데이터를 입출력하기 전에 임시로 저장하는 곳입니다.
      • 바로바로 입출력하면 오버헤드가 발생합니다.
    • 입출력 작업의 상태를 처리합니다.
      • 다음 4개의 비트로 상태를 판단합니다.
        • goodbit - 스트림에 입출력 작업이 가능
        • badbit - 스트림에 복구 불가능한 오류 발생
        • failbit - 스트림에 복구 가능한 오류 발생
        • eofbit - 입력 작업시 EOF에 도달
      • good, bad, fail, eof 함수를 가지고 있으며 각각 가리키는 비트의 상태를 반환합니다.
  • istream

    • ios를 상속받습니다.

    • operator >>가 정의되어 있습니다.

      • 기본 자료형에 대해 오버로드되어 있습니다.
      • 사용자가 별도로 정의하기 위해선 다음과 같이 작성하면 됩니다.
      istream& operator>> (istream& in, T& t) {
          // 구현
      }
    • cin는 istream 클래스의 객체 중 하나입니다.

    • cin >>는 모든 공백문자(띄어쓰기, 개행문자, 탭 등)을 입력받지 않습니다.

      • 다음 코드는 무한 루프에 빠질 수 있습니다.
      int n;
      
      while(true) {
          cin >> num;
          cout << num;
          
          if (t == 0)
              break;
      }
      • 만약 런타임 도중 문자 'c'를 입력하면 무한 루프에 빠지게 됩니다.
        • 타입에 맞지 않는 값을 넣었으므로 iosfailbit가 켜지게 됩니다.
        • 따라서 입력을 받지 않고 반환합니다.
        • 남아있는 'c\n'이 스트림 버퍼에 남게됩니다.
        • 루프에 의해 cin >>이 다시 스트림 버퍼를 읽게되고 위와 같은 문제가 반복됩니다.
      • 따라서 다음과 같이 코드를 수정해야 합니다.
      int n;
      
      while (cin >> n) {
          // 생략
      }
      • 문자 'c'를 입력하면 operator>>NULL 포인터를 반환하고 이것이 void*으로 변환되면서 while 조건문은 이를 false로 판단합니다.
      • 하지만 이럴 경우 다음 입력을 받지 못합니다.
      • 외에도 다음 코드처럼 작성하면 타입에 맞지 않는 입력을 무시하고 다음 입력을 받을 수 있습니다.
      int n;
      
      while (true) {
          cin >> n;
          cout << n;
          if (cin.fail()) {
              cout << "잘못된 입력입니다." << endl;
              cin.clear();  // 상태 비트 초기화
          	cin.ignore(100, '\n');  // 최대 100번, 개행문자가 나올 때까지 스트림 버퍼를 비웁니다.
          }
          
          if (n == 0)
              break;
      }
      • 다음 코드는 16진수를 입력으로 받는 방법입니다.
      std::cin >> std::hex >> n
      // input
      0xFF
      ff
      ABCDE
      
  • streambuf 클래스

    • 스트림에 대한 가장 기본적인 제어를 담당하고 있습니다.
    • 스트림의 상태를 나타내기 위해 3개의 포인터를 정의하고 있습니다.
      • 시작 포인터: 버퍼의 시작 부분을 가리키는 포인터
      • 스트림 위치 지정자: 다음으로 읽을 위치를 가리키는 포인터
      • 끝 포인터: 버퍼의 끝 부분을 가리키는 포인터
    • 입력 버퍼와 출력 버퍼를 각각 get areaput area라고 합니다.
    #include <iostream>
    #include <stream>
    
    int main() {
        std::string s;
        std::cin >> s;
        
        char peek = std::cin.rdbuf()->snextc();
        if (std::cin.fail())
            std::cout << "Fail" << endl;
        std::cout << '두 번째 단어 맨 앞글자 : ' << peek << std::endl;
        std::cin >> s;
        std::cout << "다시 읽으면 : " << s << std::endl;
    }
    // input
    hello world
    
    // output
    두 번째 단어 맨 앞글자 : w
    다시 읽으면 : world
    
    • std::cin >> s이후 스트림 위치 지정자는 "hello world"에서 ' '를 가리키고 있습니다.
    • snextc()는 스트림 위치 지정자가 다음 위치를 가리킵니다.
    • 따라서 두 번쨰 std::cin >> s를 실행하면 s에 "world"가 저장됩니다.