실습 개요
본 실습에서는 C语言的 구조체, 포인터, 연결 리스트 등 핵심 개념을 실습을 통해 학습한다. 각 과제별로 다양한 데이터 구조를 활용하는 방법을 익힌다.
과제 1: 학생 성적 관리 시스템
학생 정보를 구조체로 정의하고, 성적 계산 및 정렬 기능을 구현한다.
#include
#include
#define MAX_STUDENTS 3
typedef struct {
int student_id;
char name[20];
char subject[20];
double assignment;
double midterm;
double final exam;
double final_score;
char grade[10];
} StudentRecord;
void read_records(StudentRecord[], int);
void display_records(StudentRecord[], int);
void calculate(StudentRecord[], int);
int collect_fails(StudentRecord[], StudentRecord[], int);
void ranking(StudentRecord[], int);
int main() {
StudentRecord students[MAX_STUDENTS], failed[MAX_STUDENTS];
int fail_count;
printf("학생 성적 정보를 입력하세요:\n");
read_records(students, MAX_STUDENTS);
printf("\n성적 처리를 진행합니다...\n");
calculate(students, MAX_STUDENTS);
fail_count = collect_fails(students, failed, MAX_STUDENTS);
ranking(students, MAX_STUDENTS);
printf("\n성적 순위:\n");
display_records(students, MAX_STUDENTS);
printf("\n미달료생 목록:\n");
display_records(failed, fail_count);
return 0;
}
void read_records(StudentRecord data[], int count) {
int i;
for (i = 0; i < count; i++) {
scanf("%d %s %s %lf %lf %lf",
&data[i].student_id,
data[i].name,
data[i].subject,
&data[i].assignment,
&data[i].midterm,
&data[i].final_exam);
}
}
void display_records(StudentRecord data[], int count) {
int i;
printf("----------------------------------------\n");
printf("학번 이름 과목 과제 중간 기말 총점 등급\n");
for (i = 0; i < count; i++) {
printf("%d %-6s %-4s %-4.0f %-4.0f %-4.0f %-4.1f %s\n",
data[i].student_id,
data[i].name,
data[i].subject,
data[i].assignment,
data[i].midterm,
data[i].final_exam,
data[i].final_score,
data[i].grade);
}
}
void calculate(StudentRecord data[], int count) {
int i;
for (i = 0; i < count; i++) {
data[i].final_score = data[i].assignment * 0.2 +
data[i].midterm * 0.2 +
data[i].final_exam * 0.6;
if (data[i].final_score >= 90)
strcpy(data[i].grade, "A");
else if (data[i].final_score >= 80)
strcpy(data[i].grade, "B");
else if (data[i].final_score >= 70)
strcpy(data[i].grade, "C");
else if (data[i].final_score >= 60)
strcpy(data[i].grade, "D");
else
strcpy(data[i].grade, "F");
}
}
int collect_fails(StudentRecord source[], StudentRecord target[], int count) {
int i, fail_cnt = 0;
for (i = 0; i < count; i++) {
if (source[i].final_score < 60) {
target[fail_cnt++] = source[i];
}
}
return fail_cnt;
}
void ranking(StudentRecord data[], int count) {
int i, j;
StudentRecord temp;
for (i = 0; i < count - 1; i++) {
for (j = 0; j < count - 1 - i; j++) {
if (data[j].final_score < data[j + 1].final_score) {
temp = data[j];
data[j] = data[j + 1];
data[j + 1] = temp;
}
}
}
}
과제 2: 도서 정보 관리
구조체 배열과 포인터를 활용하여 도서 정보를 관리하고 검색하는 프로그램을 작성한다.
#include
#include
#define MAX_BOOKS 10
#define MAX_LEN 80
typedef struct {
char title[MAX_LEN];
char writer[MAX_LEN];
} BookInfo;
int main() {
BookInfo library[MAX_BOOKS] = {
{"1984", "George Orwell"},
{"Brave New World", "Aldous Huxley"},
{"The World of Yesterday", "Stefan Zweig"},
{"1587, A Year of No Significance", "Ray Huang"},
{"A Distinctive Pig", "Wang Xiaobo"},
{"One Hundred Years of Solitude", "Gabriel Garcia Marquez"},
{"84, Charing Cross Road", "Helene Hanff"},
{"Just Kids", "Patti Smith"},
{"The Razor's Edge", "Somerset Maugham"},
{"The Silent Majority", "Wang Xiaobo"}
};
BookInfo *ptr;
int i;
char search_author[MAX_LEN];
printf("=== 전체 도서 목록 ===\n");
for (ptr = library; ptr < library + MAX_BOOKS; ptr++) {
printf("%-30s%-30s\n", ptr->title, ptr->writer);
}
printf("\n검색할 저자 이름 입력: ");
gets(search_author);
printf("검색 결과:\n");
for (ptr = library; ptr < library + MAX_BOOKS; ptr++) {
if (strcmp(ptr->writer, search_author) == 0) {
printf("%-30s%-30s\n", ptr->title, ptr->writer);
}
}
return 0;
}
과제 3: 영화 정보 연결 리스트
동적 메모리 할당을 사용하여 연결 리스트를 구현하고 영화 정보를 관리한다.链表的头部插入和遍历输出。
#include
#include
#include
#define MAX_LEN 80
typedef struct MovieNode {
char title[MAX_LEN];
char director[MAX_LEN];
char country[MAX_LEN];
int release_year;
struct MovieNode *next;
} Movie;
void show_all(Movie *head);
Movie* add_node(Movie *head, int count);
int main() {
int num;
Movie *head;
head = NULL;
printf("영화 개수 입력: ");
scanf("%d", &num);
head = add_node(head, num);
printf("\n=== 영화 목록 ===\n");
show_all(head);
return 0;
}
Movie* add_node(Movie *head, int count) {
int i;
Movie *new_node;
for (i = 1; i <= count; i++) {
new_node = (Movie*)malloc(sizeof(Movie));
printf("영화%d 정보 입력 (제목 감독 국가 개봉연도): ", i);
scanf("%s %s %s %d",
new_node->title,
new_node->director,
new_node->country,
&new_node->release_year);
new_node->next = head;
head = new_node;
}
return head;
}
void show_all(Movie *head) {
Movie *current = head;
while (current != NULL) {
printf("%-20s %-20s %-20s %d\n",
current->title,
current->director,
current->country,
current->release_year);
current = current->next;
}
}
과제 3 (수정 버전): 더미 노드 사용
헤드 노드를 사용하여链表을 구성하는另一种方法.
#include
#include
#include
#define MAX_LEN 80
typedef struct MovieNode {
char title[MAX_LEN];
char director[MAX_LEN];
char country[MAX_LEN];
int release_year;
struct MovieNode *next;
} Movie;
void show_all(Movie *head);
Movie* add_node(Movie *head, int count);
int main() {
int num;
Movie *head;
Movie *dummy;
dummy = (Movie*)malloc(sizeof(Movie));
dummy->next = NULL;
head = dummy;
printf("영화 개수 입력: ");
scanf("%d", &num);
head = add_node(head, num);
printf("\n=== 영화 목록 ===\n");
show_all(head);
return 0;
}
Movie* add_node(Movie *head, int count) {
int i;
Movie *new_node;
for (i = 1; i <= count; i++) {
new_node = (Movie*)malloc(sizeof(Movie));
printf("영화%d 정보 입력: ", i);
scanf("%s %s %s %d",
new_node->title,
new_node->director,
new_node->country,
&new_node->release_year);
new_node->next = head->next;
head->next = new_node;
}
return head;
}
void show_all(Movie *head) {
Movie *p = head->next;
while (p != NULL) {
printf("%-20s %-20s %-20s %d\n",
p->title,
p->director,
p->country,
p->release_year);
p = p->next;
}
}
과제 4: 도서 판매 데이터 처리
구조체 배열을 활용하여 도서 판매량을 정렬하고 총액을 계산한다.
#include
#define MAX_BOOKS 10
typedef struct {
char isbn[20];
char title[80];
char author[80];
double price;
int quantity;
} BookData;
void print_list(BookData[], int);
void order_by_sales(BookData[], int);
double total_revenue(BookData[], int);
int main() {
BookData inventory[MAX_BOOKS] = {
{"978-0-06-093546-7", "The Fountainhead", "Ayn Rand", 84, 59},
{"978-0-452-28423-4", "1984", "George Orwell", 48, 16},
{"978-0-7432-7357-1", "Fahrenheit 451", "Ray Bradbury", 72.6, 27},
{"978-0-316-76948-0", "The Great Gatsby", "F. Scott Fitzgerald", 74.9, 49},
{"978-0-452-25933-1", "Brave New World", "Aldous Huxley", 49, 42},
{"978-0-679-72020-1", "Animal Farm", "George Orwell", 34.5, 39},
{"978-0-553-38016-3", "Dune", "Frank Herbert", 37.5, 55},
{"978-0-06-112008-4", "To Kill a Mockingbird", "Harper Lee", 29.5, 31},
{"978-0-452-28424-1", "The Catcher in the Rye", "J.D. Salinger", 118, 42},
{"978-0-7432-7356-4", "Lord of the Flies", "William Golding", 22.5, 44}
};
printf("=== 판매량 순위 ===\n");
order_by_sales(inventory, MAX_BOOKS);
print_list(inventory, MAX_BOOKS);
printf("\n총 매출액: %.2f\n", total_revenue(inventory, MAX_BOOKS));
return 0;
}
void print_list(BookData data[], int count) {
int i;
printf("ISBN\t\t\t제목\t\t\t\t저자\t\t\t단가\t\t판매수량\n");
for (i = 0; i < MAX_BOOKS; i++) {
printf("%-24s%-32s%-24s%.2f\t\t%d\n",
data[i].isbn,
data[i].title,
data[i].author,
data[i].price,
data[i].quantity);
}
}
void order_by_sales(BookData data[], int count) {
int i, j;
BookData temp;
for (i = 0; i < MAX_BOOKS; i++) {
for (j = 0; j < MAX_BOOKS - 1; j++) {
if (data[j].quantity < data[j + 1].quantity) {
temp = data[j];
data[j] = data[j + 1];
data[j + 1] = temp;
}
}
}
}
double total_revenue(BookData data[], int count) {
int i;
double sum = 0.0;
for (i = 0; i < MAX_BOOKS; i++) {
sum += data[i].price * data[i].quantity;
}
return sum;
}
과제 5: 날짜 처리 함수
날짜를 나타내는 구조체를 정의하고, 1년 중 몇 번째 날인지 계산하거나 두 날짜를 비교하는 함수를 구현한다.
#include
typedef struct {
int year;
int month;
int day;
} Calendar;
void enter_date(Calendar *date_ptr);
int day_number(Calendar date);
int compare(Calendar first, Calendar second);
void test_one();
void test_two();
int main() {
printf("테스트 1: 입력한 날짜가 1년 중 몇 번째 날인지 출력\n");
test_one();
printf("\n테스트 2: 두 사람의 생년월일 비교\n");
test_two();
return 0;
}
void test_one() {
Calendar d;
int i;
printf("날짜 입력 (형식: 2024-06-01):\n");
for (i = 0; i < 3; i++) {
enter_date(&d);
printf("%04d-%02d-%02d는 1년 중 %d번째 날입니다.\n\n",
d.year, d.month, d.day, day_number(d));
}
}
void test_two() {
Calendar alice, bob;
int i;
int result;
printf("Alice와 Bob의 생년월일 입력 (형식: 2005-08-11):\n");
for (i = 0; i < 3; i++) {
enter_date(&alice);
enter_date(&bob);
result = compare(alice, bob);
if (result == 0)
printf("Alice와 Bob의 나이가 같습니다.\n\n");
else if (result == -1)
printf("Alice가 Bob보다 나이가 많습니다.\n\n");
else
printf("Alice가 Bob보다 나이가 적습니다.\n\n");
}
}
void enter_date(Calendar *date_ptr) {
scanf("%04d-%02d-%02d",
&(date_ptr->year),
&(date_ptr->month),
&(date_ptr->day));
}
int day_number(Calendar date) {
int i, days = 0;
for (i = 1; i < date.month; i++) {
if (i == 1 || i == 3 || i == 5 || i == 7 || i == 8 || i == 10 || i == 12) {
days += 31;
} else if (i == 2) {
if ((date.year % 4 == 0 && date.year % 100 != 0) || date.year % 400 == 0)
days += 29;
else
days += 28;
} else {
days += 30;
}
}
days += date.day;
return days;
}
int compare(Calendar first, Calendar second) {
int first_day, second_day;
first_day = day_number(first);
second_day = day_number(second);
if (first.year < second.year)
return -1;
if (first.year > second.year)
return 1;
else {
if (first_day == second_day)
return 0;
if (first_day < second_day)
return -1;
else
return 1;
}
}
과제 6: 계정 관리 시스템
열거형을 사용하여 계정 유형을 정의하고, 비밀번호는 별표(*)로 대체하여 표시하는 프로그램을 구현한다.
#include
#include
enum UserRole {administrator, educator, learner};
typedef struct {
char user_id[20];
char pwd[20];
enum UserRole role;
} AccountInfo;
void show_accounts(AccountInfo list[], int count);
int main() {
AccountInfo accounts[] = {
{"S1001", "pass123", learner},
{"S1002", "abc456def", learner},
{"S1009", "xyz78900", learner},
{"A1009", "admin2024", administrator},
{"T11553", "teacher99", educator},
{"S3005", "student55", learner}
};
int total;
total = sizeof(accounts) / sizeof(AccountInfo);
show_accounts(accounts, total);
return 0;
}
void show_accounts(AccountInfo list[], int count) {
int i, j, pwd_len;
for (i = 0; i < count; i++) {
printf("%-8s", list[i].user_id);
pwd_len = strlen(list[i].pwd);
for (j = 0; j < pwd_len; j++)
printf("*");
printf("\t");
switch (list[i].role) {
case administrator:
printf("administrator\n");
break;
case educator:
printf("educator\n");
break;
case learner:
printf("learner\n");
break;
}
}
}