[C 프로그래밍] 파일 출력 함수_3.연결 리스트 저장, 불러오기

 

#1 ■연결 리스트를 파일에 저장하고 불러오기
연결리스트는  C언어의 기본자료형이 아닌 '사용자 정의 자료형'이기에 파일을 바이너리 쓰기 모드로 오픈하고 읽고 써야한다.

연습 1-1 : 구조체 Node 정의, 함수 saveList 구현
-데이터를 담을 구조체와 리스트의 데이터를 파일에 저장할 함수 구현

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

//연결 리스트의 노드로 사용될 Node 구조체를 정의
struct Node{
    int val1;
    float val2;
    struct Node* next;
};

//saveList 함수 구현 - 연결 리스트를 파일에 저장하는 기능
void saveList(FILE* fp, struct Node *p){
    while(p != NULL){ //노드가 없을 때까지 반복
        //전달된 연결 리스트의 모든 노드를 반복하면서 구조체의 바이너리 정보를 fwrite 함수를 이용해서 파일에 쓴다.
        fwrite((void*)p, sizeof(struct Node), 1, fp);
        p = p->next;
    }
}

연습 1-2 : 함수 loadList 구현

- 파일 포인터를 전달 받아서 파일에 저장되어 있는 바이너리 정보를 읽어 구조체에 값을 저장하는 함수
//loadList 함수 구현 - 파일 포인터를 전달 받아서 파일에 저장된 바이너리 정보를 읽어 구조체에 저장
//결과적으로 연결 리스트를 반환하기 때문에 반환을 struct Node*로 한다.
struct Node* loadList(FILE* fp){
    //연결리스트의 처음 노드를 가리킬 포인터 head, 노드 가리킬 포인터 p 선언
    struct Node *head = NULL, *p = NULL;

    while(1) //무한 반복
    {
        //파일에서 읽어올 값을 저장할 구조체 동적 할당
        struct Node* node = (strcut Node*)malloc(sizeof(struct Node));
        //구조체 1개에 해당하는 정보를 파일에서 읽어 node 변수에 할당
        int isRead = fread((void*)node, sizeof(struct Node), 1, fp);

        //읽어온 값이 없을 경우 반복문 탈출
        if(!isRead)
            break;

        //head가 비어있을 경우 node를 head로 사용
        if(head == NULL){
            head = node;
            p = node;
        }else{ //head가 비어있지 않을 경우 마지막 노드에 node 연결
            p->next = node;
            p = p->next;
        }
    }
    //마지막 노드의 next를 NULL로 설정
    p->next = NULL;
    //연결 리스트의 첫 노드를 반환
    return head;
}

C언어에는 boolean타입이 없는 것을 생각하며 if(!isRead) 작동을 예상하자.

연습 1-3 : getLastNode 함수
- 연결리스트의 마지막 노드를 반환하는 함수, 연결리스트의 node중 하나를 매개체로 받으면 마지막 노드를 반환할 수 있다.

 

 

//getLastNode 함수 구현 - 연결 리스트의 마지막 노드를 반환하는 함수
struct Node* getLastNode(struct Node *p)
{
    //연결 리스트의 마지막 노드를 P 에 저장한 뒤, 반환
    while(p->next !=NULL){
        p=p->next;
    }
    return p;
}

 

연습 1-4: freeNodes 함수

- 연결 리스트에 사용된 동적 메모리를 모두 해제하는 함수
 
//freeNodes 함수 - 연결 리스트에 사용된 동적 메모리를 모두 해제하는 함수
void freeNodes(struct Node* head){
    struct Node *last = head; //free할 노드를 가리키는 포인터
    struct Node *temp; //다음 노드를 기억하기 위한 포인터 temp, free를 하기전 값을 저장하기 위한 용도

    while(last !=NULL){
        temp = last -> next; //다음 노드를 가리킨다.
        free(last); //해당 노드의 메모리 해제
        last = temp; //저장해놨던 다음노드를 last에도 저장
    }
}

 

 

연습 1-5: makeNode 함수
- 사용자의 입력을 받아 구조체를 만들고 반환해주는 기능

 

//makeNode 함수 - 사용자의 입력을 받아 구조체를 만들고 반환해주는 기능
struct Node* makeNode()
{
    int val1;
    float val2;
    struct Node* node;

    //구조체에 저장할 값을 입력 받음
    printf("구조체의 값을 입력하시오  INT =  ");
    scanf_s("%d" , &val1);
    printf(" FLOAT = ");
    scanf_s("%f" , &val2);

    //Node 구조체를 동적 할당한 뒤, 위의 값들을 저장
    node = (struct Node*)malloc(sizeof(struct Node));
    node->val1= val1;
    node->val2= val2;
    node->next = NULL

    //생성한 구조체를 반환
    return node;
}

 

연습 1-6 :  addNode 함수
- 함수의 인자로 전달된 연결리스트의 마지막 노드에 새로 생성된 노드를 추가하는 역할
- 새로 생성된 노드는 makeNode함수일 것이고 마지막 노드를 찾기위해 getLastNode함수가 쓰일 것이다.

경축! 아무것도 안하여 에스천사게임즈가 새로운 모습으로 재오픈 하였습니다.
어린이용이며, 설치가 필요없는 브라우저 게임입니다.
https://s1004games.com

 

//addNode 함수 - 함수의 인자로 전달된 연결리스트의 마지막 노드에 새로 생성된 노드를 추가하는 역할
//새로 생성된 노드는 makeNode함수일 것이고 마지막 노드를 찾기위해 getLastNode함수가 쓰일 것이다.
struct Node* addNode(struct Node *head){

    //새로운 노드를 생성
    struct Node *node = makeNode();

    // head가 비어있을 경우 추가할 노드를 head로 사용 = 첫 노드
    if(head == NULL){
        head = node;
    }
    else{ //head 가 비어있지 않을 경우 head 의 마지막 노드에 추가할 노드를 연결
        struct Node *last = getLastNode(head);
        last->next = node;
    }
    
    return head; //노드가 추가된 연결 리스트를 반환
}

 

연습 1-7 : printList 함수
- 연결리스트의 값을 화면에 출력하는 기능

 

//printList 함수 - 연결리스트의 값을 화면에 출력하는 기능
void printList(struct Node *p)
{
    int count = 1;
    printf("-------입력된 데이터 -------\n");

    //연결리스트의 각 노드를 순환하며 값을 화면에 출력
    while(p!=NULL){
        printf("[%d] %d, %.2f\n", count, p->val1, p->val2);
        p = p->next;
        count++;
    }
    printf("---------------------------\n");
}

연습 1-8 main 함수 작성

 

void main()
{
    //파일 포인터, 연결 리스트 첫 노드 포인터 변수 선언
    FILE *fp1, *fp2;
    struct Node *head;
    int input = 1;
    
    //list.txt를 바이너리 읽기 모드로 오픈하고 fp1으로 지정한다. 실패한다면 fp1은 NULL이 될 것이다.
    fp1 = fopen("list.txt", "rb");

    if(fp1) //fp1가 NULL이 아니면 실행, 즉 불러올 파일 존재
    {
        head = loadList(fp1); //파일에 저장된 연결 리스트를 head 변수에 저장
        printList(head); //불러온 연결 리스트를 화면에 출력
        fclose(fp1); //읽기에 사용한 파일 포인터 해제
    }
    else
    {
        printf("저장된 자료가 없음\n");
        head = NULL; //파일이 없을 경우 head를 NULL로 초기화
    }

    //사용자의 입력을 확인하며 연결리스트에 노드 추가
    while(1)
    {
        printf(" [ 입력 : 1, 중단 : 0 ] ");
        scanf_s("%d",&input);

        if(input == 0)
            break;
        else
            head = addNode(head); //새로운 노드를 연결리스트에 추가
    }

    //연결리스트의 모든 노드 값을 화면에 출력
    printList(head);

    //list.txt 파일을 바이너리 쓰기 모드로 오픈
    fp2 = fopen("list.txt", "wb");
 
    if(fp2) 
    {
        //연결리스트의 모든 값을 파일에 저장
        saveList(fp2, head);
        fclose(fp2); //파일포인터 해제
    }

    //연결리스트에 사용된 모든 동적 메모리 해제
    freeNodes(head);

}

[출처] https://gosmcom.tistory.com/10

 

 

 

 

 

본 웹사이트는 광고를 포함하고 있습니다.
광고 클릭에서 발생하는 수익금은 모두 웹사이트 서버의 유지 및 관리, 그리고 기술 콘텐츠 향상을 위해 쓰여집니다.
번호 제목 글쓴이 날짜 조회 수
72 [linux master][리눅스 마스터][국가기술자격] [리눅스] socat 명령어(proxy) file 졸리운_곰 2024.02.28 0
71 [linux master][리눅스 마스터][국가기술자격] [리눅스] Linux nc 명령어는 무엇이고 어떻게 쓰는 가? 졸리운_곰 2024.02.28 0
70 [linux master][리눅스 마스터][국가기술자격] [리눅스] AWK 명령어 사용법과 여러가지 실용적인 예제 모음 file 졸리운_곰 2024.02.02 1
69 [linux master][리눅스 마스터][국가기술자격] [vi 명령어] vi 명령어 정리 file 졸리운_곰 2024.02.02 1
68 [linux telnet(ssh) 창에서 MSDOS emulation 에뮬레이션 Install dosemu2 dos emulator in Ubuntu and Ubuntu based distributions file 졸리운_곰 2024.01.05 0
67 [linux master][리눅스 마스터][국가기술자격] [Azure] Linux(ubuntu) 우분투 서버 GUI 환경으로 원격 접속하기 - feat. Ubuntu-desktop file 졸리운_곰 2023.11.22 3
66 [linux master][리눅스 마스터][국가기술자격] [Linux] vim(vi) editor 한글 입력시 깨짐 해결방법 file 졸리운_곰 2023.11.22 2
65 [리눅스][linux] 리눅스 서버 다운 원인 분석과 해결 (책) 방안 졸리운_곰 2023.10.03 7
64 [리눅스][linux] Ubuntu/Linux에서 user password를 짧거나 쉬운 password로 변경하는 방법. file 졸리운_곰 2023.01.08 6
63 [linux master][리눅스 마스터][국가기술자격] [GCP 원데이] 서버가 죽는 이유, Message Queue file 졸리운_곰 2023.01.01 8
62 [linux master][리눅스 마스터][국가기술자격] 리눅스 서버 다운 원인 5가지 졸리운_곰 2023.01.01 3
61 [linux master][리눅스 마스터][국가기술자격] Shell In A Box-원격 Linux 서버에 액세스하기위한 웹 기반 SSH 터미널 file 졸리운_곰 2022.11.17 4
60 [linux dev env] [우분투 서버] noVNC 접속 file 졸리운_곰 2022.11.16 3
59 [Linux WSL2] WSL2에서 Ubuntu GUI 프로그램 실행하기 (VcXsrv) file 졸리운_곰 2022.08.20 29
58 [리눅스, Linux] 우분투에서 NTFS 를 Read/Write로 마운트 (듀얼 부팅 화일 공유) file 졸리운_곰 2022.08.13 12
57 [UBUNTU] 우분투 20.04 USB 스틱에 설치 How to Install Ubuntu on a USB Flash Drive file 졸리운_곰 2022.06.02 49
56 [linux mater] Linux passwd : 인증 토큰 수정 오류 졸리운_곰 2022.03.04 30
55 [리눅스 마스터][linux, UNIX] 전설의 라인 에디트 Man page — ED 사용법 졸리운_곰 2021.11.18 15
54 [리눅스 마스터][linux, UNIX] [편집][shell] ed (line editer) 사용예 졸리운_곰 2021.11.17 24
53 [죽기전에 경험해봐야 하는 미니 코어 리눅스 5가지] 5 tiny Linux distros to try before you die file 졸리운_곰 2021.04.25 14
대표 김성준 주소 : 경기 용인 분당수지 U타워 등록번호 : 142-07-27414
통신판매업 신고 : 제2012-용인수지-0185호 출판업 신고 : 수지구청 제 123호 개인정보보호최고책임자 : 김성준 sjkim70@stechstar.com
대표전화 : 010-4589-2193 [fax] 02-6280-1294 COPYRIGHT(C) stechstar.com ALL RIGHTS RESERVED