카테고리 없음

[C/자료구조] 이진 파일 입출력 /Random Access

미친토끼 2021. 3. 2. 14:21
// studentInfoFull.c
// 학생의 ID와 이름, 점수를 입력받아 이진파일로 저장한다.
// 입력 기능, 찾기 기능, 이진 파일 저장 기능이 있음.
//참고 유튜브 영상: "HPC Lab. KOREATECH" 채널의 "C언어 Lv2] 8강. 파일 입출력 (5/5) - Random access (임의접근)"

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_NUM_STUDENT 255
#define ADD 0
#define FIND 1
#define EXIT 2

//enum action {ADD=0, FIND=1, EXIT=2};

typedef struct {
    int ID;  // 4 bytes
    char name[8]; // 8 bytes
    float score; // 4 bytes
} Student; // 16 bytes

int fileOpen(FILE **fp, char *fileName, char *_mode) {
    *fp = fopen(fileName, _mode);
    if (*fp == NULL) {
        printf("Fail to open : %s\n", fileName);
        return -1;
    }
    return 0;
}

int selectAction(void) {
    int sel = -1;
    printf("[%d]add [%d]find [%d]exit: ", ADD, FIND, EXIT);
    scanf("%d", &sel);
    //printf("scanf = %d\n", sel);
    if (sel == ADD || sel == FIND || sel == EXIT)
        return sel;
     return EXIT;
}

int printStudentInfo(Student *info) {
    printf("%d %s %.2f\n", info->ID, info->name, info->score);
}

int addStudentInfo(FILE *fp, Student *info) {
    printf("Enter ID Name Score : ");
    scanf("%d %s %f", &(info->ID), &(info->name), &(info->score));
    getchar();
    fseek(fp, 0, SEEK_END);
    fwrite(info, sizeof(Student), 1, fp);
    return 0;
}

long findStudent(FILE *fp, Student *info) {
    char name[255] = {0};
    printf("Name: ");
    scanf("%s", name); getchar();

    int elementSize = sizeof(Student); // 16 types
    fseek(fp, 0, SEEK_SET); 
    while (!feof(fp)) {
        fread(info, elementSize, 1, fp);
        if (strcasecmp(info->name, name) == 0) { // Find!
            fseek(fp, -elementSize, SEEK_CUR);
            return ftell(fp);
        }
    }
    return -1;
}

int main () {
    FILE *fp = NULL;
    Student data = {0};
    fileOpen(&fp, "studentDB", "ab+");

    while (1) {
        switch (selectAction()) {
        case ADD:
            addStudentInfo(fp, &data);
            break;
        case FIND:
            if (findStudent(fp, &data) < 0)
                printf("Cannot find the student\n");
            else    printStudentInfo(&data);
            break;
        case EXIT:
            fclose(fp);
            return 0;
        default:
            fclose(fp);
            return 0;
        }
    }

    return 0;
}

-------------- 실행 결과 -------------
[Don@localhost]$ ./studentInfoFull
[0]add [1]find [2]exit: 0
Enter ID Name Score : 18 Hong 78
[0]add [1]find [2]exit: 0
Enter ID Name Score : 22 Jang 82
[0]add [1]find [2]exit: 0
Enter ID Name Score : 33 Han 92
[0]add [1]find [2]exit: 0
Enter ID Name Score : 45 KimLip 88
[0]add [1]find [2]exit: 1
Name: KimLip
45 KimLip 88.00
[0]add [1]find [2]exit: 2
[Don@localhost]$ ls -al studentDB
-rw-rw-r--. 1 Don Don 64  3월  2 14:17 studentDB

**참고: 4명의 정보를 입력해서 16바이트 * 4 = 64바이트 이진 파일이 만들어졌음.