구조체 내에서의 메모리할당..

yangam의 이미지

/*

최대 10 명까지의 학생에 대한 이번 학기에 수강하는 과목 및 성적
(중간고사,기말고사,수시고사,출결)을 입력 받아서 각 과목에 대한
평균점수와 이에 해당하는 학점(A+,A,B+,B,C+,C,D,F)을 계산하고
이에 대한 평점(최종성적) 및 석차를 구해서 석차순으로 학생들의
리스트를 출력하는 프로그램을 작성하라.

전제: 0. 학생들의 과는 모두 같다.
      1. 각 과목을 입력받을 때, 각 과목에 대한 학점도 함께 입력받는다.
      2. 입력받을 수 있는 과목의 수는 5개 - 8개로 제한.
      3. 출결은 16번을 만점으로 한다. 
      4. 중간고사, 기말고사, 수시고사는 100점을 만점으로 한다. 

*/

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

// 상수 LEN 은 임시로 사용되는 문자형 배열의 길이
#define	LEN	64

typedef struct grade {
	char *student_name;		// 학생의 이름
	char **subject_name;		// 과목 이름을 저장
	int num_of_subject;		// 과목수를 저장
	int *credit;
} S;

int how_many_data_enter(char *temp);
void remove_newline_character(char *temp);
void enter_student_name(char *temp, S *pstudent, int num_of_student);
void enter_subject_name_and_credit(char *temp, S *pstudent, int index);

int main()
{
	char temp[LEN];
	int num_of_student;
	int i;
 	S *student;
	
	// 몇 명의 학생에 대한 성적을 입력할지를 결정한다.
	// (구조체 포인터의 동적할당에 대한 기초자료로 활용됨)
	num_of_student = how_many_data_enter(temp);	

	// 메모리 할당
	// S 구조체가 num_of_student 의 값만큼 생성됨
	student = (S *)malloc(sizeof(S) * num_of_student);

	// 학생의 이름을 입력받음
	enter_student_name(temp, student, num_of_student);

	// 입력받은 학생 이름 출력
	puts("\n------------------------------------------");
	puts("다음 학생들에 대한 데이터를 입력받겠습니다");
	puts("------------------------------------------\n");
	for (i = 0; i < num_of_student; i++)
		printf("%2d 번째 학생 : %s\n", i + 1, student[i].student_name);
	
	// 학생의 전공, 과목이름 및 학점, 시험성적, 출결을 입력받음
	for (i = 0; i < num_of_student; i++)
	{
		puts("\n-----------------------------------");
		printf("-> %s 학생에 대한 데이터 입력 <-\n", student[i].student_name);
		puts("-----------------------------------\n");

		// 과목 및 학점을 입력받음
		enter_subject_name_and_credit(temp, student, i);
	}

	// 학생 이름을 저장하는 배열에 설정된 메모리 해제
	for (i = 0; i < num_of_student; i++)
		free(student[i].student_name);

	// 구조체 포인터에 설정된 메모리 해제
	free(student);

	return 0;
}

// 입력받을 데이터의 학생의 수를 입력받는다. 
int how_many_data_enter(char *temp)
{
	int num_of_student;

	while (1)
	{
		printf("\n몇 명의 학생에 대한 성적을 입력 하실건가요..? (최대 10명): ");
		fgets(temp, LEN, stdin);
		num_of_student = atoi(temp);

		if (num_of_student >= 1 && num_of_student <= 10)
		{
			puts("\n-------------------------------------------");
			printf("%d 명의 학생들에 대한 성적을 입력받겠습니다.\n", num_of_student);
			puts("-------------------------------------------\n");
			return num_of_student;
		}

		else
		{
			printf("\n입력 가능한 값의 범위는 1 - 10명 입니다.\n");
		}
	}	
}

// remove newline character
void remove_newline_character(char *temp)
{
	int j = 0;

	while (1)
	{
		if (temp[j] == '\n')
		{
			temp[j] = '\0';
			break;
		}
			j++;
	}

}

void enter_student_name(char *temp, S *pstudent, int num_of_student)
{
	int i;

	for (i = 0; i < num_of_student; i++)
	{
		printf("%2d 번째 학생의 이름을 입력하세요: ", i + 1);
		fgets(temp, LEN, stdin);

		// '\n' 을 제거
		remove_newline_character(temp);
		
		// 학생의 이름을 ragged char array 로 저장(메모리 할당)
		pstudent[i].student_name = malloc(strlen(temp) + 1);

		// 학생의 이름을 저장함
		strcpy(pstudent[i].student_name, temp);
	}
}

void enter_subject_name_and_credit(char *temp, S *pstudent, int index)
{
	int i;

	// 신청한 과목의 수를 입력받음
	while (1)
	{
		printf("몇 개의 과목을 신청하셨나요..? (최소 5개, 최대 8개): ");
		fgets(temp, LEN, stdin);

		pstudent[index].num_of_subject = atoi(temp);

		if (pstudent[index].num_of_subject >= 5 && pstudent[index].num_of_subject <= 8)
		{
			// 학생의 과목수에 대한 메모리 할당
			pstudent[index].subject_name = (char **)malloc(pstudent[index].num_of_subject);
			puts("\n----------------------------------");
			printf("%d 개의 과목을 신청하셨습니다.\n", pstudent[index].num_of_subject);
			puts("----------------------------------\n");

			break;
		}

		else
		{
			puts("\n-------------------------------------");
			puts("입력 가능한 값의 범위는 5 - 8 입니다.");
			puts("-------------------------------------\n");
		}
	}


	for (i = 0; i < pstudent[index].num_of_subject; i++)
	{
		printf("%d 번째 과목의 이름을 입력하세요: ", i + 1);
		fgets(temp, LEN, stdin);

		// remove newline character
		remove_newline_character(temp);

		// dynamic memory allocation
		pstudent[index].subject_name[i] = (char *)malloc(strlen(temp) + 1);
		// 문자열 복사
		strcpy(pstudent[index].subject_name[i], temp);
	}	

	for (i = 0; i < pstudent[index].num_of_subject; i++)
	{
		printf("(for문밖)%s\n", pstudent[index].subject_name[i]);
	}
}

enter_subject_name_and_credit() 때문에 그러는데요;;
메모리 할당을 저렇게 하면 안되는건가요?

char **t;
t = (char **)malloc(3);
t[0] = (char *)malloc(2);
t[1] = (char *)malloc(2);
t[2] = (char *)malloc(2);

이렇게 해서 사용할 때는 잘되던데..
구조체에 들어가니 잘 안되네요;;

어떤점이 잘못됐는지 지적좀 해주세요..

참고로 간단한 설명을 하자면...
과목 수를 입력받고, 과목이름을 입력받는데요.

과목 수가 유동적이여서 우선 과목수만큼의 포인터 배열을 할당합니다.
그 다음에 과목 이름을 입력받는데요.
과목 이름의 길이만큼의 메모리를 각각의 포인터 배열에 할당하려는 것이
목표입니다.

1 byte 도 버리지 않고 메모리를 사용하고 싶어서요.
답변 부탁드립니다...

참고로 다른 소스파일을 열어서 이렇게 하니까 제대로 되네요;;

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

#define LEN	70

// 프로그램을 위한 구조체 필드 선언
typedef struct grade {
	char **subject;		// 학생이 신청한 과목명
} S;

int main()
{
	// 학생 구조체 정의
	S *student;

	student = (S *)malloc(sizeof(S) * 2);

	student[0].subject = malloc(3);
	student[1].subject = malloc(3);

	student[0].subject[0] = malloc(2);
	student[0].subject[1] = malloc(4);
	student[0].subject[2] = malloc(5);
	student[1].subject[0] = malloc(2);
	student[1].subject[1] = malloc(4);
	student[1].subject[2] = malloc(5);

	strcpy(student[1].subject[0], "o");
	strcpy(student[1].subject[1], "ih!");
	strcpy(student[1].subject[2], "www!");

	strcpy(student[0].subject[0], "h");
	strcpy(student[0].subject[1], "hi!");
	strcpy(student[0].subject[2], "wow!");

	printf("%s\n%s\n%s\n", student[0].subject[0], student[0].subject[1], student[0].subject[2]);
	printf("%s\n%s\n%s\n", student[1].subject[0], student[1].subject[1], student[1].subject[2]);
}
lyster의 이미지

char **stringArray;

stringArray = (char**)malloc(sizeof(char*) * num);

int i;
for (i = 0; i < num; ++i) {
    stringArray[i] = (char*)malloc(sizeof(char) * (len+1));
}

char*의 크기는 1이 아닙니다.

게으름은 이제 그만

yangam의 이미지

그렇게 사용해야 되는거였네요.. ㅎ_ㅎ
감사합니다

작은 것들, 사소한 것들을 소중히 여기고,
항상 최선을 다하는 멋진 사람이 되고 싶다.
그들이 나에게 일깨워준 것처럼,
그들 자신이 얼마나 소중한 존재인지 알 수 있도록
도와주는 그런 좋은 사람이 되고 싶다

vuccell의 이미지

구조체 메모리의 최소할당 크기는 4입니다.
malloc(2) 이건 좀 이상한 코딩이 되는거죠..
그냥 malloc(sizeof(blah~)*개수) 이렇게 하시는것이....
typedef stucture tagA { char a; } CA
하시면 sizeof(CA)는 4가 됩니다.

typedef structure tagB
{
    char a1;
    int    a2;
    char a3;
    int    a4;
} CB
typedef structure tagC
{
    char a1;
    char a3;
    int    a2;
    int    a4;
} CC


이렇게하면 CB는 16바이트가 되고,
CC는 12바이트가 됩니다.
포인터는 char* short* int* CA* 모두 4바이트입니다.(64bit머신 이상에서는 몰라염 -,-;; )

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.