프로그래밍/C언어

[쉽게 풀어쓴 C언어 Express 개정4판] 14장 Exercise & Programming

곰탱이들 2024. 10. 17.

14장 Exercise & Programming

14장 Exercise

 

1. 다음은 무엇을 선언하는 문장인가?

 

a) int형 포인터에 대한 포인터 선언

b) 10개의 int형 포인터를 저장하는 배열의 선언

c) 3개의 int를 가지는 배열에 대한 포인터

d) int 형 인자를 받는 void 반환형의 함수에 대한 포인터


2. 다음의 설명에 맞는 문장을 작성해보자

int **ptr;						// a번
double *arr[5];						// b번
double (*func_ptr)(char);				// c번
int (*func_arr[2])(short, short);			// d번
void *p = NULL;						// e번

 

3. 다음 프로그램의 출력을 쓰시오

a) 100 100 100

b) 1

    3

c) 서울

d) 2

 

14장 Programming

1. 정수 배열  {30, 80, 100, 50, 60, 20, 40, 90, 70, 10}을 내림차순으로 정렬하는 프로그램을 작성해보자. 라이브러리 함수 qsort()를 사용한다

#include <stdio.h>
#include <stdlib.h>

int compare_desc(const void *a, const void *b) {
    return (*(int *)b - *(int *)a);
}

int main(void) {
    int arr[] = {30, 80, 100, 50, 60, 20, 40, 90, 70, 10};
    int size = sizeof(arr) / sizeof(arr[0]);

    qsort(arr, size, sizeof(int), compare_desc);

    printf("내림차순으로 정렬된 배열: ");
    for (int i = 0; i < size; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");

    return 0;
}

 

2. 학생(학번 int number, 이름 char name[10], 성적 double score)을 나타내는 구조체 Student를 정의한다. 구조체 Student의 배열에 학생 30명의 정보를 저장한다. 모든 정보는 난수로 생성해보자. 라이브러리 함수 qsort()를 사용하여 성적을 기준으로 정렬하는 프로그램을 작성해보자

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

typedef struct {
    int number;
    char name[10];
    double score;
} Student;

int compare_score(const void *a, const void *b) {
    double score_a = ((Student *)a)->score;
    double score_b = ((Student *)b)->score;
    return (score_a < score_b) - (score_a > score_b);
}

void generate_random_string(char *str, int length) {
    static const char charset[] = "abcdefghijklmnopqrstuvwxyz";
    for (int i = 0; i < length - 1; i++) {
        int key = rand() % (int)(sizeof(charset) - 1);
        str[i] = charset[key];
    }
    str[length - 1] = '\0';
}

int main(void) {
    srand(time(NULL));
    Student students[30];

    for (int i = 0; i < 30; i++) {
        students[i].number = i + 1;
        generate_random_string(students[i].name, 10);
        students[i].score = (double)rand() / RAND_MAX;
    }

    qsort(students, 30, sizeof(Student), compare_score);

    printf("성적으로 정렬한 결과:\n");
    for (int i = 0; i < 30; i++) {
        printf("%d %.6f %s\n", students[i].number, students[i].score, students[i].name);
    }

    return 0;
}

 

3. 10개 정도의 속담을 문자열의 형태로 함수 set_proverb() 내부에 저장하고 있다가 사용자가 set_proverb()를 호출하면 인수로 받은 이중 포인터를 이용하여 외부에 있는 char형 포인터 p를 설정하는 함수 set_proverb()를 작성하고 테스트하라.

#include <stdio.h>

void set_proverb(char **a, int n) {
    static char *array[10] = {
        "A bad shearer never had a good sickle.",
        "A bad workman (always) blames his tools.",
        "A bad workman quarrels with his tools.",
        "A bad thing never dies.",
        "A barking dog never bites.",
        "A bird in the hand is worth two in the bush.",
        "A burnt child dreads the fire.",
        "A cat has nine lives.",
        "A chain is only as strong as its weakest link.",
        "A drowning man will clutch at a straw."
    };
    if (n >= 1 && n <= 10) {
        *a = array[n - 1];
    } else {
        *a = "Invalid selection.";
    }
}

int main(void) {
    char *proverb;
    int choice;

    printf("몇 번째 속담을 선택하시겠습니까? ");
    scanf("%d", &choice);

    set_proverb(&proverb, choice);
    printf("선택된 속담 = %s\n", proverb);

    return 0;
}

 

4.  2차원 배열에 점수가 저장되어 있다고 가정한다. 우리가 가지고 있는 단 하나의 함수는 1차원 배열에 저장된 점수의 합을 구하는 int get_sum(int array[], int size)라고 가정하자. 2차원 배열의 각 행에 대하여 get_sum()을 호출해서 각 행의 합을 구한 후에, 이것들을 모두 합쳐서 전체 2차원 배열에 저장된 점수들의 합을 구하는 프로그램을 작성하여보자.

#include <stdio.h>

int get_sum(int array[], int size) {
    int sum = 0;
    for (int i = 0; i < size; i++) {
        sum += array[i];
    }
    return sum;
}

int main(void) {
    int scores[4][3] = {
        {60, 60, 60},
        {60, 60, 60},
        {10, 10, 10},
        {10, 10, 10}
    };
    int total_sum = 0;

    for (int i = 0; i < 4; i++) {
        total_sum += get_sum(scores[i], 3);
    }

    printf("점수의 합 = %d\n", total_sum);
    return 0;
}

 

5. 학생들의 성적이 scores라는 2차원 배열에 저장되어 있다고 가정하자. scores의 행은 한 학생에 대한 여러 과목의 성적이고, 열은 한 과목에 대한 여러 학생들의 성적이다. 학생별로 성적의 평균을 구하려고 한다. 2차원 배열의 각 행이 1차원 배열임을 이용하여 다음과 같이 1차원 배열의 평균을 구하는 함수 get_average()를 호출하여 각 학생에 대한 평균 성적을 계산하여보자.

#include <stdio.h>

double get_average(int list[], int n) {
    int sum = 0;
    for (int i = 0; i < n; i++) {
        sum += list[i];
    }
    return (double)sum / n;
}

int main(void) {
    int scores[3][3] = {
        {65, 70, 60},
        {55, 80, 70},
        {50, 50, 60}
    };

    for (int i = 0; i < 3; i++) {
        printf("%d행의 평균점수 = %.2f\n", i, get_average(scores[i], 3));
    }

    return 0;
}

 

6. 문자열의 배열을 인수로 받아서 저장된 문자열을 전부 출력하는 pr_str_array() 함수를 작성하여 테스트하여보자. pr_str_array()는 다음과 같은 원형을 가진다.

#include <stdio.h>

void pr_str_array(char **dp, int n) {
    for (int i = 0; i < n; i++) {
        printf("%s\n", dp[i]);
    }
}

int main(void) {
    char *proverbs[] = {
        "A bad shearer never had a good sickle.",
        "A bad workman (always) blames his tools.",
        "A bad workman quarrels with his tools.",
        "A bad thing never dies."
    };
    int size = sizeof(proverbs) / sizeof(proverbs[0]);

    pr_str_array(proverbs, size);

    return 0;
}

 

7. int형 배열과 int형 포인터를 받아서 포인터가 배열의 가장 큰 값을 가리키게 하는 함수 set_max_ptr()`을 구현하고 테스트하여보자.

#include <stdio.h>

void set_max_ptr(int m[], int size, int **pmax) {
    *pmax = &m[0];
    for (int i = 1; i < size; i++) {
        if (m[i] > **pmax) {
            *pmax = &m[i];
        }
    }
}

int main(void) {
    int m[6] = {5, 6, 1, 3, 7, 9};
    int *pmax;

    set_max_ptr(m, 6, &pmax);
    printf("가장 큰 값은 %d\n", *pmax);

    return 0;
}

 

8. 문자열을 가리키고 있는 포인터의 배열을 인수로 받아서 문자열을 알파벳 순으로 정렬하는 함수 sort_strings()를 작성하고 테스트하여 보라. 다음과 같은 원형을 가진다.

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

void sort_strings(char *list[], int size) {
    int i, j, least;
    char *temp;

    for (i = 0; i < size - 1; i++) {
        least = i;
        for (j = i + 1; j < size; j++) {
            if (strcmp(list[j], list[least]) < 0) {
                least = j;
            }
        }
        temp = list[i];
        list[i] = list[least];
        list[least] = temp;
    }
}

int main(void) {
    char *s[] = {"mycopy", "src", "dst"};
    int size = sizeof(s) / sizeof(s[0]);

    sort_strings(s, size);

    for (int i = 0; i < size; i++) {
        printf("%s\n", s[i]);
    }

    return 0;
}

 

9. 디지털 영상은 보통 2차원 배열로 표현된다. 각 배열 요소는 픽셀이라고 불린다. 흑백 영상의 경우, 하나의 픽셀은 보통 0에서 255의 값을 가지며 0은 검정색을, 255는 흰색을 나타낸다. 중간값은 회색을 나타낸다. 영상이 unsigned char image[ROWS][COLS]에 저장되어 있다고 가정하고 픽셀 값이 128 미만이면 0으로 만들고 128 이상이면 255로 만들어보자.

#include <stdio.h>

#define ROWS 5
#define COLS 5

void process_image(unsigned char image[ROWS][COLS]) {
    for (int i = 0; i < ROWS; i++) {
        for (int j = 0; j < COLS; j++) {
            if (image[i][j] < 128) {
                image[i][j] = 0;
            } else {
                image[i][j] = 255;
            }
        }
    }
}

int main(void) {
    unsigned char image[ROWS][COLS] = {
        {30, 80, 100, 150, 200},
        {120, 180, 70, 60, 90},
        {255, 140, 10, 5, 200},
        {50, 200, 130, 128, 255},
        {10, 220, 240, 80, 100}
    };

    process_image(image);

    for (int i = 0; i < ROWS; i++) {
        for (int j = 0; j < COLS; j++) {
            printf("%d ", image[i][j]);
        }
        printf("\n");
    }

    return 0;
}

 

10. 크기가 3 x 3인 2차원 배열을 다른 2차원 배열로 복사하는 함수 void array_copy(int src[][WIDTH], int dst[][WIDTH])를 구현하고 테스트하여 보라. 수행 속도를 위하여 배열 첨자 방법 대신에 포인터를 사용해보자.

#include <stdio.h>

#define WIDTH 3
#define HEIGHT 3

void array_copy(int src[HEIGHT][WIDTH], int dst[HEIGHT][WIDTH]) {
    for (int i = 0; i < HEIGHT; i++) {
        for (int j = 0; j < WIDTH; j++) {
            dst[i][j] = src[i][j];
        }
    }
}

int main(void) {
    int src[HEIGHT][WIDTH] = {
        {100, 30, 67},
        {89, 50, 12},
        {19, 60, 90}
    };
    int dst[HEIGHT][WIDTH];

    array_copy(src, dst);

    for (int i = 0; i < HEIGHT; i++) {
        for (int j = 0; j < WIDTH; j++) {
            printf("%d ", dst[i][j]);
        }
        printf("\n");
    }

    return 0;
}

 

11. 생명 게임(game of life)라고 불리는 인구 증가 게임을 구현하여보자. John H. Conway에 의해 발명된 생명 게임은 출생과 생존, 죽음의 모델을 가정한다. 이 게임은 가로와 세로로 20개의 셀을 갖는 보드 위에서 게임을 한다. 각 셀은 비어 있거나, 생명체를 나타내는 0 값을 가질 수 있다. 각 셀은 8개의 이웃을 갖는다. 생명체의 다음 세대는 다음 규칙에 따라 결정된다.

  • (a) 생성 - 3개의 이웃에 사람이 살면 현재의 위치에서 사람이 태어난다.
  • (b) 죽음 - 4개 이상의 이웃에 사람이 살면 과밀로 인해 죽게 된다. 또한 0개의 이웃일 경우에도 고립으로 죽게 된다.
  • (c) 생존 - 둘 또는 셋의 이웃에 사람이 살면 현재 위치의 사람은 다음 세대까지 생존하게 된다.

보드는 2차원 배열을 이용하여 생성하고 포인터를 최대한 많이 사용하여 생명 게임의 속도를 높이도록 하라.

#include <stdio.h>

#define ROWS 5
#define COLS 5

void next_generation(int board[ROWS][COLS]) {
    int next[ROWS][COLS] = {0};

    for (int i = 0; i < ROWS; i++) {
        for (int j = 0; j < COLS; j++) {
            int live_neighbors = 0;

            for (int x = -1; x <= 1; x++) {
                for (int y = -1; y <= 1; y++) {
                    if (x == 0 && y == 0) continue;
                    int ni = i + x;
                    int nj = j + y;

                    if (ni >= 0 && ni < ROWS && nj >= 0 && nj < COLS) {
                        live_neighbors += board[ni][nj];
                    }
                }
            }

            if (board[i][j] == 1) {
                if (live_neighbors < 2 || live_neighbors > 3) {
                    next[i][j] = 0;
                } else {
                    next[i][j] = 1;
                }
            } else {
                if (live_neighbors == 3) {
                    next[i][j] = 1;
                }
            }
        }
    }

    for (int i = 0; i < ROWS; i++) {
        for (int j = 0; j < COLS; j++) {
            board[i][j] = next[i][j];
        }
    }
}

int main(void) {
    int board[ROWS][COLS] = {
        {0, 1, 0, 0, 0},
        {1, 1, 0, 0, 0},
        {0, 0, 1, 0, 0},
        {0, 0, 0, 1, 0},
        {0, 0, 0, 0, 0}
    };

    printf("현재 세대:\n");
    for (int i = 0; i < ROWS; i++) {
        for (int j = 0; j < COLS; j++) {
            printf("%c ", board[i][j] ? 'X' : '-');
        }
        printf("\n");
    }

    next_generation(board);

    printf("\n다음 세대:\n");
    for (int i = 0; i < ROWS; i++) {
        for (int j = 0; j < COLS; j++) {
            printf("%c ", board[i][j] ? 'X' : '-');
        }
        printf("\n");
    }

    return 0;
}

15장 Exercise & Programming은 아래 클릭하시면됩니다.

[쉽게 풀어쓴 C언어 Express 개정4판] 15장 Exercise & Programming

 

[쉽게 풀어쓴 C언어 Express 개정4판] 15장 Exercise & Programming

15장 Exercise & Programming14장 Exercise 1. 다음 중 표준 파일 스트림이 아닌 것은?정답: 4번 stdcon 2. 다음은 표준 입출력 함수들에 대한 설명이다. 설명에 가장 일치하는 함수를 보기에서 골라서 쓰시오

gomszone.tistory.com

댓글