Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Построение словаря по файлу, Построение словаря по файлу 
V
    Опции темы
viluyr
  Дата 7.1.2007, 19:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 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
PM MAIL   Вверх
Maxx
Дата 18.1.2007, 08:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 19
Регистрация: 2.11.2006

Репутация: нет
Всего: нет



Алгоритм удаления какой? 
PM MAIL   Вверх
viluyr
Дата 18.1.2007, 09:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 12
Регистрация: 5.1.2007

Репутация: нет
Всего: нет



спасибо я уже все зделал сасм.
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0470 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.