반응형
입출력 버퍼
  • 버퍼는 특정 크기의 메모리 공간을 의미
  • 운영체제가 버퍼를 생성하여 제공
  • 입출력 함수로 데이터 입출력 시 버퍼를 거친다.

출력함수가 반환 될 때 출력버퍼로 데이터가 전송된다.

엔터를 입력할 때 입력버퍼로 데이터가 전달된다.

 

 

 

fflush 함수 : 출력버퍼 비우는 함수

출력버퍼를 비워주는 함수.

출력버퍼를 비운다는것은 데이터를 지우는 것이 아니라,

저장된 데이터를 전송한다는 뜻.

fflush(stdout);

 

 

입력버퍼 비우는 방식

입력버퍼의 비움은 입력버퍼에 저장된 데이터의 소멸을 뜻한다.

아래의 방식으로 입력버퍼를 비울 수 있다.

while(getchar() != '\n');

 

반응형

 

반응형

'C' 카테고리의 다른 글

구조체  (0) 2023.05.22
문자열 관련 함수  (0) 2023.05.22
문자와 문자열 함수  (0) 2023.05.22
함수 포인터  (0) 2023.05.19
다차원 배열과 포인터의 관계  (0) 2023.05.18
반응형
스트림과 데이터의 이동

데이터는 한 방향으로 이동하는데 이것이 물이 흐르는 것과

유사하여 스트림(물의 흐름)이라 부릅니다.

 

이 스트림은 입출력장치에 사용된다.

 

컴퓨터 내부로의 데이터 이동은 입력,

외부로의 데이터 이동은 출력이다.

 

출력 스트림, 입력 스트림이 존재하기에 데이터 입출력이 가능하다.

 

입출력 스트림은 OS에서 데이터의 입출력을 위한 소프트웨어를 뜻한다.

 

 

 

스트림 생성 소멸
  • stdin : 표준 입력 스트림 / 키보드 대상으로 입력
  • stdout : 표준 출력 스트림 / 모니터 대상으로 출력
  • stderr : 표준 에러 스트림 / 모니터 대상으로 출력

스트림은 프로그램 시작과 동시에 형성되고 종료시 소멸된다.

출력 리다이렉션이라는 것을 통해서 stdout과 stderr이

향하는 데이터 전송 방향을 달리 할 수 있다.

 

 

 

문자 입출력 함수
  • 하나의 문자 출력 함수

함수호출 성공 시 문자정보, 실패 시 EOF 반환

EOF란 ? define상수 : -1

int putchar(int c);	// 인자로 전달된 문자를 출력
int fputs(int c, FILE* stream);	// 두 번째 인자를 통해서 출력대상 지정

 

  • 하나의 문자 입력 함수

파일 끝에 도달, 함수 호출 실패 시 EOF 반환

int getchar(void);	// 입력된 문자 정보 반환
int fgets(FILE* stream);	// 입력 받을 대상정보 인자로 전달

 

 

 

문자 입출력 예제
	int ch1, ch2;
	scanf("%c", &ch1);	// 123 입력, ch1 = 1

	ch1 = getchar();	// 2 입력
	ch2 = fgetc(stdin);	// 3 입력

	putchar(ch1);		// 2 출력
	fputc(ch2, stdout);	// 3 출력

 

콘솔창에서의 Ctrl + Z 는 EOF를 뜻한다.

 

 

puts, fputs : 문자열 출력 함수

성공 시 0이 아닌 값을, 실패 시 EOF 반환

int puts(const char* s);		// 문자열 출력 후 개행O
int fputs(const char* s, FILE* stream);	// 문자열만 출력, 개행X

 

 

gets, fgets : 문자열 입력 함수

파일의 끝에 도달하거나 함수호출 실패 시 NULL 포인터 반환

  • gets : 입력된 문자열의 길이가 배열을 넘어설 경우 할당 받지 않은 메모리 참조하는 오류 발생
  • fgets : 입력을 널 문자를 포함하여 n의 크기만큼 str에 저장한다.
char* gets(char* s);	// 문자열 입력
char* fgets(char* s, int n, FILE* stream);	// 문자열 입력

 

 

fgets 함수 예제

아래의 예제에서 fgets는 최대 6개의 문자를 입력받을 수 있다.

입력이 6개를 넘으면 그 다음 fgets로 넘어가게 되고, 6개를 안넘으면

입력을 계속 받는다. 엔터키와 공백또한 문자열로 받는다.

char str[7];
for(int i = 0; i < 3; i++)
{
    fgets(str, sizeof(str), stdin);
    printf("Read %d: %s \n", i+1, str);
}

// 입력 1 : 1234567890124567890
// Read 1: 123456
// Read 2 : 789012
// Read 3 : 345678

// 입력 2: Hi
// Read 1 : Hi
// 입력 : Hello
// Read 2 : Hello
// 입력 : good morning
// Read 3 : good m

 

반응형

 

반응형

'C' 카테고리의 다른 글

문자열 관련 함수  (0) 2023.05.22
표준 입출력 버퍼  (0) 2023.05.22
함수 포인터  (0) 2023.05.19
다차원 배열과 포인터의 관계  (0) 2023.05.18
다중포인터  (0) 2023.05.18
반응형
Debug모드

Debug모드는 해당 코드를 컴파일하면서 디버깅을 하고 빌드를 해서 exe실행파일을 만들어줍니다.

이 실행파일에 디버깅에 도움이 되는 파일까지 들어가서 exe실행파일의 용량이 더 커집니다.

 

Release모드

Release모드는 해당 코드를 컴파일하고 디버깅을 거치지 않고 빌드를 해서 exe실행파일을 만들어줍니다.

이 실행파일에는 디버깅에 도움이 되는 파일이 들어가지 않아서 더 적은 용량의 exe실행파일을 만들 수 있습니다.

테스트가 모든 끝난 파일을 만들때 사용하는 용도로 쓰면 됩니다.

 

 

 

x64, x86

x64는 64비트 모드를 뜻하며

x86은 32비트 모드를 뜻합니다.

x64모드에서는 프로그램이 커질수 있다

사용할 수 있는 메모리가 많아진다.

x86, 32비트 모드에서는 제한이 있다.

 

예전에는 하드웨어의 발달이 지금과는 달리 느렸기에

큰 어플리케이션을 쓸 경우가 많이 없었기에 

주로 x86모드에서 작업을 했지만,

 

최근에는 하드웨어 또한 많이 성장하여

최근에 나온 게임이나 어플리케이션은

x64모드를 많이 사용합니다.

 

반응형

 

반응형
반응형
#include <stdio.h>

void BoardPrint(int(*board)[3], int(*playerX)[3], int(*playerO)[3])
{

	for (int i = 0; i < 3; i++)
	{
		for (int j = 0; j < 3; j++)
		{
			if (board[i][j] == 1 && playerX[i][j] == 1)
			{
				printf("| %c ", 'X');
				continue;
			}

			if (board[i][j] == 1 && playerO[i][j] == 1)
			{
				printf("| %c ", 'O');
				continue;
			}
			printf("| %c  ", '\0');

		}
		printf("|\n");
	}


	//printf("| %c | %c | %c |\n", '\0', '\0', '\0');
	//printf("| - | - | - |\n");
	//printf("| %c | %c | %c |\n", '\0', '\0', '\0');
	//printf("| - | - | - |\n");
	//printf("| %c | %c | %c |\n", '\0', '\0', '\0');

}
int CheckCount(int(*player)[3])
{
	int count[3] = { 0 };
	for (int i = 0; i < 3; i++)
	{
		if (player[0][i] == 1)
			count[0]++;
		if (player[1][i] == 1)
			count[1]++;
		if (player[2][i] == 1)
			count[2]++;
		if (count[0] == 3)
			return count[0];
		else if (count[1] == 3)
			return count[1];
		else if (count[2] == 3)
			return count[2];
	}

	for (int i = 0; i < 3; i++)
		count[i] = 0;

	for (int i = 0; i < 3; i++)
	{
		if (player[i][0] == 1)
			count[0]++;
		if (player[i][1] == 1)
			count[1]++;
		if (player[i][2] == 1)
			count[2]++;
		if (count[0] == 3)
			return count[0];
		else if (count[1] == 3)
			return count[1];
		else if (count[2] == 3)
			return count[2];
	}

	for (int i = 0; i < 3; i++)
		count[i] = 0;

	for (int i = 0, j=0; i < 3; i++, j++)
	{
		if (player[i][j] == 1)
			count[0]++;
		if (count[0] == 3)
			return count[0];
	}
		count[0] = 0;

	for (int i = 2; i >= 0; i--)
	{
		if (player[2 - i][i])
			count[1]++;
		if (count[1] == 3)
			return count[1];
	}
	count[1] = 0;
	return 0;
}

int main()
{
	int playerXrow = 0;
	int playerXcol = 0;
	int playerX[3][3] = { 0 };

	int playerOrow = 0;
	int playerOcol = 0;
	int playerO[3][3] = { 0 };

	int board[3][3] = { 0 };
	int count = 0;
	int playerTurn = 0;
	int emptyCount = 9;

	while (count < 3 && emptyCount >0)
	{
		playerTurn = 0;
		if (playerTurn == 0)	// X 차례
		{
			printf("Player X, 움직임을 입력하세요(행[0 - 2]과 열[0 - 2]) : ");
			scanf("%d %d", &playerXrow, &playerXcol);
		}

		//보드판 채우기 중복 검사 , 잘못된 입력
		if (board[playerXrow][playerXcol] == 1 || playerXrow > 2 || playerXcol > 2 || playerXrow < 0 || playerXcol < 0)
		{
			printf("잘못된 움직임! 다시 시도해주세요.\n");
			continue;
		}

		// 보드판 채우기
		board[playerXrow][playerXcol] = 1;
		playerX[playerXrow][playerXcol] = 1;

		// 빈칸
		emptyCount--;

		// 보드판 출력
		BoardPrint(board, playerX, playerO);

		count = CheckCount(playerX);
		if (count == 3)
		{
			printf("플레이어 X 승리\n");
			break;
		}


		//턴넘김
		playerTurn++;
		while (count < 3 && playerTurn == 1 && emptyCount >0)
		{
			if (playerTurn == 1)	// O 차례
			{
				printf("Player O, 움직임을 입력하세요(행[0 - 2]과 열[0 - 2]) : ");
				scanf("%d %d", &playerOrow, &playerOcol);
			}

			//보드판 채우기 중복 검사 , 잘못된 입력
			if (board[playerOrow][playerOcol] == 1 || playerOrow > 2 || playerOcol > 2 || playerOrow < 0 || playerOcol < 0)
			{
				printf("잘못된 움직임! 다시 시도해주세요.\n");
				continue;
			}

			// 보드판 채우기
			board[playerOrow][playerOcol] = 1;
			playerO[playerOrow][playerOcol] = 1;


			// 빈칸
			emptyCount--;

			// 보드판 출력
			BoardPrint(board, playerX, playerO);
			count = CheckCount(playerO);
			if (count == 3)
			{
				printf("플레이어 O 승리\n");
				break;
			}

			// 턴 종료
			playerTurn = 0;
		}



		//출력


	}
	printf("게임 종료");
	return 0;
}

 

반응형

 

반응형

'연습문제' 카테고리의 다른 글

C언어 달팽이 정렬  (0) 2023.05.22
C언어 90도씩 회전하기  (0) 2023.05.22
C 포인터2 문제  (0) 2023.05.18
C 포인터 문제  (0) 2023.05.17
C언어 카드게임  (0) 2023.05.12
반응형
함수 포인터란?
  • 함수의 이름은 그 함수가 저장된 메모리의 주소이다 (함수 포인터)
  • 함수의 주소값을 함수 포인터 변수를 선언해서 저장할 수 있다.
  • 함수 포인터에 함수의 주소를 담아서 함수처럼 사용이 가능하다

 

 

 

함수 포인터 변수 선언

함수 포인터 변수는 아래와 같이 선언할 수 있습니다.

반환형 (*변수명) (매개변수 데이터타입, ...);

int (*fptr) (int, int);	// 반환형 (*변수명) (매개변수 데이터타입, ...);

 

아래와 같이 함수 포인터 변수를 선언하고

그 변수에 함수를 할당받고 함수처럼 사용하면

함수와 같이 동일하게 쓰입니다.

이렇게 함수 포인터 변수에 저장된 값을 통해서도

함수호출이 가능합니다!

int Add(int num1, num2){...}
int (*fptr) (int, int);

fptr = Add;
fptr(1, 2);	// Add(1, 2)와 동일한 결과를 보임

 

 

 

 

 

함수 포인터 주의사항

매개변수가 다르면 참조 불가능

반환형이나 매개변수가 다르면 다른타입이기에 함수 포인터 변수에

그 함수를 할당할 수 없다

 

함수 이름은 같지만 매개변수랑 반환형이 다르면 함수 포인터형이 다른것이다.

 

void 포인터

어떠한 주소 값도 저장이 가능한 void형 포인터

형 정보가 존재하지 않는 포인터 변수이기에 어떠한 주소 값도 저장이 가능하다.

형 정보가 존재하지 않기 때문에 메모리 접근을 위한 *연산은 불가능하다.

 

함수의 형태든 int형이든 다 저장이 가능하다.

주소 값만을 저장하기에 값 할당, 주소의 값을 가져오는

포인터 연산이 안된다.

 

 

 

void 포인터 주의사항

void 포인터 또한  int포인터로 형변환이 가능하다

하지만 void포인터에 함수형 또한 담기는데 함수주소를 담을때

int포인터로 강제 형변환을 하면 컴파일 에러는 없지만,

함수의 기능이 정수형으로 사용되는 오작동을 하게 된다.

 

반응형

 

반응형

'C' 카테고리의 다른 글

표준 입출력 버퍼  (0) 2023.05.22
문자와 문자열 함수  (0) 2023.05.22
다차원 배열과 포인터의 관계  (0) 2023.05.18
다중포인터  (0) 2023.05.18
다차원 배열  (0) 2023.05.17

+ Recent posts