[자료구조 - C언어] 자료구조 제5강: 전화번호부 v2.0

2022. 5. 6. 16:25CS/자료구조

728x90

//공부 기록용 포스팅입니다. 틀린 부분이 있을 경우 댓글로 알려주시면 감사합니다! 😎

 

파일로 저장하고 로드하기, 알파벳 순으로 정렬

https://ksk9820.tistory.com/138

코드 참고

void load();
void save();
int search();
if (strcmp(command, "read") == 0)
   load();
else if (strcmp(command, "save") == 0)
   save();

 

1. load()

void load(){
    char fileName[BUFFER_SIZE];
    char buf1[BUFFER_SIZE];
    char buf2[BUFFER_SIZE];
    
    scanf("%s", fileName);    // 파일의 이름을 입력받음
    
    FILE *fp = fopen(fileName, "r");    //파일에 접근하기 위해 파일을 open
    if (fp==NULL){    //파일을 오픈하는데 실패한 경우의 예외처리 
        printf("Open failed.\\n");
        return;
    }
    
    while((fscanf(fp, "%s", buf1) != EOF)){    //파일의 끝에 도달할 때 까지
        fscanf(fp, "%s", buf2);
        names[n] = strdup(buf1);
        numbers[n] = strdup(buf2);
        n++;
    }
    fclose(fp);    //사용이 끝난 파일은 반드시 닫아야 한다
}
  • fopen함수는 file pointer라는 값을 리턴: FILE
    • file에 접근한다 = file을 읽고 쓴다
  • 파일을 오픈하는데 실패한 경우 예외처리
    • 없는 파일명
    • 다른 디렉토리에 위치
  • EOF: End Of File
    • fscanf 함수는 파일의 끝에 도달하면 EndOfFile값 리턴
  • fscanf: 파일로부터 읽기 위해 fscanf 함수 사용
    • fscanf(fp, “%s”, buf1): 첫 번째 string(=이름)을 읽어 buf1에 저장
    • fscanf(fp, “%s”, buf2): 두 번째 string(=번호)을 읽어 buf2에 저장
  • fclose(fp);
    • 사용이 끝난 파일은 반드시 닫아야 한다.
    • fp는 fopen에서 리턴받은 파일 포인터

2. save()

void save(){
    int i;
    char fileName[BUFFER_SIZE];
    
    scanf("%s", fileName);
    
    FILE *fp = fopen(fileName, "w");    //file에 쓸 때는 "w"모드
    if (fp==NULL){
        printf("Open failed.\\n");
        return;
    }
    for(i=0; i<n; i++){
        fprintf(fp, "%s %s\\n", names[i], numbers[i]);    //공백단위로 입력
    }
    fclose(fp);
}
  • 파일에 쓸 때는 “w”모드로 fopen()
    • “w” 모드일 때는 파일이 미리 존재하지 않아도 된다.
    • “r” 모드일 때는 파일이 미리 존재해야 한다.
  • fprintf 함수로 파일에 write 할 수 있다.
    • “%s %s”: 사이 공백을 기준으로 names[i]와 numbers[i]에 차례대로 저장

3. 데이터를 정렬된 상태로 유지하려면 - add()

  • 버블이나 선택 정렬 알고리즘은 새로운 데이터가 계속적으로 추가되는 우리의 상황에서는 부적절
  • 새로운 데이터가 추가될 때마다 제자리를 찾아 삽입하는 방법: 삽입 정렬
    • 맨 뒤에서부터 검사해서 새로운 데이터보다 큰 것(= 사전식으로 뒤에 있는 경우)들은 한 칸 뒤로 이동
    • 새로운 데이터보다 작은 것 or 배열의 시작을 지나치면 그다음 차례에 새로운 데이터 삽입
void add(){
	char buf1[BUFFER_SIZE], buf2[BUFFER_SIZE];
    scanf("%s", buf1);
    scanf("%s", buf2);
    
    int i = n-1;    //맨 뒤에서 부터 검색
    while(i >= 0 && strcmp(names[i], buf1)>0){    //strcmp
        names[i+1] = names[i];    
        numbers[i+1] = numbers[i];    //한 칸씩 뒤로 이동
        i--;
    }
    names[i+1] = strdup(buf1);    
    numbers[i+1] = strdup(buf2);    //처음으로 작은 항목이 나오면 그것 바로 뒤에 삽입
    
    n++;    //데이터가 하나 추가되었기 때문에 
    printf("%s was added successfully.\\n", buf1);
}
  • 맨 뒤에서부터 검색하기 때문에 i의 값은 n-1이다.
    • 배열은 0부터 시작하기 때문에
  • strcmp는 비교하는 두 string이
    • 동일하면 0을 리턴
    • 다른 경우 str1 > str2 (= 사전식 순서로 str1이 str2보다 더 뒤쪽에 나오면) → 음수를 리턴
      • strcmp(names[i], buf1) > 0 : buf1보다 names[i]가 사전식 순서로 더 뒤쪽에 있다면
  • 배열의 시작을 지나치거나 (i<0), names[i]가 buf1보다 사전식 순서로 앞에 있다면(strcmp <0)
    • 그다음 차례(i+1)에 buf1을 저장

4. delete()

void delete(){
	char buf[BUFFER_SIZE];
    scanf("%s", buf);
    
    int index = search(buf);    //search 함수가 -1을 리턴하면 배열에 해당 이름이 없는 경우
    if (index == -1){    
        printf("No person named '%s' exists.\\n", buf);
        return;
    }

    int j = index;
    for (;j<n-1;j++){
        names[j] = names[j+1];
        numbers[j] = numbers[j+1];
    }
    n--;
    printf("'%s' was deleted successfully. \\n", buf);
}
  • 정렬되어 있기 때문에 v1.0처럼 삭제하고 맨 뒤에 값을 삭제한 자리에 삽입할 수 없다.
  • 삭제한 후 → 한 칸씩 당겨야 한다.

5. find()

void find(){
	char buf[BUFFER_SIZE];
    scanf("%s", buf);
    int index = search(buf);
    if (index == -1)
        printf("No person named '%s' exists.\\n", buf);
    else
        printf("%s\\n", numbers[index]);
}

6. search()

int search(char *name){
    int i;
    for (i=0;i<n;i++){
        if(strcmp(name, names[i]) == 0){
            return i;
        }
    }
    return -1;
}

7. status()

void status(){
    int i;
    for (i=0; i<n; i++)
        printf("%s %s\\n", names[i], numbers[i]);
    printf("Total %d persons\\n", n);
}

8. 결과

$ save directory.txt
$ add Jungwoo 123456789
Jungwoo was added successfully.
$ add Mark 102030405
Mark was added successfully.
$ status
Jungwoo 123456789
Mark 102030405
Total 2 persons
$ add simons 1029484
simons was added successfully.
$ status
Jungwoo 123456789
Mark 102030405
simons 1029484
Total 3 persons
$ add Andrew 58473920
Andrew was added successfully.
$ status
Andrew 58473920
Jungwoo 123456789
Mark 102030405
simons 1029484
Total 4 persons
$ delete Mark
'Mark' was deleted successfully. 
$ status
Andrew 58473920
Jungwoo 123456789
simons 1029484
Total 3 persons
$ find Jungwoo
123456789
$ exit
Program ended with exit code: 0

 

9. 전체 코드

더보기
//  version2.c

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

#define CAPACITY 100
#define BUFFER_SIZE 20


char * names[CAPACITY];
char * numbers[CAPACITY];
int n = 0;

//뒤에 작성할 함수들의 프로토타입을 main 함수 앞에 나열
void add();
void find();
void status();
void delete();
void load();
void save();
int search();


int main(){
    char command[BUFFER_SIZE];
    while(1){
        printf("$ ");
        scanf("%s", command);
        if (strcmp(command, "read") == 0)
            load();
        else if (strcmp(command, "save") == 0)
            save();
        else if (strcmp(command, "add") == 0)
            add();
        else if (strcmp(command, "find") == 0)
            find();
        else if (strcmp(command, "status") == 0)
            status();
        else if (strcmp(command, "delete") == 0)
            delete();
        else if (strcmp(command, "exit") == 0)
            break;
    }
    return 0;
}

void load(){
    char fileName[BUFFER_SIZE];
    char buf1[BUFFER_SIZE];
    char buf2[BUFFER_SIZE];
    
    scanf("%s", fileName);
    
    FILE *fp = fopen(fileName, "r");
    if (fp==NULL){
        printf("Open failed.\n");
        return;
    }
    
    while((fscanf(fp, "%s", buf1) != EOF)){
        fscanf(fp, "%s", buf2);
        names[n] = strdup(buf1);
        numbers[n] = strdup(buf2);
        n++;
    }
    fclose(fp);
}


void add(){
    char buf1[BUFFER_SIZE], buf2[BUFFER_SIZE];
    scanf("%s", buf1);
    scanf("%s", buf2);
    
    int i = n-1;
    while(i >= 0 && strcmp(names[i], buf1) >0){
        names[i+1] = names[i];
        numbers[i+1] = numbers[i];
        i--;
    }
    names[i+1] = strdup(buf1);
    numbers[i+1] = strdup(buf2);
    
    n++;
    printf("%s was added successfully.\n", buf1);
    
}

void save(){
    int i;
    char fileName[BUFFER_SIZE];
    
    scanf("%s", fileName);
    
    FILE *fp = fopen(fileName, "w");
    if (fp==NULL){
        printf("Open failed.\n");
        return;
    }
    for(i=0; i<n; i++){
        fprintf(fp, "%s %s\n", names[i], numbers[i]);
    }
    fclose(fp);
}

void find(){
    char buf[BUFFER_SIZE];
    scanf("%s", buf);
    int index = search(buf);
    if (index == -1)
        printf("No person named '%s' exists.\n", buf);
    else
        printf("%s\n", numbers[index]);
}

void status(){
    int i;
    for (i=0; i<n; i++)
        printf("%s %s\n", names[i], numbers[i]);
    printf("Total %d persons\n", n);
}

void delete(){
    char buf[BUFFER_SIZE];
    scanf("%s", buf);
    
    int index = search(buf);
    if (index == -1){
        printf("No person named '%s' exists.\n", buf);
        return;
    }
    int j = index;
    for (;j<n-1;j++){
        names[j] = names[j+1];
        numbers[j] = numbers[j+1];
    }
    n--;
    printf("'%s' was deleted successfully. \n", buf);
}

int search(char *name){
    int i;
    for (i=0;i<n;i++){
        if(strcmp(name, names[i]) == 0){
            return i;
        }
    }
    return -1;
}

 

 

 

 


부경대학교 권오흠 교수님의 [c로 배우는 자료구조 및 여러 가지 예제 실습] 강의 정리입니다. 감사합니다.

https://www.youtube.com/watch?v=gwji1bX4MpI&feature=emb_title 

 

728x90