일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- inflearn
- gan
- strdup
- 문자열
- 김영한스프링부트
- C언어로쉽게풀어쓴자료구조
- 자바
- ChatGPT
- 다차원배열순회
- 웹기초
- VGG-S
- 백준
- 시간복잡도
- 오븐시계
- VGG-M
- VGG-F
- 스프링기초
- 파일읽고쓰기
- 스프링입문
- 다차원
- vgg
- 자료구조
- springboot
- 김영한
- 조건문
- 포인터
- 배열
- 이미지생성
- Intellij
- C
- Today
- Total
YUIN
자료구조 5 [전화번호부.v2] 본문
Main Idea: 자료구조는 phonebookv1과 동일하게 하되, 여기에 파일로 저장하고 로드하기, 알파벳 순으로 정렬하기 기능을 추가하도록 하자.
1. 실행 예시
변경사항:
- 파일로부터 데이터를 읽어오는 부분에 대한 코딩 작업이 필요하다.
- status에 대한 정보를 불러들일 때, 항상 알파벳 순으로 정렬된 상태를 유지하도록 한다.
- 마지막 부분에 save as "파일명"으로 저장하는데, 같은 파일명일 경우 기존의 내용을 덮어쓰게 되고, 다른 파일명을 입력할 경우 새로운 파일이 생성된다 (이 부분에 대한 별도의 코딩을 필요하지 않다).
- 자료구조는 phonebookv1과 동일하다.
2. main 함수
int main() {
char command[BUFFER_SIZE];
while (1) {
printf("$ ");
scanf("%s", command);
if (strcmp(command, "read") == 0)
load();
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)
erase();
else if (strcmp(command, "save") == 0)
save();
else if (strcmp(command, "exit") == 0)
break;
}
return 0;
}
phonebookv1과 달라진 점이 있다면 read와 save 명령을 추가했고 각각을 처리하는 함수 load()와 save()를 추가했다는 점이다.
3. load 함수
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);
}
load 함수에서 파일명을 입력받는데, C 프로그램에서 파일에 접근하기 위해서는 먼저 파일을 열어야 하므로 fopen을 사용하여 파일을 열 수 있도록 해준다. fopen은 파일 포인터 fp를 리턴해주는데, 여기서의 fp의 타입은 FILE이다. 그리고 if문을 사용하여 파일을 여는데 실패했을 경에 대한 예외처리를 해준다.
(while문)- fscanf를 통해 파일을 읽는데, 이때 EOF(end of file)이면 읽기를 멈춘다. 파일의 형식은 이름-전화번호일 것이므로 buf1에는 사용자의 이름이, buf2에는 전화번호가 저장돼 있을 것이다. 즉, 파일의 끝에 도달할 때까지 반복해서 이름과 전화번호를 읽어서 배열에 저장한다.
fclose를 통해 파일을 닫아주도록 한다.
4. save 함수
void save() {
int i;
char fileName[BUFFER_SIZE];
char tmp[BUFFER_SIZE];
scanf("%s", tmp);
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);
}
실행 예시에서 파일을 저장할 때 save as "파일명"으로 저장하게 했는데, save는 함수 이름이며, 따라서 명령을 읽으면 이 함수를 호출하게 된다. as는 필요없는 문자열이므로 그냥 무시하게 하고, 그 뒤에 오는 문자열인 파일명만 fileName으로 저장하게 된다.
파일을 저장하기 위해선 파일을 열어야 하므로 fopen을 사용하는데, 파일에 쓸 때는 모드를 "w"로 하고 열어야 한다.
5. 데이터 정렬된 상태로 유지하기
- bubblesort 등의 정렬(sorting) 알고리즘 사용하는 방법 -> 새로운 데이터가 계속적으로 추가되는 상황에서는 부적절하다.
- 새로운 데이터가 추가될 때마다 제자리를 찾아서 삽입하는 방식
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);
}
add 함수는 과 같이 바뀐다.
사전식 순서로 나보다 큰 항목들은 모두 한 칸씩 뒤로 이동시키고, 처음으로 나보다 작은 항목이 나오면 그것 바로 뒤에 삽입한다.
6. remove/erase 함수
void erase() {
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("No person named '%s' exists.\n", buf);
}
7. 전체 코드
#include <stdio.h>
#include <string.h>
#define CAPACITY 100
#define BUFFER_SIZE 20
char* names[CAPACITY];
char* numbers[CAPACITY];
int n = 0;
void add();
void find();
void status();
void remove();
void load();
void save();
int main() {
char command[BUFFER_SIZE];
while (1) {
printf("$ ");
scanf("%s", command);
if (strcmp(command, "read") == 0)
load();
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)
erase();
else if (strcmp(command, "save") == 0)
save();
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 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);
}
void find() {
char buf[BUFFER_SIZE];
scanf("%s", buf);
int i;
for (i = 0; i < n; i++) {
if (strcmp(buf, names[i]) == 0) {
printf("%s\n", numbers[i]);
return;
}
}
printf("No person named %s exists.\n", buf);
}
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 erase() {
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("No person named '%s' exists.\n", buf);
}
'자료구조' 카테고리의 다른 글
C언어로 쉽게 풀어 쓴 자료구조 1장 연습문제 (0) | 2023.12.26 |
---|---|
C 언어로 쉽게 풀어 쓴 자료구조 1장 자료구조와 알고리즘 (4) | 2023.12.26 |
자료구조 4 [전화번호부.v1] (0) | 2023.08.15 |
자료구조 3 [문자열 예제] (0) | 2023.08.08 |
자료구조 2 [문자열] (0) | 2023.08.03 |