본문 바로가기
프로그래머의 길/알고리즘

이중 연결 리스트로 구현한 텍스트 뷰어

by 하늘아래. 2007. 3. 28.
반응형

#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>

#define PGUP 0x4800
#define PGDN 0x5000
#define ESC  27
#define PAGESIZE 25              // 한 페이지에 보여질 줄 수

typedef struct list *linked_list;

struct list
{
 char *buf;
 linked_list prev;          // 이전 포인터
 linked_list next;          // 다음 포인터
};

linked_list head, tail;          // 시작과 끝 노드
int total, now;                   // 전체 노드와 현재 노드
char filename[13];

void gotoxy(int, int);

void init_linked_list(void)
{
 head = (linked_list)malloc(sizeof(struct list));
 tail = (linked_list)malloc(sizeof(struct list));

 head->next = tail;
 head->prev = head;
 tail->next = tail;
 tail->prev = head;
}

void load_file(void)
{
 FILE *fp;
 char buf[256];
 linked_list t;
 if((fp = fopen(filename, "rt")) == NULL)
 {
  printf("\n 에러 : 파일 열기 실패.\n");
  exit(1);
 }
 total = 0;
 printf("\n File 불러오는 중...\n");
 while(!feof(fp))
 {
  fgets(buf, 255, fp);
  if(strlen(buf) > 100)     // 100이상의 문자열을 짤림
   buf[100] = 0;
  else
   buf[strlen(buf)-1] = 0;

  if((t = (linked_list)malloc(sizeof(struct list))) == NULL)
  {
   printf("\n 에러 : 노드 만들 메모리가 부족합니다.\n");
   exit(1);
  }
  if((t->buf = (char *)malloc(strlen(buf))) == NULL)
  {
   printf("\n 에러 : 버퍼 만들 메모리가 부족합니다.\n");
   exit(1);
  }

  strcpy(t->buf, buf);
  t->prev = tail->prev;
  t->next = tail;
  tail->prev->next = t;
  tail->prev = t;
  total++;
 }
 fclose(fp);
}

void move_linked_list(int d, linked_list *t)
{
 if(d<0)
  while(d++ != 0 && (*t)->prev != head)
  {
   *t = (*t)->prev;
   now--;
  }
 else
 {  
  if ((int)now/PAGESIZE+1 == (int)total/PAGESIZE+1)
  return;

  while(d-- != 0 && (*t)->next != tail)
  {
   *t = (*t)->next;
   now++;
  } 
 }
}

void show_header(void)
{
 gotoxy(1, 1);
 printf("TVIEW : %-12s  위치 : %6d of %6d", filename, (int)now/PAGESIZE+1, (int)total/PAGESIZE+1);
}

void show_page(linked_list t)
{
 int i=0;
 
 if(now == total)
  return;

 system("cls");
 show_header();
 gotoxy(1, 3);
 while(i++ < PAGESIZE && t != tail)
 {  
  printf("%-100s\n", t->buf);
  t = t->next;
 }
}

void key_proc(void)
{
 linked_list t;
 int key;
 now = 1;
 t = head->next;
 show_page(t);
 while((key = getch()) != ESC)
 {
  if(key == 224)
  {
   key = getch();
   key <<= 8;
  }
  switch(key)
  {
  case PGUP:
   move_linked_list(-PAGESIZE, &t);
   show_page(t);
   break;
  case PGDN:
   move_linked_list(+PAGESIZE, &t);
   show_page(t);
   break;

  }
 }
 system("cls");
}

void main(int argc, char **argv)
{
 if(argc<2)
 {
  printf("\n사용법 : TVIEW <파일명.확장명>\n");
  exit(0);
 }
 strcpy(filename, "test.cpp");//argv[1]);
 init_linked_list();
 load_file();
 key_proc();
 printf("\n프로그램이 끝났습니다...\n");
}

void gotoxy(int x, int y)
{
 COORD Pos = {x-1, y-1};
 SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), Pos);
}

반응형