Новичок
Профиль
Группа: Участник
Сообщений: 12
Регистрация: 5.1.2007
Репутация: нет Всего: нет
|
у меня ошибка в проге.....не понимаю из-за чего,может кто сталкивался и знает как помочь? Суть в следующем: программа строит дерево по файлу - первое слово за корень, а потом чтоб построить словарь в алфавитном порядке сравнивает если слово стоит раньше по алфавиту, то спускает его налево, есил после него то направо, потом из этого дерева строится второе - из самого левого узла. Ошибка в ---> первое дерево(любое хоть первое хоть второе) функция удаляет на ура, а вот со вторым вызывает ошибку в free(pnode->data)....вот код | Код | #include <stdio.h> #include <stdlib.h> #include <stdarg.h> #include <string.h> #include <conio.h> #define STR_LENGTH 255 #define FILE_NAME_LENGTH 300
// Структура для описания узла дерева
typedef struct NODE_ { void* data; int counter; /* сщётчик употребления слова */ struct NODE_* left; struct NODE_* right; } NODE;
// Структура для описания дерева
typedef struct { NODE* root; // указатель на корень int count; // число узлов в дереве // сюда можно добавить другие поля, если нужно } TREE; TREE* CreateTree(void) { // Создать (пустое) дерево
TREE* r; if( (r = malloc(sizeof(TREE))) == NULL) return NULL; // взять память для корня r->root = NULL; // инициализировать r->count = 0; // корень
return r; }
int InsertNode( // Добавить узел в дерево TREE* p, // указатель на дерево void* item, // указатель на добавляемый элемент int (*fcmp)(void*, void*) // указатель на функцию сравнения элементов, // она возвращает значения -1, 0, +1 ) // Возвращаемое значение 1 - элемент успешно вставлен // 2 - такой элемент в дереве уже есть // 0 - элемента в дереве нет, но он не вставлен // из-за нехватки памяти
{ NODE *node, **anode;
node = p->root; // текущий узел anode = &p->root; // адрес текущего узла for(;;) if(node == NULL) // если текущего узла нет, то создать его { if((node = *anode = malloc(sizeof(*node))) != NULL) { // узел создан, нужно node->data = item; // 1) связать его с данными node->counter = 1; // 2) счётчик встречаемости приравниваем 1 node->left = node->right = NULL; // 3) указать, что после него ничего нет p->count++; // 4) увеличить счетчик узлов return 1; } else return 0; // нет места для очередного узла } else switch( fcmp(item, node->data) ) { case 0: node->counter++; // повторяющееся слово - наращиваем счётчик return 2; // ничего делать не надо
case 1: anode = &node->right; // пойти направо node = node->right; break;
case -1: anode = &node->left; // пойти налево node = node->left; break; }
}
int intcmp(void* a, void* b) // Функция для сравнения целых { // возвращаемое значение 1 - число а больше числа б if( *(int*)a > *(int*)b) // -1 - число а меньше либо = числу б return 1; // 0 - нет элементво для сравнения else if( (*(int*)a <=*(int*)b) ) return -1; else return 0; }
int NodeCntCmp(void* a1, void* b1)// Функция для сравнения значения со значением счетчика, // присоединенного к узлу { void *a, *b; a = &(((NODE*)a1)->counter); b = &(((NODE*)b1)->counter); return intcmp(a, b);
}
int wordcmp(void* a, void* b)// Функция для сравнения слов { return strcmp( (char*)a, (char*)b ); }
int NodeWordCmp(void* a1, void* b1)// Функция для сравнения слов, присоединенных к узлам { void *a, *b; a = ((NODE*)a1)->data; b = ((NODE*)b1)->data; return wordcmp( a, b ); }
int InsertNode2( // Добавить узел в дерево TREE* p, // указатель на дерево NODE* node1 // указатель на узел в первом дереве, откуда берется добавляемый элемент ) { NODE *node, **anode;
node = p->root; // текущий узел anode = &p->root; // адрес текущего узла while (1>0) { if(node == NULL) // если текущего узла нет, то создать его { if((node = *anode = malloc(sizeof(*node))) != NULL) { // узел создан, нужно node->data = node1->data; // 1) связать его с данными из первого дерева node->counter = node1->counter; // 2) связываем счёчик со счётчиком из первого дерева node->left = node->right = NULL; // 3) указать, что после него ничего нет p->count++; // 4) увеличить счетчик узлов 2-ого дерева return 1; } else printf("net mesta dlya yzla"); return 0; // нет места для очередного узла } else { switch( NodeCntCmp(node1, node) ) //node1 - на данном этапе это уже счётчик употребеления слова { case 0: break; case -1: anode = &node->right; // пойти направо node = node->right; break;
case 1: anode = &node->left; // пойти налево node = node->left; break; } } } } TREE* WalkAndBuildNewTree( NODE* pnode, TREE* ptree2) { // Рекурсивный обход дерева словаря (первого дерева) и создание другого дерева для сортировки по // значениям счетчика слов
if(pnode == NULL)return ptree2; WalkAndBuildNewTree(pnode->left, ptree2); if(InsertNode2(ptree2, pnode) == 0) return NULL; WalkAndBuildNewTree(pnode->right, ptree2); return ptree2; }
void WalkAndPrintStr( NODE* pnode, FILE* fp) { // Рекурсивный обход дерева и печать данных, связанных с узлами, // в строковом формате
if(pnode == NULL)return; WalkAndPrintStr(pnode->left, fp); // печать данных, связанных с левым поддеревом fprintf(fp, "%4d %s\n",pnode->counter,pnode->data); // печать данных, связанных с узлом WalkAndPrintStr(pnode->right, fp); // печать данных, связанных с правым поддеревом }
void WalkAndPrintTreeStr( TREE* ptree, FILE* fp)
{ // Обход дерева и печать данных в строковом формате
WalkAndPrintStr(ptree->root, fp); }
void WalkAndPrintTreeStr2( TREE* ptree2, FILE* fp)
{ // Обход дерева и печать данных в строковом формате
WalkAndPrintStr(ptree2->root, fp); }
void Delete(NODE* p) { // Рекурсивное уничтожение поддерева // Информация,связанная с узлами через поле data, остается. if(p==NULL) return; Delete(p->left); // уничтожить левое поддерево Delete(p->right); // уничтожить правое поддерево free(p); // уничтожить указатель }
void DeleteTree(TREE* p) { // Уничтожить корень
Delete(p->root); free(p); }
void WalkAndDeleteData( NODE* pnode) { // Рекурсивный обход дерева и уничтожение данных, связанных с узлами
if(pnode == NULL)return; WalkAndDeleteData(pnode->left); // ликвидация данных, связанных с левым поддеревом free(pnode->data); // ликвидация данных, связанных с узлом (слово) WalkAndDeleteData(pnode->right); // ликвидация данных, связанных с правым поддеревом }
void main (int argc, char *argv[]) { char s[STR_LENGTH+1]; // место для строки
char separators[] = " ,.?:;+-*/()[]{}\\\"\n\r\t!123456789_><^#%&"; // разделители слов
char *c, *t; FILE *fp, *fdict, *fchas; char fname[40]; TREE *p3,*p4; static char InputFileName[FILE_NAME_LENGTH]; static char DictFileName[FILE_NAME_LENGTH]; static char ChasFileName[FILE_NAME_LENGTH]; int temp=0; int len=0; switch(argc) {
case 1: //не введены никакие параметры работы программы
printf("V komandnoi stroke ne vvedeno imya faila\n"); printf("vvedite imya vxodnogo faila :"); scanf("%s", InputFileName);
strcat(DictFileName,"dict.txt"); // здесь должны быть твои выходные файлы printf("Fail yporyado4enniy po alfavity: %s",DictFileName); //вместо printf
strcpy(ChasFileName,"chas.txt"); printf("\nFail yporyado4enniy pochastotno: %s\n",ChasFileName); break;
case 2: strcpy(InputFileName, argv[1]); //означает, что входной файл ты указал в командной строке printf("\nVhodnoi fail : %s",InputFileName); strcat(DictFileName,"dict.txt"); printf("\nFail yporyado4enniy po alfavity: %s",DictFileName);
strcpy(ChasFileName,"chas.txt"); printf("\nFail yporyado4enniy pochastotno: %s\n",ChasFileName); break;
case 3: strcpy(InputFileName, argv[1]); printf("\nVhodnoi fail: %s",InputFileName); strcpy(DictFileName, argv[2]);//означает, что и имя одного из выходных файлов тоже указано printf("\nFail yporyado4enniy po alfavity: %s",DictFileName);
strcpy(ChasFileName,"chas.txt"); printf("\nFail yporyado4enniy pochastotno: %s\n",ChasFileName);
break;
case 4: strcpy(InputFileName, argv[1]); printf("\nVhodnoi fail: %s",InputFileName);
strcpy(DictFileName, argv[2]); printf("\nFail yporyado4enniy po alfavity: %s",DictFileName);
strcpy(ChasFileName, argv[3]); printf("\nFail yporyado4enniy pochastotno: %s\n",ChasFileName); break;
default: printf("mnogo parametrov");
} //закончился switch
printf("\n********************Postroenie Slovarya********************\n"); printf("\nVvedite imya vhodnogo faila? : "); scanf("%s", fname);
if( (fp=fopen(fname, "rt")) == NULL) { printf("\n Nevozmojno otkrit fail %s", fname); exit(1); }
if( (fdict = fopen("dict.txt", "wt")) == NULL) { printf("\nNevozmojno otkrit fail %s", "dict.txt"); exit(1); } if( (fchas = fopen("chas.txt", "wt")) == NULL) { printf("\nNevozmojno otkrit fail %s", "chas.txt"); exit(1); }
p3 = CreateTree(); // создать пустое дерево
while(!feof(fp)) // цикл по строкам файла { fgets(s, STR_LENGTH, fp); // взять строку из файла
c = strtok(s, separators); // получить указатель на следующее слово
while(c != NULL ) // цикл по словам в строке { t = malloc(strlen(c)+1); // отвести память для этого слова strcpy(t, c); // копировать слово в память
switch(InsertNode( p3, t, wordcmp)) // построить очередной узел дерева { case 1 :/* printf("\nЭлемент %s включен", temp);*/ break; case 2 : //printf("\nЭлемент %s не включен, он уже есть", temp); free(t); break; case 0 :/* printf("\nЭлемент %s не включен, нет места", word[i]);*/ free(t); break; } // switch
c = strtok(NULL, separators); // получить указатель на следующее слово
} // while( c != NULL)
} // конец цикла по строкам
p4 = CreateTree(); WalkAndBuildNewTree( p3->root, p4); WalkAndPrintTreeStr ( p3,fdict ); WalkAndPrintTreeStr2( p4,fchas );
printf("\nSlovar` faila postroen %s i zapisan v fail dict.txt", fname); printf("\nSlovar` faila postroen %s i zapisan v fail chas.txt", fname);
fclose(fp); fclose(fchas); fclose(fdict);
WalkAndDeleteData( p4->root ); // уничтожить данные, связанные с деревом DeleteTree(p4); // уничтожить дерево WalkAndDeleteData( p3->root ); // когда удаляет вот тут, то ошибка в free(pnode->data); DeleteTree(p3); printf("programma yspeshno zavershena!"); }
|
Mayk: снёс красный цветЭто сообщение отредактировал(а) Mayk - 18.1.2007, 10:00
|