cin, cout

Yama·2024년 1월 12일
0

어소트락 수업

목록 보기
43/55

printf, scanf -> cout, cin

	cout << "Output" << endl;
	wcout << L"Output" << L"  Add" << endl;

  • cout은 ostream이라는 클래스에 잇는 전역변수일뿐이다.
    • ostream안에 operator를 구현을 해놨을것이다.
  • cout은 헤더파일에 extern으로 선언을해놔서 모든파일에서 접근가능하다.
  • 이걸 토대로 구현을해보장
class MyOStream
{

public:
	void operator << (const wchar_t* _str)
	{
		wprintf_s(L"%s", _str);
	}
};
mycout/*.operator*/ << L"Output";
  • 연산자 오버로딩을 한것이다.
	int i = 1;
	i <<= 2; // 4
  • <<는 원래 비트 쉬프트 연산자이지만 저 위의 cout의 <<는 연산자 오버로딩을 내부적으로해줘서 출력을 하는 용도로 됐당.
	wcout << L"Output" << L"  Add" << endl;
  • 표준 라이브러리처럼 문자열을 이어주고싶다.
	MyOStream& operator << (const wchar_t* _str)
	{
		wprintf_s(L"%s", _str);
		return  (*this);
	}
  • 반환타입을 자기를주고 레퍼런스로 참조시킴
  • 문자열을 이어서 출력할려면 반환값으로 본인(mycout)을 줘야한다.
	mycout/*.operator*/ << L"Output" << L"  Output" << L" Test" < endl;
  • 우리도 이어서 사용 가능해졌다.

endl;을 설명할려면 함수 포인터를 알아야한다.

  • 함수도 스택에 쌓이니까 분명히 주소가 있을것이다 이것을 가리켜서 주소를 주는 데 사용하는게 함수 포인터다.
void MyEndl()
{
	printf("\n");
}
  • 함수를 호출해주면 개행을 해주는 함수를 만들어두공.
  • 반환타입이 void이고 인자가 없다.
    • 이런 함수의 주소를 받는 함수의 포인터를 만들수 있다.(정답 아래)
	// 1
	void(*pFunc)(void) = nullptr;
    // 2
    (void)*pFunc(void) = nullptr;
    // 3
    (void)(pFunc*)void = nullptr;
    // 4
    void(pFunc)(void) = nullptr;
  • 정답 함수 포인터는 1번이다.
  • 반환타입은 void이고 포인터 변수명은 (*pFunc) 인자를 받지않는 (void)라 한다.
    • 잘 헥갈리므로 구분을 잘하자.
    • 실제 함수 선언할떄 인자는 괄호를 열고 인자를받고 반환타입은 괄호를 안쓴다.
      • void반환타입은 괄호가 없고
      • (void)입력 인자에는 함수를 선언할떄괄호로 열고 닫고
      • (*pFunc)변수명 가운데 적고 포인터니까 앞에 *을 붙인다.
    • 함수 포인터는 우리가 선언하는거랑 많이 달라서 면접에서 잘 물어본다.
	int Test(int _a, int _b)
	{
		return _a + _b;
	}
  • 인자를 두개받는 함수의 포인터도 맞춰줘야한다.
	int(*pFunc1)(int, int) = &Test;
  • 반환타입은 int
  • 인자는 (int, int)
  • 앞에 붙여서 포인터변수는 가운데 `(pFunc)`
	// 1
	mycout/*.operator*/ << L"Output" << L"  Output" << L" Test" < endl;
    // 2
    mycout/*.operator*/ << L"Output" << L"  Output" << L" Test" << &MyEndl;
  • 함수포인터를 이용해서 1번을 2번처럼 사용 가능하다.
    • 2번에서 &를 생략해도 문법오류는 아니다.
  • 함수 포인터를 이용한 이러한 설계도 가능
    • 나의 상태에 따라서 A함수 호출하고 저런 상황이면 B함수 호출하고 또 다른상황이면 C함수호출하는 매번 호출할때마다 의미 없는 비교를 맨날 할 것을 함수 포인터로 한번에 가능.
      • 이럴빠에는 내가 호출하는 모든 함수를 가리키는 함수포인터를 하나 만들어서 나의 상태가 변환하는 순간에 &MyEndl요런식으로 주소를 넣어버려서 함수에서 다른 함수로 변화는 상태일떄의 주소를 넣어두면 알아서 함수 포인터로 의미 없는 비교없이 바로 지목 가능.
	void operator << (void(*_pFunc)(void))
	{
		_pFunc();
	}
  • 함수포인터로 오버로딩한것.

cin

	int input = 0;
    MyCin >> input;
    cin >> input;
  • 우리 MyCin도 표준라이브러리에 cin처럼 쓰고싶다.
class MyIStream
{
public:
	void operator >> (const int* _input)
	{
		scanf_s("%d", _input);
	}
};
  • _input복사받은거니까 포이터와 레퍼런스로 접근가능.
  • 포인터를 이용한 오버로딩
	MyCin >> &input;
  • 우리 원하는 형태가 아니다.
class MyIStream
{
public:
	void operator >> (const int& _input)
	{
		scanf_s("%d", _input);
	}
};
  • 레퍼런스를 사용하면 우리가 원하는 형태로 완성
MyCin >> input;

강의코드

#pragma once

#include <iostream>

using std::cout;
using std::wcout;
using std::endl;

using std::cin;

// printf, scanf -> cout, cin

class MyOStream
{

public:
	MyOStream& operator << (const wchar_t* _str)
	{
		wprintf_s(L"%s", _str);
		return (*this);
	}

	void operator << (void(*_pFunc)(void))
	{
		_pFunc();
	}

};

MyOStream mycout;

void MyEndL()
{
	printf("\n");
}

int Test(int _a, int _b)
{
	return _a + _b;
}

class MyIStream
{
public:
	void operator >> (int& _input)
	{
		scanf_s("%d", &_input);
	}
};

MyIStream MyCin;


int main()
{
	int i = 1;
	i <<= 2;

	mycout << L"Output" << L"  Output" << L" Test" << MyEndL;

	// 함수 포인터
	void(*pFunc)(void) = &MyEndL;
	int(*pFunc1)(int, int) = &Test;

	pFunc();
	pFunc1(10, 20);

	cout << "Output" << endl;
	wcout << L"Output" << L"  Add" << endl;

	int input = 0;
	MyCin >> input;

	cin >> input;


	return 0;
}

1차 24.01.12
2차 24.01.15
3차 24.01.16
4차 24.01.17
5차 24.01.18

0개의 댓글