구조체 내에서의 메모리할당..
글쓴이: yangam / 작성시간: 토, 2004/09/25 - 12:06오후
/* 최대 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]); }
Forums:
[code:1]char **stringArray;stringA
char*의 크기는 1이 아닙니다.
게으름은 이제 그만
감사합니다~
그렇게 사용해야 되는거였네요.. ㅎ_ㅎ
감사합니다
작은 것들, 사소한 것들을 소중히 여기고,
항상 최선을 다하는 멋진 사람이 되고 싶다.
그들이 나에게 일깨워준 것처럼,
그들 자신이 얼마나 소중한 존재인지 알 수 있도록
도와주는 그런 좋은 사람이 되고 싶다
구조체 메모리의 최소할당 크기는 4입니다.malloc(2) 이건 좀
구조체 메모리의 최소할당 크기는 4입니다.
malloc(2) 이건 좀 이상한 코딩이 되는거죠..
그냥 malloc(sizeof(blah~)*개수) 이렇게 하시는것이....
typedef stucture tagA { char a; } CA
하시면 sizeof(CA)는 4가 됩니다.
이렇게하면 CB는 16바이트가 되고,
CC는 12바이트가 됩니다.
포인터는 char* short* int* CA* 모두 4바이트입니다.(64bit머신 이상에서는 몰라염 -,-;; )
댓글 달기