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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> [Cи] Проблема с удалением структуры из файла, Некорретно удаляется. 
:(
    Опции темы
A1Exey
Дата 18.2.2010, 10:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Доброго времени суток! Заранее скажу что поиск юзал =)
Вводные данные:
Используя функции и режим меню, создать файл из 10 структур, просмотреть файл, добавить в файл новую информацию и, применяя режим прямого доступа, выполнить задание по своему варианту.
Структура имеет вид: фамилия спортсмена, его номер, количество набранных очков. Удалить из списка информацию о спортсмене с наименьшим количеством очков.

Создаю структуру:
Код

struct sportsman{
  char surname[255];
  int number;
  int points;
} data

С помощью ф-ии NewFile(FILE *) создаю новый файл и вношу в него необходимые записи:
Код

void NewFile(FILE *fp)
{
  char ch;
  clrscr();
  fp=fopen("database.dat","wb");
  printf("\nWARNING! THE OLD DATA WILL BE LOST! CONTINUE? Y/N");
  ch=getch();
  if (ch=='n')
    return;
  else
  do
  {
    printf("\nEnter sportsmans surname: ");
    scanf("%s",data.surname);
    printf("\nEnter sportsmans number: ");
    scanf("%d",&data.number);
    printf("\nEnter sportsmans points: ");
    scanf("%d",&data.points);
    fwrite(&data,sizeof(data),1,fp);
    printf("\n End entering? y/n ");
    ch=getch();
  }
  while (ch!='y');
  fclose(fp);
}

Интересует вопрос: как удалить какую - либо запись из файла? Для начала без сортировки(не по заданию), а допустим по фильтру вводимому с клавиатуры, по полю number структуры sportsman.
Написал такую функцию:
Код

void SearchFile(FILE *fp)
{
  char ch;
  int num;
  clrscr();
  fp=fopen("database.dat","rb+");
  printf("Enter sportsmans number:");
  scanf("%d",&num);
  while(!feof(fp))
  {
    fread(&data,sizeof(data),1,fp);
    printf("\n%4s %3d  %3d",data.surname,data.number,data.points);
    if (data.number==num)
    {
      printf(":%s ---- SPOTSMAN = SEARCHED",data.surname);
      fseek(fp,-sizeof(data),2);
      fwrite(NULL,sizeof(data),1,fp);
      break;
    }
  }
  getch();
  fclose(fp);
}

Т.е. вводим с клавиатуры num,далее последовательно считываем все структуры из файла,в случае если введенный num совпадает с sportsman.number - перемещаем указатель на начало найденной структуры, и прописываем в это место NULL:
Код
 fseek(fp,-sizeof(data),2);
      fwrite(NULL,sizeof(data),1,fp);

Не работает..зараза....подскажите что не так делаю?
Вот полный текст программы с комментариями:
Код

#include <stdio.h>
#include <conio.h>

//-------------PROTOTYPES SECTION-----------------;
void NewFile(FILE *);
void ViewFile(FILE *);
void AppendFile(FILE *);
void SearchFile(FILE *);
//--------------STRUCTURE DECLARE-----------------;
struct sportsman{
  char surname[255];
  int number;
  int points;
} data;
//-------------GLOBAL DATA DECLARE----------------;
FILE *fp;
//-------------ENTRY POINT------------------------;
main()
{

  char choise;
  do
  {
    clrscr();
    printf("\n1 - New file");
    printf("\n2 - View file");
    printf("\n3 - Append file");
    printf("\n4 - Search");
    printf("\n0 - Exit");
    printf("\n\nSelect option: ");
    choise=getch();
    switch(choise)
    {
      case '1': NewFile(fp); break;
      case '2': ViewFile(fp); break;
      case '3': AppendFile(fp); break;
      case '4': SearchFile(fp); break;
      default: printf("Incorrect enter");
    }
  }
  while (choise!='0');

}

//-------------FUNCTIONS SECTION-----------------;
void NewFile(FILE *fp)
{
  char ch;
  clrscr();
  fp=fopen("database.dat","wb");
  printf("\nWARNING! THE OLD DATA WILL BE LOST! CONTINUE? Y/N");
  ch=getch();
  if (ch=='n')
    return;
  else
  do
  {
    printf("\nEnter sportsmans surname: ");
    scanf("%s",data.surname);
    printf("\nEnter sportsmans number: ");
    scanf("%d",&data.number);
    printf("\nEnter sportsmans points: ");
    scanf("%d",&data.points);
    fwrite(&data,sizeof(data),1,fp);
    printf("\n End entering? y/n ");
    ch=getch();
  }
  while (ch!='y');
  fclose(fp);
}

void ViewFile(FILE *fp)
{
  char ch;
  int i=1;
  clrscr();
  fp=fopen("database.dat","rb");
  fread(&data,sizeof(data),1,fp);
  while(!feof(fp))
  {
    printf("\n#%d Surname:%15s Number:%3d Points:%3d",i,data.surname,data.number,data.points);
    fread(&data,sizeof(data),1,fp);
    i++;
  }
  fclose(fp);
  getch();
}

void AppendFile(FILE *fp)
{
  char ch;
  clrscr();
  fp=fopen("database.dat","ab");
  do
  {
    printf("\nEnter sportsmans surname: ");scanf("%s",data.surname);
    printf("\nEnter sportsmans number: ");scanf("%d",&data.number);
    printf("\nEnter sportsmans points: ");scanf("%d",&data.points);
    fwrite(&data,sizeof(data),1,fp);
    printf("\nEnd entering? y/n");
    ch=getch();
  }while (ch!='y');
  fclose(fp);
}

void SearchFile(FILE *fp)
{
  char ch;
  int num;
  clrscr();
  fp=fopen("database.dat","rb+");
  printf("Enter sportsmans number:");
  scanf("%d",&num);
  while(!feof(fp))
  {
    fread(&data,sizeof(data),1,fp);
    printf("\n%4s %3d  %3d",data.surname,data.number,data.points);
    if (data.number==num)
    {
      printf("%s SPOTSMAN = SEARCHED",data.surname);
      fseek(fp,-sizeof(data),2);
      fwrite(NULL,sizeof(data),1,fp);
      break;
    }
  }
  getch();
  fclose(fp);
}


Это сообщение отредактировал(а) A1Exey - 18.2.2010, 11:17
PM MAIL   Вверх
bsa
Дата 18.2.2010, 12:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

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



fwrite(NULL,sizeof(data),1,fp); эта операция вызовет сбой программы, так как NULL указывает в никуда.
Удалить запись из файла без его пересоздания нельзя. Можно ввести в структуру еще одно поле, которое будет означать, что запись удалена. Можно удалить старый файл и на его месте создать новый.
PM   Вверх
A1Exey
Дата 18.2.2010, 12:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Цитата(bsa @ 18.2.2010,  12:26)
Удалить запись из файла без его пересоздания нельзя. Можно ввести в структуру еще одно поле, которое будет означать, что запись удалена. Можно удалить старый файл и на его месте создать новый.

Т.е. предварительно нужно считать все структуры(за исключением удаляемой) из файла в динамический массив, после чего заново создать файл и прописать туда считанные структуры?
P.S.: тогда возникает еще один вопрос - как быть в случае с файлами большого размера?(>1Gb к примеру) Это я так, из познавательных целей интересуюсь.

Это сообщение отредактировал(а) A1Exey - 18.2.2010, 12:44
PM MAIL   Вверх
azesmcar
Дата 18.2.2010, 12:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

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



Цитата(A1Exey @  18.2.2010,  12:41 Найти цитируемый пост)
P.S.: тогда возникает еще один вопрос - как быть в случае с файлами большого размера?(>1Gb к примеру) Это я так, из познавательных целей интересуюсь.

Хранить данные в базе данных, она специально для этого создана.
PM   Вверх
bsa
Дата 18.2.2010, 13:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

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



Цитата(A1Exey @  18.2.2010,  12:41 Найти цитируемый пост)
P.S.: тогда возникает еще один вопрос - как быть в случае с файлами большого размера?(>1Gb к примеру)
Очень просто, считать N структур в буфер, записать в новый файл, повторять для оставшихся. Удалить старый файл. Новый переименовать...
Но, как уже успел заметить azesmcar, базы данных именно для этих целей и создавались. Поэтому логичней использовать именно их в этом случае.
PM   Вверх
borisbn
Дата 18.2.2010, 14:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

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



Насколько я понял автору нужно выполнить какое-то задание (курсовую, контрольную ets.)
Цитата(A1Exey @  18.2.2010,  10:49 Найти цитируемый пост)
выполнить задание по своему варианту

поэтому совет использовать СУБД, наверное, не подойдёт, а вот создание нового файла с удаленной структурой - нормальный вариант, при этом необязательно считывать весь первый файл в память, достаточно считывать по одной структуре, и - если она не удовлетворяет условию удаления - записывать её в выходной файл

P.S.
Цитата(A1Exey @  18.2.2010,  10:49 Найти цитируемый пост)
fseek(fp,-sizeof(data),2)

последний параметр == 2, или SEEK_END, так, что этот код будет отступать не назад от текущего положения, а на sizeof(data) от КОНЦА файла. Чтобы отступить назад нужно указать
Код

fseek( fp, -sizeof(data), SEEK_CUR );

кстати, предпочтительнее указывать константы (define'ы), чтобы код понятней был


Это сообщение отредактировал(а) borisbn - 18.2.2010, 14:14


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
azesmcar
Дата 18.2.2010, 14:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

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



Цитата(borisbn @  18.2.2010,  14:09 Найти цитируемый пост)
Насколько я понял автору нужно выполнить какое-то задание (курсовую, контрольную ets.)


Цитата(borisbn @  18.2.2010,  14:09 Найти цитируемый пост)
поэтому совет использовать СУБД, наверное, не подойдёт


хотелось бы обратить ваше внимание
Цитата(A1Exey @  18.2.2010,  12:41 Найти цитируемый пост)
тогда возникает еще один вопрос - как быть в случае с файлами большого размера?(>1Gb к примеру) Это я так, из познавательных целей интересуюсь.


PM   Вверх
A1Exey
Дата 21.2.2010, 21:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Всем спасибо за помощь! Реализовал через динамический массив, однако столкнулся со некоторыми проблемами...
Изменил ф-ю SearchFile, теперь алгоритм выглядит так:
1) Файл открывается в режиме "rb", происходит подсчёт кол-ва записанных в файл структур:
Код

n=0;
  while(!feof(fp))
  {
    fread(&data,sizeof(data),1,fp);
    n++;
  }
  printf("\nAFTER COUNTING OF FILE: N=%d",n);//отладочное сообщение

2) Указатель чтения переводится на начало файла, создаётся динамический массив, все записи из файла последовательно считываются в массив, файл закрывается:
Код

fseek(fp,0,0);
  p=(sportsman *)malloc(n*sizeof(data));
  for (i=0;i<n;i++)  //заполняем массив
  {
    fread(&data,sizeof(data),1,fp);
    p[i]=data;
    printf("\n%d %3s  %3d %3d",i,data.surname,data.number,data.points);
  }
  printf("\nAFTER FILLING ARRAY: N=%d",n);
  fclose(fp);

3) Файл открывается в режиме "wb", считанный массив сортируется "инвертированным" алгоритмом пузырьковой сортировки(самый лёгкий элемент опускается вниз), после чего массив записывается в файл, за исключением последнего элемента(он откидывается по условию задачи):
Код

fp=fopen("database.dat","wb");
  //inverted bubble sorting array, i think this surprise my teacher in the previos program? or not.. :)
  j=1; //true-false bubble sort counter
  while (j)
  {
    j=0;
    for (i=0;i<n-1;i++)
    {
      if (p[i].points<p[i+1].points)
      {
        buff=p[i];
        p[i]=p[i+1];
        p[i+1]=buff;
        j=1;
      }
    }
  }
  for(i=0;i<n;i++)
    fwrite(&p[i],sizeof(data),1,fp);
  printf("\nThe sportsman with the minimun points are:%5s with %3d points",p[n-1].surname,p[n-1].points);
  getch();
  free(p);
  fclose(fp);


Сталкиваюсь с проблемой в пунктах 1 и 2. 
Допустим что мы записали в файл 4ре структуры, однако значение переменной n после считывания содержимого файла равняется 5(пяти). Что ещё оно считывает?

Полный текст функции SearchFile():
Код

void SearchFile(FILE *fp)
{
  char ch;
  int i,j,n;
  sportsman *p,buff;
  clrscr();
  fp=fopen("database.dat","rb");
  //counting number of records in file
  n=0;
  while(!feof(fp))
  {
    fread(&data,sizeof(data),1,fp);
    n++;
  }
  printf("\nAFTER COUNTING OF FILE: N=%d",n);
  fseek(fp,0,0);
  p=(sportsman *)malloc(n*sizeof(data));
  //filling array
  for (i=0;i<n;i++)
  {
    fread(&data,sizeof(data),1,fp);
    p[i]=data;
    printf("\n%d %3s  %3d %3d",i,data.surname,data.number,data.points);
  }
  printf("\nAFTER FILLING ARRAY: N=%d",n);
  fclose(fp);
  fp=fopen("database.dat","wb");
  //inverted bubble sorting array, i think this surprise my teacher in the previos program? or not.. :)
  j=1; //true-false bubble sort counter
  while (j)
  {
    j=0;
    for (i=0;i<n-1;i++)
    {
      if (p[i].points<p[i+1].points)
      {
        buff=p[i];
        p[i]=p[i+1];
        p[i+1]=buff;
        j=1;
      }
    }
  }
  for(i=0;i<n;i++)
    fwrite(&p[i],sizeof(data),1,fp);
  printf("\nThe sportsman with the minimun points are:%5s with %3d points",p[n-1].surname,p[n-1].points);
  getch();
  free(p);
  fclose(fp);
}



Полный текст программы можно посмотреть в первом сообщении, изменена только ф-я SearchFile.
Дополнение: после запуска ф-ии SearchFile некоторые структуры считанные из файла записываются во вновь созданный файл по 2 раза. Логически вроде бы я всё правильно написал, подскажите что не так? :(%-)
Код



PM MAIL   Вверх
borisbn
Дата 21.2.2010, 22:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

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



1. Количество записей в файле проще вычислить так
Код

n = fseek( fp, 0, 2 ) / sizeof( sportsman); // fseek перемещает указатель на 0 байт (2-й параметр) от конца файла (3-й параметр =2) и возвращает позицию в файле 

а лишний fread в твоем коде возвоащает количество считанных записей равное 0.
 


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
A1Exey
Дата 21.2.2010, 22:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Цитата(borisbn @ 21.2.2010,  22:35)
1. Количество записей в файле проще вычислить так
Код

n = fseek( fp, 0, 2 ) / sizeof( sportsman); // fseek перемещает указатель на 0 байт (2-й параметр) от конца файла (3-й параметр =2) и возвращает позицию в файле 

а лишний fread в твоем коде возвоащает количество считанных записей равное 0.

Логически вроде Вы правильно написали, однако поправил в коде:
Код

 n=0;
  printf("\nBEFORE FREAD OF FILE: N=%d",n);
  n = fseek( fp, 0, 2 ) / sizeof( sportsman);
  //while(!feof(fp))
  //{
  //    fread(&data,sizeof(data),1,fp);
  //    n++;
  //}
  printf("\nAFTER COUNTING OF FILE: N=%d",n);

и теперь переменная n = 0 (кол-во считанных записей), что до считывания, что после считывания.
Что то не так...
PM MAIL   Вверх
andrew_121
Дата 21.2.2010, 23:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Кодофей
****


Профиль
Группа: Завсегдатай
Сообщений: 3448
Регистрация: 3.1.2008

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



Цитата(A1Exey @  21.2.2010,  22:53 Найти цитируемый пост)
Что то не так... 

потому что указатель находится в конце файла.
Код

n = fseek( fp, 0, SEEK_END ) / sizeof( sportsman);
fseek(fp, 0, SEEK_SET);




--------------------
Удалил аккаунт. Прощайте!
PM MAIL   Вверх
A1Exey
Дата 22.2.2010, 08:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Цитата(andrew_121 @ 21.2.2010,  23:50)
Цитата(A1Exey @  21.2.2010,  22:53 Найти цитируемый пост)
Что то не так... 

потому что указатель находится в конце файла.
Код

n = fseek( fp, 0, SEEK_END ) / sizeof( sportsman);
fseek(fp, 0, SEEK_SET);

Указатель находится в конце файла, соответсвенно 
Код

fseek(fp,0,2)/sizeof(sportsman)

должен возвращать количество записанных в файл элементов.
PM MAIL   Вверх
borisbn
Дата 22.2.2010, 08:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

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



дико извиняюсь, fseek не возвращает положение указателя в файле. Нужно вот так:
Код

fseek( fp, 0, SEEK_END );
n = ftell( fp ) / sizeof( sportsman);


sorry, sorry


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
A1Exey
Дата 22.2.2010, 09:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



borisbn , спасибо!
Заменил цикл подсчёта записанных структур:
Код

while(!feof(fp))
  {
    fread(&data,sizeof(data),1,fp);
    n++;
  }

на 
Код

 fseek( fp, 0, 2 );
  n = ftell(fp) / sizeof(sportsman);

и всё заработало...правда так и не понял, почему после первой попытки (считать кол-во структур циклом), оно возвращало на один элемент больше чем было реально записано в файл...может кто нибудь расскажет? smile
Если кому - либо интересно выкладываю полный текст рабочей ф-ии SearchFile():
Код

void SearchFile(FILE *fp)
{
  char ch;
  int i,j,n;
  sportsman *p,buff;
  clrscr();
  fp=fopen("database.dat","rb");
  //counting number of records in file
  n=0;
  printf("\nBEFORE FREAD OF FILE: N=%d",n);
  fseek( fp, 0, 2 );
  n = ftell(fp) / sizeof(sportsman);
  //while(!feof(fp))
  //{
  //    fread(&data,sizeof(data),1,fp);
  //    n++;
  //}
  printf("\nAFTER COUNTING OF FILE: N=%d",n);
  rewind(fp);
  p=(sportsman *)malloc(n*sizeof(data));
  //filling array
  for (i=0;i<n;++i)
  {
    fread(&data,sizeof(data),1,fp);
    p[i]=data;
    printf("\n%d %3s  %3d %3d",i,data.surname,data.number,data.points);
  }
  printf("\nAFTER FILLING ARRAY: N=%d",i);
  fclose(fp);
  fp=fopen("database.dat","wb");
  //inverted bubble sorting array, i think this surprise my teacher in the previos program? or not.. :)
  j=1; //true-false bubble sort counter
  while (j)
  {
    j=0;
    for (i=0;i<n-1;i++)
    {
      if (p[i].points<p[i+1].points)
      {
        buff=p[i];
        p[i]=p[i+1];
        p[i+1]=buff;
        j=1;
      }
    }
  }
  for(i=0;i<n-1;++i)
    fwrite(&p[i],sizeof(data),1,fp);
  printf("\nThe sportsman with the minimun points are:%5s with %3d points",p[n-1].surname,p[n-1].points);
  getch();
  free(p);
  fclose(fp);
}

PM MAIL   Вверх
borisbn
Дата 22.2.2010, 09:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

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



Цитата(A1Exey @  22.2.2010,  09:01 Найти цитируемый пост)
оно возвращало на один элемент больше чем было реально записано в файл...может кто нибудь расскажет? 


Цитата(borisbn @  21.2.2010,  22:35 Найти цитируемый пост)
а лишний fread в твоем коде возвращает количество считанных записей равное 0.


нужно было

Код

while(!feof(fp))
{
     if ( fread(&data,sizeof(data),1,fp) == 1 )
     {
         n++;
      }
}


но это дольше, чем, fseek/ftell


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


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

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


 




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


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

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