C 프로그래밍 실습 - 구조체와 포인터 활용

실습 개요

본 실습에서는 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;
        }
    }
}

태그: C structure pointer linked-list Enum

7월 13일 04:24에 게시됨