풍성한 라벤더농장이 될때까지
article thumbnail

[Conflict]

delete_record() 함수는 사용자가 입력한 이름과 일치하는 모든 레코드를 삭제해야 하는 건가요, 아니면 첫 번째로 일치하는 레코드만 삭제해야 하는 건가요? 만약 연락처에 동명이인이 있다면 둘 다 삭제되는지 문득 궁금했습니다…

 

[Merge]

기존 코드

#include <stdio.h>
#include <string.h>

#define SIZE 100
typedef struct person{ // 연락처 구조체로 표현
    char name[SIZE]; // 이름
    char address[SIZE]; // 주소
    char mobilephone[SIZE]; // 휴대폰
    char desc[SIZE]; // 특징
} PERSON;

void menu();
PERSON get_record();
void print_record(PERSON data);
void add_record(FILE *fp);
void search_record(FILE *fp);
void update_record(FILE *fp);
void delete_record(FILE *fp); 
void print_all_records(FILE *fp);

int main(void){
    FILE *fp;
    int select;
		
		// 이진 파일 추가모드로 오픈
    if((fp = fopen("address.dat", "wb+")) == NULL){
        fprintf(stderr, "입력을 위한 파일을 열 수 없습니다.");
        return 1;
    }

    while(1){
        menu(); // 메뉴를 표시
        printf("번호를 입력하시오: "); // 사용자로부터 정수를 받는다
        scanf("%d", &select);
        while(getchar() != '\n'); // 행의 끝까지 표준입력버퍼의 내용을 읽어 옴
        switch(select){
            case 1: add_record(fp); break; // 데이터 추가
            case 2: update_record(fp); break; // 데이터 수정
            case 3: search_record(fp); break; // 데이터 탐색
            case 4: delete_record(fp); break; // 데이터 삭제
            case 5: print_all_records(fp); break; // 데이터 전체 출력
            case 6: fclose(fp); return 0; // 종료
        }
    }

}

void menu(){
    printf("\n");
    printf("=====================\n");
    printf(" 1. 추가\n");
    printf(" 2. 수정\n");
    printf(" 3. 검색\n");
    printf(" 4. 삭제\n");
    printf(" 5. 출력\n");
    printf(" 6. 종료\n");
    printf("=====================\n");
}

// 데이터 추가 
void add_record(FILE *fp){
    PERSON data;
    data = get_record(); // 사용자로부터 데이터 받아 구조체에 저장
    fseek(fp, 0, SEEK_END); // 파일 끝으로 이동
    fwrite(&data, sizeof(data), 1, fp); // 구조체 데이터 파일에 쓴다
}
// 사용자로부터 데이터 받아 구조체로 반환
PERSON get_record(){
    PERSON data;
    printf("이름: "); gets(data.name);
    printf("주소: "); gets(data.address);
    printf("휴대폰: "); gets(data.mobilephone);
    printf("특징: "); gets(data.desc);
    return data;
}

// 구조체 데이터 화면에 출력
void print_record(PERSON data){
    printf("\n");
    printf("<이름> %s\n", data.name); 
    printf("<주소> %s\n", data.address); 
    printf("<휴대폰> %s\n", data.mobilephone); 
    printf("<특징> %s\n", data.desc);
}

// 데이터 수정
void update_record(FILE *fp){
    char name[SIZE];
    PERSON data;

    fseek(fp, 0, SEEK_SET); // 파일 처음으로 간다
    printf("\n데이터를 수정할 사람의 이름: "); 
    gets(name); // 이름 입력받음

    while(!feof(fp)){ // 파일 끝까지 반복
        fread(&data, sizeof(data), 1, fp);
        if(strcmp(data.name, name) == 0){ // 이름 비교
            print_record(data);
            printf("\n새로운 데이터를 입력하세요.\n");
            data = get_record();
            fseek(fp, -1*sizeof(data), SEEK_CUR);
            fwrite(&data, sizeof(data), 1, fp);
            break;
        }
    }
}

// 데이터 탐색
void search_record(FILE *fp){
    char name[SIZE];
    PERSON data;

    fseek(fp, 0, SEEK_SET); // 파일 처음으로
    printf("\n검색할 사람의 이름: ");
    gets(name); // 이름 입력받음

    while(!feof(fp)){ // 파일 끝까지 반복
        fread(&data, sizeof(data), 1, fp);
        if(strcmp(data.name, name) == 0){ // 이름 비교
            print_record(data);
            break;
        }
    }
}

delete_record(FILE *fp){
    char name[SIZE];
    PERSON data;

    fseek(fp, 0, SEEK_SET);
    printf("\n삭제할 사람의 이름: ");
    gets(name);

    while(!feof(fp)){
        fread(&data, sizeof(data), 1, fp);
        if(strcmp(data.name, name) == 0){
            print_record(data);
            printf("위 연락처를 삭제합니다.\n");
            strcpy(data.name, ""); // 연락처 삭제 (이름을 빈 문자열로 설정)
            fseek(fp, -1*sizeof(data), SEEK_CUR); // 파일 포인터를 방금 읽은 데이터의 시작 위치로 이동
            fwrite(&data, sizeof(data), 1, fp); // 수정한 데이터를 파일에 다시 씀
            break;
        }
    }
}


void print_all_records(FILE *fp){
    PERSON data;

    fseek(fp, 0, SEEK_SET);

    while(fread(&data, sizeof(data), 1, fp) == 1){
        if(strlen(data.name) != 0){
            print_record(data);
        }
    }
}

 

delete_record() 함수는 사용자가 입력한 이름과 일치하는 첫 번째 레코드만을 삭제하고, 그 후에는 함수가 종료됩니다.

함수가 동작하는걸 보면, 이 함수는 이름이 일치하는 첫 번째 레코드를 찾고, 찾으면 해당 레코드의 이름 필드를 빈 문자열로 바꾼 다음, 함수가 종료(break)됩니다. 그래서 만약 주소록에 동명이인이 있다면, 이 함수를 사용해 한 번에 모든 동명이인을 삭제하는 것은 불가능합니다.

3개의 데이터(2개의 중복된 이름)을 미리 추가해둔 상태에서 ‘**현’ 데이터를 삭제할 시 첫번째 데이터만 삭제되는 모습입니다.

 

만약 모든 동명이인을 삭제하고 싶다면, delete_record() 함수를 아래와 같이 수정하면 됩니다

void delete_record(FILE *fp){
    char name[SIZE];
    PERSON data;
    int found = 0;

    fseek(fp, 0, SEEK_SET);
    printf("\n삭제할 사람의 이름: ");
    gets(name);

    while(!feof(fp)){
        fread(&data, sizeof(data), 1, fp);
        if(strcmp(data.name, name) == 0){
            print_record(data);
            printf("위 연락처를 삭제합니다.\n");
            strcpy(data.name, "");
            fseek(fp, -1*sizeof(data), SEEK_CUR);
            fwrite(&data, sizeof(data), 1, fp);
            found = 1;
        }
    }

    if(!found) {
        printf("해당 이름을 가진 사람이 없습니다.\n");
    }
}

 

profile

풍성한 라벤더농장이 될때까지

@그레이라벤더

느리지만 꾸준히 굴러서 큰 바다가 되고싶은 개발 어린이