표준 입출력

하루공부·2024년 1월 24일
0

C++

목록 보기
22/25
post-thumbnail

C++ 아이콘 제작자: Darius Dan - Flaticon


ios_base

  • 스트림의 가장 기초적인 부분이다.
  • 모든 스트림 객체의 공통적인 부분을 의미한다 아래 같은 정보를 관리한다.

  • 서식 정보
  1. format flag : 입출력 작업들이 어떤 형식으로 해석될지 결정하는 내부 지시자들의 집합이다.
    ㄴ fmtflags flags() const; ==> 현재 스트림의 format flag가 어떻게 설정되어 있는지 알려준다
    ㄴ fmtflags flags(fmtflags fmtfl); ==> 인자로 전달된 플래그로 format flag를 설정하고 기존의 플래그를 리턴한다. (기존 플래그는 지워짐 ==> 새로운 플래그로 덮어짐)
    여기서 원하는 서식 플래그만 바꾸고 싶으면 setf함수나 unsetf함수를 사용한다.

    format flag 종류는 여기에 format flag

  1. 필드 너비 : 출력될 다음 원소의 너비의 정보 width함수로 현재 정보를 가져오거나 수정한다
  1. 출력 정밀도(display precision) : 부동 소수점 데이터 출력시 몇자리 까지 출력할지 설정 precision 함수로 정보를 가져오거나 수정한다

  • 상태 정보
  1. 오류 상태 : 내부 지시자가 현재 스트림의 오류 상태를 나타낸다.
    ㄴ 현재 오류 상태 플래그를 얻는 방법은 iostate rdstate() const; 함수호출시 플래그를 리턴한다
    ㄴ 해당 플래그는 오류에 따라 자동으로 설정됨

    • goodbit : 오류 없음
    • badbit : 스트림에 복구 불가능한 오류 발생시
    • failbit : 스트림에 복구 가능한 오류 발생시
    • eofbit : 입력 작업시에 EOF 도달시

  • 각각의 오류상태가 설정되었는지 확인하는 함수가 있고 clear와 setstate로 수정한다.
  1. 예외 마스크: 내부 예외 상태 지시자. exceptions()함수로 현재 정보를 가져오거나 수정한다

등등...
위에서 말한 함수로 현재 정보를 가져오거나 수정하는 함수 사용법은 ios_base 참조



Manipulation(조작자)

  • 아래 처럼 스트림을 조작하여 스트림 방식을 바꿔주는 함수이다.
    std::cin >> std::hex >> 1
    ==> hex가 방식을 바꿔버림.

    위의 format 플래그 hex는 단순한 값이지만 조작자의 hex의 경우 함수이다.
    >> 또는 <<와 함께 사용하여 단순히 format플래그를 설정하는 함수이다.

    위 hex의 경우 setf(std::ios_base::hex, std::ios_base::basefield)를 수행

다양한 조작자는 manipulator 참조




streambuf

  • 모든 입출력 객체들은 이에 대응되는 스트림 객체를 가지고 있는데 C++ 의 입출력 라이브러리에는
    대응되는 스트림 버퍼 클래스도 있는데 이름이 streambuf 클래스 이다.
    (스트림이란 그냥 흐름, 문자들의 나열 정도로 생각하면 편하다.)
  • 해당 클래스는 스트림에 대해 가장 기본적인 제어를 담당한다.

입력 객체 cin 의 rdbuf 를 호출하게 되면, cin 객체가 입력을 수행하고 있던 streambuf 객체를 가리키는 포인터를 리턴하게 된다.

  • snextc 함수는 스트림 위치 지정자를 한 칸 전진시킨 후 그 자리에 해당하는 문자를 엿본다.
  • 엿보는 것과 읽는 것의 차이점은 보통 streambuf 객체에서 읽게 되면 스트림 위치 지정자를 한 칸 전진시켜서 다음 읽기 때 다음 문자를 읽을 수 있도록 준비를 한다.
  • 하지만 엿본다는 것은, 해당 문자를 읽고도 스트림 위치 지정자를 움직이지 않는다.
    따라서 다음 읽기 때 엿본 문자를 읽을 수 있다.

C++ 에서 streambuf 를 도입한 중요한 이유는
1 바이트 짜리 문자 뿐만이 아니라 wchar_t 같은 다중 바이트 문자들 (우리가흔히 말하는 UTF-8 같은 것)에 대한 처리도 용이하게 하기 위해서 생겨났다.



문자열 스트림

  • sstream 헤더 파일에는 std::istringstream 이 정의되어 있는데 문자열을 하나의 스트림이라 생각하게 해주는 가상화 장치이다

std::istringstream ss("123");

문자열 "123" 이 기록되어 있는 입력 스트림을 생성.
마치 파일에 123 이라 기록해놓고 거기서 입력 받는 것과 동일하다고 생각하면 된다.

int x;
ss >> x; // 위에서 기록한 문자열 123을 숫자로 출력

그래서 마치 파일에서 숫자를 읽어내는 것 처럼 std::istringstream 을 통해서 123 을 읽을 수 있다.
거꾸로 데이터를 출력할 수 있는 std::ostringstream 가 있다.

std::ostringstream ss(1);
ss << x;
ss.str();

반대로 1이 들어있는 문자열 스트림에 출력했다.



리터럴

  • C 에서 문자열 리터럴을 정의하기 위해선 아래와 같이 하였다.
const char* s = "hello";
char s[] = "hello";
  • C++ 의 경우는?
    auto str = "hello"를 하면 str 는 string가 아닌 const char * 로 정의된다.

string으로 만들고 싶다면 string str = "hello" 처럼 타입을 꼭 명시해줘야 한다.
하지만 C++ 14 에 이 문제를 깜찍하게 해결할 수 있는 방법인 리터럴 연산자가 생겼다


auto str = "hello"s;

  • 위와 같이 " " 뒤에 s 를 붙여주면 auto 가 string 으로 추론된다.

    std::string operator"" s(const char *str, std::size_t len); 처럼 정의
    위의 "hello"s 는 컴파일 과정에서 operator""s("hello", 5); 로 컴파일이 해석한다.
    참고로 해당 리터럴 연산자를 사용하기 위해서는 std::string_literals 네임스페이스를 사용해야 한다.


  • C++ 11 에 추가된 유용한 기능으로 Raw string literal 이라는 것이 생겼다.
std::string str = R"(asdfasdf 
이 안에는
어떤 것들이 와도
// 이런것도 되고
#define hasldfjalskdfj
\n\n <--- Escape 안해도 됨
)";

==> ()안의 모든 내용이 특수문자도 다 출력됨

R"()" 안에 오는 문자들은 모두 문자 그대로 char 배열 안에 들어가게 간다.
원래라면 특수기호 같은 경우는 /를 앞에 써줘야하지만 무엇이든지 그냥 그대로 문자로 들어간다.

다만 한 가지 문제는 닫는 괄호 )" 를 문자열 안에 넣을 수 없다는 점입니다.
하지만 이는 구분 문자를 추가함으로써 해결 가능하다.
std::string str = R"foo(
)"; <-- 무시됨
)foo"; 출력 : )"; <-- 무시됨
보면 foo라는 기준으로 문자를 구분한다.

Raw string 문법을 정확히 살펴보자면
R" /* delimiter */ ( /* 문자열 */ ) /* delimiter */ "
delimiter는 구분자로써 () 밖에서 작성해주는데 복잡하다고 느끼면 문자로 된 괄호라고 생각하면 편하다.


format flag
ios_base
manipulator
공부한 내용 복습

개인 공부 기록용 블로그입니다.
틀린 부분 있으다면 지적해주시면 감사하겠습니다!!

0개의 댓글