linked list 질문입니다. (C)

진로나라의 이미지

솔직히 숙제 입니다.. -_-;

숙제올리면 욕먹을꺼 뻔히 알면서도 올리게 되내요.. 도저히 몰라서..

답은 저도 바라지 않구요..

왜 않되는지를 알았으면 합니다.. ㅠㅠ

문제는 아래 open_file() 함수 부분입니다.

data.txt에서 data를 읽어 정렬하면서 linked list에 넣어야 하는대

뭐가 문제인지를 모르겠습니다.

void open_file(char *file_name){
	FILE *fp;
	node *t;
	node *s;
	node *p;
	node *r;

	p = head;
	s = p->next;

	if ((fp = fopen(file_name,"rb")) == NULL){
		printf("\n Error : %s is not exise.", file_name);
		return;
	}
	while(1){
		t = (node*)malloc(sizeof(node)); /* 임시로 t하나 만든다 */
		if(fscanf(fp,"%d%s%d%d%d",&t->id,t->name,&t->kor,&t->eng,&t->math) == EOF){
			free(t); /* EOF면 만든 t 지운다 */
			break;
		} else {
			while((s->kor + s->eng + s->math) <= (t->kor + t->eng + t->math) && s != tail){
				p = p->next;
				s = p->next;
			}
			r = (node*)malloc(sizeof(node));
			r = t;
			p->next = r;
			r->next = tail;			
			free(t);
		}

	}
	fclose(fp);
}

----전체 소스 -----

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

#define NAME_SIZE 10

/* 구조체 선언 */
typedef struct _node{
	int id, kor, eng, math;
	char name[NAME_SIZE];
	/* 다음노드의 위치저장 */
	struct _node *next;
} node;

node *head, *tail;

/* linked list 초기화 함수 */
void init_list(void); 
/* 파일을 열 함수 */
void open_file(char *file_name);
/* 화면출력 함수 */
void display_list(node *t); 
/* 메모리 해제함수 */
void delete_all(void); 

int main(void)
{
	init_list(); /* linked list 초기화 */
	open_file("data.txt"); /*파일을 연다 */
	display_list(head->next); /* 출력 */
	delete_all(); /* 메모리해제 */
	return 0;
}

void init_list(void){
	head = (node*)malloc(sizeof(node)); /* 머리공간 확보 */
	tail = (node*)malloc(sizeof(node)); /* 꼬리공간 확보 */
	head->next = tail; /*머리의 다음은 꼬리 */
	tail->next = tail; /*꼬리의 다음은 꼬리 */
}

void open_file(char *file_name){
	FILE *fp;
	node *t;
	node *s;
	node *p;
	node *r;

	p = head;
	s = p->next;

	if ((fp = fopen(file_name,"rb")) == NULL){
		printf("\n Error : %s is not exise.", file_name);
		return;
	}
	while(1){
		t = (node*)malloc(sizeof(node));
		if(fscanf(fp,"%d%s%d%d%d",&t->id,t->name,&t->kor,&t->eng,&t->math) == EOF){
			free(t); /* EOF면 만든놈 지운다 */
			break;
		} else {
			while((s->kor + s->eng + s->math) <= (t->kor + t->eng + t->math) && s != tail){
				p = p->next;
				s = p->next;
			}
			r = (node*)malloc(sizeof(node));
			r = t;
			p->next = r;
			r->next = tail;			
			free(t);
		}

	}
	fclose(fp);
}

void display_list(node *t){
	int i = 1;
	float avg = 0;

	printf("번호\t이름\t국어\t영어\t수학\t평균\t등수\n");
	while (t != tail){
		avg = ((float)t->kor + (float)t->eng + (float)t->math) / 3;
		printf("%d\t%s\t%d\t%d\t%d\t%3.1f\t%d\n",t->id,t->name,t->kor,t->eng,t->math,avg,i++);
		t = t->next;
	}
}

void delete_all(void){
	node *s;
	node *t;
	t = head->next;
	while (t != tail){
		s = t;
		t = t->next;
		free(s);
	}
	head->next = tail;	
}	

-------data.txt----
1 가가가 78 90 93
2 나나나 73 86 90
3 다다다 100 98 88
4 라라라 60 65 66
5 마마마 61 59 100
최병현의 이미지

초기화와 pointer에 대한 잘못된 이해로 발생하는 문제로 생각됩니다.

진로나라 wrote:
void open_file(char *file_name){
	FILE *fp;
	node *t;
	node *s;
	node *p;
	node *r;

	p = head;
	s = p->next;

	if ((fp = fopen(file_name,"rb")) == NULL){
		printf("\n Error : %s is not exise.", file_name);
		return;
	}
	while(1){
		t = (node*)malloc(sizeof(node)); /* 임시로 t하나 만든다 */
		if(fscanf(fp,"%d%s%d%d%d",&t->id,t->name,&t->kor,&t->eng,&t->math) == EOF){
			free(t); /* EOF면 만든 t 지운다 */
			break;
		} else {
			while((s->kor + s->eng + s->math) <= (t->kor + t->eng + t->math) && s != tail){
				p = p->next;
				s = p->next;
			}
			r = (node*)malloc(sizeof(node));
			r = t;
			p->next = r;
			r->next = tail;			
			free(t);
		}

	}
	fclose(fp);
}

위의 코드를 포함해서 전체 코드에서 tail에 대한 초기화, 그러니까 tail의 각 member 변수에 대한 초기화가 없습니다.
따라서 위에 인용한 코드 내에서 s의 member 변수들은 초기화 되지 않은 값들이 사용될 것으로 생각됩니다.

그리고, 왜 t를 free()시켰는지는 모르겠지만,
원래 목적은 p->next에 t를 주려고 했던 것으로 생각됩니다.
그렇게 하기 위해서 r을 이용한 것으로 생각되고요.

하지만, pointer는 assign만으로 그 내용이 모두 복사되는 것이 아니기 때문에... :wink:
위에서 생성한 t를 free() 시키면 안될 것으로 생각됩니다.

제 생각으로는 r은 전혀 필요 없는 변수입니다.
꼭 r을 사용하셔야 겠다면 assign이 아니라 memcpy를 이용하시는 것이 맞습니다.

To be a rich

exsider의 이미지

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

#define NAME_SIZE 10

/* 구조체 선언 */
typedef struct _node{
        int id, kor, eng, math;
        char name[NAME_SIZE];
        struct _node *next;
} node;

node *head, *tail;

/* linked list 초기화 함수 */
void init_list(void);
/* 파일을 열 함수 */
void open_file(char *file_name);
/* 화면출력 함수 */
void display_list(node *t);
/* 메모리 해제함수 */
void delete_all(void);

int main(void)
{
    init_list(); /* linked list 초기화 */
    open_file("data.txt"); /*파일을 연다 */
    display_list(head->next); /* 출력 */
    delete_all(); /* 메모리해제 */
    return 0;
}

void init_list(void){
    head = (node*)malloc(sizeof(node)); /* 머리공간 확보 */
    tail = (node*)malloc(sizeof(node)); /* 꼬리공간 확보 */
    head->next = tail; /*머리의 다음은 꼬리 */
    tail->next = tail; /*꼬리의 다음은 꼬리 */
}

void open_file(char *file_name){
    FILE *fp;
    node *t;                    /* 넣을 노드 */
    node *s;                    /* 넣을 위치 */
    node *p;                    /* 넣을 위치의 앞 */



    if ((fp = fopen(file_name,"rb")) == NULL){
        printf("\n Error : %s is not exise.", file_name);
        return;
    }
    while(1){
        /* 노드를 한개씩 넣을 때 마다 초기화 해야함*/
        p = head;
        s = p->next;

        t = (node*)malloc(sizeof(node));
        if(fscanf(fp,"%d%s%d%d%d",&t->id,t->name,
                  &t->kor,&t->eng,&t->math) == EOF){
            free(t); /* EOF면 만든놈 지운다 */
            break;
        } else {
            /* 넣을 위치를 찾는다. */

            /* 끝에 왔는지 부터 검사해야 함 */
            while( (s !=  tail) && 
                   ( (s->kor + s->eng + s->math) 
                     <= (t->kor + t->eng + t->math))){
                p = s;
                s = s->next;
            }


            p->next = t;

            t->next = s;
        }

    }
    fclose(fp);
}

void display_list(node *t){
    int i = 1;
    float avg = 0;

    printf("번호\t이름\t국어\t영어\t수학\t평균\t등수\n");
    while (t != tail){
        avg = ((float)t->kor + (float)t->eng + (float)t->math) / 3;
        printf("%d\t%s\t%d\t%d\t%d\t%3.1f\t%d\n",
               t->id,t->name,t->kor,t->eng,t->math,avg,i++);
        t = t->next;
    }

}

void delete_all(void){
    node *s;
    node *t;
    t = head->next;
    while (t != tail){
        s = t;
        t = t->next;
        free(s);
    }
    head->next = tail;

    /* head노드와 tail노드는 삭제하지 않아도 되는지??? */
    /*
    free(head);
    free(tail);
    */
} 

출력결과

번호	이름	국어	영어	수학	평균	등수
4	라라라	60	65	66	63.7	1
5	마마마	61	59	100	73.3	2
2	나나나	73	86	90	83.0	3
1	가가가	78	90	93	87.0	4
3	다다다	100	98	88	95.3	5

원한 출력결과가 이게 맞나요???

진로나라의 이미지

답변 정말 감사합니다...

원하던 결과가 맞습니다. (정렬순서야 고치면 되겠죠 :lol: )

사실 최소한의 힌트만 필요했는대 답을 주셨군요. :cry: (허긴 이런 조잡코드에 힌트만 주는게 더 어려울지도. )

감사합니다. (_ _) 행복하세요~~

댓글 달기

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 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <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].
  • 사용할 수 있는 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>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <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].
  • You can use Textile markup to format text.
  • 사용할 수 있는 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>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <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].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 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>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.