과거에 C언어를 한참 배웠을때 진행했던 프로젝트이다....
1. 메인 소스코드
/*전처리 지시자*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <windows.h>
#include <mmsystem.h>
#include "ideal.h"
#pragma comment (lib, "winmm.lib")
int main() {
Custom cus;
int selection;
system("mode con cols=60 lines=35"); // 콘솔창 크기
main:
selection = main_menu();
if (selection == -1) return -1;
cus = user_custom(selection);
if (cus.round == -1) goto main; // round.user가 -1이 반환값이라면 파일 오류..
char* cand = (char*)malloc(sizeof(char) * cus.round);
random_candidate(*cand , cus.file_txt, cus.round);
return 0;
}
2. 헤더파일
/*구조체*/
// 사용자가 선택하는 데이터를 담을 사용자 정의 자료형
typedef struct {
char file_txt[100];
int round;
} Custom;
// 구조체 타입재정의 Custom
/*열거형*/
// SetColor 함수에 인수로 들어가는 열거형 정의
typedef enum {
BLACK,
DARK_BLUE,
DARK_GREEN,
DARK_SKYBLUE,
DARK_RED,
DARK_VOILET,
DAKR_YELLOW,
GRAY,
DARK_GRAY,
BLUE,
GREEN,
SKYBLUE,
RED,
VIOLET,
YELLOW,
WHITE,
} Color;
// 열거형 타입 재정의 Color
/*함수선언*/
int ch_max(FILE* TXT); // 파일 글자 수의 최대 값을 파악하여 리턴 함
void line_printer(int max); // 매개변수로 들어간 수 만큼 라인을 만들어줌
Custom user_custom(int select_num); // 사용자의 정의 (선택한 파일, 몇 강 진행, 텍스트파일의 배열 주소값)
char* select_txt(int select_num); // 선택한 번호를 넣으면, txt형태로 반환해준다.
int round_find (int cand_cnt); // 후보 갯수를 넣으면 후보 갯수 이하의 가장 가까운 라운드를 반환한다.
int round_num(int round_max); // 최대라운드 값을 넣으면 2강 까지의 가능한 라운드 수를 반환
void round_ary(int round_max ,int* ary, int num ); // 라운드의 최대값, 배열의 주소값과 2부터 가능한 라운드 수를 계산하여 넣으면 배열에 가능한 라운드를 저장
void random_candidate(char* candidate, char* file_txt, int round); // 랜덤한 후보들을 배치! 인수로 (후보파일명, 유저가 선택한 라운드)
void setColor(Color text) {
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), text);
}
/*메인메뉴*/
int main_menu(void) {
FILE* event; // 파일 구조체 포인터
int ch; // txt 파일 위치지시자를 담을 변수
unsigned int event_cnt = 0; // 종목 갯수의 카운트 용도
unsigned int max_cnt = 0;
unsigned int event_select;
unsigned int cnt = 0;
unsigned int event_add = 0 ,cand_add = 0;
system("cls");
PlaySound(TEXT("main.wav"), NULL, SND_FILENAME | SND_ASYNC);
setColor(DAKR_YELLOW);
printf(" ■■■■■■■■■■■■ \n");
printf(" ■ 이상형 월드컵 v1.0 ■ \n");
printf(" ■■■■■■■■■■■■ \n");
event = fopen("event.txt", "r");
if (event == NULL)
{
setColor(RED);
printf("\a [ERROR] 종목 파일을 불러오지 못하였습니다.");
return -1;
}
setColor(BLUE);
printf("\n ■■■■■\n");
printf(" ■ 종목 ■ \n");
printf(" ■■■■■ \n");
printf("\n");
setColor(YELLOW);
/*파일 출력 글자의 최대 글자수 파악*/
max_cnt = ch_max(event);
max_cnt++;
line_printer(max_cnt);
printf("\n");
while (1)
{
ch = fgetc(event);
if (ch == EOF) break;
else if (ch == '\n')
{
printf("\n");
line_printer(max_cnt);
event_cnt++; // 종목 갯수를 카운트, 엔터 개행문자의 갯수를 파악함.
}
putchar(ch);
}
event_cnt++;// 엔터의 갯수를 파악 했으므로 while문을 빠져나오면 +1을 해준다
event_add = (event_cnt + 1);
cand_add = (event_cnt + 2);
printf("\n");
line_printer(max_cnt);
printf("\n[%d] 종목 추가\n", event_add );
line_printer(max_cnt);
printf("\n[%d] 후보 추가\n", cand_add );
line_printer(max_cnt);
fclose(event);
// 종목선택
select:
setColor(WHITE);
printf("\n 번호를 선택하세요: ");
if (scanf_s("%d", &event_select) == 0) // scanf 함수는 이상한 값이 들어오면 0을 반환한다.
{
setColor(RED);
rewind(stdin); // 표준 입력 버퍼에 담긴 모든 문자를 제거
printf(" \a[ ERROR ] : 입력을 다시 확인하세요!");
goto select; // 예외처리 무조건 분기문
}
else if (event_select > cand_add || event_select < 0)
{
setColor(RED);
printf(" \a[ ERROR ] : 범위를 다시 확인하세요!");
rewind(stdin); // 표준 입력 버퍼에 담긴 모든 문자를 제거
goto select; // 예외처리 무조건 분기문
}
return event_select;
}
int ch_max(FILE* TXT)
{
int ch; // txt 파일 위치지시자를 담을 변수
unsigned int ch_cnt = 0, max = 0; // 글자의 갯수를 카운트할 변수, 최댓값을 저장
while (1)
{
ch = fgetc(TXT);
if (ch == EOF) break;
else if (ch == '\n') ch_cnt = 0;
ch_cnt++;
if (ch_cnt > max) max = ch_cnt;
}
rewind(TXT);
return max;
}
void line_printer(int max)
{
for (int i = 0; i < max; i++) printf("─");
}
Custom user_custom(int select_num ) // user.round가 -1반환이면 오류
{
int ch;// 파일 위치지시자를 담을 변수
int cnt = 0;
int round_max = 0; // round의 최대값을 담을 변수
FILE* select_event;
Custom user; // 구조체 변수 user
Custom* p_user = &user; // 구조체 user 포인터
setColor(DARK_GREEN);
system("cls");
PlaySound(TEXT("main.wav"), NULL, SND_FILENAME | SND_ASYNC);
strcpy((p_user->file_txt), select_txt(select_num));
printf("───────────────────────────────────────────\n");
printf(" ※ %s 파일을 열겠습니다. ※ \n", (p_user->file_txt));
printf("───────────────────────────────────────────\n");
Sleep(500);
select_event = fopen(user.file_txt, "r");
if (select_event == NULL)
{
setColor(RED);
printf("───────────────────────────────────────────\n");
printf("\a[ERROR] %s 파일을 불러오지 못하였습니다.\n", user.file_txt);
printf("───────────────────────────────────────────\n");
user.round = -1; // -1 오류값 반환
Sleep(3000);
return user;
}
while (1)
{
ch = fgetc(select_event);
if (ch == ';') break; //후보파일의 마지막후보는 끝에 ;를 표시하기로 약속.
else if (ch == EOF)
{
fclose(select_event);
setColor(RED);
printf("─────────────────────────────────────────────\n");
printf("\a[ERROR] ; 지시자가 없습니다. 후보파일 에러\n");
printf("─────────────────────────────────────────────\n");
user.round = -1; // -1 오류값 반환
Sleep(3000);
return user;
}
else if (ch == '\n') cnt++; // 후보 갯수를 카운트
}
cnt++;
fclose(select_event); // 파일 닫기.
setColor(SKYBLUE);
printf("───────────────────────────────────────────\n");
printf(" 총 %3d개의 후보를 탐색하였습니다.\n", cnt);
printf("───────────────────────────────────────────\n");
round_max = round_find(cnt);
if (round_max == -1)
{
setColor(RED);
printf("─────────────────────────────────────────────\n");
printf("\a[ERROR] 후보가 2개 미만의 잘못 된 후보 파일 \n");
printf("─────────────────────────────────────────────\n");
user.round = -1;
Sleep(3000);
return user;
}
select:
setColor(WHITE);
printf("─────────────────────────────────────────────");
printf("\n%3d강 이하 부터 시작 할 수 있습니다.\n", round_max);
printf("─────────────────────────────────────────────\n");
int num = round_num(round_max);
int* ary = (int*)malloc(sizeof(int) * num);
round_ary(round_max, ary, num);
printf("\n 몇 강을 진행하시겠습니까? : ");
int round_tmp = 0;
if (scanf_s("%d", &round_tmp) == 0)
{
setColor(RED);
rewind(stdin); // 표준 입력 버퍼에 담긴 모든 문자를 제거
printf("\a [ ERROR ] : 입력을 다시 확인하세요!\n");
goto select; // 예외처리 무조건 분기문
}
if (round_tmp >= num || round_tmp < 0)
{
setColor(RED);
rewind(stdin); // 표준 입력 버퍼에 담긴 모든 문자를 제거
printf("\a [ ERROR ] : 가능한 숫자를 입력하세요!\n");
goto select;
}
setColor(YELLOW);
user.round = ary[round_tmp];
PlaySound(TEXT("main.wav"), NULL, SND_FILENAME | SND_ASYNC);
printf("\n─────────────────────────────────────────────\n");
printf("\n %3d강을 선택하셨습니다.\n", user.round);
printf("\n─────────────────────────────────────────────\n");
Sleep(3000);
return user;
}
char* select_txt(int select_num)
{
char buffer[100];
itoa(select_num, buffer, 10); // itoa 함수 : int형을 10진수로 표현하여 문자열로 담는다.
strcat(buffer, ".txt"); // strcat 함수 : 앞에 인수로 받은 문자열에 뒤의 인수로 받은 문자열을 더한다.
return buffer;
}
int round_find(int cand_cnt)
{
if (cand_cnt <= 1) return -1;
int x = 2;
while (1)
{
if (x < cand_cnt) x *= 2; // 2의 거듭제곱이 인수보다 작으면 계속 2를 곱함
else if (x == cand_cnt) break; // 2의 거듭제곱이 인수와 같으면 바로 브레이크
else if (x > cand_cnt) { x /= 2; break;} // 2의 거듭제곱이 인수보다 크면 2로 나눈뒤 브레이크
}
return x;
}
int round_num(int round_max)
{
int cnt = 0; // 카운트 용도
while (round_max > 1)
{
if (round_max == 2) {cnt++; break;}
round_max /= 2;
cnt++;
}
return cnt;
}
void round_ary(int round_max , int* ary, int num)
{
printf("─────────────────────────────────────────────\n");
for (int i = 0; i < num; i++)
{
ary[i] = round_max;
printf("[%d]:%3d강 | %3d강으로 진행! \n", i, ary[i], ary[i]);
if(i < (num-1)) printf("─────────────────────────────────────────────\n");
round_max /= 2;
}
printf("─────────────────────────────────────────────\n");
}
/*후보 배열 랜덤으로 정렬하기*/
void random_candidate (char** candidate ,char* file_txt, int round)
{
}
마지막 헤더파일은 작성하다 말았다....
3. 윈도우 콘솔 실행화면
'Embedded System > 소프트웨어 (C,C++)' 카테고리의 다른 글
[C/C++] Call By Value, Call by address (0) | 2023.08.07 |
---|---|
[Arduino] Wire 라이브러리 (0) | 2023.04.19 |
[Arduino] Servo 라이브러리 (0) | 2023.04.06 |
임베디드 C언어/ 툴체인 개념 (0) | 2023.01.31 |
[C/C++] 포인터 개념 정리 (0) | 2022.12.21 |