💡 자료구조

전화번호부 v2.0 - 파일을 저장하고 로드하기, 알파벳 순으로 정렬

ji-hyun 2021. 6. 19. 21:51

 

실습결과

 

directory 파일의 변화

 

 

 

 

2021.06.19 - [자료구조] - 전화번호부 v1.0

 

전화번호부 v1.0

오늘은 권오흠 교수님께서 전화번호부를 만드는 예제를 가르쳐주셨다. 여태까지 배웠던 C언어의 기초를 응용해서 전화번호부 예제를 만들 수 있었다. void add() { char buf1[BUFFER_SIZE], buf2[BUFFER_SIZE];

ts2ree.tistory.com

이전과 다른 점은 파일을 저장하고 로드하며, 전화번호부는 알파벳 순으로 정렬되어야 한다.

전화번호부 v2.0는 파일을 저장하고 로드하기 위한 load 함수와, save 함수가 추가되었다. 나머지 함수의 변화는 밑에서 살펴볼 것이다.

 

 

 

 

void load() {  // command = read
	char fileName[BUFFER_SIZE];
	char buf1[BUFFER_SIZE];
	char buf2[BUFFER_SIZE];

	scanf("%s", fileName);  // 파일 이름을 입력받는다.

	FILE *fp = fopen(fileName, "r");  // 파일을 읽기 모드(r)로 열기.
                                       // 파일 포인터를 반환
	if (fp = NULL) {
		printf("Open failed.\n");
		return;
	}

	while ((fscanf(fp, "%s", buf1) != EOP)) {  // 파일의 끝에 도달할 때까지 반복해서 이름과 전화번호를 읽어서 배열에 저장한다.
		fscanf(fp, "%s", buf2);
		names[n] = strdup(buf1);
		numbers[n] = strdup(buf2);
		n++;
	}
	fclose(fp); // 볼일이 끝난 파일은 반드시 닫아 주어야 한다.
}

 

텍스트 파일 입출력에 관련된 라이브러리 함수

파일 입출력 함수들은 앞에 f 가 붙어 있고 FILE 포인터를 매개변수로 받는다.

fscanf( fp, "%d", &x )

fprintf( fp, "%d", x )

fscanf 함수는 파일 포인터를 넣는다는 점 말고는 scanf 함수와 사용법이 같다. 

 

 

 

① directory.txt 파일의 이름을 입력받는다.

② 파일을 읽기모드로 연다.

③ while 문은 이름 전화번호 순으로 읽는다.

Davide 0517778888

    Henry 0243737788

⑤ buf1 배열에는 사람의 이름이 저장되고, buf2 배열에는 그 사람의 전화번호가 저장된 형태이다.

 

 

 

 

 

 

void save() { 
	int i;
	char fileName[BUFFER_SIZE];
	char tmp[BUFFER_SIZE];

	scanf("%s", tmp);  // which is "as", discarded
	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 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){  //사전식 순서로 buf보다 큰 항목들은 모두 한 칸씩 뒤로 이동시키고, 처음으로 buf보다 작은 항목이 나오면 그것 바로 뒤에 삽입한다.
    	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);

앞서 게시물 전화번호부 v1.0은 사람의 이름과 전화번호를 추가할 때 그냥 배열의 뒤에 추가해줬다면, 전화번호부 v2.0은 사람의 이름과 전화번호를 추가할때 알파벳 순으로 정렬된 배열의 형태로 저장되어야 한다. 그러면 위와 같은 bubble sort 알고리즘을 생각해볼 수 있다.

 

 

 

strcmp 함수

(1) str1 < str2 인 경우에는 음수 반환

(2) str1 > str2 인 경우에는 양수 반환

(3) str1 == str2 인 경우에는 0을 반환 합니다.

 

 

 

 

 

 

 

 

 

실습코드

 

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

#define CAPACITY 100
#define BUFFER_SIZE 20


char * names[CAPACITY]; /* names */
char * numbers[CAPACITY]; /* phone numbers */

int n = 0; /* number of people in phone directory */




void add();
void find();
void status();
void remover();
void load();    // 버전 1과 다른 점 : load, save 함수가 추가됨
void save();





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


void load() {  // read
	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);
}

void save() {
	int i;
	char fileName[BUFFER_SIZE];
	char tmp[BUFFER_SIZE];

	scanf("%s", tmp); // which is "as", discarded
	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 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);
}



char *strdup(char *s)
{
	char *p;
	p = (char *)malloc(strlen(s) + 1);
	if (p != NULL)
		strcpy(p, s);
	return p;
}


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]);
}


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


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 remover() {
	char buf[BUFFER_SIZE];
	scanf("%s", buf);

	int index = search(buf); /* returns -1 if not exists */

	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);
}