거북이처럼 천천히

C - [혼공C] 16장, 직접 해보는 손코딩 (동적 할당 영역의 문자열을 함수로 출력) 본문

Algorithm/알고리즘 문제 풀이

C - [혼공C] 16장, 직접 해보는 손코딩 (동적 할당 영역의 문자열을 함수로 출력)

유로 청년 2024. 6. 20. 08:54

1. 문제

문제 제목 : 동적 할당을 통해 문자열을 저장 및 출력

메모리 동적 할당을 통해 메모리 공간을 확보한 뒤, 해당 공간에 문자열을 저장

 

 

 

 

2. 생각

2.1) 정적 메모리 할당의 한계 및 문제

  • 위 예시를 통해 알 수 있듯이 Compile 시점에서 얼마만큼의 문자열과 어느 정도의 길이를 갖는 문자열이 들어올지 모르기 때문에 정적인 메모리 할당을 통해 미리 메모리 공간을 확보하기 힘들다.
  • 또한 여유있게 정적 메모리 공간 할당을 받으면 실제로 사용하지 않는 메모리 공간이 발생하여 메모리 자원 낭비가 발생한다.

 

2.2) 동적 메모리 할당시 주의점

  • 동적 메모리 할당을 받으면 2차원 형태로 받아야 할 것이기 때문에 동적 메모리 할당은 포인터 배열 형태를 갖는다.
  • 포인터 배열은 각 원소가 포인터이기 때문에 각각의 원소들에 대해서도 동적할당을 받을 필요가 있다.

 

 

동적 할당 영역의 문자열 저장 예시

 

 

 

3. 풀이 및 코드 분석

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

// Function prototype.
void get_strings(char*** board, unsigned int* p_capacity, unsigned int* p_size);
void print_the_board(char** board, unsigned int size);
void free_board(char** board, unsigned int size);

// Main method
int main(void) {
	// 초기 사이즈
	unsigned int capacity = 5;
	unsigned int size = 0;

	// 문자열을 저장하기 위해 동적 메모리 할당
	// 동적 메모리 할당은 포인터 배열 형태이다.
	char** board = (char**)malloc(capacity * sizeof(char*));

	// 문자열을 받는다.
	get_strings(&board, &capacity, &size);

	// 문자열들 출력.
	print_the_board(board, size);

	// 동적 메모리 할당 해체
	free_board(board, size);
	free(board);

	return 0;
}

// Get string 
void get_strings(char*** board, unsigned int* p_capacity, unsigned int* p_size) {
	char input_string[80];

	while (1) {
		rewind(stdin);
		printf("문자열을 입력하세요 : ");
		gets_s(input_string, sizeof(input_string));

		if (strcmp(input_string, "end") == 0) return;
		else if (*p_size >= *p_capacity) {
			*p_capacity *= 2;
			*board = (char**)realloc(*board, *p_capacity * sizeof(char*));
		}

		unsigned short length = (unsigned short)strlen(input_string);
		(*board)[*p_size] = (char*)malloc((length + 1) * sizeof(char));

		strcpy_s((*board)[*p_size], length + 1, input_string);
		(*p_size)++;
	}
}

// Get board.
void print_the_board(char** board, unsigned int size) {
	puts("입력한 문자열은 다음과 같습니다.");

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

// Free board.
void free_board(char** board, unsigned int size) {
	for (unsigned int i = 0; i < size; i++)
		free(board[i]);
}

 

  • get_strings 함수의 첫 번째 argument로 이중 포인터의 메모리 주소 값을 전달했다.
    이유 : get_strings 함수 내부를 보게 되면 size 값이 capacity 값보다 크거나 같게 되면 더이상 문자열을 수용할 수 없기 때문에 realloc 함수를 통해 새로운 메모리 동적 할당 받게 되는데, 이 과정에서 이중 포인터인  board의 값을 수정하기 때문이다.
  • 만약 단순히 get_strings 함수의 첫 번째 argument 값으로 이중 포인터를 전달하면 get_strings 내부에서 수정된 board의 값이 caller인 main 함수 측에서도 영향이 없기 때문에 이를 위해 이중 포인터의 메모리 주소 값을 전달했다.

 

동적 할당을 통해 메모리 공간을 확보한 뒤, 문자열을 저장 및 출력했다.

 

4. 문제 출처

  • 한빛미디어, 혼자 공부하는 C언어, 저자 서현우