C언어 구조체 관련 질문입니다.


C언어 코딩 중 실행 결과가 도무지 이해가 되지않아 질문을 올립니다. 디렉토리 안의 txt 파일 내용은 다음과 같습니다.

4
10:00 12:00 Lectures
12:00 13:00 Lunch, like always
13:00 15:00 Boring lectures
16:45 17:45 Reading

또한 코드는 다음과 같습니다.

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

typedef struct SCHEDULE
{
    char* time1; //hh:mm
    char* time2; //hh:mm
    int time1_h; //hh
    int time1_m; //mm
    int time2_h; //hh
    int time2_m; //mm
    char* appointment;
}Schedule;

void Split_line(FILE* ifp, int schedule_num, Schedule *schedule);
void Split_time(int schedule_num, Schedule *schedule);

int main(void)
{
    FILE *ifp;
    int schedule_num=0;
    int i;
    Schedule *schedule;

    ifp = fopen("input.txt", "r");
    fscanf(ifp,"%d\n", &schedule_num);

    schedule = (Schedule*)malloc(sizeof(Schedule)*schedule_num);

    Split_line(ifp, schedule_num, schedule); // 각 라인을 time1, time2, appointment로 쪼개기
    //Split_time(schedule_num, schedule); // 각 라인의 time1, time2 쪼개기
}

void Split_line(FILE* ifp, int schedule_num, Schedule *schedule){

    int i;
    char buff[255];
    char* tmp;

    printf("%d\n",schedule_num);

    for(i=0; i<schedule_num; i++){
        //printf("%d\n", i);
        fgets(buff, 255, (FILE*)ifp); // 각 line 읽기
        tmp = strtok(buff," "); //time1 분리하기
        schedule[i].time1 = tmp;
        tmp = strtok(NULL, " "); //time2 분리하기
        schedule[i].time2 = tmp;
        tmp = strtok(NULL, "\n"); //appointment 분리하기
        schedule[i].appointment = tmp;

        printf("%s %s %s\n",schedule[i].time1, schedule[i].time2, schedule[i].appointment);
    }
    printf("\nCheck\n");
    printf("%s %s %s\n",schedule[0].time1, schedule[0].time2, schedule[0].appointment);
    printf("%s %s %s\n",schedule[1].time1, schedule[1].time2, schedule[1].appointment);
    printf("%s %s %s\n",schedule[2].time1, schedule[2].time2, schedule[2].appointment);
    printf("%s %s %s\n",schedule[3].time1, schedule[3].time2, schedule[3].appointment);
        fclose(ifp);        
}   
}

이미지

실행 결과입니다. 어째서 schedule[0], schedule1, schedule[2], schedule[3]이 for문 돌 때는 제대로 들어가있다가 for문이 끝난 직후 다시 확인하면 [3]의 값으로 모두 바뀌어있는지 혹시 알려주실 수 있으실까요??


조회수 145


1 답변


좋아요
2
싫어요
채택취소하기

저도 정확히 이유는 모르겠으나 역시 배열과 문자열다룰때는 메모리 영역 침범하는게 제일 조심스럽고 어렵더라구요.디버깅 하면서 우선 해결한 결과는 일단 다음과 같습니다.

malloc으로 스케쥴 배열 생성하신다음에 배열로 각각 구조체의 char배열에 다시 50byte정도 malloc으로 공간확보뒤에 쓰레기공간들을 다시 memset으로 0으로 체웁니다. 다음으로 tmp로 구조체의 char배열에 직접 대입하지 마시구 tmp로 대입할적에 strcat으로 붙이면 일단 문제없이 잘 출력됩니다.

본문상의 코드의 문제점이나 더 좋은 코드는 다른 고수분들이 남겨주시리라 믿습니다 ㅋ

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#pragma warning(disable: 4996)

typedef struct SCHEDULE
{
    char* time1; //hh:mm
    char* time2; //hh:mm
    int time1_h; //hh
    int time1_m; //mm
    int time2_h; //hh
    int time2_m; //mm
    char* appointment;
}Schedule;

void Split_line(FILE* ifp, int schedule_num, Schedule *schedule);
void Split_time(int schedule_num, Schedule *schedule);

int main(void)
{
    FILE *ifp = NULL;
    int schedule_num = 0;
    int i;
    Schedule *schedule;

    fopen_s(&ifp, "C:\\sample.txt", "r");
    fscanf(ifp, "%d\n", &schedule_num);

    schedule = (Schedule*)malloc(sizeof(Schedule)*schedule_num);
    for (i = 0; i < 4; i++) {
        schedule[i].time1 = (char*)malloc(sizeof(char) * 50);
        memset(schedule[i].time1, 0, 50);
        schedule[i].time2 = (char*)malloc(sizeof(char) * 50);
        memset(schedule[i].time2, 0, 50);
        schedule[i].appointment = (char*)malloc(sizeof(char) * 50);
        memset(schedule[i].appointment, 0, 50);

    }
    Split_line(ifp, schedule_num, schedule); // 각 라인을 time1, time2, appointment로 쪼개기
                                             //Split_time(schedule_num, schedule); // 각 라인의 time1, time2 쪼개기
}

void Split_line(FILE* ifp, int schedule_num, Schedule *schedule) {

    int i, l = 0;
    char buff[255];
    char* tmp;

    printf("%d\n", schedule_num);

    for (i = 0; i<schedule_num; i++) {
        //printf("%d\n", i);
        fgets(buff, 255, (FILE*)ifp); // 각 line 읽기
        tmp = strtok(buff, " "); //time1 분리하기
        strcat(schedule[i].time1, tmp);
        tmp = strtok(NULL, " "); //time2 분리하기
        strcat(schedule[i].time2, tmp);
        tmp = strtok(NULL, "\n"); //appointment 분리하기
        strcat(schedule[i].appointment, tmp);

        printf("%s %s %s\n", schedule[i].time1, schedule[i].time2, schedule[i].appointment);
        /*for (l = 0; l <= i; l++) {
            printf("%s %s %s\n", schedule[l].time1, schedule[l].time2, schedule[l].appointment);
        }*/
    }
    printf("\nCheck\n");
    printf("%s %s %s\n", schedule[0].time1, schedule[0].time2, schedule[0].appointment);
    printf("%s %s %s\n", schedule[1].time1, schedule[1].time2, schedule[1].appointment);
    printf("%s %s %s\n", schedule[2].time1, schedule[2].time2, schedule[2].appointment);
    printf("%s %s %s\n", schedule[3].time1, schedule[3].time2, schedule[3].appointment);
    fclose(ifp);

}
  • 2016년 09월 03일에 작성됨

  • 정성어린 답변에 진심으로 감사의 말씀 전합니다. 저는 tmp에 계속 buff의 새로운 주소가 덧씌워진다는 것을 알게되어 buff를 2차원배열로 만드는 것으로 해결하였습니다. 그러나 현재 코드를 완성하였는데 실행했을 때 한번씩 결과값이 달라지는 일이 발생하고 있습니다. 혹시 여력이 되신다면 한번 더 살펴주시면 정말 감사하겠습니다.     ShinDongHyuk   2016.9.4 11:55     
  • 네 제가 도와드릴 수 있는 수준이면 도와드리겠습니다.    PuppyRush   2016.9.4 12:17     
  • 다시한번 감사의 말씀 먼저 전하겠습니다. "C언어 포인터 관련하여, 실행했을 때 종종 결과값이 달라지는 경우는 어떻게 해결해야할까요?" 라는 제목으로 새로 질문글을 올렸습니다. 부디 너무 어리석은 실수가 아니어 답변자님께도 공부가 되는 질문이었으면 좋겠습니다.    ShinDongHyuk   2016.9.4 12:26     
  • 저도 많이 부족합니다... ㅋㅋ 시간이 허락하는대로 확인해보겠습니다. 제 한도를 넘어가면 다른분에게 맡겨야 겠지만요 ㅜㅜ    PuppyRush   2016.9.4 15:21     

로그인이 필요한 기능입니다.

Hashcode는 개발자들을 위한 무료 QnA사이트 입니다. 작성한 답변에 다른 개발자들이 댓글을 작성하거나 좋아요/싫어요를 할 수 있기 때문에 계정을 필요로 합니다.
► 로그인
► 계정만들기
Close