본문 바로가기
코스웨어/16년 스마트컨트롤러

2016-11-03_조재찬_스터디일지_단순 연결리스트에 파일 입출력 응용 / C복습

by 알 수 없는 사용자 2016. 11. 3.
728x90
반응형

단순 연결리스트에 파일 입출력을 응용


위와 같은 형태의 연결리스트에 파일 입출력을 응용해본다.


연결리스트를 파일로 저장

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void save_File()
{
    FILE *fp;
    fp = fopen("DATA.DBF""wb");
 
    if (fp == NULL)
    {
        printf(" 오류 \n");
        return;
    }
 
    cur = head->next;
    while (cur != NULL)
    {
        fwrite(cur, DATA_SIZE, 1, fp);    // Data_SIZE는 pointer(*next)를 제외한 구조체 size
        cur = cur->next;
    }
    fclose(fp);
}
cs
DATA_SIZE는 define된것으로 *next 멤버를 제외한 구조체의 size이다.


파일을 읽어들여 연결리스트로 구성

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
void load_File()
{
    FILE *fp;
    fp = fopen("DATA.DBF""rb");
 
    Book *nN;
 
    if (fp == NULL)
    {
        printf(" 오류 \n");
        return;
    }
 
    while (1)
    {
        nN = (Book*)calloc(1sizeof(Book));
 
        if (!fread(nN, Data_SIZE, 1, fp))    // 파일의 끝이면
        {
            free(nN);
            break;
        }
 
        else if (head->next == NULL)
        {
            head->next = nN;
        }
        else
        {
            tail->next = nN;
        }
        tail = nN;
        nN->next = NULL;
    }
    fclose(fp);
}
cs


rb모드로 파일을 열고 리스트를 재구성하는 작업을 해준다. 


malloc() 함수는 메모리를 할당후 초기화하지 않기 때문에 출력된 파일을 메모장으로 열어보면 데이터를 알아보기 힘들게 된다.

하지만 문자열의 끝은 NULL로 구분하게 되므로 콘솔환경의 파일 입출력시에는 아무 문제없다.


만약 식별하기 쉬운 파일 데이터를 원하면, 위와 같이 calloc함수를 통해 동적할당하면 된다. (calloc함수는 모든 비트를 0으로 초기화 http://wowcat.tistory.com/3001)


따로 파일을 읽어들이는 메뉴를 구성한다면 노드의 추가전에 남아있는 모든 노드를 제거하는 과정을 추가할 필요도 있겠다.



아래와 같이 리스트의 초기화 함수 호출후 load_File함수를 호출하도록 한다. 종료시에 save_File() 함수를 호출하거나 따로 메뉴를 구성하는 것도 좋겠다.

1
2
3
4
5
6
7
int main()
{    
    list_init();
    load_File();
    (...)
    return 0;
}
cs




공용체 union 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>
 
union smart
{
    int A;    short B;
    int C;    char D;
}obj;
 
int main()
{    
    obj.A = 0x12345678;    obj.B = 0x12345678;
    obj.C = 0x12345678;    obj.D = 0x12345678;
        
    printf("Size of Smart: %d\n"sizeof(union smart));
    printf("%x\n", obj.A);    printf("%x\n", obj.B);
    printf("%x\n", obj.C);    printf("%x\n", obj.D);
    return 0;
}
cs


위 공용체의 size는 4byte


Little Endian

78 

 56

 34

 12


obj.A=12345678   // int A

obj.B=5678        // short B

obj.C=12345678  // int C

obj.D=78           // char D



함수 포인터


: 함수를 가리키는 포인터 


int SoSimple(int num1, int num2) { ....}


위 함수에 대한 함수 포인터 변수 선언

int (*fptr) (int, int);



함수 포인터 변수에 SoSimple 주소값 저장

fptr = SoSimple



이는 fptr(3, 4);    // SoSimple(3, 4)와 동일한 결과


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>
 
void Add(int n1, int n2)
{
    printf("%d + %d = %d \n", n1, n2, n1 + n2);
}
 
int main()
{    
    int num1 = 10, num2 = 20;
 
    void(*fptr)(intint= Add;
    fptr(num1, num2);
    return 0;
}
cs

Output :

10 + 20 = 30



void형 포인터 변수는 어떠한 변수의 주소 값이든 담을 수 있지만(함수의 주소값도)

값의 변경이나 참조를 비롯한 어떤 포인터 연산도 불가

: type 정보가 없기 때문에 당연


1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>
 
void voidFunc(void)
{
    printf("void ptr test\n");
}
 
int main()
{
    void(*fptr)(void= voidFunc;
    fptr();
    return 0;
}
cs

Output :

void ptr test




가변 인자 함수


num = Sum(3, 1, 2, 3);    // 3은 이후에 전달되는 인자의 갯수 (1,2,3)


1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>
 
int Sum(int n, ...)    // 가변 인자에 대한 선언
{
    printf("n=%d \n", n);    
    return 0;
}
 
int main()
{    
    Sum(3123);
    return 0;
}
cs

Output :

n=3


가변 인자 함수의 호출을 통해 전달되는 인자 정보 추출


#include <stdarg.h>

1. 가변인자를 가리킬 수 있는 참조자 선언     : va_list

2. 참조자가 가변인자를 실제 참조                : va_start

3. 참조자를 통해 전달된 정보 추출               : va_arg

4. 참조자가 가변인자를 가리키지 않도록 해제 : va_end


Output :

3+5=2=10



22행 : (vlist, int) 첫번째 인자는 참조자 이름, 두번째 인자는 참조대상의 type


728x90