사용자 입력, 연사 기능

조진호·2023년 5월 3일
0

우리는 그동안 scanf를 통해 입력을 받았으나 이 함수 외에도 다른 많은 함수들이 있다.

fgetc, getc, getchar 등 다양한 함수들이 있는데 어떤 차이가 있을까?

사용자 입력

fgetc

#include <stdio.h>

int fgetc(FILE* stream);

스트림(stream) 에서 문자 하나를 읽어온다

인자로 전달한 stream의 파일 위치 지정자가 가리키는 문자를 리턴한다. 이 때 파일 위치 지정자는 그 다음 문자를 가리키게 된다.

왜 리턴값이 int인가요?

fgetc는 읽어들인 문자를 int값으로 리턴하는데 이는 EOF를 리턴하기 위함이다.

EOF의 int값은 -1로, 만일 파일의 끝(End-of-File) 에 도달하였거나, 읽는 도중 오류가 발생하였다면 EOF를 리턴하고, 이에 대응하는 오류 표시자나 파일 끝 표시자가 설정된다.

getc

getcfgetc와 기능적으로 동일하지만 getc는 매크로 형태로 구현이 되어있는 반면, fgetc는 함수 형태로 구현되어 있다.
getc는 매크로 형태로 구현되어 있어 fgetc보다 속도가 빠르다는 이점이 있다.

getchar

#define getchar getc(File* stream)

int getchar(void)

getchar 함수는 결국 getc 함수를 좀 더 편하게 사용할 수 있도록 만들어진 매크로 함수로, 스트림을 인자로 받지 않는다는 편리성을 지니고 있다.


위 세 함수에 대해 알아보았으니 이제 다음과 같은 질문을 해도 되겠다.

scanf는 왜 getchar()보다 느린 것인가?

scanf 함수는 키보드로 부터 input을 받아 format specifer (출력 타입 %d, %c...)에 저장시킨다. 이때 format specifer variable이 읽을 수 있는지 없는지를 확인하는데 getchar함수는 그런 과정 없이 바로 읽어 성능이 더 빠르다.


그러나 아직 끝난게 아니다. getchegetch 함수가 남았다.
먼저 getch를 사용하기 위해선 conio.h란 헤더를 이용하여야 한다.
conio란 console input/output을 뜻한다.

getchar(), getch(), getche()간의 차이

비교getchar()getche()getch()
버퍼 사용OXX
화면 표시OOX
종료 인식\n\r\r
  • 첫 번째 차이는 버퍼의 사용유무에 있다.

getchar는 버퍼를 사용하고 getchgetche는 버퍼를 사용하지 않는다.
입력을 하면 바로 들어가는게 아니라 입력버퍼 라는 곳에 담긴다. 엔터가 들어올 때 까지 입력을 계속 담아두다가 엔터가 들어오면 입력을 중지하고 지금까지 입력된 내용에서 첫 글자를 리턴한다. 따라서 잘못 입력해도 엔터를 치기 전엔 수정 가능하다.

버퍼를 사용하지 않는 경우는 키보드를 눌렀다가 떼는 동시에 그 값을 가져가 버린다.

  • 두 번째 차이는 화면 표시의 차이에 있다.

getch의 경우 입력하는 값이 화면에 나타나지 않는다
getche() 의 경우 입력하는 값이 화면에 출력되며 이를 echo 라고 해서 앞자를 딴 e가 붙는다고 한다.
getchar() 또한 화면에 나타난다

  • 세 번째 차이는 종료 인식의 차이에 있다.

각각의 함수가 Enter 값을 인식하는데 차이가 있다.
getchar()의 경우 \n 으로 인식, getch(), getche() 는 \r 인식한다.


연사 기능

int main()
{
	Canvas* canvas = new Canvas(80);
	Player* player = new Player("(^___^)", 50, true);
	Enemy* enemy = new Enemy("(*-*)", 10, true);

	const int max_bullets = 5;

	Bullet* bullets[max_bullets];
	for (int i = 0; i < max_bullets; i++) {
		bullets[i] = nullptr;
	}

	while (true)
	{
		canvas->clear();
		

		if (_kbhit()) {
			Bullet* found;
			char input = _getch();
			switch (tolower(input)) {
			case 'a': player->setPos(player->getPos() - 1);
				break;
			case 'd': player->setPos(player->getPos() + 1);
				break;
			case ' ': 
				found = nullptr;
				for (int i = 0; i < max_bullets; i++) {
					Bullet* bullet = bullets[i];
					if (bullet == nullptr) { //이렇게 하는 것보다 bullets 초기화 단계에서 동적할당을 하는 것이 낫지 않았나?
						bullet = new Bullet(">", 0, false, 0, 0);
						bullets[i] = bullet;
						found = bullet;
						break;
					}

					if (bullet->isVisible() == true) continue;
					found = bullet;
					break;
				}
				if (found != nullptr) found->fire(*player, *enemy);
			}
		}

		player->draw(*canvas);
		enemy->draw(*canvas);
		for (int i = 0; i < max_bullets; i++) {
			if (bullets[i] == nullptr) continue;
			bullets[i]->draw(*canvas);
		}

		player->update();
		enemy->update();
		for (int i = 0; i < max_bullets; i++) {
			if (bullets[i] == nullptr) continue;
			bullets[i]->update(*player, *enemy);
		}

		canvas->render();
		Sleep(100);
	}

	for (int i = 0; i < max_bullets; i++) {
		delete bullets[i];
	}
	delete[] bullets;
	delete enemy;
	delete player;
	delete canvas;

	return 0;
}
int main()
{
	Canvas* canvas = new Canvas(80);
	Player* player = new Player("(^___^)", 50, true);
	Enemy* enemy = new Enemy("(*-*)", 10, true);

	const int max_bullets = 5;

	Bullet* bullets[max_bullets];
	for (int i = 0; i < max_bullets; i++) {
		bullets[i] = new Bullet(">", 0, false, 0, 0);
	}

	while (true)
	{
		canvas->clear();


		if (_kbhit()) {
			Bullet* found;
			char input = _getch();
			switch (tolower(input)) {
			case 'a': player->setPos(player->getPos() - 1);
				break;
			case 'd': player->setPos(player->getPos() + 1);
				break;
			case ' ':
				for (int i = 0; i < max_bullets; i++) {
					if (bullets[i]->isVisible() == false) {
						bullets[i]->fire(*player, *enemy);
						break;
					}
					else continue;
				}
			}
		}

		player->draw(*canvas);
		enemy->draw(*canvas);
		for (int i = 0; i < max_bullets; i++) {
			if (bullets[i] == nullptr) continue;
			bullets[i]->draw(*canvas);
		}

		player->update();
		enemy->update();
		for (int i = 0; i < max_bullets; i++) {
			if (bullets[i] == nullptr) continue;
			bullets[i]->update(*player, *enemy);
		}

		canvas->render();
		Sleep(100);
	}

	for (int i = 0; i < max_bullets; i++) {
		delete bullets[i];
	}
	delete[] bullets;
	delete enemy;
	delete player;
	delete canvas;

	return 0;
}
profile
코린이

0개의 댓글

관련 채용 정보