에 의해 생성 된 트리를 엉망으로되어있는 tsearch/tfind/twalk 기본적으로 정렬하고 문서에 고유 한 단어를 계산하는 프로그램에서 search.h 라이브러리 기능을합니다. 이후 문서에 얼마나 많은 단어가 있는지 모르겠으므로 malloc을 사용하여 처음에는 모든 단어를 담고있는 배열에 일정량의 메모리를 할당 한 다음 realloc을 사용하여 그것을 채운다면 더 크게 만듭니다. . 그러나 realloc은 tsearch에 의해 관리되는 트리를 손상시키고 명백히 정크 노드를 반환하기 시작하거나 노드의 내용이 손상됩니다.realloc을 내가 사용하고 tsearch
구조체 정의 :
struct word {
char word[MAX_MTEXT];
int occur;
};
struct mymsg {
long mtype;
char mtext[MAX_MTEXT];
int occur;
};
아래의 코드는 모든 자식 프로세스 번호 및 메시지 큐에서 말씀을 받고 다루는 다른 물건이 있습니다
f = 1;
i = 0;
words_entered = 0;
entry = (struct word *) malloc(words_allocated * sizeof(struct word));
while(f) {
if (msgrcv(m_key, &mymsg, sizeof(struct mymsg), (long) getpid(), 0) == -1) {
perror("recieve");
exit(EXIT_FAILURE);
}
//printf("%s recieved\n",mymsg.mtext);
if (mymsg.mtext[0] == '\0') {
//printf("term recv\n");
f = 0;
}
else {
//printf("mtext = %s\n",mymsg.mtext);
memcpy(&entry[i].word,&mymsg.mtext,MAX_MTEXT);
//printf("entry = %s\n",entry[i].word);
entry[i].occur = 1;
//printf("%s entered\n",entry[i].word);
words_entered++;
if (words_entered == words_allocated) {
printf("About to realloc\n\n");
twalk (root, action);
words_allocated = words_allocated *2;
entry = (struct word *) realloc(entry,(size_t) words_allocated * sizeof(struct word));
printf("After realloc\n\n");
twalk (root, action);
}
ptr = tfind(&entry[i],&root,compare);
if (ptr == NULL) {
//printf("null\n");
ptr = tsearch(&entry[i],&root,compare);
//printf("%s added to tree\n",(*ptr)->word);
}
else {
(*ptr)->occur++;
}
i++;
//printf("check\n");
}
}
twalk (root, action);
mymsg.mtype = ret_id;
mymsg.mtext[0] = '\0';
mymsg.occur = 0;
if (msgsnd(m_key, &mymsg, sizeof(mymsg)-sizeof(long), 0) == -1) {
perror("send");
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
이 코드를 도보로 호출 된 작업 :
void action(const void *nodep, VISIT value, int level) {
struct word *w = *((struct word **) nodep);
struct mymsg mymsg;
switch (value) {
case leaf:
case postorder:
printf("%s: %i, level %i\n",w->word, w->occur, level);
mymsg.mtype = ret_id;
strcpy(mymsg.mtext,w->word);
//printf("%s vs %s\n",w->word,mymsg.mtext);
mymsg.occur = w->occur;
if (msgsnd(m_key, &mymsg, sizeof(mymsg)-sizeof(long), 0) == -1) {
perror("send");
exit(EXIT_FAILURE);
}
break;
default:
break;
}
return;
}
다음은 초기 할당량을 실행 한 결과입니다. on of 5 :
About to realloc
each: 1, level 1
is: 1, level 0
therefore: 1, level 2
translator: 1, level 1
After realloc
Ð3³: 1, level 1
is: 1, level 0
therefore: 1, level 2
translator: 1, level 1
About to realloc
for: 1, level 2
his: 1, level 1
$p : 158343352, level 2
is: 1, level 0
own: 1, level 3
portion;: 1, level 2
responsible: 1, level 3
therefore: 1, level 1
p p rlator: 1, level 2
After realloc
for: 1, level 2
his: 1, level 1
$p : 158343352, level 2
is: 1, level 0
own: 1, level 3
portion;: 1, level 2
responsible: 1, level 3
therefore: 1, level 1
p p rlator: 1, level 2
나는 tsearch는 NULL을 반환 할 수 있다고 생각하지 않습니다. 항상 일치하는 항목을 반환하거나 하나를 만듭니다. 단일 단어 요소를 할당하려면 코드 작성 방법, 구체적으로 변수를 작성하고 참조하는 방법에 대해 명확하지 않습니다. 배열에 있다면 인덱스 할 수 있지만 각 단어마다 동적으로 새 변수를 만들 수는 없습니다. 마지막 하나에 관해서는 ... 그래서 새로운 배열을 malloc 할 것이고 이전 배열을 통해 새로운 원소를 추가 한 다음 이전 원소를 해제 할 것입니다. – HamHamJ
"항목을 만들어야하고 프로그램의 공간이 부족한 경우 NULL이 반환됩니다." - 문서에서 직접 – FRob