1. 배열 메모리 구조 이해
다음 코드는 1차원 및 2차원 정수 배열의 메모리 할당 방식을 분석합니다.
#include <stdio.h>
#define N 4
#define M 2
void test1() {
int arr[N] = {1, 9, 8, 4};
int i;
printf("sizeof(arr) = %d\n", sizeof(arr));
for (i = 0; i < N; ++i)
printf("%p: %d\n", &arr[i], arr[i]);
printf("arr = %p\n", arr);
}
void test2() {
int matrix[M][N] = {{1, 9, 8, 4}, {2, 0, 4, 9}};
int i, j;
printf("sizeof(matrix) = %d\n", sizeof(matrix));
for (i = 0; i < M; ++i)
for (j = 0; j < N; ++j)
printf("%p: %d\n", &matrix[i][j], matrix[i][j]);
printf("\n");
printf("matrix = %p\n", matrix);
printf("matrix[0] = %p\n", matrix[0]);
printf("matrix[1] = %p\n", matrix[1]);
printf("\n");
}
int main() {
printf("1차원 int 배열 테스트\n");
test1();
printf("\n2차원 int 배열 테스트\n");
test2();
return 0;
}
핵심 분석:
- 1차원 배열은 메모리에 연속적으로 저장됩니다.
- 2차원 배열은 행 우선(row-major) 방식으로 연속 저장되며,
matrix[0]과matrix는 같은 주소를 가리킵니다. matrix[0]과matrix[1]의 주소 차이는 각 행이 차지하는 바이트 크기(여기서는 16바이트, int 4개)와 일치합니다.
2. 함수를 활용한 배열 처리
2.1 평균 계산 (최대/최소 제외)
#include <stdio.h>
#define MAX 100
void read_array(int data[], int size);
double compute_trimmed_mean(int data[], int size);
int main() {
int values[MAX];
int count;
double result;
while (printf("개수 입력: "), scanf("%d", &count) != EOF) {
read_array(values, count);
result = compute_trimmed_mean(values, count);
printf("결과 = %.2f\n\n", result);
}
return 0;
}
void read_array(int data[], int size) {
for (int i = 0; i < size; ++i)
scanf("%d", &data[i]);
}
double compute_trimmed_mean(int data[], int size) {
int maxVal = data[0], minVal = data[0];
double sum = 0;
for (int i = 0; i < size; ++i) {
sum += data[i];
if (data[i] > maxVal) maxVal = data[i];
else if (data[i] < minVal) minVal = data[i];
}
return (sum - maxVal - minVal) / (size - 2);
}
설명:
read_array함수는 사용자 입력을 배열에 저장합니다.compute_trimmed_mean함수는 최대값과 최소값을 제외한 평균을 계산하여 반환합니다.
2.2 2차원 배열 초기화 및 출력
#include <stdio.h>
#define DIM 100
void display_matrix(int grid[][DIM], int size);
void fill_matrix(int grid[][DIM], int size, int fill_value);
int main() {
int matrix[DIM][DIM];
int n, val;
while (printf("크기와 값 입력: "), scanf("%d%d", &n, &val) != EOF) {
fill_matrix(matrix, n, val);
display_matrix(matrix, n);
printf("\n");
}
return 0;
}
void display_matrix(int grid[][DIM], int size) {
for (int i = 0; i < size; ++i) {
for (int j = 0; j < size; ++j)
printf("%d ", grid[i][j]);
printf("\n");
}
}
void fill_matrix(int grid[][DIM], int size, int fill_value) {
for (int i = 0; i < size; ++i)
for (int j = 0; j < size; ++j)
grid[i][j] = fill_value;
}
참고: 2차원 배열을 함수 인자로 전달할 때 두 번째 차원 크기는 반드시 명시해야 합니다.
2.3 중간값(Median) 계산
#include <stdio.h>
#define MAX 100
void read_array(int data[], int size);
double find_median(int data[], int size);
int main() {
int values[MAX];
int count;
double med;
while (printf("개수 입력: "), scanf("%d", &count) != EOF) {
read_array(values, count);
med = find_median(values, count);
printf("중간값 = %g\n\n", med);
}
return 0;
}
void read_array(int data[], int size) {
for (int i = 0; i < size; ++i)
scanf("%d", &data[i]);
}
double find_median(int data[], int size) {
// 버블 정렬 (오름차순)
for (int i = 0; i < size - 1; ++i) {
for (int j = 0; j < size - 1 - i; ++j) {
if (data[j] > data[j + 1]) {
int temp = data[j];
data[j] = data[j + 1];
data[j + 1] = temp;
}
}
}
if (size % 2 == 1)
return (double)data[size / 2];
else
return (double)(data[size / 2 - 1] + data[size / 2]) / 2.0;
}
설명: 배열을 정렬한 후 홀수 개이면 중앙값, 짝수 개이면 두 중앙값의 평균을 반환합니다.
3. 배열 변환 및 진법 변환
3.1 행 우측 회전
#include <stdio.h>
#define DIM 100
void read_matrix(int grid[][DIM], int size);
void print_matrix(int grid[][DIM], int size);
void rotate_rows_right(int grid[][DIM], int size);
int main() {
int matrix[DIM][DIM];
int n;
printf("크기 입력: ");
scanf("%d", &n);
read_matrix(matrix, n);
printf("원본 행렬:\n");
print_matrix(matrix, n);
rotate_rows_right(matrix, n);
printf("변환된 행렬:\n");
print_matrix(matrix, n);
return 0;
}
void read_matrix(int grid[][DIM], int size) {
for (int i = 0; i < size; ++i)
for (int j = 0; j < size; ++j)
scanf("%d", &grid[i][j]);
}
void print_matrix(int grid[][DIM], int size) {
for (int i = 0; i < size; ++i) {
for (int j = 0; j < size; ++j)
printf("%4d", grid[i][j]);
printf("\n");
}
}
void rotate_rows_right(int grid[][DIM], int size) {
for (int i = 0; i < size; ++i) {
int last = grid[i][size - 1];
for (int j = size - 1; j > 0; --j)
grid[i][j] = grid[i][j - 1];
grid[i][0] = last;
}
}
설명: 각 행의 요소를 오른쪽으로 한 칸씩 이동하고, 마지막 요소는 첫 번째 위치로 옮깁니다.
3.2 진법 변환 (2진법, 8진법, 16진법)
#include <stdio.h>
#define MAX_DIGITS 100
void convert_base(int decimal, int base);
int main() {
int number;
while (printf("10진수 입력: "), scanf("%d", &number) != EOF) {
convert_base(number, 2);
convert_base(number, 8);
convert_base(number, 16);
printf("\n");
}
return 0;
}
void convert_base(int decimal, int base) {
int digits[MAX_DIGITS], count = 0;
if (decimal == 0) {
printf("0\n");
return;
}
while (decimal > 0) {
digits[count++] = decimal % base;
decimal /= base;
}
for (int i = count - 1; i >= 0; i--) {
printf("%c", digits[i] < 10 ? digits[i] + '0' : digits[i] - 10 + 'A');
}
printf("\n");
}
설명: 10진수 입력을 받아 각각 2진수, 8진수, 16진수로 변환하여 출력합니다.
4. 마방진(Magic Square) 검증
#include <stdio.h>
#define DIM 100
void read_square(int grid[][DIM], int size);
void print_square(int grid[][DIM], int size);
int is_magic_square(int grid[][DIM], int size);
int main() {
int square[DIM][DIM];
int n;
while (printf("크기 입력: "), scanf("%d", &n) != EOF) {
printf("정사각형 입력:\n");
read_square(square, n);
printf("출력:\n");
print_square(square, n);
if (is_magic_square(square, n))
printf("마방진입니다\n\n");
else
printf("마방진이 아닙니다\n\n");
}
return 0;
}
void read_square(int grid[][DIM], int size) {
for (int i = 0; i < size; ++i)
for (int j = 0; j < size; ++j)
scanf("%d", &grid[i][j]);
}
void print_square(int grid[][DIM], int size) {
for (int i = 0; i < size; ++i) {
for (int j = 0; j < size; ++j)
printf("%4d", grid[i][j]);
printf("\n");
}
}
int is_magic_square(int grid[][DIM], int size) {
if (size % 2 == 0 || size <= 0) return 0;
int target = size * (size * size + 1) / 2;
int used[DIM * DIM + 1] = {0};
// 1) 숫자 범위 및 중복 확인
for (int i = 0; i < size; ++i) {
for (int j = 0; j < size; ++j) {
int val = grid[i][j];
if (val < 1 || val > size * size || used[val])
return 0;
used[val] = 1;
}
}
// 2) 각 행과 열의 합 확인
for (int i = 0; i < size; ++i) {
int row_sum = 0, col_sum = 0;
for (int j = 0; j < size; ++j) {
row_sum += grid[i][j];
col_sum += grid[j][i];
}
if (row_sum != target || col_sum != target)
return 0;
}
// 3) 두 대각선 합 확인
int diag1_sum = 0, diag2_sum = 0;
for (int i = 0; i < size; ++i) {
diag1_sum += grid[i][i];
diag2_sum += grid[i][size - 1 - i];
}
if (diag1_sum != target || diag2_sum != target)
return 0;
return 1;
}
설명: 마방진 조건(1~n²의 유일한 숫자, 모든 행/열/대각선 합 동일)을 만족하는지 검사합니다.