// 이름과 숫자 1~4까지의 답 10개를 입력 받아 O,X 표시 및 평균 및 최고득점자와 최소 득점자 출력하는 로직
#include<stdio.h>
#include<windows.h>
#include<conio.h>
#define Read "c:\\saram.txt" // 데이터가 저장되어 있는 파일
#define Wirt "c:\\result.txt" // 결과값을 저장할 파일
int max=0, min=100; // max는 커져야 함을 0이고 min은 작아져야 함으로 100이다.
double avg=0;
struct AA // 사람 이름과 답을 저장해 놓은 구조체
{
char name[10];
char num[11];
};
void result(char *); // 데이터를 받아 계산한 후 result.txt로 저장하는 함수
void menu(char *); // 처음 select 화면을 보여주는 함수
void view(char *); // result.txt에 저장되어 있는 값을 보여주는 함수
void input(); // saram.txt에 데이터 추가 입력 하는 함수
void maxmin(); // 최대/최소 득점자와 점수 및 전체 평균값을 출력하는 함수
void main()
{
char anwer[11];
printf("정답을 입력해 주세요 : ");
scanf("%s", anwer);
result(anwer); // 문자열이기 때문에 주소값을 전달
system("cls"); // 화면 클리어
while(1)
{
menu(anwer); // menu의 포함된 함수에서 anwer의 주소값을 알아야 하기때문에 menu에도 주소값을 전달해야 한다
}
}
void menu(char *anwer) // 받을때는 *를 붙여서 주소값임을 명시해줘야 한다
{
char i;
printf("1.Input data\n");
printf("2.View data\n");
printf("3.Max / Min\n");
printf("4.Exit program\n");
printf("Select number : ");
i = getche();
printf("\n");
getch(); // 문자 하나를 입력받을 때 까지 대기하라는 함수
system("cls"); // 화면 클리어
switch(i){
case '1' : input(); result(anwer); break; // 입력 받은 후에 입력 받은 데이터에 대해서도 계산을 해주어야 한다
case '2' : view(anwer); break;
case '3' : maxmin(); break;
case '4' : exit(0);
}
}
void maxmin()
{
struct AA saram;
int score;
FILE *fp;
fp = fopen(Wirt, "r"); // c:\\result.txt에서 그냥 읽어 옴
while(1){
fscanf(fp, "%s", saram.name); // fp에서 스트링 만큼을 읽어서 saram.name에 저장을 하라
if(feof(fp)) // 파일을 끝까지 읽었나?
break; // 그렇다면 break
fscanf(fp, "%s", saram.num);
fscanf(fp, "%d", &score);
if(score==max){
printf("최고점수는 %d점이고 %s의 점수이다.\n", max, saram.name);
}
}
fclose(fp);
FILE *tp; // 처음부터 다시 읽어야 하기때문에 새로 열어줘야 함
tp = fopen(Wirt, "r");
while(1){
fscanf(tp, "%s", saram.name);
if(feof(tp)) // feof(tp)는 반드시 하나의 입력 후에 실행해 주어야 한다. 안그러고 위에 넣으면 마지막 값이 2번 출력된 됨
break;
fscanf(tp, "%s", saram.num);
fscanf(tp, "%d", &score);
if(score==min){
printf("최저점수는 %d점이고 %s의 점수이다.\n", min, saram.name);
}
}
printf("평균 점수는 %.2lf이다.\n", avg); // 소수점 2째자리 가지 double형으로 출력하라
getch();
system("cls");
fclose(tp);
}
void input()
{
struct AA saram;
FILE *fp;
fp = fopen(Read, "a"); // 추가저장 "a", 처음부터 저장 "w", 읽어오기만 "r"
printf("이름 ? : ");
scanf("%s", saram.name);
printf("답안 ? : ");
scanf("%s", saram.num);
fprintf(fp, "%s ", saram.name); // fprintf는 말 그래도 file에 printf 즉, 화면이 아닌 file에 기록하라는 것이다
fprintf(fp, "%s\n", saram.num);
fclose(fp);
system("cls");
}
void view(char *anwer)
{
char data[25];
int cnt=0;
FILE *fp;
fp = fopen(Wirt, "r");
printf("이름 점수\n");
printf("======================\n");
while(1)
{
fgets(data, 25, fp);
if(cnt==3) // 결과 값을 3개 단위로 끊기 위한 if문
{
cnt=0;
printf(".................more");
getch();
system("cls");
printf("이름 점수\n");
printf("======================\n");
}
if(feof(fp))
break;
printf("%s", data);
cnt++;
}
printf(".................end\n");
getch();
system("cls");
fclose(fp);
}
void result(char *anwer)
{
struct AA saram;
int i, l=0, k=0;
FILE *temp1, *temp2;
temp1 = fopen(Read, "r");
temp2 = fopen(Wirt, "w");
while(1)
{
k=0;
fscanf(temp1, "%s", saram.name);
if(feof(temp1))
break;
l++; // 몇명 읽어 들였는지 계산
fprintf(temp2, "%s ", saram.name);
fscanf(temp1, "%s", saram.num);
for(i=0; i<10; i++){ // 입력된 값들과 하나씩 비교함
if(anwer[i]==saram.num[i]){
fprintf(temp2, "%c", '0'); // 맞으면 0을 기록
k++;
}
else
fprintf(temp2, "%c", 'X'); // 틀리면 X를 기록
}
k *= 10; // 10개에 100점 만점 이기 대문에 곱하기 10을 해줌
fprintf(temp2, " %d\n", k);
if(k>max){
max = k;
}
if(k<min){
min = k;
}
avg += k; // 누적으로 모든 점수들을 더해 나간다
}
avg /= l; // 총 개수로 나누어 주어 평균을 구한다.
fclose(temp1);
fclose(temp2);
}
이거는 순전히 나 혼자서 구현 했다는 의미에서 나에게는 감명 깊었던 프로그램이다. 지금까지 파일 입출력 및 포인터 개념에 막연한 두려움까지 안고 있던 나에게 구현하면서도 '과연 이렇게 해서 제대로 컴파일이 될까?'하는 막연함을 말끔히 없애줬다. 역시 완벽한 이론 아래 어설픈 실전 없다고... 아무튼 이걸로 나는 파일 입출력 및 포인터 개념을 확실하게 잡을 수 있었다. 물론 아직 갈길은 멀고도 멀고, 늦기도 애지간히 늦었지만 지금이라도 자신있는 첫발을 디딜수 있었다는 사실에 나는 기쁘다.
자세한 설명은 주석으로 다 달았기에 기타 설명은 쓰지 않겠다.
'Computer & Program > 잡다한 이모저모' 카테고리의 다른 글
구조체를 통한 링크드 리스트의 예 (0) | 2009.03.04 |
---|---|
문자열 출력 예 (0) | 2009.03.04 |
포인터 (0) | 2009.03.04 |
이름과 점수를 입력받아 관리하는 프로그램 (0) | 2009.03.04 |
KMP 알고리즘... (0) | 2009.03.04 |
댓글