2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




 
 Работа с просматриваемой таблицей: нужна помощь!
Сообщение02.06.2012, 18:31 
Написала программу для работы с просматриваемой таблицей по запросам оператора. И таблица, и информация, относящаяся к элементу таблицы, хранятся в основной памяти. Код:

Код:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct

{
   int busy;
   char key[8];
   char *info;
}Item;

Item* Table(int SIZE)
{
   int i;
   Item *mass=(Item*)malloc(SIZE*sizeof(Item));
   for(i=0; i<SIZE; i++)
      mass[i].busy=0;
   return mass;
}

void newelt(char key[8], char *info, Item *mass, int SIZE)
{
   int n=-1,i;
   for (i=0; i<SIZE; i++)
   {
      if (mass[i].busy==0) n=i;
      if (strcmp(mass[i].key,key)==0)
      {
         printf("Error: key is not unique\n");
         break;
      }
   }
   if (n==-1) printf("Error: incorrect number of elements\n");
   else
   {
         strncpy(mass[n].key,key,8);
         mass[n].info=info;
         mass[n].busy=1;
   }
}
void del(char key1[8], char key2[8], Item *mass, int SIZE)//удаляемый диапазон в лексико-графическом порядке
{
   int n=0,i;   
   for (i=0; i<SIZE; i++)
   {
      if ((strcmp(key1,mass[i].key)>=0)&&(strcmp(key2,mass[i].key)<=0))
      {
            mass[i].busy=0;
            n=n++;
            free(mass[i].info);
      }
   }
   printf("%i elements are deleted\n",n);
}
void find(char key1[8], char key2[8], Item *mass, Item *mass1,int SIZE)
{
   int n=0,i;   
   mass1=Table(SIZE);
   for (i=0; i<SIZE; i++)
   {
      if ((strcmp(key1,mass[i].key)>=0)&&(strcmp(key2,mass[i].key)<=0)&&(mass[i].busy==1)) //key1 - верхняя граница.
      {
         newelt(mass[i].key,mass[i].info,mass1,SIZE);
         n=n++;
      }
   }
   printf("%i elements are founded\n",n);
   prt(mass1, SIZE);
}

char *entKey()
{
   char *a=(char*)malloc(1000*(sizeof(char)));
   char key[8];
   int f=1;
   do
   {
      printf("enter key\n");
      scanf("%s",a);
      if (strlen(a)!=8)
         {
            printf("error: illegal key\n");
            f=0;
         }
   }
   while(f==0);
   strncpy(key,a,8);
   free(a);
   return key;
}
char* schit()//возвращение указателя на строку, размер которой заранее неизвестен (считывание вводимой строки)
{
   int i=1;//кол-во симвролов, на которое выделена память вне цикла
   char *a;//задаем указатель на ячейку памяти, где лежат данные типа char
   a=(char*)malloc(sizeof(char));//выделение памяти на один символ
   /*a=0;*/
   do
   {
      i=strlen(a);
      a=(char*)realloc(a,strlen(a)+1);//довыделение памяти
      *(a+i)=getch();//считывание символа,смещенного на i ячеек относительно начала
      *(a+i+1)=0;//конец строки, либо присваивание значения следующей ячейки
   }
   while (*(a+i)!=13);//13 - код enter'а (считывание до тех пор, пока не нажмем enter)
   a[i]=0;//конец строки
   return a;//возвращение адреса строки (а - указатель)
}
char *entInfo()
{
   char *a=schit();
   printf("enter info: \n");
   scanf("%s",a);      
   return a;
}

int prt(Item *mass, int SIZE)
{
   int i;
   for(i=0; i<SIZE; i++)
   {
      if (mass[i].busy==1)
      printf("%s  %s\n",mass[i].key,mass[i].info);
   }
}

int main()
{
   char key[8], key1[8], key2[8], *info;
   char* a=(char*)malloc(1000*sizeof(char));
   const int SIZE = 5;   



   Item *mass=Table(SIZE);
   Item *mass1=Table(SIZE);
   do
   {
      printf("Choose operation:\n 1. Add new element\n 2. Delete element\n 3. Find element\n 4. Print the table\n 5. Exit\n");
      scanf("%s",a);
      if (strlen(a)>1)
      {
         printf("Error: incorrect operation\n");
         continue;
      }
      switch(a[0])
      {
         case '1':
            strncpy(key,entKey(),8);
            info=entInfo();
            newelt(key, info, mass, SIZE);
         break;
         case '2':
            strncpy(key1,entKey(),8);
            strncpy(key2,entKey(),8);
            del(key1, key2, mass, SIZE);
         break;
         case '3':
            strncpy(key1,entKey(),8);
            strncpy(key2,entKey(),8);
            find(key1, key2, mass,mass1, SIZE);
         break;
         case '4':
            prt(mass, SIZE);
         break;
         case '5':
         break;
         default:
            printf("Error: incorrect operation\n");
            continue;
      }
   }
   while (a[0]!='5');
   return 0;
}


Вопрос в следующем. Нужно переделать программу так, чтобы и таблица, и информация, относящаяся к элементу таблицы, хранились во внешней памяти (используется двоичный файл). При этом имя файла вводится по запросу из программы.

Если кто сталкивался, подскажите, пожалуйста, как это сделать.

 
 
 
 Re: Работа с просматриваемой таблицей: нужна помощь!
Сообщение02.06.2012, 19:20 
0. Пишете на C++ — используйте классы. И стандартную библиотеку. Ваша homebrew реализация массива настолько ужасна... реализация ввода строки, впрочем, не лучше. realloc, надо же. Да getline(cin, str) вызовите и не парьтесь.
1. Как по мне, проще всего включить sqlite3.h, а не писать заново мини-СУБД.
2. Ну, если так уж хотите... создаете классы Table, Item, перегружаете operator<< и operator>>, и в принципе, дело в шляпе.

 
 
 
 Re: Работа с просматриваемой таблицей: нужна помощь!
Сообщение02.06.2012, 20:54 
Ой, перечитал внимательно... ужас.

Функция Table: память после malloc() забита мусором — где ее обнуление memset()'ом? Далее, malloc() может и NULL вернуть!

Логика newelt() порушена напрочь: если busy == 0, сравнивать ключи НЕЛЬЗЯ — вы сравниваете с мусором.

Логика del() также небезупречна: вы не проверяете, что у удаляемого элемента busy != 0, поэтому free(mass[i].info) может спокойно освободить мусорный укзаатель и порушить вам всю память.

В find() есть две беды — маленькая и большая. Маленькая: (mass[i].busy==1) должна быть впереди всех остальных сравнений в if-е. Большая: нехилая утечка памяти в mass1 — его нужно передавать как Item **mass.

В entkey() у вас потенциальное переполнение плюс возврат указателя на локальную переменную — ох.

В schit() (ну и название) есть запись за пределы массива и совершенно поломанное отслеживание размера выделенного буффера — как я уже говорил, malloc() возвращает буффер с мусором, так что strlen() выдаст совершенно любое число.

Что ж, вы ухитрились допустить смертельную (grave) ошибку практически в каждой процедуре — мои поздравления.

 
 
 
 Re: Работа с просматриваемой таблицей: нужна помощь!
Сообщение03.06.2012, 13:24 
Joker_vD
Цитата:
Пишете на C++

Дело в том, что пишу на С; С++ будет только в следующем семестре)

Большое Вам спасибо за конструктивную критику, однако, не судите строго: с языком С только начинаю знакомится, поэтому, если то, что я написала, хотя бы заработало - уже за счастье :-)

 
 
 [ Сообщений: 4 ] 


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group