C언어

04. C언어_동적 메모리 할당 (2차원 배열)

만수르코딩방 2024. 5. 15. 16:43

1. 행, 열의 파라미터가 주어진 이차원 배열의 동적메모리 할당

예제) 학생수를 입력받아 5과목에 대한 성적처리를 해라 (int(*p)[5] 배열 포인터 활용)

 

#include<stdio.h>//파일 입출력
#include<stdlib.h> //동적 메모리 할당

typedef int(*multiPtr)[5]; //원소 5개를 동시에 가리키는 배열 포인터 자료형 타입 선언
multiPtr myAlloc(int); //동적 메모리의 시작주소를 나타내는 배열 포인터의 주소 반환
void myDelete(multiPtr); //동적 메모리의 시작주소를 받아 동적메모리 해제
void dataInput(multiPtr, int); //동적 메모리의 시작주소와 row수를 전달인자로 받아 데이터 입력
void dataOutput(multiPtr, int); //동적 메모리의 시작주소와 row수를 전달인자로 받아 데이터 출력

int main(void){
    int (*ip)[5] = NULL; // 동적 메모리를 가리키는 정적 메모리 할당 int[5] 크기의 배열을 가리키는 포인터 (국,영,수,과,사)
    int row;
    printf("학생수를 입력하시오");
    scanf("%d", &row) ; //3명
    ip = myAlloc(row); //입력받은 크기만큼 동적 메모리 할당
    if (ip==NULL){ //동적메모리 할당이 정상적으로 이루어지면 ip에 메모리 시작주소 반환, 실패 시 NULL반환
        return 1; //에러 발생 시 프로세스 종료
    }
    dataInput(ip, row); //
    dataOutput(ip, row);
    myDelete(ip); //동적 메모리 해제

    return 0;

}

multiPtr myAlloc(int row){
    int (*p)[5]; //동적메모리의 시작주소를 가리키는 임시 포인터
    scanf("%d", &row);
    p = (int(*)[5])malloc(sizeof(int[5])*row); //메모리 크기를 할당받고 int[5]를 가리키는 배열 포인터로 return
    return p; //할당된 동적 메모리의 시작주소
}

void myDelete(multiPtr p){
    if (p!=NULL){
        free(p); //동적메모리를 할당한 기억공간을 반납
    }
    return;
}

void dataInput(multiPtr ip, int row){
    for (int i = 0; i < row; i++){ //행-> 열의 순서로 반복문 수행
        for (int j=0; j<5; j++){
            scanf("%d", &ip[i][j]); //포인터가 가리키는 배열은 포인터를 활용하여 표시할 수 있다
            //ip[i][j] 주소를 참조하여 배열 입력받아
        }
    }
}

void dataOutput(multiPtr ip, int row){
    for (int i = 0; i<row; i++){
            for (int j=0; j<5; j++){
            printf("%3d", ip[i][j]); //포인터가 가리키는 배열은 포인터를 활용하여 표시할 수 있다
            //ip[i][j] 주소를 참조하여 배열 입력받아
        }
        printf("\n");
    }
}

출력값

100 90 95 80 70
100100100 90 90

 

2. 행과 열을 입력받아 2차원 배열의 동적 메모리 할당

- 학생수와 과목수를 입력받아 2차원 배열의 동적 메모리를 할당하시오(int** 이중 포인터 이용)

 ( 이중 포인터를 활용하여 기둥 배열(row 개수를 나타내)을 먼저할당하고 곁가지 배열을 연결(column개수를 나타내))

#include<stdio.h>
#include<malloc.h>
#pragma warning(disable:4996)
int** myAlloc(int, int); //전달인자 2개 (row/column), 기둥을 가리키기 위해 int**로 return )
void dataInput(int**, int, int); //동적메모리 주소, (row/column)를 전달인자로 입력받아 데이터 입력
void dataOutput(int**, int, int);//동적메모리 주소, (row/column)를 전달인자로 입력받아 데이터 출력
void myDelete(int**, int); //동적메모리 주소를 입력받아 동적 메모리 해제 
int main()
{
	int** ip; //기둥을 가리키는 정적 변수 선언
	int  col, row;
	printf("row 수 입력 : ");
	scanf("%d", &row);
	printf("column 수 입력 : ");
	scanf("%d", &col);
	ip = myAlloc(row, col);
	if (ip == NULL) {
		return 1;
	}
	dataInput(ip, row, col);
	dataOutput(ip, row, col);
	myDelete(ip, row);
	return 0;
}
int** myAlloc(int row, int col) {
	int i;
	int** p;
	p = (int**)malloc(sizeof(int*) * row); //행의 개수를 나타내는 기둥 배열 먼저 할당
	if (p == NULL) return p; //retrun NULL 
	for (i = 0; i < row; i++) {
		p[i] = (int*)malloc(sizeof(int) * col); //열에 해당하는 배열의 크기만큼 동적메모리를 할당하고 그 주소를 기둥 배열 원소에 반환
        //p[0],p[1],p[2] int[col] 자료형의 메모리를 할당한 이후 메모리의 주소를 각 행에 연결 (기둥 배열(int*)이 곁가지 배열(int)을 가리킨다) 
		if (p[i] == NULL) {
			myDelete(p, i); //한 행에 대해 동적메모리가 할당되지 않은 경우 기억공간 반납
			break;
		}//for문 바깥으로 나가자
	}
	return p; //할당된 동적메모리 주소 반환
}

void myDelete(int** p, int row) {
	int i;
	if (p == NULL) { return ; }
	for (i = 0; i < row; i++) {//곁가지 해제
		if (p[i]!= NULL) {
			free(p[i]);
		}
	}
	free(p);
}

void dataInput(int **ip, int row, int col) {
	for (int i = 0; i < row; i++) {
		for (int j = 0; j < col; j++) {
			scanf("%d", &ip[i][j]);
		}
	}
}

void dataOutput(int **ip, int row, int col) {
	for (int i = 0; i < row; i++) {
		for (int j = 0; j < col; j++) {
			printf("%d", ip[i][j]);
		}
		printf("\n");

	}
}