C++ 파일입출력 fgets
글쓴이: 익명 사용자 / 작성시간: 토, 2017/12/02 - 8:33오후
#include "stdafx.h"
#include <iostream>
#include <time.h>
#include <stdlib.h>
using namespace std;
const int black = 0;
const int red = 1;
const int N = 10000;
struct node
{
int b;
char *key;
struct node *l, *r;
node(int bb, char *k, struct node*ll, struct node *rr)
{
b = bb;
key = k;
l = ll;
r = rr;
};
};
struct node *head, *z, *gg, *g, *p, *x;
void split(char *insert_key);
struct node *rotate(char *insert_key, struct node *y);
class Dict
{
public:
Dict() // 생성자: z와 head 초기화
{
z = new node(black, 0, 0, 0);
z->l = z;
z->r = z;
head = new node(black, 0, 0, z);
}
char* search(char *search_key);
void insert(char *v);
};
char* Dict::search(char *search_key)
{
struct node *x = head->r; // 첫번째 노드를 가리킴
while (x != z) // 비어있는 노드를 만날때까지
{
if (x->key == search_key) // 현재 노드와 탐색 키가 같으면
return x->key; // 현재 노드 반환
// 현재 키 값보다 탐색 키 값이 작으면 현재 포인터 왼쪽으로, 크면 오른쪽으로 이동
x = (x->key > search_key) ? x->l : x->r;
}
return "doesn't exist"; // 탐색 키가 없으면 -1 반환
}
void Dict::insert(char *v)
{
x = head; p = head; g = head;
while (x != z) // 비어있는 노드를 만날때까지
{
gg = g; g = p; p = x;
if ((x->key) && (!strcmp(x->key, v))) // 만약 삽입할 키가 이미 존재한다면 종료
return;
// 만약 삽입할 키가 현재 키보다 작다면 왼쪽으로, 크면 오른쪽으로 이동
if (x->key) x = (strcmp(x->key, v) == 1) ? x->l : x->r;
else x = x->r;
// 만약 왼쪽과 오른쪽 노드 색이 빨간색이라면 분할
if (x->l->b && x->r->b) split(v);
}
x = new node(red, v, z, z); // 새로운 노드 생성
if (p->key == NULL) p->r = x; // 최초의 노드일 경우 헤드의 오른쪽에 삽입
else if (strcmp(p->key, v) == 1) p->l = x; // 맨 오른쪽 노드보다 삽입 키 값이 작으면 삽입 키를 왼쪽에 삽입
else p->r = x; // 맨 오른쪽 노드보다 삽입 키 값이 크면 삽입 키를 오른쪽에 삽입
printf("%s", v);
split(v);
head->r->b = black;
}
void split(char *v)
{
x->b = red; // 만약 왼쪽과 오른쪽 노드 색이 빨간색이라면 분할
x->l->b = black;
x->r->b = black;
if (p->b) // 맨 오른쪽 노드가 빨간색이라면
{
g->b = red;
if ( (strcmp(g->key, v) == 1) != (strcmp(p->key, v) == 1) ) // 빨간색 꺾인 노드 회전
p = rotate(v, g);
x = rotate(v, gg); // 빨간색 일자 노드 회전
x->b = black;
}
}
struct node *rotate(char *v, struct node *y)
{
struct node *gc, *c;
c = (strcmp(y->key, v) == 1) ? y->l : y->r;
if (strcmp(c->key, v) == 1)
{
gc = c->l;
c->l = gc->r;
gc->r = c;
}
else
{
gc = c->r;
c->r = gc->l;
gc->l = c;
}
if (strcmp(y->key, v) == 1) y->l = gc;
else y->r = gc;
return gc;
}
int main()
{
Dict d; // 객체 생성
double start_time;
char *insert_key, *search_key, *result; // 문자열 포인터
insert_key = (char *)malloc(5 * sizeof(char)); // char 5개 크기만큼 동적 메모리 할당
search_key = (char *)malloc(5 * sizeof(char));
result = (char *)malloc(5 * sizeof(char));
FILE *fp1 = fopen("dict.txt", "r"); // 읽기 전용으로 키 값 불러옴
FILE *fp2 = fopen("search_key.txt", "r");
if (fp1 == NULL || fp2 == NULL)
{
cout << "파일 open 실패." << endl;
return 0;
}
start_time = clock();
while (!feof(fp1))
{
fgets(insert_key, 6, fp1);
d.insert(insert_key); // key를 트리에 삽입
}
cout << "레드-블랙 트리의 삽입 시간: " << clock() - start_time << endl;
start_time = clock();
while (!feof(fp2))
{
fgets(search_key, 6, fp2); // 5 문자씩 불러와서 search_key에 저장
strcpy(result, d.search(search_key)); // search_key 탐색
if (strcmp(result, search_key)) // 탐색 키가 없거나 잘못된 값을 찾으면
{
cout << "탐색 오류: " << search_key; // 오류 출력
return 0;
}
}
cout << "레드-블랙 트리의 탐색 시간: " << clock() - start_time << endl;
fclose(fp1);
fclose(fp2);
return 0;
}main의 첫번째 while문 속 fgets에 대한 질문입니다.
디버깅으로 확인해본 결과
첫 루프를 수행하면 첫번째 insert_key가 head->r에 들어가고,
두번째 루프에서 fgets만 수행하고 insert는 하기 전인데도 불구하고 inserted_key가
head->r에 덮어씌워져 첫번째 insert_key가 사라집니다...
아무리 고민하고 디버깅을 해봐도 왜 그런지 이유를 알 수가 없습니다..
txt파일도 함께 첨부합니다. 제발 고수님들 도와주세요..ㅜㅠㅠㅠ
File attachments:
| 첨부 | 파일 크기 |
|---|---|
| 2.18 MB | |
| 2.18 MB |
Forums:

지극히 당연한 현상입니다.
지극히 당연한 현상입니다.
Dict 자료구조 안의 key가 insert_key와 똑같은 포인터가 되잖아요. 즉 같은 메모리를 가리킨다는 말이지요.
insert_key가 가리키는 문자열을 바꿔도 자료구조 안의 값은 그대로 유지되기를 바란다면, 사본을 만들어 저장해야지요.
답변 감사합니다.
그럼 트리의 사본을 만들어야한다는건가요..?
댓글 달기