2014 dxdy logo

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

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




Начать новую тему Ответить на тему
 
 Работа с просматриваемой таблицей: нужна помощь!
Сообщение02.06.2012, 18:31 


02/06/12
2
Написала программу для работы с просматриваемой таблицей по запросам оператора. И таблица, и информация, относящаяся к элементу таблицы, хранятся в основной памяти. Код:

Код:
#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 
Заслуженный участник


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

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


09/09/10
3729
Ой, перечитал внимательно... ужас.

Функция 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 


02/06/12
2
Joker_vD
Цитата:
Пишете на C++

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

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

 Профиль  
                  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 4 ] 

Модераторы: Karan, Toucan, PAV, maxal, Супермодераторы



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group