간단한 도서 관리용 프로그램을 작성해보자.
[제목, 저자명, 페이지수]에 대한 정보를 저장할 수 있는 구조체를 정의하고, 구조체 배열을 선언해서 도서에 대한 정보를 저장하는 구조로 작성해 보자.
main 함수에서는 사용자로부터 3권의 도서에 대한 정보를 입력 받고, 입력이 끝나면 도서에 대한 내용을 출력해 주도록 하자.
실행 예시
도서 정보 입력
저자: Yoon
제목: C Programming
페이지 수 : 200
저자: Hong
제목: C++ Programming
페이지 수 : 250
저자: James
제목: OS for Programmer
페이지 수 : 300
도서 정보 출력
book 1
저자: Yoon
제목: C Programming
페이지 수 : 200
book 2
저자: Hong
제목: C++ Programming
페이지 수 : 250
book 3
저자: James
제목: OS for Programmer
페이지 수 : 300
#include <stdio.h>
#include <string.h>
struct Book {
char title[50];
char author[50];
int page;
} Book;
int main()
{
struct Book books[3];
int i;
printf("<도서 정보> - 입력\n");
for(i = 0; i < 3; i++)
{
printf("저자: ");
fgets(books[i].author, sizeof(books[i].author), stdin);
strtok(books[i].author, "\n"); // 개행 문자 제거
printf("제목: ");
fgets(books[i].title, sizeof(books[i].title), stdin);
strtok(books[i].title, "\n"); // 개행 문자 제거
printf("페이지: ");
scanf("%d", &books[i].page);
getchar(); // 개행 문자 제거
printf("\n");
}
printf("<도서 정보> - 출력\n");
for(i = 0; i < 3; i++)
{
printf("도서 %d\n", i + 1);
printf("제목: %s\n", books[i].title);
printf("저자: %s\n", books[i].author);
printf("페이지: %d\n", books[i].page);
printf("\n");
}
return 0;
}
>출력
<도서 정보> - 입력
저자: Yoon
제목: C Programing
페이지: 200
저자: Hong
제목: C++ Programing
페이지: 250
저자: James
제목: OS for Programmer
페이지: 300
<도서 정보> - 출력
도서 1
제목: C Programing
저자: Yoon
페이지: 200
도서 2
제목: C++ Programing
저자: Hong
페이지: 250
도서 3
제목: OS for Programmer
저자: James
페이지: 300
-풀이-
처음에는 바로 printf와 scanf를 사용해서 문제를 풀려고 했는데 그렇게 하다보니 제목에서 띄어쓰기가 들어가면 페이지를 입력할 수 없게 되었다.
따라서 fgets함수를 이용해서 사용자로부터 입력받게 수정했다.
strtok
함수는 string을 tokenize로 문자열(string)을 토큰(token)처럼 조각조각 내는 함수다. 쉼표(,)와 띄어쓰기( )를 구분자로 넣어서 띄어쓰기를 제외한 단어들을 가져올 수 있다.
도전 1에서 구현한 프로그램에 약간의 변경을 줘보자.
구조체 배열을 선언하는 것이 아니라, 구조체 포인터 배열을 선언하고 구조체 변수를 동적으로 할당하는 형태로 프로그램을 재 구현해 보자.
그리고 도전 1에서 구현한 방법보다 도전 2에서 구현한 방법이 지니는 장점이 무엇인지도 생각해보자.
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Book {
char title[50];
char author[50];
int page;
};
int main() {
struct Book **books; // 구조체 포인터 배열
int i;
int num_books = 3; // 도서 개수
// 구조체 포인터 배열 동적 할당
books = (struct Book **)malloc(num_books * sizeof(struct Book *));
for (i = 0; i < num_books; i++) {
books[i] = (struct Book *)malloc(sizeof(struct Book));
}
printf("<도서 정보> - 입력\n");
for (i = 0; i < num_books; i++) {
printf("저자: ");
fgets(books[i]->author, sizeof(books[i]->author), stdin);
strtok(books[i]->author, "\n"); // 개행 문자 제거
printf("제목: ");
fgets(books[i]->title, sizeof(books[i]->title), stdin);
strtok(books[i]->title, "\n"); // 개행 문자 제거
printf("페이지: ");
scanf("%d", &books[i]->page);
getchar(); // 개행 문자 제거
printf("\n");
}
printf("<도서 정보> - 출력\n");
for (i = 0; i < num_books; i++) {
printf("도서 %d\n", i + 1);
printf("제목: %s\n", books[i]->title);
printf("저자: %s\n", books[i]->author);
printf("페이지: %d\n", books[i]->page);
printf("\n");
}
// 동적으로 할당한 메모리 해제
for (i = 0; i < num_books; i++) {
free(books[i]);
}
free(books);
return 0;
}
>출력
<도서 정보> - 입력
저자: Yoon
제목: C Programing
페이지: 200
저자: Min
제목: Choregraphy Basic
페이지: 150
저자: Kim
제목: What is Love
페이지: 100
<도서 정보> - 출력
도서 1
제목: C Programing
저자: Yoon
페이지: 200
도서 2
제목: Choregraphy Basic
저자: Min
페이지: 150
도서 3
제목: What is Love
저자: Kim
페이지: 100
-풀이-
<도전 1과 도전 2 비교>
유연한 메모리 관리:
도전 1 - 고정된 크기의 배열을 사용하여 메모리를 할당하므로, 프로그램 시작 시 도서의 개수를 정해야 함.
도전 2 - 동적 메모리 할당을 사용하여 필요에 따라 도서의 개수를 조절할 수 있음. 이로 인해 메모리 사용이 더 효율적.
메모리 사용 최적화:
도전 1 - 배열의 크기를 미리 정해야 하므로, 필요하지 않은 메모리가 낭비될 수 있음.
도전 2 - 입력받는 도서의 수에 따라 메모리를 동적으로 조절할 수 있어, 필요한 만큼만 메모리를 사용할 수 있음.
재사용 가능성:
도전 1 - 배열의 크기를 변경하려면 프로그램을 수정해야 함.
도전 2 - 동적 할당을 사용하면, 프로그램 실행 중에 도서의 수를 쉽게 변경하거나 확장할 수 있음.
[결론]
동적 메모리 할당을 사용하면 더 유연하고 효율적인 메모리 관리가 가능하여, 다양한 조건에서 프로그램을 보다 쉽게 수정하고 확장할 수 있다.
복소수(Complex Number)를 나타내는 구조체를 정의하고, 복소수의 덧셈과 곱셈을 위한 함수를 각각 정의하자. 그리고 이를 기반으로 프로그램 사용자로부터 두 개의 복소수 정보를 입력 받아서 두 복소수의 덧셈과 곱셈의 결과를 출력하는 프로그램을 작성하자.
실행 예시
복소수 입력1[실수 허수]: 1.2 2.4
복소수 입력2[실수 허수]: 1.1 2.2
합의 결과] 실수: 2.300000, 허수: 4.600000
곱의 결과] 실수: -3.960000, 허수: 5.280000
복소수 공식
#include <stdio.h>
typedef struct {
double real;
double imaginary;
} ComplexNumber;
ComplexNumber addComplexNumbers(ComplexNumber num1, ComplexNumber num2)
{
ComplexNumber result;
result.real = num1.real + num2.real;
result.imaginary = num1.imaginary + num2.imaginary;
return result;
}
ComplexNumber multiplyComplexNumbers(ComplexNumber num1, ComplexNumber num2)
{
ComplexNumber result;
result.real = num1.real * num2.real - num1.imaginary * num2.imaginary;
result.imaginary = num1.real * num2.imaginary + num1.imaginary * num2.real;
return result;
}
int main()
{
ComplexNumber num1, num2, sum, mul;
printf("복소수 입력1[실수 허수]: ");
scanf("%lf %lf", &num1.real, &num1.imaginary);
printf("복소수 입력2[실수 허수]: ");
scanf("%lf %lf", &num2.real, &num2.imaginary);
sum = addComplexNumbers(num1, num2);
mul = multiplyComplexNumbers(num1, num2);
printf("합의 결과] 실수: %.5lf, 허수: %.5lf\n", sum.real, sum.imaginary);
printf("곱의 결과] 실수: %.5lf, 허수: %.5lf\n", mul.real, mul.imaginary);
return 0;
}
>출력
복소수 입력1[실수 허수]: 1.2 2.4
복소수 입력2[실수 허수]: 1.1 2.2
합의 결과] 실수: 2.30000, 허수: 4.60000
곱의 결과] 실수: -3.96000, 허수: 5.28000
-풀이-
복소수를 오랜만에 다시 보게 됐는데 단순하게 복소수의 덧셈 공식과 곱셈 공식을 함수로 만들어서 해결했다.
문자열을 저장하고 있는 파일을 열어서 A와 P로 시작하는 단어의 수를 세어서 출력하는 프로그램을 작성해보자.
단, 모든 단어는 공백문자(space bar, \t, \n)에 의해서 구분된다고 가정한다.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#define MAX_WORD_LENGTH 100
int main(int argc, char *argv[]) // argc: 명령행 인자의 수, argv: 명령행 인자를 문자열 배열로 저장.
{
if (argc != 2) // 파일 이름이 인자로 제공되지 않으면 오류 메세지 출력하고 종료.
{
printf("사용법: %s <파일이름>\n", argv[0]);
return 1;
}
FILE *file = fopen(argv[1], "r"); // 파일 열기. 실패시 perror 함수 사용하여 오류 메세지 출력하고 종료.
if (file == NULL)
{
perror("파일을 열 수 없습니다");
return 1;
}
char word[MAX_WORD_LENGTH]; // 각 단어 저장.
int countA = 0, countP = 0;
while (fscanf(file, "%s", word) == 1) // fscanf으로 파일에서 단어 하나씩 읽어오기. %s로 공백으로 구분된 단어 읽음.
{
// 첫 글자를 대문자로 변환하여 비교
char firstChar = toupper(word[0]); // 단어의 첫 글자 대문자로 변환.
if (firstChar == 'A') {
countA++; // A로 시작하는 단어 카운트.
} else if (firstChar == 'P') {
countP++; // P로 시작하는 단어 카운트.
}
}
fclose(file);
printf("A로 시작하는 단어의 수: %d\n", countA);
printf("P로 시작하는 단어의 수: %d\n", countP);
return 0;
}
>명령어 & 출력
>gcc -o wordcnt ch4.c
>.\wordcnt text.txt
A로 시작하는 단어의 수: 2
P로 시작하는 단어의 수: 6
-풀이-
ctype.h 헤더 파일은 C 표준 라이브러리의 일부로, 문자 처리에 관련된 여러 함수를 제공한다. 이 파일에 포함된 함수들은 주로 문자 분류와 변환을 위한 기능을 제공하며, 다음과 같은 함수들이 포함되어 있다.
이 프로그램에서는 toupper() 함수를 사용하여 단어의 첫 글자를 대문자로 변환하고, A 또는 P와 비교하기 위해 사용했다.
참고로 나의 text.txt에는 아래와 같이 적었었다.
apple
avocado
banana
blackberry
blueberry
cherry tomato
cherry
coconut
grape
kiwi
lemon
lime
mango
melon
orange
papaya
peach
pear
persimmon
pineapple
plum
strawberry
tangerine
tomato
watermelon
두 개의 텍스트 파일이 같은지 다른지를 확인하는 프로그램을 작성해 보자.
단순히 공백문자 하나가 차이를 보여도 두 텍스트 파일은 다른 것으로 판별이 나야 한다.
명령어: .\comp d1.txt d2.txt
두 개의 파일은 완전히 일치 합니다.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
if (argc != 3)
{
printf("사용법: %s <파일1> <파일2>\n", argv[0]);
return 1;
}
FILE *file1 = fopen(argv[1], "r");
FILE *file2 = fopen(argv[2], "r");
if (file1 == NULL || file2 == NULL)
{
perror("파일을 열 수 없습니다");
return 1;
}
char ch1, ch2;
int areEqual = 1; // 파일이 같다고 가정
while ((ch1 = fgetc(file1)) != EOF && (ch2 = fgetc(file2)) != EOF)
if (ch1 != ch2)
{
areEqual = 0; // 파일이 다름
break;
}
// 파일의 끝을 넘어선 경우: 하나의 파일이 더 길 경우
if (areEqual && (fgetc(file1) != EOF || fgetc(file2) != EOF))
areEqual = 0; // 파일 길이가 다름
fclose(file1);
fclose(file2);
if (areEqual)
printf("두 개의 파일은 완전히 일치합니다.\n");
else
printf("두 개의 파일은 다릅니다.\n");
return 0;
}
>명령어 & 출력
>gcc -o comp ch5.c
>.\comp text.txt text1.txt //아까 위에서 사용한 파일 또 사용.
두 개의 파일은 완전히 일치합니다.
-풀이-
두 파일의 길이 또는 내용을 확인하는 것이 관건이었다.
전화번호 관리 프로그램을 작성해 보자.
이 프로그램이 기본적으로 지녀야 하는 기능은 다음과 같다.
실행 예시와 비슷하게 동작하는 전화번호 관리 프로그램을 구현하기 바란다.
*****MENU*****
1. Insert
2. Delete
3. Search
4. Print All
5. Exit
Choose the item: 1
[INSERT]
Input Name: Yoon
Input Tel Number: 333-4444
Data Inserted
*****MENU*****
1. Insert
2. Delete
3. Search
4. Print All
5. Exit
Choose the item: 2
[DELETE]
Input Name that You Want to Delete: Yoon
Data Deleted
*****MENU*****
1. Insert
2. Delete
3. Search
4. Print All
5. Exit
Choose the item: 3
[SEARCH]
Input Name that You Want to Find: Yoon
[Data]
Name: Yoon
Tel: 333-4444
Data Searched
*****MENU*****
1. Insert
2. Delete
3. Search
4. Print All
5. Exit
Choose the item: 4
[Print All Data]
Name: Yoon Tel: 333-4444
Data Printed
// ch6_func.h
#ifndef CH6_FUNC_H
#define CH6_FUNC_H
#define MAX_CONTACTS 100
#define NAME_LENGTH 50
#define TEL_LENGTH 15
// 연락처 구조체 정의
typedef struct {
char name[NAME_LENGTH];
char tel[TEL_LENGTH];
} Contact;
// 함수 선언
void insertContact();
void deleteContact();
void searchContact();
void printAllContacts();
#endif
// ch6_func.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ch6_func.h" // 헤더 파일 포함
#define MAX_CONTACTS 100
#define NAME_LENGTH 50
#define TEL_LENGTH 15
// 전화번호 목록
Contact contacts[MAX_CONTACTS];
int contactCount = 0;
void InsertContact()
{
if(contactCount >= MAX_CONTACTS)
{
printf("전화번호 목록이 가득 찼다.(100/100)\n\n");
return;
}
printf("[INSERT]\n");
printf("Input Name: ");
fgets(contacts[contactCount].name, NAME_LENGTH, stdin);
strtok(contacts[contactCount].name, "\n");
printf("Input Tel Number: ");
fgets(contacts[contactCount].tel, TEL_LENGTH, stdin);
strtok(contacts[contactCount].tel, "\n");
contactCount++;
printf("\t\t\tData Inserted\n\n");
}
void DeleteContact()
{
char name[NAME_LENGTH];
printf("[DELETE]\n");
printf("Input Name that You Want to Delete: ");
fgets(name, NAME_LENGTH, stdin);
strtok(name, "\n");
for(int i = 0; i < contactCount; i++)
{
if(strcmp(contacts[i].name, name) == 0)
{
for(int j = i; j < contactCount - 1; j++)
{
strcpy(contacts[j].name, contacts[j + 1].name);
strcpy(contacts[j].tel, contacts[j + 1].tel);
}
contactCount--;
printf("\t\t\tData Deleted\n\n");
return;
}
}
printf("No such contact found with the name '%s'\n\n", name);
}
void SearchContact()
{
char name[NAME_LENGTH];
printf("[SEARCH]\n");
printf("Input Name that You Want to Find: ");
fgets(name, NAME_LENGTH, stdin);
strtok(name, "\n");
for(int i = 0; i < contactCount; i++)
{
if(strcmp(contacts[i].name, name) == 0)
{
printf("[Data]\n");
printf("Name: %s\n", contacts[i].name);
printf("Tel: %s\n", contacts[i].tel);
printf("\t\t\tData Searched\n\n");
return;
}
}
printf("No such contact found with the name '%s'\n\n", name);
}
void PrintAllContacts()
{
printf("[Print All Data]\n");
for(int i = 0; i < contactCount; i++)
{
printf("Name: %s\tTel: %s\n", contacts[i].name, contacts[i].tel);
}
printf("\t\t\tData Printed\n\n");
}
// ch6.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 함수 참조
void InsertContact();
void DeleteContact();
void SearchContact();
void PrintAllContacts();
int main()
{
int choice;
while(1)
{
printf("*****MENU*****\n");
printf("1. Insert\n");
printf("2. Delete\n");
printf("3. Search\n");
printf("4. Print All\n");
printf("5. Exit\n");
printf("Choose the item: ");
scanf("%d", &choice);
getchar();
switch(choice)
{
case 1:
InsertContact();
break;
case 2:
DeleteContact();
break;
case 3:
SearchContact();
break;
case 4:
PrintAllContacts();
break;
case 5:
printf("Exiting...\n");
return 0;
default:
printf("Invalid choice! Please try again.\n\n");
}
}
}
>명령어 & 출력
>gcc -o phonebook ch6.c ch6_func.c
>.\phonebook.exe
*****MENU*****
1. Insert
2. Delete
3. Search
4. Print All
5. Exit
Choose the item: 1
[INSERT]
Input Name: Kim
Input Tel Number: 111-2222
Data Inserted
*****MENU*****
1. Insert
2. Delete
3. Search
4. Print All
5. Exit
Choose the item: 2
[DELETE]
Input Name that You Want to Delete: Min
No such contact found with the name 'Min'
*****MENU*****
1. Insert
2. Delete
3. Search
4. Print All
5. Exit
Choose the item: 2
[DELETE]
Input Name that You Want to Delete: Kim
Data Deleted
*****MENU*****
1. Insert
2. Delete
3. Search
4. Print All
5. Exit
Choose the item: 1
[INSERT]
Input Name: Kim
Input Tel Number: 111-2222
Data Inserted
*****MENU*****
1. Insert
2. Delete
3. Search
4. Print All
5. Exit
Choose the item: 1
[INSERT]
Input Name: Min
Input Tel Number: 222-3333
Data Inserted
*****MENU*****
1. Insert
2. Delete
3. Search
4. Print All
5. Exit
Choose the item: 3
[SEARCH]
Input Name that You Want to Find: Jung
No such contact found with the name 'Jung'
*****MENU*****
1. Insert
2. Delete
3. Search
4. Print All
5. Exit
Choose the item: 3
[SEARCH]
Input Name that You Want to Find: Min
[Data]
Name: Min
Tel: 222-3333
Data Searched
*****MENU*****
1. Insert
2. Delete
3. Search
4. Print All
5. Exit
Choose the item: 4
[Print All Data]
Name: Kim Tel: 111-2222
Name: Min Tel: 222-3333
Data Printed
*****MENU*****
1. Insert
2. Delete
3. Search
4. Print All
5. Exit
Choose the item: 6
Invalid choice! Please try again.
*****MENU*****
1. Insert
2. Delete
3. Search
4. Print All
5. Exit
Choose the item: 5
Exiting...
-풀이-
나는 Part 4에서 배운 내용을 사용하기 위해서 헤더 파일과 다른 파일로 나누어 이번 문제를 해결해보려 했다.
그리고 delete와 search를 했을 때는 기존에 작성한 데이터와 맞는지 안맞는지 경우에 따라 다른 알림 문장을 보여주려 했다.
도전 6에서 구현한 프로그램의 문제점은 프로그램이 종료되고 나면 기존에 저장된 데이터가 전부 사라진다는 것이다. 이 문제점을 해결하자.
프로그램이 종료되기 전에 파일을 하나 생성해서 기존에 입력받은 데이터를 저장하고, 프로그램을 다시 실행하면 파일에 저장된 데이터를 읽어 들이는 방식으로 프로그램을 변경해보자.
// ch7_func.h
#ifndef CH7_FUNC_H
#define CH7_FUNC_H
#define MAX_CONTACTS 100
#define NAME_LENGTH 50
#define TEL_LENGTH 15
typedef struct
{
char name[NAME_LENGTH];
char tel[TEL_LENGTH];
} Contact;
void InsertContact();
void DeleteContact();
void SearchContact();
void PrintAllContacts();
void SaveContacts(); // 파일 저장 함수 추가
void LoadContacts(); // 파일 로드 함수 추가
#endif
// ch7_func.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ch7_func.h"
Contact contacts[MAX_CONTACTS];
int contactCount = 0;
void InsertContact()
{
if (contactCount >= MAX_CONTACTS)
{
printf("전화번호 목록이 가득 찼다.(100/100)\n\n");
return;
}
printf("[INSERT]\n");
printf("Input Name: ");
fgets(contacts[contactCount].name, NAME_LENGTH, stdin);
strtok(contacts[contactCount].name, "\n"); // 개행 문자 제거
printf("Input Tel Number: ");
fgets(contacts[contactCount].tel, TEL_LENGTH, stdin);
strtok(contacts[contactCount].tel, "\n"); // 개행 문자 제거
contactCount++;
printf("\t\t\tData Inserted\n\n");
}
void DeleteContact()
{
char name[NAME_LENGTH];
printf("[DELETE]\n");
printf("Input Name that You Want to Delete: ");
fgets(name, NAME_LENGTH, stdin);
strtok(name, "\n"); // 개행 문자 제거
for (int i = 0; i < contactCount; i++)
{
if (strcmp(contacts[i].name, name) == 0)
{
for (int j = i; j < contactCount - 1; j++)
{
contacts[j] = contacts[j + 1]; // 데이터 이동
}
contactCount--;
printf("\t\t\tData Deleted\n\n");
return;
}
}
printf("No such contact found with the name '%s'.\n\n", name);
}
void SearchContact()
{
char name[NAME_LENGTH];
printf("[SEARCH]\n");
printf("Input Name that You Want to Find: ");
fgets(name, NAME_LENGTH, stdin);
strtok(name, "\n"); // 개행 문자 제거
for (int i = 0; i < contactCount; i++)
{
if (strcmp(contacts[i].name, name) == 0)
{
printf("[Data]\n");
printf("Name: %s\n", contacts[i].name);
printf("Tel: %s\n", contacts[i].tel);
printf("\t\t\tData Searched\n\n");
return;
}
}
printf("No contact found with the name '%s'.\n\n", name);
}
void PrintAllContacts()
{
printf("[Print All Data]\n");
for (int i = 0; i < contactCount; i++)
{
printf("Name: %s\tTel: %s\n", contacts[i].name, contacts[i].tel);
}
printf("\t\t\tData Printed\n\n");
}
void SaveContacts()
{
FILE *file = fopen("phonebook.txt", "w");
if (file == NULL)
{
perror("Unable to open file for writing.\n");
return;
}
for (int i = 0; i < contactCount; i++)
{
fprintf(file, "%s\n%s\n", contacts[i].name, contacts[i].tel);
}
fclose(file);
printf("Contacts saved to phonebook.txt\n\n");
}
void LoadContacts()
{
FILE *file = fopen("phonebook.txt", "r");
if (file == NULL)
{
printf("No existing contact data found. Starting fresh.\n");
return;
}
while (fscanf(file, "%[^\n]\n%[^\n]\n", contacts[contactCount].name, contacts[contactCount].tel) == 2)
{
contactCount++;
}
fclose(file);
printf("Contacts loaded from phonebook.txt\n\n");
}
// ch7.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ch7_func.h"
int main()
{
int choice;
// 데이터 로드
LoadContacts();
while (1)
{
printf("*****MENU*****\n");
printf("1. Insert\n");
printf("2. Delete\n");
printf("3. Search\n");
printf("4. Print All\n");
printf("5. Exit\n");
printf("Choose the item: ");
scanf("%d", &choice);
getchar(); // 개행 문자 처리
switch (choice)
{
case 1:
InsertContact();
break;
case 2:
DeleteContact();
break;
case 3:
SearchContact();
break;
case 4:
PrintAllContacts();
break;
case 5:
SaveContacts(); // 데이터 저장
printf("Exiting...\n");
return 0;
default:
printf("Invalid choice! Please try again.\n\n");
}
}
}
>명령어 & 출력
>gcc -o phonebook_new ch7_func.c ch7.c
>.\phonebook_new.exe
No existing contact data found. Starting fresh.
*****MENU*****
1. Insert
2. Delete
3. Search
4. Print All
5. Exit
Choose the item: 1
[INSERT]
Input Name: Kim
Input Tel Number: 111-2222
Data Inserted
*****MENU*****
1. Insert
2. Delete
3. Search
4. Print All
5. Exit
Choose the item: 5
Contacts saved to phonebook.txt
Exiting...
>.\phonebook_new.exe
Contacts loaded from phonebook.txt
*****MENU*****
1. Insert
2. Delete
3. Search
4. Print All
5. Exit
Choose the item: 1
[INSERT]
Input Name: Min
Input Tel Number: 010-2222-3333
Data Inserted
*****MENU*****
1. Insert
2. Delete
3. Search
4. Print All
5. Exit
Choose the item: 3
[SEARCH]
Input Name that You Want to Find: Jung
No contact found with the name 'Jung'.
*****MENU*****
1. Insert
2. Delete
3. Search
4. Print All
5. Exit
Choose the item: 3
[SEARCH]
Input Name that You Want to Find: Kim
[Data]
Name: Kim
Tel: 111-2222
Data Searched
*****MENU*****
1. Insert
2. Delete
3. Search
4. Print All
5. Exit
Choose the item: 4
[Print All Data]
Name: Kim Tel: 111-2222
Name: Min Tel: 010-2222-3333
Data Printed
*****MENU*****
1. Insert
2. Delete
3. Search
4. Print All
5. Exit
Choose the item: 1
[INSERT]
Input Name: Jung
Input Tel Number: 010-1234-5678
Data Inserted
*****MENU*****
1. Insert
2. Delete
3. Search
4. Print All
5. Exit
Choose the item: 5
Contacts saved to phonebook.txt
Exiting...
-풀이-
전화번호 데이터를 다른 파일에 저장하고 불러오기 위해서는 저장하는 함수와 로드하는 함수를 따로 만들어 줘야했다.
저장하는 함수
void SaveContacts()
{
FILE *file = fopen("phonebook.txt", "w");
if (file == NULL)
{
perror("Unable to open file for writing.\n");
return;
}
for (int i = 0; i < contactCount; i++)
{
fprintf(file, "%s\n%s\n", contacts[i].name, contacts[i].tel);
}
fclose(file);
printf("Contacts saved to phonebook.txt\n\n");
}
로드하는 함수
void LoadContacts()
{
FILE *file = fopen("phonebook.txt", "r");
if (file == NULL)
{
printf("No existing contact data found. Starting fresh.\n");
return;
}
while (fscanf(file, "%[^\n]\n%[^\n]\n", contacts[contactCount].name, contacts[contactCount].tel) == 2)
{
contactCount++;
}
fclose(file);
printf("Contacts loaded from phonebook.txt\n\n");
}
이렇게 해서 만들어진 phonebook.txt
파일을 확인해보면
Kim
111-2222
Min
010-2222-3333
Jung
010-1234-5678
내용이 잘 들어가있는 것을 확인할 수 있다.
<Review>
Visual Studio Code에서 C언어를 하면서 컴파일할 때 한글이 제대로 컴파일 되지 않는 오류가 계속 발생해서 이에 대한 해결책을 찾아보았다. 해결 방안으로는 다음 4가지와 같다.
소스 파일 인코딩 확인
소스 파일이 UTF-8로 인코딩되어 있는지 확인한다. Visual Studio Code에서 파일을 열고 오른쪽 아래의 인코딩 표시를 클릭하여 UTF-8로 변경한다.
GCC 컴파일 시 인코딩 설정
GCC에서 한글을 제대로 출력하도록 하기 위해, 컴파일할 때 다음과 같은 플래그를 추가할 수 있다.
gcc -o example your_file.c -finput-charset=UTF-8 -fexec-charset=UTF-8
콘솔 인코딩 설정 (Windows)
Windows 콘솔의 기본 인코딩이 UTF-8이 아닐 수 있다. 이를 해결하기 위해 아래 명령어를 사용하여 콘솔 인코딩을 UTF-8로 변경한다.
chcp 65001
이 명령어를 실행한 후 프로그램을 다시 실행해 보면 잘 되는 것을 확인할 수 있다.
마지막 6, 7번 문제는 쉬운듯 어려운듯 여태까지 배운 것들을 모두 사용할 수 있어서 재밌는 문제였다.