본문 바로가기

컴퓨터/언어,프로그래밍

C언어 :: 파일 입출력 - 사용

1.2  프로그램밍에서의 파일 입출력

프로그래밍 언어를 배우는 이들은 파일 입출력 함수에 대한 많은 두려움을 갖고 있는 것 같습니다.  실제로 프로그래밍에서 파일을 통해 자료를 관리하는 것은 쉬운 일은 아니지만 이는 파일 입출력 함수가 어려운 것이 아니라 프로그래밍을 하면서 무엇을 저장하고 어떻게 읽어올 것인지에 대한 규칙을 정하는 것이 어려운 것이라 생각이 듭니다.  이 또한 많은 경험을 통해 극복할 수 있고 극복해야 하는 것이기 때문에 두려워 피하지 마시기 바랍니다.

 

 여기서는 8장에서 얘기했던 회원 관리 프로그램을 예로 들어 정적 인덱스 배열, 동적 순수 배열, 동적 인덱스 배열에서 파일 입출력에서 각 주의할 사항에 대해서 파악해 보기로 합시다.(fread, fwrite함수를 소개하면서 보여준 예제가 정적 순수 배열에서의 파일 I/O입니다.)  참고로 fread fwrite를 이용한 파일 I/O만 설명하도록 하겠습니다.

 

1.2.1        정적 인덱스 배열

이 책에서 얘기하는 정적 인덱스 배열은 배열의 크기는 개발시에 정해지고 각 배열의 원소가 관리할 데이터의 위치정보를 갖도록 하는 배열을 의미합니다. 

 

#define MAX_MEMBER           50

member *base[MAX_MEMBER];

 

 8장에서도 얘기했듯이 위와 같이 최대 관리 데이터 수가 정해져 있고 배열의 원소가 회원데이터의 포인터가 되겠지요.  그리고 실제 회원 데이터를 삽입하기 전에 메모리가 할당되고 삭제하면서 메모리가 해제 될 것입니다.

 

해당 프로그램에서 관리하는 데이터들은 회원 데이터들이 연속적이지 않은 메모리에 할당되어 있다는 것을 알 수 있습니다.  , 파일에 저장할 때에는 해당 회원의 데이터가 있는지 확인해서 저장을 해야 할 것입니다. 

 

void fnSave(const char *fname)

{

           FILE *fp=0;

        int cnt = 0;

 

           if((fp = fopen(fname,"w"))!=NULL)

           {

                while(cnt < MAX_MEMBER) 

                {

                     if(base[cnt])  //해당 회원의 데이터가 존재하면

                     {

                         fwrite(base[cnt],sizeof(member),1,fp); //해당 멤버 데이터 파일에 저장

                     }

                     cnt++;

                }

                     fclose(fp);

           }

           else

           {

                     printf("저장하지 못했습니다.\n");

           }

}

 

, 정적 인덱스 배열에서는 관리 데이터가 있는지 확인해서 해당 데이터 하나를 저장하는 것을 반복하여야 할 것입니다.  그리고, 이를 로딩을 할 때에는 먼저 회원 데이터 하나를 로딩할 메모리를 할당받고 로딩 후 관리 공간과 연결하는 것을 파일의 끝까지 반복합니다.  특히, 맨 마지막에 할당한 메모리는 파일의 끝을 만나 실제 로딩을 한 것이 아니기 때문에 반드시 메모리 해제를 해 주어야 겠지요.

 

void fnLoad(const char *fname)

{

           FILE *fp=0;

        int cnt = 0;

        member *lm = 0;

 

           if((fp = fopen(fname,"r"))!=NULL)

           {

                lm = (member *)malloc(sizeof(member));  //로딩할 메모리 할당

                while(fread(lm,sizeof(member),1,fp))     //로딩 파일의 끝까지

                {

                     base[lm.mnum-1] = lm;            //관리 공간에 mapping

                     lm = (member *)malloc(sizeof(member));  //로딩할 메모리 할당

}

free(lm);  //마지막에 할당된 메모리 해제

                     fclose(fp);

           }

           else

           {

                     printf("저장하지 못했습니다.\n");

           }

}

 

여기서 while의 조건이 fread함수의 반환값으로 되어 있습니다.  파일의 끝을 만나면 더 이상 읽을 내용이 없으니 반환값이 0이 되겠지요.  이를 파일의 끝을 확인하는 곳에 이용하였습니다.

 

1.2.2      동적 순수배열 와 동적 인덱스 배열

  동적 순수 배열의 경우 관리하는 회원 데이터는 연속적인 메모리에 잡혀 있습니다.  , 정적 순수 배열에서의 파일 입출력과 동일하다는 것이지요.  그리고 동적 인덱스 배열의 경우도 정적 인덱스 배열과 마찬가지로 각 회원 데이터의 존재 유무를 확인한 후 저장하게 될 것입니다.  실제 파일 입출력 기능의 함수는 정적 인덱스 배열과 다르지 않습니다.  , 배열을 사용하여 데이터를 관리할 때에는 순수 배열, 인덱스 배열 중에 어떠한 것을 사용하였는지가 이슈가 되지 동적배열, 정적 배열이 이슈가 되지 않습니다.  여러분들은 여기서 기본적인 파일 입출력 라이브러리 사용법을 익히시고 프로젝트 과정에서 각 프로젝트에 맞게 파일 입출력을 하는 능력을 기르시길 바랍니다.  이 책에서도 여러 형태의 프로젝트 예제를 통해 각 데이터 관리 구조에 따른 파일 입출력 예를 소개를 하겠습니다.  물론, 프로젝트에서는 자세한 설명은 생략됩니다.

제주삼다수, 2L,... 오뚜기 진라면 매운... 상하목장 유기농 흰... 남양 프렌치카페 카... 고려인삼유통 홍삼 ... 종근당건강 오메가3... 요이치 카링 유무선...