본문 바로가기

it관련

파일에서 입력한 자료를 단순연결리스트로 만들기

반응형

파일에서 입력한 자료를 단순연결리스트로 만들기


키보드로 부터 학생을 더하고, 삭제하는 기능이외에 

번호순으로 정렬, 이름순으로 정렬, 점수순으로 정렬하는 기능이 있습니다.


#include <stdio.h> 

#include <string.h> 

#include <stdlib.h>

// 학생 구조체의 포인터 pStudent

typedef struct Student *pStudent;

typedef struct Student Student;

// 학생 구조체 번호, 이름, 점수, 다음 구조체 포인터 next 

struct Student { 

    int  number;

    char name[20]; 

    int  score; 

    pStudent next; 

}; 

// 연결리스트 구조체를 List로 재정의

typedef struct studentList List;

// 연결리스트 구조체의 포인터 pList

typedef struct studentList *pList;

// 연결리스트 구조체 : head와 tail을 가지고 있다.

struct studentList {

    pStudent head;

    pStudent tail;

};  

// 새노드를 만들고 포인터를 NULL로 초기화 시킨다.

pStudent makeNode();

// 파일로 부터 중복검사를 하지 않고, 번호, 이름, 점수를 읽어 삽입한다.

void insertFromFile(pList, FILE *fin1); 

// 키보드로 부터 중복검사를 하지 않고, 번호, 이름, 점수를 읽어 삽입한다.

// 노드들은 입력받은 순서대로 되어있다.

void insertNode(pList); 

// 이름을 입력받아 이름을 가진 노드를 삭제한다.

// 같은 이름이 있을 경우 먼저 발견한 노드만 삭제한다.

void deleteNode(pList); 

// 이름으로 찾은 학생정보를 보여준다.

void searchNode(pList); 

// 이름순으로 학생리스트를 보여준다.

void showByNames(pList); 

// 번호순으로 학생리스트를 보여준다.

void showByNumbers(pList); 

// 점수순으로 학생리스트를 보여준다.

void showByScores(pList); 

// 입력된 순으로 전화번호부를 보여준다.

void showAll(pList); 

// 모든 노드들을 삭제한다.

void quitNode(pList); 

int main() { 

    // 입력 파일

    FILE *inf1;

    // 학생리스트 list

    pList list;

    // 메뉴선택을 위한 변수, 7을 입력하면 종료한다.

    int menu=1; 


    // 리스트를 초기화한다. 더미 노드를 한개 만들어서 head와 tail이 이 노드를 가리키게 한다.

    // 이렇게 해서 항상 실제로 가리키기를 원하는 노드 보다 앞의 노드를 가지고 찾아다니면

    // 어떤 위치에서든디 삽입과 삭제를 할 수 있다.

    // 또 이중 포이터를 사용해야하는 번거러움을 피할 수가 있다.

    // head는 리스트의 시작하는 노드(항상 더미노드)를 가리킨다.

    // tail은 리스트의 맨 마지막 노드를 가리킨다. 처음에는 더미노드를 가리키다가,

    // 실제로 노드가 삽입되면 가장 나중에 삽입된 노드를 가리키게 된다.

    // tail 을 이용해서 우리는 새로 삽입되는 노드를 가장 뒤에 바로 삽일할 수 있다.

    list=(pList)malloc(sizeof(List));

    list->head=makeNode();

    list->tail=list->head;


    // 메뉴를 보여주고 선택을 입력 받는다.

    while(menu!=9) { 

        puts("*************"); 

        puts("* 1. 파일로 부터 입력: "); 

        puts("* 2. 직접 입력: "); 

        puts("* 3. 삭제: "); 

        puts("* 4. 검색: "); 

        puts("* 5. 번호순 전체출력: "); 

        puts("* 6. 이름순 전체출력: "); 

        puts("* 7. 점수순 전체출력: "); 

        puts("* 8. 전체출력:"); 

        puts("* 9. 끝내기"); 

        puts("*************"); 

        printf("선택="); 

        scanf("%d", &menu); 

        fflush(stdin); 

        switch(menu) { 

            case 1: 

                inf1=fopen("student.txt", "r");

                if(inf1==NULL) {

                    printf("student.txt 파일을 읽을 수 없습니다.");

                    return 1;

                }

                // 삽입

                insertFromFile(list, inf1);

                fclose(inf1); 

                break; 

            case 2: 

                // 삽입

                insertNode(list); 

                break; 

            case 3: 

                // 삭제

                deleteNode(list); 

                break; 

            case 4: 

                // 검색

                searchNode(list); 

                break; 

            case 5: 

                // 이름순

                showByNumbers(list); 

                break; 

            case 6: 

                // 이름순

                showByNames(list); 

                break; 

            case 7: 

                // 점수순

                showByScores(list); 

                break; 

            case 8: 

                // 전체출력

                showAll(list); 

                break; 

            case 9: 

                // 종료

                quitNode(list); 

                break; 

        } 

    }

    // 마지막으로 list를 free시킨다.

    free(list);


    return 0;

// 새노드를 만든다.

pStudent makeNode() { 

    pStudent p;


    p=(pStudent)malloc(sizeof(Student));

    p->number=0;

    strcpy(p->name,"");

    p->score=0;

    p->next=NULL;

    return p;

}

// 노드를 복사한다.

pStudent copyNode(pStudent q) { 

    pStudent p;


    p=(pStudent)malloc(sizeof(Student));

    p->number=q->number;

    strcpy(p->name,q->name);

    p->score=q->score;

    p->next=NULL;

    return p;

}

// 파일로 부터 번호, 이름과 점수를 입력받아 새노드를 삽입한다.

void insertFromFile(pList list, FILE *fin1) {

    pStudent newnode; 

    int num, c, i;

    while(!feof(fin1)) {

        fscanf(fin1, "%d", &num);

        if(feof(fin1)) break;

        newnode = makeNode(); 

        newnode->number=num;

        i=0; 

        while((c=fgetc(fin1))==' ');

        newnode->name[i++]=c;

        while((c=fgetc(fin1))!='#') newnode->name[i++]=c;

        newnode->name[i]=0;

        fscanf(fin1, "%d", &(newnode->score));

        list->tail->next=newnode;

        list->tail=newnode;

    }

// 이름과 번호를 입력받아 새노드를 삽입한다.

void insertNode(pList list) {

    pStudent newnode = makeNode(); 

    printf("번호를 입력하세요 : "); 

    scanf("%d", &(newnode->number)); 

    fflush(stdin);

    printf("이름을 입력하세요 : "); 

    gets(newnode->name); 

    fflush(stdin); 

    printf("점수를 입력하세요 : "); 

    scanf("%d", &(newnode->score)); 

    fflush(stdin); 

    list->tail->next=newnode;

    list->tail=newnode;

// 이름을 입력받아 그 노드를 찾아서 삭제한다.

void deleteNode(pList list) {

    pStudent t = list->head;

    pStudent temp; 

    char str[20]={0,}; 

    printf("이름을 입력하세요 : "); 

    gets(str); 

    fflush(stdin); 

    while(t->next) {

        // 여기서 t->next->name과 str을 비교한 것에서

        // 실제로 가리키는 노드의 한칸 앞의 포인터를 가지고

        // 찾는다는 의미를 알 수 있다.

        if(strcmp(t->next->name,str)==0) {

            temp = t->next; 

            // 우리가 찾은 노드가 temp노드 이다. 이노드가 마지막 노드라면 tail을 수정해 주어야 한다.

            if(list->tail==temp) list->tail=t;

            // t->next를 t->next->next로 바꾸어 준다.

            // 이렇게 해주면 temp는 리스트 상에서 사라지게 된다.

            t->next=t->next->next; 

            // temp를 free시켜준다.

            free(temp);

            return;

        } 

        t=t->next;

    }

// 이름으로 학생을 찾는다.

void searchNode(pList list) {

    pStudent t = list->head;

    char str[20]={0,}; 

    printf("이름을 입력하세요 : "); 

    gets(str); 

    fflush(stdin); 

    while(t->next) {

        if(strcmp(t->next->name,str)==0) {

            printf("번호: \t%d \t이름: \t%s\t점수:\t%d\n", 

                t->next->number, t->next->name, t->next->score); 


            return;

        } 

        t=t->next;

    }

// 이름순으로 정렬하기 

void showByNames(pList list) {

    pStudent t = list->head;

    pStudent temp;

    pStudent root=makeNode();

    pStudent s=root;

    int comp;

 

    // 학생리스트를 처음부터 끝까지 가면서

    // 새로운 리스트 root에 이름순으로 삽입을 한다.

    while(t->next) {

        // 먼저 현재 노드를 복사한다.

        temp=copyNode(t->next);

        // 새로운 리스트 root의 처음부터 시작하여

        s=root;

        // temp의 이름과 root에서 시작하는 노드의 이름을 비교한다.

        while(s->next) {

            comp=strcmp(s->next->name, temp->name);

            // temp의 이름이 root에서 시자하는 현재 노드의 이름보다 작다면

            if(comp>=0) {

                // s->next 앞에 temp를 끼워 넣어야 한다.

                // 따라서 temp->next는 s->next가 되어야 한다.

                temp->next=s->next;

                break;

            }

            // 만약 temp의 이름이 현재노드의 이름보다 크다면 다음 노드로 간다.

            else s=s->next;

        }

        // s->next앞에 temp를 끼워 넣어야 하므로

        // s->next에 temp를 넣어 주면 된다.

        s->next=temp;

        // 원래 학생리스트에서 남아있는 노드를 처리히기 위해서 t의 값을 다음 노드로 이동시킨다.

        t=t->next;

    }

    // 새로 만들어진 root리스트를 모두 출력해 준다.

    t=root;

    while(t->next) {

        printf("번호: \t%d \t이름: \t%s\t점수:\t%d\n", 

            t->next->number, t->next->name, t->next->score); 


        t = t->next; 

    }

    // 새로 만들어진 root리스트를 모두 삭제해 준다. 

    t=root;

    while(t->next) {

        temp = t->next;

        t=t->next; 

        free(temp); 

    } 

    free(root);

// 번호순 출력도 이름순 출력과 같다. (오름차순)

// 단지 비교할 때 이름대신 번호를 사용하는 것만 다른다.

void showByNumbers(pList list) {

    pStudent t = list->head;

    pStudent temp;

    pStudent root=makeNode();

    pStudent s=root;

    int comp;

 

    while(t->next) {

        temp=copyNode(t->next);

        s=root;

        while(s->next) {

            if(s->next->number>=temp->number) {

                temp->next=s->next;

                break;

            }

            else s=s->next;

        }

        s->next=temp;

        t=t->next;

    }

    t=root;

    while(t->next) {

        printf("번호: \t%d \t이름: \t%s\t점수:\t%d\n", 

            t->next->number, t->next->name, t->next->score); 


        t = t->next; 

    } 

    t=root;

    while(t->next) {

        temp = t->next;

        t=t->next; 

        free(temp); 

    } 

    free(root);

// 점수순 출력도 이름순 출력과 같다. (내림차순)

// 단지 비교할 때 이름대신 점수를 사용하는 것만 다른다.

void showByScores(pList list) {

    pStudent t = list->head;

    pStudent temp;

    pStudent root=makeNode();

    pStudent s=root;

    int comp;

 

    while(t->next) {

        temp=copyNode(t->next);

        s=root;

        while(s->next) {

            if(s->next->score>temp->score) {

                temp->next=s->next;

                break;

            }

            else s=s->next;

        }

        s->next=temp;

        t=t->next;

    }

    t=root;

    while(t->next) {

        printf("번호: \t%d \t이름: \t%s\t점수:\t%d\n", 

            t->next->number, t->next->name, t->next->score); 


        t = t->next; 

    } 

    t=root;

    while(t->next) {

        temp = t->next;

        t=t->next; 

        free(temp); 

    } 

    free(root);

// 전체 학생 리스트를 출력한다.

void showAll(pList list) {

    pStudent t = list->head; 

    while(t->next) {

        printf("번호: \t%d \t이름: \t%s\t점수:\t%d\n", 

            t->next->number, t->next->name, t->next->score); 

        t = t->next; 

    } 

// 리스트의 모든 노드를 삭제한다.

void quitNode(pList list) { 

    pStudent t=list->head;

    pStudent temp;

  

    while(t->next) {

        temp = t->next;

        t=t->next; 

        free(temp); 

    } 

    free(list->head);

}


===============================================

입력 파일 student.txt 는 다음과 같이 줍니다.


반응형