Take action every day.

파일처리

by 오민
#define _CRT_SECURE_NO_WARNINGS //visual studio에서 scanf를 사용할때 발생하는 오류를 무시하기 위한 명령어
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void insert(FILE *f);
void bulk_insert(FILE *f);
void search_name(FILE *f);
void search_range(FILE *f);
void display_total(FILE *f);
void display_single(FILE *f);
void printhead();
void update(FILE *f);
void del(FILE *f);
void removal(FILE *f);
void grade(FILE *f);

typedef struct student
{
    int num;
    char name[20];
    int mid;
    int final;
    int quiz;
} student;
//구조체 형식 선언. dypedef struct student를 student라고 쓰겠다는 것이다.
//구조체의 형식만 지정해주었으니 해당 구조체를 쓰기 위해선 사용할 때 구조체를 선언해줘야 한다.
long int studsize = (long)sizeof(student);
//원래 studsize은 long int에 해당하기 때문에 int 앞에 long을 붙여줘야 한다.
//하지만 vs code에서는 붙여주지 않아도 잘 작동한다.
int main()
{
    char fname[] = "student.bin";
    //이진파일의 이름을 변수에 담았다. 귀찮음을 덜기 위함이다.
    //이진파일이 텍스트 파일보다 용량도 적고 빠르다.
    FILE *f; //파일포인터 변수 선언.이제 파일을 열고 파일주소를 해당 파일포인터에 저장할 수 있다.
    char option = 0;
    if ((f = fopen(fname, "rb+")) == NULL)
    { //파일을 열어서 포인터에 담고, 제대로 담겼는지 확인을 하기 위해 null과 비교를 한다.
        if ((f = fopen(fname, "wb+")) == NULL)
        {
            printf("파일이 열리지 않습니다\n");
            exit(1); //메인함수에서의 return과 동일한 기능을 하는 함수. 다만 stdlib.h이 있어야 작동한다.
        }
        /*
            "r" : 읽기. 파일 없으면 에러.
            “w” : 덮어쓰기. 없으면 만듦.
            “a” : 파일끝에서쓰기. 없으면 만듦.
            “r+” : 읽고쓰기. 없으면 에러.
            “w+” : 읽고쓰기. 없으면 만듦.
            “a+” : 파일끝에서읽고쓰기. 없으면 만듦.
            t : text, b : binary. 아무것도 없으면 기본으로 t모드.
            */
    }
    while (1)
    {
        if (option != '\n')
            printf("전체정보출력(t), 탐색(s),이름 탐색(n),범위탐색(q),입력(i),대량삽입(b).수정(u),삭제(d),전체삭제(r),성적처리(g),종료(f)를 선택하세요:");
        scanf("%c", &option);
        fflush(stdin); //표준입력스트림 버퍼를 비워준다. vs의 경우 작동안하는 버전도 있다고 한다.
        switch (option)
        {
        case 't':
            display_total(f);
            break;
        case 's':
            display_single(f);
            break;
        case 'n':
            search_name(f);
            break;
        case 'q':
            search_range(f);
            break;
        case 'i':
            insert(f);
            break;
        case 'b':
            bulk_insert(f);
            break;
        case 'u':
            update(f);
            break;
        case 'd':
            del(f);
            break;
        case 'r':
            removal(f);
            break;
        case 'g':
            grade(f);
            break;
        case 'f':
            break;
        }
        if (option == 'f')
            break;
    }
    fclose(f);
    return 0;
}

void display_total(FILE *f) //전체 정보 출력
{
    rewind(f);    //position indicator 위치 초기화
    student stud; //구조체를 사용하기위해 변수를 선언해준다.
    int cnt = 0;
    fread(&stud, studsize, 1, f); //한명이라도 있는지 확인하려고 미리 한명의 정보를 읽어온다.
    printhead();
    if (stud.num) //stud.num에 든 수가 0이 아닐때
    {
        while (!feof(f))
        { //feof함수는 스트림(f)의 위치 지정자 (position indicator)가 파일의 끝에 있으면 0이 아닌 값을 출력한다.
            fprintf(stdout, "%6d%18s%8d%8d%8d\n", stud.num, stud.name, stud.mid, stud.final, stud.quiz);
            //fprintf(stdout,)는 printf()와 같은 의미
            fread(&stud, studsize, 1, f); //f에서 구조체 크기로 1개를 읽어서 stud에 담기.
            cnt++;
        }
    }
    printf("-----------------------------------------\n");
    printf("모두 %d명 입니다\n", cnt);
}
void search_range(FILE *f)
{
    rewind(f);
    student stud;
    char minname[30];
    char maxname[30];
    int cnt = 0;
    printf("탐색할 이름의 최솟값을 입력하세요(가나다순):");
    scanf("%s", minname);
    printf("탐색할 이름의 최댓값을 입력하세요(가나다순):");
    scanf("%s", maxname);
    printhead();
    while (!feof(f))
    {
        fread(&stud, studsize, 1, f);
        if (strcmp(stud.name, minname) >= 0 && strcmp(stud.name, maxname) <= 0)
        {
            printf("%6d%18s%8d%8d%8d\n", stud.num, stud.name, stud.mid, stud.final, stud.quiz);
            cnt++;
        }
    }
    printf("-----------------------------------------\n");
    printf("모두 %d명 입니다\n", cnt);
}

void search_name(FILE *f)
{
    rewind(f);
    student stud;
    char name[30];
    int cnt = 0;
    printf("탐색할 이름을 입력하세요:");
    scanf("%s", name);
    printhead();
    while (!feof(f))
    {
        fread(&stud, studsize, 1, f);
        if (strcmp(stud.name, name) == 0)
        {
            fprintf(stdout, "%6d%18s%8d%8d%8d\n", stud.num, stud.name, stud.mid, stud.final, stud.quiz);
            cnt++;
        }
    }
    printf("-----------------------------------------\n");
    printf("모두 %d명 입니다\n", cnt);
}
void insert(FILE *f) //입력,추가
{
    student stud = {0};
    char line[50];
    if ((f = fopen("student.bin", "ab+")) == NULL)
    {
        printf("파일이 열리지 않습니다\n");
        exit(1);
    }
    fread(&stud, studsize, 1, f);
    if (stud.num)
    {
        fseek(f, -studsize, SEEK_END);
        fread(&stud, studsize, 1, f); //여기서 어차피 위치 지정자가 파일의 끝에 위치할텐데
        fseek(f, 0L, SEEK_END);       //이 문장이 불필요한 것 같은데 지우면 에러가 난다. vs에서는 지워도 잘 작동을 한다.
    }                                 //long과 int의 차이 때문에 발생하는 오류정도로 예상된다.
    printf("이름과 성적(중간,기말,퀴즈)을 입력하세요\n");
    fgets(line, 50, stdin);
    sscanf(line, "%s %d %d %d", stud.name, &stud.mid, &stud.final, &stud.quiz);
    stud.num++;
    fwrite(&stud, studsize, 1, f);
    fclose(f);
}

void bulk_insert(FILE *f)
{
    student stud = {0};
    char line[50];
    if ((f = fopen("student.bin", "ab+")) == NULL)
    {
        printf("파일이 열리지 않습니다\n");
        exit(1);
    }
    fread(&stud, studsize, 1, f);
    if (stud.num)
    {
        fseek(f, -studsize, SEEK_END);
        fread(&stud, studsize, 1, f);
        fseek(f, 0L, SEEK_END); //중간 값이 0이 아니라 0L인 것도 (long)int 0을 의미하는 것이다.
    }                           //마지막 학생의 stud.num값을 구하기 위한 과정.
    rewind(stdin);
    while (1)
    {
        printf("추가할 정보:");
        fgets(line, 50, stdin);
        if (feof(stdin))
            break;
        sscanf(line, "%s %d %d %d", stud.name, &stud.mid, &stud.final, &stud.quiz);
        stud.num++;
        fwrite(&stud, studsize, 1, f); //stud에 든 정보를 f 스트림에 한번 작성하겠다.
    }                                  //성공시 1(한 번)반환, 실패시 1보다 작은 수 반환.
    fclose(f);
}

void display_single(FILE *f) // 탐색
{
    student s1;
    int search = 0;
    printf("탐색할 정보의 번호를 입력하세요:");
    scanf("%d", &search);
    fseek(f, studsize * (search - 1), SEEK_SET);
    fread(&s1, studsize, 1, f);
    printf("%d번의 정보: (%s,%d,%d,%d)\n", search, s1.name, s1.mid, s1.final, s1.quiz);
}

void update(FILE *f)
{
    int i = 0;
    int fix = 0;
    student stud;
    printf("수정할 정보의 번호를 입력하세요:");
    scanf("%d", &fix);
    fseek(f, studsize * (fix - 1), SEEK_SET);
    fread(&stud, studsize, 1, f);
    printf("%d번의 정보: (%s,%d,%d,%d)\n", stud.num, stud.name, stud.mid, stud.final, stud.quiz);
    printf("수정할 내용:");
    scanf("%s %d %d %d", stud.name, &stud.mid, &stud.final, &stud.quiz);
    fseek(f, studsize * (fix - 1), SEEK_SET);
    fwrite(&stud, studsize, 1, f);
}

void del(FILE *f)
{
    rewind(f);
    int delnum = 0, num = 0;
    student stud[30];
    printf("삭제할 정보의 번호를 입력하세요:");
    while (!feof(f))
        fread(&stud[++num], studsize, 1, f);
    num--;
    scanf("%d", &delnum);
    printf("%d번의 정보: (%s,%d,%d,%d)\n", stud[delnum].num, stud[delnum].name, stud[delnum].mid, stud[delnum].final, stud[delnum].quiz);
    fclose(f);
    remove("student.bin");
    if ((f = fopen("student.bin", "ab+")) == NULL)
    {
        printf("파일이 열리지 않습니다\n");
        exit(1);
    }
    for (int i = delnum; i <= num; i++)
    {
        stud[i] = stud[i + 1];
        stud[i].num--;
    }
    for (int i = 1; i < num; i++)
        fwrite(&stud[i], studsize, 1, f);
    printf("삭제되었습니다\n");
}

void removal(FILE *f)
{
    fclose(f);
    remove("student.bin");

    if ((f = fopen("student.bin", "ab+")) == NULL)
    {
        printf("파일이 열리지 않습니다\n");
        exit(1);
    }
    printf("모든 레코드들이 삭제되었습니다\n");
}

void grade(FILE *f)
{
    printf("학점:A(200이상),B(150이상),C(150미만)\n");
    rewind(f);
    student stud;
    int cnt = 0;
    int hap = 0;
    char hakjum;
    int readcnt = fread(&stud, studsize, 1, f);
    if (readcnt == 0)
    {
        printhead();
        printf("-----------------------------------------\n");
        printf("모두 0명 입니다\n");
        return;
    }

    printf("-----------------------------------------\n");
    printf("%8s%15s%10s%8s%8s%8s%8s\n", "번호", "이름", "중간", "기말", "퀴즈", "합", "학점");
    printf("-----------------------------------------\n");
    while (!feof(f))
    {
        ++cnt;
        hap = stud.mid + stud.final + stud.quiz;
        if (hap >= 200)
            hakjum = 'A';
        else if (hap >= 150)
            hakjum = 'B';
        else
            hakjum = 'C';
        printf("%6d%18s%8d%8d%8d%8d%8c\n", stud.num, stud.name, stud.mid, stud.final, stud.quiz, hap, hakjum);
        fread(&stud, studsize, 1, f);
    }
    printf("-----------------------------------------\n");
    printf("모두 %d명 입니다\n", cnt);
}
void printhead()
{
    printf("-----------------------------------------\n");
    printf("%8s%15s%10s%8s%8s\n", "번호", "이름", "중간", "기말", "퀴즈");
    printf("-----------------------------------------\n");
}

 파일처리 화이팅!

삭제함수 아래쪽은 건드리지 못했다.

'Language > C' 카테고리의 다른 글

승자 트리  (0) 2021.03.29
Heap  (0) 2021.03.29
포인터  (0) 2021.03.29
BST  (0) 2021.03.28
kmp  (0) 2021.03.18

블로그의 정보

OMIN

오민

활동하기