구조체 변수 메모리 할당오류 및 초기화 관련 질문

조회수 2935회
#include <stdio.h>
#include <stdlib.h>
#define SIZE_QUEUE 100  //the maximum size of the news_queue
#define CAPACITY 6      //the capacity of ZNN.com (per sec)
#define NUM_USER 20     //the number of users
#define NUM_LOOP 100    //the number of loops


//ContentFidelity is one of the types: video, image, text
typedef enum { Video, Image, Text } ContentFidelity;

typedef struct {
    unsigned int requestedBy;
    ContentFidelity fidelity;
} news; // 사용자 8이 동영상을 요청하면, 요청한 뉴스 콘텐츠를 (8,video)로 출력한다

typedef struct {
    news queue[SIZE_QUEUE];
    unsigned int front;
    unsigned int rear;
} Queue; // 사용자가 요청한 뉴스 콘텐츠 쌓는 큐

Queue *news_queue;
ContentFidelity currentFidelity = Video; // 처음 콘텐츠는 동영상

                                         /**/
typedef struct Person { // 사용자 구조체(콘텐츠 개수와 대기시간 정보)
    int content_num;    // 요청한 콘텐츠 전체개수
    int receive_content; // 수신받은 콘텐츠 전체개수
    int waiting_time;   // 총 delay time
    int content_score;  // 수신받은 콘텐츠들의 총점수
}Person;

typedef struct PersonArray {    // 사용자 구조체를 위한 구조체(배열)
    Person people[NUM_USER];
    int total_waiting_time;     // 총 대기시간
    int total_waiting_people;   // 지금까지 콘텐츠를 요청한 사용자들의 수(중복 가능)
}PersonArray;


PersonArray *PeopleArray = (PersonArray*)malloc(sizeof(PeopleArray));
for (int i = 0; i < NUM_USER; i++) {
    PeopleArray->people[i].content_num = 0;
    PeopleArray->people[i].receive_content = 0;
    PeopleArray->people[i].waiting_num = 0;
    PeopleArray->people[i].content_score = 0;
}

/*PeopleArray초기화*/

int individual_count = 0;   // 한 콘텐츠 받기까지의 개인당 대기시간을 측정하기 위한 변수

void request(Queue *news_queue, int count_start) {  // count_start : enqueue한 시점
    individual_count = count_start; // enqueue한 시점 저장
    int request[20];
    for (int i = 0; i < 20; i++) {  // 20명이므로 20번 돌린다
        int tf = rand() % 2;    // true of false -> request 할지 말지
        if (tf) {
            news_queue->rear = (news_queue->rear + 1) % SIZE_QUEUE;
            news_queue->queue[news_queue->rear].requestedBy = i;
            news_queue->queue[news_queue->rear].fidelity = currentFidelity;
            PeopleArray->total_waiting_people++;    // 총 대기인수 +1
            PeopleArray->people[i].content_num++;   // i번 사람의 요청 콘텐츠 개수 +1
            request[i] = i; // request한 사용자 번호 임시저장
        }
    }
    printf(" >>>>Requesting(ENQUEUE):");
    for (int j = 0; j < sizeof(request) / sizeof(request[0]); j++) {
        printf(" %d,", request[j]);
    }
    printf("\n");
}

//enqueue 하고 count 시작 -> dequeue하고 count 끝. 총 대기시간을 person구조체에 넣어줘야 한다.

void setFidelity(Queue *news) {
    float average_wait;

    if (PeopleArray->total_waiting_people == 0)
        average_wait = 0;
    else
        average_wait = PeopleArray->total_waiting_time / PeopleArray->total_waiting_people; // 평균 콘텐츠 대기 시간

    if (average_wait >= 3) {
        if (currentFidelity == Video)
            currentFidelity = Image;
        else if (currentFidelity == Image)
            currentFidelity = Text;
        else if (currentFidelity == Text)
            currentFidelity = Text;
    }
    else if (average_wait <= 2) {
        if (currentFidelity == Text)
            currentFidelity = Image;
        else if (currentFidelity == Image)
            currentFidelity = Video;
        else if (currentFidelity == Video)
            currentFidelity = Video;
    }
    printf("Average waiting time: %f, Current Quality: %c\n", average_wait, currentFidelity);

}

void provide(Queue *news, int count_end) {  // count_end : dequeue한 시점. request함수의 count_start에서 -count_end를 하면 개인당 대기시간이 나온다
    int i = 0; // 1초당 제공 가능한 크기(최대 6)
    int num; // 누구에게 콘텐츠 제공하는지 확인하기 위한 num

    individual_count = count_end - individual_count;    // dequeue한 시점 - enqueue한 시점 = 개인이 걸린 대기시간
    printf("Providing(DEQUEUE) : ");
    while (i <= 6 && news->front != news->rear) { // i가 6이 될 때까지, 큐가 빌 때까지 dequeue 한다
        switch (news->queue[news->front].fidelity) {
        case Video:
            i = i + 3;
            if (i > 6)  // i가 6보다 크면 break;
                break;
            printf("(%d, %c), ", news->queue[news->front].requestedBy, news->queue[news->front].fidelity);
            num = news->queue[news->front].requestedBy; // 현재 콘텐츠 제공 받은 사람의 번호 정보
            PeopleArray->people[num].receive_content++; // num번 사람이 수신한 콘텐츠 개수 +1
            PeopleArray->people[num].waiting_time += individual_count; // num번 사람이 대기한 총시간 +
            PeopleArray->people[num].content_score += 3; // num번 사람의 콘텐츠 점수 +3
            PeopleArray->total_waiting_time += PeopleArray->people[num].waiting_time; // 총 대기시간에 그만큼 +
            news->front = (news->front + 1) % SIZE_QUEUE;
            /*PeopleArray->total_waiting_people--;  //대기인수 -1*/
            break;
        case Image:
            i = i + 2;
            if (i > 6)  // i가 6보다 크면 break;
                break;
            printf("(%d, %c), ", news->queue[news->front].requestedBy, news->queue[news->front].fidelity);
            num = news->queue[news->front].requestedBy; // 현재 콘텐츠 제공 받은 사람의 번호 저장
            PeopleArray->people[num].receive_content++; // num번 사람이 수신한 콘텐츠 개수 +1
            PeopleArray->people[num].waiting_time += individual_count; // num번 사람이 대기한 총시간 +
            PeopleArray->people[num].content_score += 2; // num번 사람의 콘텐츠 점수 +2
            PeopleArray->total_waiting_time += PeopleArray->people[num].waiting_time; // 총 대기시간에 그만큼 +
            news->front = (news->front + 1) % SIZE_QUEUE;
            /*PeopleArray->total_waiting_people--;  //대기인수 -1*/
            break;
        case Text:
            i = i + 1;
            if (i > 6)  // i가 6보다 크면 break;
                break;
            printf("(%d, %c), ", news->queue[news->front].requestedBy, news->queue[news->front].fidelity);
            num = news->queue[news->front].requestedBy; // 현재 콘텐츠 제공 받은 사람의 번호 저장
            PeopleArray->people[num].receive_content++; // num번 사람이 수신한 콘텐츠 개수 +1
            PeopleArray->people[num].waiting_time += individual_count; // num번 사람이 대기한 총시간 +
            PeopleArray->people[num].content_score += 1; // num번 사람의 콘텐츠 점수 +1
            PeopleArray->total_waiting_time += PeopleArray->people[num].waiting_time; // 총 대기시간에 그만큼 +
            news->front = (news->front + 1) % SIZE_QUEUE;
            /*PeopleArray->total_waiting_people--;  //대기인수 -1*/
            break;
        }
    }
}

void printQueue(Queue *news) {
    int i = news->front;
    printf("In the queue: [");
    do {
        printf("(%d, %c), ", news->queue[i].requestedBy, news->queue[i].fidelity);
        i = (i + 1) % SIZE_QUEUE;
    } while (i != news->rear);  // 큐의 rear까지 도달할 때까지 출력
    printf("]\n");
}

void printResult() {
    float average_time[20]; // 평균대기시간
    for (int i = 0; i < 20; i++) {
        average_time[i] = PeopleArray->people[i].waiting_time / PeopleArray->people[i].receive_content;
    }

    float average_score[20];    // 평균 콘텐츠 점수
    for (int i = 0; i < 20; i++) {
        average_score[i] = PeopleArray->people[i].content_score / PeopleArray->people[i].receive_content;
    }

    printf("******Result*****\n");
    printf("User    Avg.wait        Avg.score\n");
    for (int i = 0; i < 20; i++) {
        printf("User%d:  %fs       %f", i, average_time[i], average_score[i]);
    }

}

void main() {
    unsigned int nthLoop;
    for (nthLoop = 0; nthLoop < NUM_LOOP; nthLoop++) {
        printf("\n=======%d seconds======\n", nthLoop);
        //users can request contents every two loops
        if (nthLoop % 2 == 0) {
            setFidelity(news_queue);
            request(news_queue, nthLoop);
        }
        printQueue(news_queue);
        provide(news_queue, nthLoop);
    }

    printResult();
}

위는 전체 고드입니다. 제가 도저히 해결하지 못하는 부분은 아래 부분의 코드입니다.

#include <stdio.h>
#include <stdlib.h>
#define SIZE_QUEUE 100  //the maximum size of the news_queue
#define CAPACITY 6      //the capacity of ZNN.com (per sec)
#define NUM_USER 20     //the number of users
#define NUM_LOOP 100    //the number of loops


//ContentFidelity is one of the types: video, image, text
typedef enum { Video, Image, Text } ContentFidelity;

typedef struct {
    unsigned int requestedBy;
    ContentFidelity fidelity;
} news; // 사용자 8이 동영상을 요청하면, 요청한 뉴스 콘텐츠를 (8,video)로 출력한다

typedef struct {
    news queue[SIZE_QUEUE];
    unsigned int front;
    unsigned int rear;
} Queue; // 사용자가 요청한 뉴스 콘텐츠 쌓는 큐

Queue *news_queue;
ContentFidelity currentFidelity = Video; // 처음 콘텐츠는 동영상

                                         /**/
typedef struct Person { // 사용자 구조체(콘텐츠 개수와 대기시간 정보)
    int content_num;    // 요청한 콘텐츠 전체개수
    int receive_content; // 수신받은 콘텐츠 전체개수
    int waiting_time;   // 총 delay time
    int content_score;  // 수신받은 콘텐츠들의 총점수
}Person;

typedef struct PersonArray {    // 사용자 구조체를 위한 구조체(배열)
    Person people[NUM_USER];
    int total_waiting_time;     // 총 대기시간
    int total_waiting_people;   // 지금까지 콘텐츠를 요청한 사용자들의 수(중복 가능)
}PersonArray;


PersonArray *PeopleArray = (PersonArray*)malloc(sizeof(PeopleArray));
for (int i = 0; i < NUM_USER; i++) {
    PeopleArray->people[i].content_num = 0;
    PeopleArray->people[i].receive_content = 0;
    PeopleArray->people[i].waiting_num = 0;
    PeopleArray->people[i].content_score = 0;
}

/*PeopleArray초기화*/

보시다시피 제가 원하는 것은 PersonArray의 포인터 구조체 PeopleArray에 메모리할당을 하여 초기화하는 것입니다.

하지만 위는 함수 밖에서 메모리 할당을 하는 거여서 그런지 malloc부분에 붉은 줄표시가 뜨면서 '상수식에 함수 호출을 사용할 수 없습니다' 라고 뜹니다.

PersonArray *PeopleArray = (PersonArray*)malloc(sizeof(PeopleArray));

이 문장을 아무 함수 안에서 적으면 malloc에 전혀 붉은줄이 뜨지 않습니다.

int num = sizeof(PersonArray);
PersonArray *PeopleArray = (PersonArray*)malloc(num);
PersonArray *PeopleArray = (PersonArray*)malloc(88);

도 마찬가지로 malloc에 붉은 줄이 뜨며 '상수식~' 의 문장이 뜨며 에러가 뜹니다.

PersonArray *ptrPeopleArray; 
PersonArray  l_personArray; 
ptrPeopleArray = &l_personArray; 

을 이용하려고 해도 초기화만 하려고 하면

l_personArray.total_content_num = 0;

에서 . 부분에 붉은줄이 표시되며 ';가 필요합니다' 라는 오류문구가 뜹니다....

현재 상황이 main함수를 변경하면 안되는 상황이기에 저는 PeopleArray의 메모리 할당, 초기화, PeopleArray안의 people배열을 반복문을 이용한 초기화하는 과정을 함수 밖, 전역부분에서 해결해야 하는 상황입니다.

(위 코드에서 for부분에서 '선언이 필요합니다' 라는오류가 뜹니다)

어떻게 해야 이 오류를 해결할 수 있을까요?

1 답변

  • 좋아요

    0

    싫어요
    채택 취소하기

    전역부분에서는 malloc()을 비롯한 함수호출, for문, while문, if문 등이 사용불가합니다.

    따라서 이 문제를 해결하기 위해서는 다음과 같이 init함수를 정의하여 해결하시면 될 것 같습니다.

    /*****************
        구조체 정의
     (news, Queue 등)
    *****************/
    
    int individual_count; // 한 콘텐츠 받기까지의 개인당 대기시간을 측정하기 위한 변수
    PersonArray *PeopleArray;
    Queue *news_queue;
    ContentFidelity currentFidelity;
    
    void init(void)
    {
        individual_count = 0;
        currentFidelity = Video; // 처음 콘텐츠는 동영상
        /*PeopleArray초기화*/
        PeopleArray = (PersonArray*)malloc(sizeof(PersonArray));
        for (int i = 0; i < NUM_USER; i++) {
            PeopleArray->people[i].content_num = 0;
            PeopleArray->people[i].receive_content = 0;
            PeopleArray->people[i].waiting_time = 0;
            PeopleArray->people[i].content_score = 0;
        }
    }
    
    /*************************
            함수 정의
    (request, setFidelity 등)
    *************************/
    
    void main() {
        init(); //init함수를 제일 먼저 호출
    
        unsigned int nthLoop;
        for (nthLoop = 0; nthLoop < NUM_LOOP; nthLoop++) {
            printf("\n=======%d seconds======\n", nthLoop);
            //users can request contents every two loops
            if (nthLoop % 2 == 0) {
                setFidelity(news_queue);
                request(news_queue, nthLoop);
            }
            printQueue(news_queue);
            provide(news_queue, nthLoop);
        }
    
        printResult();
    }
    
    • (•́ ✖ •̀)
      알 수 없는 사용자

답변을 하려면 로그인이 필요합니다.

프로그래머스 커뮤니티는 개발자들을 위한 Q&A 서비스입니다. 로그인해야 답변을 작성하실 수 있습니다.

(ಠ_ಠ)
(ಠ‿ಠ)