01. 정수 배열 { 30,80,100,50,60,20,40,90,70,10 }을 내림차순으로 정렬하는 프로그램을 작성해보자. 라이브러리 함수 qsort()를 사용한다.
#include <stdio.h>
#include <stdlib.h>
int array[] = { 30,80,100,50,60,20,40,90,70,10 };
int compare(const void *a, const void *b) {
return (*(int*)b - *(int*)a);
}
int print() {
for (int i = 0; i < sizeof(array) / sizeof(array[0]); i++) {
printf("%d, ", array[i]);
}
printf("\n");
}
int main() {
printf("정렬되지 않은 배열: \n");
print();
qsort(array, sizeof(array)/sizeof(array[0]), sizeof(int), compare);
printf("내림차순으로 정렬된 배열: \n");
print();
}
02. 학생(학번 int number, 이름 char name[10], 성적 double score)을 나타내는구조체 Student를 정의한다. 구조체 Student의 배열에 학생 30명의 정보를 저장한다. 모든 정보는 난수로 생성해보자. 라이브러리 함수 qsort()를 사용하여 성적을 기준으로 정렬하는 프로그램을 작성해보자.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
typedef struct {
int number;
char name[10];
double score;
}Student;
void generate_name(char* name, int size);
int compare(const void* a, const void* b);
void print(Student* student, int size);
int main() {
srand((unsigned)time(NULL));
Student list[30];
int name_size = sizeof(list[0].name) / sizeof(list[0].name[0]);
int student_size = sizeof(list) / sizeof(list[0]);
// 구조체 배열에 값 넣기
for (int i = 0; i < student_size; i++) {
list[i].number = i;
generate_name(list[i].name, name_size);
list[i].score = (double)(rand() % 1000) / 1000; // 0.0 ~ 1.0의 랜덤 점수
}
qsort(list, 30, sizeof(Student), compare);
printf("성적으로 정렬한 결과 \n");
print(list, student_size);
}
//이름 생성 함수
void generate_name(char* name, int size) {
char alpha[] = "abcdefghijklmnopqrstuvwxyz";
int key;
for (int i = 0; i < size - 1; i++) {
key = rand() % (sizeof(alpha) - 1);
name[i] = alpha[key];
}
name[size - 1] = '\0';
}
int compare(const void* a, const void* b) {
double result;
Student* student_a = (Student*)a; // a = &list
Student* student_b = (Student*)b;
result = (*student_a).score - student_b->score;
if (result < 0) {
return -1;
}
else if (result == 0) {
return 0;
}
else {
return 1;
}
}
void print(Student* student, int size) {
for (int i = 0; i < size; i++) {
printf("%4d %lf %s \n", (student+i)->number, (student+i)->score, student[i].name);
}
}
03. 10개 정도의 속담을 문자열의 형태로 함수 set_proverb() 내부에 저장하고있다가 사용자가 set_proverb()을 호출하면인수로 받은 이중 포인터를 이용하여 외부에 있는 char형포인터 s를 설정하는 set_proverb()을 작성하고 테스트하라.
#include <stdio.h>
void set_proverb(char** q, int n);
int main() {
int user;
char* p = NULL;
printf("몇 번째 속담을 선택하시겠습니까? ");
scanf("%d", &user);
set_proverb(&p, user);
printf("선택된 속담 = %s ", p);
}
void set_proverb(char** q, int n) {
static char* array[10] = {
"A bad workman shearer never had a good sickle.",
"A bad workman (always) blames his tools.",
"A bad workman quarrles with his tools.",
"A bad thing never dies.",
"a",
"b",
"c",
"d",
"f",
"g" };
*q = array[n-1];
}
04. 2차원 배열에 정수가 저장되어 있다고 가정한다. 우리가 가지고 있는 단 하나의 함수는 1차원 배열에 저장된정수의 합을 구하는 int get_sum(int array[], int size) 라고 가정하자. 2차원배열의 각 행에 대하여 get_sum() 을 호출하여서 각 행의 합을 구한후에, 이것들을 모두 합쳐서 전체 2차원 배열에 저장된정수들의 합을 구하는 프로그램을 작성하여보자.
(hint: 2차원배열은 m[][] 이라고 하면 m[0]은 첫 번째 행이고, m[1]은 두 번째 행을 가리킨다. 이것들은 또 1차원 배열이기도하다. 즉, 2차원 배열은 1차원 배열들의 모임이라고 생각할 수 있다.)
#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() {
int array[3][6] = {
{10,10,10,10,10,10},
{10,10,10,10,10,10},
{10,10,10,10,10,10}
};
int sum_col_array[4] = { 0 };
int row = sizeof(array) / sizeof(array[0]);
int col = sizeof(array[0]) / sizeof(array[0][0]);
for (int i = 0; i < row; i++) {
sum_col_array[i] = get_sum(array[i], col);
}
for (int i = 0; i < row; i++) {
sum_col_array[3] += sum_col_array[i];
}
printf("정수의 합 = %d", sum_col_array[3]);
}
05. 학생들의 성적이 scores라는 2차원 배열에 저장되어 있다고 가정하자. scores의 행은 한 학생에 대한 여러 번의 시험 성적을나타낸다. scores의 열은 한 시험에대한 여러 학생들의 성적이다. 학생별로 성적의 평균을 구하려고 한다 . 2차원배열의 각행이 1차원 배열임을 이용하여 다음과 같이 1차원 배열의 평균을 구하는 함수 get_average()를 호출하여 각 학생에 대한 평균 성적을 계산하여보자.
double get_average(int list[], int n);
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define ROWS 3
#define COLS 6
double get_avg(int array[][COLS], int n) {
int* p, * endp;
p = &array[n][0];
endp = &array[n][COLS - 1];
int sum = 0;
while (p <= endp)
sum += *p++;
return (double)sum / COLS;
}
int main() {
int array[ROWS][COLS] = {
{10,10,10,10,10,10},
{10,10,10,10,10,20},
{10,10,10,10,10,30}
};
for (int i = 0; i < ROWS; i++) {
printf("%d행의 평균값 = %.0f \n", i, get_avg(array, i));
}
}
06. 문자열의배열을 인수로 받아서 저장된 문자열을 전부 출력하는pr_str_array() 함수를작성하여 테스트하여보자. pr_str_array()는 다음과 같은 원형을 가진다.
void pr_str_array(char **dp, int n);
#include <stdio.h>
void pr_srt_array(char** dp, int n);
int main() {
char *p[] =
{
"A bad workman shearer never had a good sickle.",
"A bad workman (always) blames his tools.",
"A bad workman quarrles with his tools.",
"A bad thing never dies.",
"a",
"b",
"c",
"d",
"f",
"g"
};
int size = sizeof(p) / sizeof(p[0]);
pr_srt_array(p, size);
}
void pr_srt_array(char** dp, int n) {
for (int i = 0; i < n; i++) {
printf("%s \n", *(dp+i)); //dp[i] 도 가능
}
}
07. int형 배열과 int형 포인터를 받아서 포인터가 배열의 가장 큰 값을 가리키게 하는함수 set_max_ptr()을 구현하고 테스트하여보자.
#include <stdio.h>
void get_max(int** q, int arr[], int size) {
*q = arr;
for (int i = 1; i < size; i++) {
if (**q < arr[i])
*q = arr + i;
}
}
int main() {
int m[6] = { 1,2,3,4,5,6 };
int* p;
get_max(&p, m, 6);
printf("%d", *p);
}
08. 문자열을 가리키고 있는 포인터의 배열을 인수로 받아서 문자열을 알파벳 순으로 정렬시키는 함수 sort_strings()를 작성하고 테스트하여 보라. 다음과 같은 원형을 가진다.
#include <stdio.h>
#include <string.h>
void sort_strings(char* list[], int size);
int main() {
char* s[] = { "src", "dst", "mycopy" };
int size = sizeof(s) / sizeof(s[0]);
sort_strings(s, size);
for (int i = 0; i < size; i++) {
printf("%s \n", s[i]);
}
}
void sort_strings(char* list[], int size) {
char* temp;
for (int i = 0; i < size - 1; i++) {
for (int j = 0; j < size - 1; j++) {
if (strcmp(list[j], list[j + 1]) > 0) {
temp = list[j];
list[j] = list[j + 1];
list[j + 1] = temp;
}
}
}
}
09. 디지털 영상은 보통 2차원 배열로 표현된다. 각 배열 요소는 픽셀이라고 불린다. 흑백 영상의 경우, 하나의 픽셀은 보통 0에서 255의 값을 가지며 0은 검정색을, 255는 흰색을 나타낸다. 중간값은 회색을 나타낸다. 영상은 unsigned char image[ROW][COLS]에 저장되어 있다고 가정하고 픽셀 값이 128 미만이면 0으로 만들고 128 이상이면 255로 만들어보자.
1) 2차원 배열의 함수 매개변수 (가장 무난한 방법, 실력 향상엔 도움 X )
#include <stdio.h>
#define ROWS 6
#define COLS 8
void process_image(unsigned char image[][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() {
unsigned char img_data[ROWS][COLS] = {
{0, 255, 255, 255, 255, 0, 255, 255},
{0, 0, 255, 255, 255, 255, 0, 255},
{0, 0, 0, 255, 255, 255, 0, 255},
{0, 0, 0, 0, 255, 255, 0, 255},
{255, 255, 0, 0, 255, 255, 0, 255},
{255, 255, 255, 0, 0, 0, 0, 255}
};
process_image(img_data);
for (int i = 0; i < ROWS; i++) {
for (int j = 0; j < COLS; j++) {
printf("%3d ", img_data[i][j]);
}
printf("\n");
}
}
2) 배열 포인터(문제의 의도와 가장 가까움)
#include <stdio.h>
#define ROWS 6
#define COLS 8
void process_image(unsigned char (*image)[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() {
unsigned char img_data[ROWS][COLS] = {
{0, 255, 255, 255, 255, 0, 255, 255},
{0, 0, 255, 255, 255, 255, 0, 255},
{0, 0, 0, 255, 255, 255, 0, 255},
{0, 0, 0, 0, 255, 255, 0, 255},
{255, 255, 0, 0, 255, 255, 0, 255},
{255, 255, 255, 0, 0, 0, 0, 255}
};
process_image(img_data);
for (int i = 0; i < ROWS; i++) {
for (int j = 0; j < COLS; j++) {
printf("%3d ", img_data[i][j]);
}
printf("\n");
}
return 0;
}
3) 이차원 배열과 일반 포인터 (2차원 배열이 어떻게 구성되는지 이해하기 좋은 코드이다)
#include <stdio.h>
#define ROWS 6
#define COLS 8
void process_image(unsigned char* image) { // 매개변수 확인
for (int i = 0; i < ROWS; i++) {
for (int j = 0; j < COLS; j++) {
if (image[i * COLS + j] < 128) { //인덱스 확인
image[i * COLS +j] = 0;
}
else {
image[i* COLS + j] = 255;
}
}
}
}
int main() {
unsigned char img_data[ROWS][COLS] = {
{0, 255, 255, 255, 255, 0, 255, 255},
{0, 0, 255, 255, 255, 255, 0, 255},
{0, 0, 0, 255, 255, 255, 0, 255},
{0, 0, 0, 0, 255, 255, 0, 255},
{255, 255, 0, 0, 255, 255, 0, 255},
{255, 255, 255, 0, 0, 0, 0, 255}
};
process_image(img_data);
for (int i = 0; i < ROWS; i++) {
for (int j = 0; j < COLS; j++) {
printf("%3d ", img_data[i][j]);
}
printf("\n");
}
}
4) 이중 포인터 와 동적 할당활용
#include <stdio.h>
#include <stdlib.h>
#define ROWS 6
#define COLS 8
void process_image(unsigned char** image) { // 매개변수 확인
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() {
//* 2차원 배열 동적 할당
//unsigned char* image[ROWS]; //아래와 역할 동일
unsigned char **image = (unsigned char**)malloc(ROWS * sizeof(unsigned char*));
for (int i = 0; i < ROWS; i++) {
image[i] = (unsigned char*)malloc(COLS * sizeof(unsigned char));
}
unsigned char img_data[ROWS][COLS] = {
{0, 255, 255, 255, 255, 0, 255, 255},
{0, 0, 255, 255, 255, 255, 0, 255},
{0, 0, 0, 255, 255, 255, 0, 255},
{0, 0, 0, 0, 255, 255, 0, 255},
{255, 255, 0, 0, 255, 255, 0, 255},
{255, 255, 255, 0, 0, 0, 0, 255}
};
// 동적 할당된 배열에 예시 이미지 데이터를 복사
for (int i = 0; i < ROWS; i++) {
for (int j = 0; j < COLS; j++) {
image[i][j] = img_data[i][j];
}
}
// 이미지 처리 함수 호출
process_image(image);
// 처리된 결과 출력
for (int i = 0; i < ROWS; i++) {
for (int j = 0; j < COLS; j++) {
printf("%3d ", image[i][j]);
}
printf("\n");
}
//* 메모리 해제
for (int i = 0; i < ROWS; i++) {
free(image[i]);
}
}
10. 크기가 3 X 3인 2차원 배열을 다른 2차원 배열로 복사하는 함수 void array_copy(int src[][WIDTH], int dst[][WIDTH])를
구현하고 테스트하여보라. 수행 속도를 위하여 배열 첨자 방법 대신에포인터를 사용해보자.
#include <stdio.h>
#define HEIGHT 3
#define WIDTH 3
void array_copy(int src[][WIDTH], int dst[][WIDTH]);
void print_array(int a[][WIDTH]);
int main() {
int src[HEIGHT][WIDTH] = { 100,30,67,89,50,12,19,60,90 };
int dst[HEIGHT][WIDTH];
array_copy(src, dst);
printf("<원본 2차원 배열>\n");
print_array(src);
printf("<복사본 2차원 배열> \n");
print_array(dst);
}
void array_copy(int src[][WIDTH], int dst[][WIDTH]) {
int* p = src; // &src[0][0] 도 가능
int* endp = &src[HEIGHT - 1][WIDTH - 1];
int* dst_p = dst;
while (p <= endp) {
*dst_p = *p++;
dst_p++;
}
}
void print_array(int a[][WIDTH]) {
for (int i = 0; i < HEIGHT; i++) {
for (int j = 0; j < WIDTH; j++) {
printf("%d ", a[i][j]);
}
printf("\n");
}
}
11. (ADVANCED) 생명게임(game of life)라고 불리는 인구 증가 게임을 구현하여보자. John H, Conway에 의해 발명된 생명 게임은 출생과 생존, 죽음의 모델을 가정한다. 이 게임은 가로와 세로로 20개씩의 셀을 갖는 보드 위에서 게임을 한다 각 셀은 비어 있거나, 생명체를 나타내는 0값을가질 수 있다. 각 셀은 8개의 이웃을 갖는다. 생명체의 다음세대는 다음 규칙에 따라 결정된다.
보드는 2차원 배열을 이용하여 생성하고 포인터를 최대한 많이사용하여 생명 게임의 속도를 높이도록 하라.
( 11번 문제는 너무 어려워서 보류.. 실력을 쌓고 돌아오겠다.)

'C' 카테고리의 다른 글
[쉽게 풀어쓴 C언어 Express 개정 4판] 16장 Programming (0) | 2024.10.16 |
---|---|
[쉽게 풀어쓴 C언어 Express 개정 4판] 15장 Programming (0) | 2024.10.15 |
[쉽게 풀어쓴 C언어 Express 개정 4판] 13장 Programming (6) | 2024.10.09 |
[쉽게 풀어쓴 C언어 Express 개정 4판] 12장 Programming (7) | 2024.10.08 |
[쉽게 풀어쓴 C언어 Express 개정 4판] 11장 Programming (1) | 2024.10.04 |