일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 소니
- Visual Studio 2005
- PostgreSQL
- 델파이
- Visual Basic
- 시리얼 통신
- SDK
- 파이어버드
- winsock
- dll
- 입문
- WIN32 SDK
- SQL
- VB.NET
- 문자열
- vb
- 설치
- 기초
- 데이터베이스
- 인스톨
- c#
- MFC
- Delphi
- MySQL
- 초보
- Firebird
- 셋업
- 예제
- xml
- 파라미터
- Today
- Total
프로그래밍 노트
[c]리스트 구조 파일에 쓰고 읽기 본문
리스트 구조를 파일에 쓰고 읽는 예제이다.
나는 머리가 안좋아서 그런지 리스트 구조가 깨끗하게 이해가 안된다. -.-;;
// 리스트 구조 파일
#define DEBUG
#include <stdio.h>
#include <stdlib.h>
// 키
// --------------------------------------------------
typedef int key;
// 키 입력
int input_key(char *szDisp, key *pKey) {
printf("%s", szDisp);
if(scanf("%d", pKey) != 1)
return 0; // 입력 에러
return (*pKey > 0); // 입력 코드 양수 체크
}
// 키 비교
int compare_key(key KeyA, key KeyB) {
return (KeyA - KeyB);
}
// 키 표시
void print_key(key KeyDisp) {
printf("%d", KeyDisp);
}
// 데이터
// --------------------------------------------------
typedef struct data {
key code;
char name[20];
long Score[2];
} data;
// 데이터 입력
int input_data(char *szDisp, data *pData) {
printf("%s", szDisp);
if(input_key("코드 번호 : ", &pData->code) == 0)
return 0; // 부정한 코드 입력
printf("이름 : ");
if(scanf("%s", pData->name) != 1)
return 0;
printf("국어 점수 : "); // 입력 에러
if(scanf("%d", &pData->Score[0]) != 1)
return 0; // 입력 에러
printf("산수 점수 : ");
return (scanf("%d", &pData->Score[1]) == 1);
}
// 데이터 비교
int compare_data(data *pDataA, data *pDataB) {
return compare_key(pDataA->code, pDataB->code);
}
// 데이터 표시
void print_data(data *pData) {
print_key(pData->code);
printf(" %s\t%d\t%d\n", pData->name,
pData->Score[0], pData->Score[1]);
}
// 노드
// --------------------------------------------------
typedef struct node {
data data;
long next;
} node;
// 노드 입력
int input_node(char *sDisp, node *pNode) {
if(input_data(sDisp, &pNode->data) == 0)
return 0; // 부정한 입력
pNode->next = 0;
return 1;
}
// 노드 비교
int compare_node(node *pNodeA, node *pNodeB) {
return compare_data(&pNodeA->data, &pNodeB->data);
}
// 노드 표시
void print_node(node *pNode) {
print_data(&pNode->data);
}
// 노드 읽기
int read_node(FILE *fp, long pos, node *pNode) {
if(fseek(fp, pos, SEEK_SET) != 0)
return 0; // 검색 에러
return (fread(pNode, sizeof(node), 1, fp) == 1);
}
// 노드 쓰기
int write_node(FILE *fp, long pos, node *pNode) {
if(fseek(fp, pos, SEEK_SET) != 0)
return 0; // 검색 에러
return (fwrite(pNode, sizeof(node), 1, fp) == 1);
}
// 리스트
// --------------------------------------------------
// 리스트 루트 포인터 읽기
int read_root(FILE *fp, long *p) {
if(fseek(fp, 0L, SEEK_SET) != 0)
return 0; // 검색 에러
return (fread(p, sizeof(long), 1, fp) == 1);
}
// 리스트 루트 포인터 쓰기
int write_root(FILE *fp, long *p) {
if(fseek(fp, 0L, SEEK_SET) != 0)
return 0; // 검색 에러
return (fwrite(p, sizeof(long), 1, fp) == 1);
}
// 미사용영역 포인터 읽기
int read_free(FILE *fp, long *p) {
if(fseek(fp, sizeof(long), SEEK_SET) != 0)
return 0; // 검색 에러
return (fread(p, sizeof(long), 1, fp) == 1);
}
// 미사용영역 포인터 쓰기
int write_free(FILE *fp, long *p) {
if(fseek(fp, sizeof(long), SEEK_SET) != 0)
return 0; // 검색 에러
return (fwrite(p, sizeof(long), 1, fp) == 1);
}
// 리스트에 새 노드 추가
int make_list(FILE *fp, node *p) {
long pos, free_area, here;
node x, y;
// 루트 포인터 읽기
if(read_root(fp, &pos) == 0) return 0;
// 미사용영역 포인터 읽기
if(read_free(fp, &free_area) == 0) return 0;
// 미사용영역이 없을 때
if(free_area == 0) {
// 파일 마지막에 추가
if(fseek(fp, 0L, SEEK_END) != 0)
return 0;
here = ftell(fp); // 파일 마지막 위치 얻기
}
else { // 미사용영역이 있을 때
here = free_area; // 최초의 미사용영역 사용
// 최초 미사용영역 읽기
if(read_node(fp, here, &x) == 0)
return 0;
free_area = x.next; // 다음 미사용영역 설정
// 미사용영역 포인터 쓰기
if(write_free(fp, &free_area) == 0)
return 0;
}
if(pos == 0) { // 리스트에 노드가 없을 때
pos = here; // 입력 데이터의 노드를 루트로 함
// 루트 포인터 쓰기
if(write_root(fp, &pos) == 0)
return 0;
// 로투 노드 등록
return write_node(fp, here, p);
}
// 최초 노드 읽기
if(read_node(fp, pos, &x) == 0)
return 0;
// 루트로서 등록할 때
if(compare_node(p, &x) < 0) {
pos = here; // 루트 지정
// 루트 포인터 변경
if(write_root(fp, &pos) == 0)
return 0;
// 루트가 다음 노드를 포인터로
p->next = x.next;
// 루트의 노드 등록
return write_node(fp, here, p);
}
while(x.next != 0) { // 최후의 노드 검색
// 다음 노드 읽기
if(read_node(fp, x.next, &y) == 0)
return 0;
// 삽입 위치 조사
if(compare_node(p, &y) < 0)
break;
pos = x.next; // 1개씩 뒤로
x = y; // 1개씩 뒤로
}
p->next = x.next; // 등록 노드 삽입
x.next = here; // 새 노드 추가
// (*)포인터 쓰기
if(write_node(fp, pos, &x) == 0)
return 0;
// 새 노드 쓰기
return write_node(fp, here, p);
}
// 리스트로부터 노드 삭제
int delete_list(FILE *fp, key *key) {
long pos, free_area, here;
node d, x, y;
int ret;
d.data.code = *key; // 키 값을 갖는 노드 작성
// 루트 포인트 읽기
if(read_root(fp, &pos) == 0)
return 0;
if(pos == 0) // 리스트에 노드가 없을 때
return 2;
// 최초 노드 읽기
if(read_node(fp, pos, &y) == 0)
return 0;
// 노드가 없을 때
if((ret = compare_node(&y, &d)) > 0)
return 2;
if(ret == 0) { // 노드가 검색됬을 때
here = pos; // 삭제할 노드 어드레스
pos = y.next; // 루트에 다음 노드 연결
// 루트의 포인터 쓰기
if(write_root(fp, &pos) == 0)
return 0;
}
else { // 노드를 다시 검색
for( ; ; ) {
if(y.next == 0) // 노드가 검색안됨
return 2;
x = y; // 하나 전의 노드를 보존
here = x.next;
// 다음 노드 읽기
if(read_node(fp, here, &y) == 0)
return 0;
// 위치 조사
if((ret = compare_node(&d, &y)) < 0)
return 2;
if(ret == 0) // 검색됨
break;
pos = here; // 다시 검색
}
x.next = y.next; // 노드 삭제
// (*)포인터 쓰기
if(write_node(fp, pos, &x) == 0)
return 0;
}
// 미사용 영역의 포인터 읽기
if(read_free(fp, &free_area) == 0)
return 0;
y.next = free_area; // 미사용 영역 연결
// (*)포인터 쓰기
if(write_node(fp, here, &y) == 0)
return 0;
free_area = here; // 새로운 미사용 영역 삽입
// 미사용 영역의 포인터 쓰기
return write_free(fp, &free_area);
}
// 검색하기
node *search_list(FILE *fp, key *key) {
static node x;
node y;
long pos;
int ret;
y.data.code = *key; // 키 값을 갖는 노드 만들기
// 루트 포인터 읽기
if(read_root(fp, &pos) == 0)
return NULL;
while(pos != 0) { // 노드가 없으면 종료
// 다음 노드 읽기
if(read_node(fp, pos, &x) == 0)
break;
// 검색 됨
if((ret = compare_node(&x, &y)) == 0)
return &x;
if(ret >= 0) // 존재 안함
break;
pos = x.next; // 다음 노드 검색
}
return NULL; // 검색 안됨
}
// 리스트의 노드를 처음부터 순서대로 표시
int print_list(FILE *fp) {
long pos;
node x;
// 루트 포인터 읽기
if(read_root(fp, &pos) == 0)
return 0;
while(pos != 0) {
// 다음의 노드 읽기
if(read_node(fp, pos, &x) == 0)
return 0;
print_node(&x);
pos = x.next;
}
return 1;
}
// 리스트 디스크에 쓰기
// --------------------------------------------------
char *filename;
FILE *fp;
// 초기화
#pragma argsused
void initialize(int argc, char *argv[]) {
long dummy = 0;
#if defined(DEBUG)
filename = "test.dat";
#else
if(argc > 2) {
printf("파라미터가 너무 많아n");
exit(1);
}
if(argc < 2) {
printf("파라미터가 없네\n");
exit(2);
}
filename = argv[1];
#endif
if((fp = fopen(filename, "r+b")) == NULL) {
if((fp = fopen(filename, "w+b")) == NULL) {
printf("파일 \"%s\" 을 열 수 없네\n", filename);
exit(3);
}
// 노드 포인터 초기화
fwrite(&dummy, sizeof(long), 1, fp);
// 미사용영역 포인터 초기화
fwrite(&dummy, sizeof(long), 1, fp);
}
}
// 종료
void terminate(void) {
fclose(fp);
}
// 메뉴
int menu(void) {
int k, end_flag = 0;
while(end_flag == 0) {
printf("\n"
"--------------------\n"
" (1) 데이터 입력\n"
" (2) 데이터 검색\n"
" (3) 데이터 삭제\n"
" (4) 데이터 표시\n"
" (5) 종료\n"
"--------------------\n"
"메뉴 선택 : ");
switch(scanf("%d", &k)+1) {
case 0: // EOF 종료 취급
k = 5;
end_flag = 1;
break;
case 1: // 부정 데이터 재입력
rewind(stdin);
break;
case 2:
if(1 <= k && k <= 5)
end_flag = 1;
break;
}
}
return k;
}
void process(void) {
int end_flag = 0;
node x, *p;
key key;
while(end_flag == 0) {
switch(menu()) {
case 1: // 입력
if(input_node("\n입력 취소 >> 0\n",
&x) != 0)
make_list(fp, &x);
//D(print_list(fp);)
print_list(fp);
break;
case 2: // 검색
if(input_key("코드 번호 : ", &key) == 0)
printf("잘못된 코드 번호\n");
else {
if((p = search_list(fp, &key)) == NULL)
printf("없음n");
else
print_node(p);
}
break;
case 3: // 삭제
if(input_key("코드 번호 : ", &key) == 0)
printf("잘못된 코드 번호\n");
else {
switch(delete_list(fp, &key)) {
case 0:
printf("파일 입출력 에러\n");
break;
case 1:
print_list(fp);
break;
case 2:
printf("없음\n");
break;
}
}
break;
case 4: // 표시
print_list(fp);
break;
case 5: // 종료
end_flag = 1;
break;
}
}
}
int main(int argc, char *argv[]) {
initialize(argc, argv);
process();
terminate();
return 0;
}