Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: 1 2 [3]  Все   Вниз
  Печать  
Автор Тема: [C++] Помогите, ПОЖАЛУЙСТА, решить задачу!!!  (Прочитано 63866 раз)
0 Пользователей и 5 Гостей смотрят эту тему.
LELECHKA
Участник

by
Offline Offline
Пол: Женский

« Ответ #60 : 06-05-2010 18:23 » 

Dimka, не получается ни с сортировкой, ни с удалением!
Записан

Все можно познать, только не самого себя. (Стендаль)

Мудр не тот, кто знает много, а тот, чьи знания полезны. (Эсхил)

Победа над страхом придает нам силы. (Виктор Гюго)
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #61 : 06-05-2010 18:59 » 

Возвращаясь от приватной переписки.

LELECHKA, представленный код близок к тому, чтобы быть правильным, но он настолько сумбурный, что мне достаточно сложно представить, как таким способом можно будет безошибочно реализовать алгоритм сортировки. Пока что написанное близко к правильному именно за счёт того, что тут нет ничего более-менее алгоритмически сложного.

Всё же прочитай внимательно то, что я говорил выше про меню и работу с файлами, проверь по своему коду и, если что-то окажется непонятным, задай вопросы.

Добавлено: о! как в воду глядел.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #62 : 06-05-2010 19:09 » 

LELECHKA, опиши алгоритмы удаления и сортировки на русском языке. Алгоритм всегда пишется для исполнителя, который умеет понимать отдельные инструкции. Считай, что твой исполнитель умеет следующее:
- открыть файл для работы,
- закрыть файл по окончании работы,
- двигать текущую позицию (курсор) внутри файла между разными записями, в том числе на самую первую и на самый конец файла,
- прочитать в память (в переменную) из файла запись в текущей позиции курсора и сдвинуть курсор к следующей записи,
- записать из памяти (из переменной) запись в файл в текущей позиции курсора и сдвинуть курсор к следующей записи,
- узнавать, номер позции, где находится курсор,
- узнавать, достигнут ли конец файла,
- сравнить две записи (в двух переменных) по указанным полям и сказать: меньше ли первая запись, нежели вторая, или нет.
Ещё исполнитель знает, что такое переменные, присваивание, ветвления, циклы и подпрограммы/функции, их аргументы и результат.

Используй только перечисленные мной понятия - никакой "художественной литературы", никакой отсебятины.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
LELECHKA
Участник

by
Offline Offline
Пол: Женский

« Ответ #63 : 07-05-2010 09:06 » 

Dimka, Объясни, пожалуйста, еще раз, какие изменения должны быть в части fstream( там не соответсвие или запись должна быть другая), честно, не понимаю?

Как прописывать движение по записям?  Я нашла seekg(), fseek().

Как записывать из памяти запись в файл?

Как узнать на какой позиции находится нужная мне запись?

В тех функциях, в которых нужно удалять, сортировать какой должен быть режим файла? (я ставила r+t)
Записан

Все можно познать, только не самого себя. (Стендаль)

Мудр не тот, кто знает много, а тот, чьи знания полезны. (Эсхил)

Победа над страхом придает нам силы. (Виктор Гюго)
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #64 : 07-05-2010 12:26 » 

LELECHKA, я писал, что работа с файлам и потоками может осуществляться с помощью двух библиотек. fstream, cin, cout относятся к стандартной библиотеке STL из языка C++, fopen, fclose, fprintf, fscanf относятся к стандартной библиотеке языка C.

Но дело не в том, что ты используешь сразу две библиотеки, а в том, что ты их используешь непоследовательно. Зачем у тебя в main находится fstream, который ты передаёшь как аргумент в другие функции, если ты в других функциях его не используешь, а используешь fopen? Это не только не нужно, это ещё и опасно: у тебя один и тот же файл открывается двумя разными способами. Каждый открытый файл в программе имеет свой дескриптор и свою текущую позицию (курсор). В твоём случае получается два дескриптора и два курсора на один и тот же файл. Если, к примеру, будешь позиционировать курсор одним способом, а записывать другим, то запись пойдёт не в то место, что может вызвать порчу данных или неожиданное для тебя самой поведение.

Это точно та же проблема, что и раньше мы разбирали с форматированием. Пока не будет порядка, будут ошибки. Выбери одну библиотеку и используй только её.

В стандартной библиотеке C движение по записям осуществляет функция fseek.

По поводу записи в файл и чтения из файла.

Если с файлом работают как с текстовым: записывать функцией fprintf, читать функцией fscanf - с ним работают только в последовательном режиме. Что ты и делаешь. В результате внутри файла окажется текст, файл можно открыть в Блокноте и посмотреть его содержимое. Но этот способ работы не годится для простой реализации алгоритма сортировки. Проблема здесь в том, что отдельные записи имеют разную длину (из-за того, что строки и строковые представления чисел имеют разное количество символов в разных записях). Это значит, что нет никакой возможности вычислить, с какого байта от начала файла начинается нужная запись. Для реализации сортировки в таком случае нужно читать исходный файл, например, по 2 соседние записи, обменивать их в памяти, если нарушен порядок, и записывать результат в другой временный файл, а затем, наоборот, временный файл перезаписывать в исходный - и так много раз, пока не будет достигнут порядок. Есть и специальные алгоритмы сортировки для последовательных файлов, но они работают по тому же принципу многократного презаписывания.

Но с файлом можно работать как с двоичным: записывать функцией fwrite и читать функцией fread - с ними работают в режиме произвольного доступа. В результате внутри файла окажется нечитаемый в текстовом редакторе набор двоичных данных, байтов, и записи будут храниться в точности в том виде, в каком они хранятся в памяти программы при работе. Записи всегда будут иметь одинаковую длину, равную размеру структуры данных. Эту длину можно получить при помощи оператора sizeof. Это позволяет свободно перемещать курсор к любой записи: нужно позицию записи умножить на размер записи - и получится номер байта, с которого начинается запись внутри файла. Функция fseek это делает сама - ей достаточно сказать номер позиции и размер структуры. В этом случае с файлом можно работать почти так же, как с массивом, и поэтому можно написать многие алгоритмы сортировки. Для функций fread и fwrite не надо перечислять поля записи, нужно передавать всю запись целиком.

Для выяснения текущей позиции в файле (на каком байте стоит курсор) служит функция ftell.

Удаление записей из файла, так чтобы файл "ужался" посередине, невозможно. Можно только подтянуть записи из конца файла вперёд на 1, чтобы затереть удаляемую запись и не оставлять "дырку". Сжатие файла, чтобы ликвидировать пустые позиции, возможно только через его копирование запись за записью в новый файл, пропуская "дырки".

Для работы с файлом в режиме произвольного доступа удобнее всего использовать режим w+ - он открывает файл на чтение и запись, и, при этом, если файла ещё нет, создаёт его. Курсор при этом будет стоять на первой (с номером 0) записи. Для перемещения в конец файла и добавления новых записей используется fseek со специальной константой (аналогично для перемещения в самое начало). Если с помощью fseek переместить курсор на конец файла и с помощью ftell узнать текущую позицию - эта позиция будет равна размеру файла (в байтах), если её поделить на размер записи (в байтах), то полученное число будет количеством записей в файле.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
LELECHKA
Участник

by
Offline Offline
Пол: Женский

« Ответ #65 : 07-05-2010 19:08 » 

Вместо My_base у меня должно теперь стоять fname?

У меня раньше стояло :
My_base.clear();
Я заменила на fname.clear(); выдает ошибку: [C++ Error] Unit1.cpp(72): E2294 Structure required on left side of . or .*
Как правильно написать?

Вот, что в общем получилось, так должно быть или бред?
Код:
#include <fstream.h>
#include <conio.h>
#include <string.h>
#include <stdio.h>
#include <iostream>
#include <math.h>
#include <iomanip.h>
#define MAX 100
#include <stdlib.h>
#define STR2 3
#define FNAME "f:\\furniture.txt\0"

struct Furniture
{
   int Num_Buyer;
   char Addres_Buyer[30];
   char Furniture_Name[30];
   char Furniture_Model[30];
   int Date_Registration;
   int Date_Execution;
};

 int enterChoice();

 void newFile (const char*newFile);
 void viewFile (const char*viewFile);
 void deleteFile (const char*deleteFile);
 void runFile  (const char*runFile);
 void outputFile  (const char*outputFile);



int main(int argc, char* argv[])
{

   char fname[40]=FNAME;
   FILE*in;


   if ((in=fopen(fname, "wt"))==NULL)
   {
      printf("The file cannot be opened");
      getch();

   }

   int choice;

   while ((choice=enterChoice())!=5)
   {
      switch (choice)
      {
         case 1:
           newFile (fname);
           break;
         case 2:
           viewFile (fname);
           break;
         case 3:
           deleteFile (fname);
           break;
         case 4:
           runFile (fname);
           break;
         case 5:
           outputFile (fname);
           break;
         default:
           cerr<<"Incorrect choice"<<endl;
           break;
        }
     fname.clear();
     }

   fclose(in);
   getch();
}

int enterChoice()
{
    cout<<endl<<"Your choise:"<<endl
        <<"1-newFile"<<endl
        <<"2-viewFile"<<endl
        <<"3-deleteFile"<<endl
        <<"4-runFile"<<endl
        <<"5-outputFile"<<endl
        <<"6-the end of the work"<<endl<<"?";

    int menuChoice;
    cin>>menuChoice;
    return menuChoice;
}
void newFile(fstream &writeFromFile)
{
   char fname[40]=FNAME;
   FILE*in;
   int i, j;

   if ((in=fopen(fname, "wt"))==NULL)
   {
      printf("The file cannot be opened");
      getch();
      return;
   }

   Furniture furniture[MAX];

   for (i=0;i<2;i++)
   {
     _flushall();

     printf("\n Num_Buyer: \n");
     scanf("%d",&furniture[i].Num_Buyer);

     printf ("\n Addres_Buyer: \n");
     scanf ("%s", &furniture[i].Addres_Buyer);

     printf ("\n Furniture_Name: \n");
     scanf("%s", &furniture[i].Furniture_Name);

     printf ("\n Furniture_Model: \n");
     scanf("%s", &furniture[i].Furniture_Model);

     printf ("\n Date_Registration: \n");
     scanf("%d",&furniture[i].Date_Registration);

     printf ("\n Date_Execution: \n");
     scanf("%d",&furniture[i].Date_Execution);

     fprintf(in,"\n Num_Buyer: %d\n Addres_Buyer: %s \n Furniture_Name: %s \n Furniture_Model: %s \n Date_Registration: %d \n Date_Execution: %d \n" , furniture[i].Num_Buyer, furniture[i].Addres_Buyer, furniture[i].Furniture_Name,
     furniture[i].Furniture_Model, furniture[i].Date_Registration,furniture[i].Date_Execution);
    }
     printf("\n\n");

   fclose(in);
   getch();
}


void viewFile(fstream &inFurnitureFile)
{
   char fname[40]=FNAME;
   FILE*in;
   int i, j;

   if ((in=fopen(fname, "rt"))==NULL)
   {
      printf("The file cannot be opened");
      getch();
      return;
   }

   Furniture furniture;

   while (!feof(in))
   {
     fscanf(in,"\n Num_Buyer: %d\n Addres_Buyer: %s \n Furniture_Name: %s \n Furniture_Model: %s \n Date_Registration: %d \n Date_Execution: %d \n" , &furniture.Num_Buyer, &furniture.Addres_Buyer, &furniture.Furniture_Name,&furniture.Furniture_Model, &furniture.Date_Registration,&furniture.Date_Execution);
     printf("\n Num_Buyer: %d\n Addres_Buyer: %s \n Furniture_Name: %s \n Furniture_Model: %s \n Date_Registration: %d \n Date_Execution: %d \n", furniture.Num_Buyer, furniture.Addres_Buyer, furniture.Furniture_Name,furniture.Furniture_Model, furniture.Date_Registration,furniture.Date_Execution);
   }
   fclose(in);
   getch();

}

void deleteFile(fstream &deleteFromFile)
{
   char fname[40]=FNAME;
   FILE*in;
   int i, d;

   if ((in=fopen(fname, "w+t"))==NULL)
   {
      printf("The file cannot be opened");
      getch();
      return;
   }

   Furniture furniture[MAX];

   cout<<"Input the date:\n";
   cin>>d;

   fclose(in);
   getch();

}

[ /code ]
void runFile  (fstream &outputFromFile)
{
   char fname[40]=FNAME;
   FILE*in;
   int i;

   if ((in=fopen(fname, "w+t"))==NULL)
   {
      printf("The file cannot be opened");
      getch();
      return;
   }

   Furniture furniture[MAX];

   fclose(in);
   getch();
}


void outputFile  (fstream &outputFromFile)
{
}
« Последнее редактирование: 07-05-2010 19:12 от Джон » Записан

Все можно познать, только не самого себя. (Стендаль)

Мудр не тот, кто знает много, а тот, чьи знания полезны. (Эсхил)

Победа над страхом придает нам силы. (Виктор Гюго)
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #66 : 07-05-2010 21:21 » new

Конечно бред. Я ведь говорил: ответь на вопрос зачем? Ну вот, допустим, строчка fname.clear() - что по-твоему она делает и зачем в этом месте написана? Ты не делаешь описаний на русском языке, о которых я уже не один раз сказал, ты постоянно показываешь код. В данном случае, поскольку прогресс по коду очень слабый (хотя и есть), это выглядит как попытка избежать необходимости тщательно разобраться.

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

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
LELECHKA
Участник

by
Offline Offline
Пол: Женский

« Ответ #67 : 08-05-2010 11:56 » 

Dimka, С main я попробую сегодня разобраться,а эту часть можно так оставить( именно то, что в скобках)?

 void newFile (const char*newFile);
 void viewFile (const char*viewFile);
 void deleteFile (const char*deleteFile);
 void runFile  (const char*runFile);
 void outputFile  (const char*outputFile);
Записан

Все можно познать, только не самого себя. (Стендаль)

Мудр не тот, кто знает много, а тот, чьи знания полезны. (Эсхил)

Победа над страхом придает нам силы. (Виктор Гюго)
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #68 : 08-05-2010 15:45 » 

LELECHKA, вопрос неправильный. Именно ты сама знаешь, можно или нельзя так оставлять, если имеешь объяснение, зачем это там написано - это твоя программа, твой творческий замысел. С тем же успехом Вера Мухина могла бы спрашивать: можно ли поместить в руки рабочего и колхозницы серп и молот? Улыбаюсь Иначе опять получается метод тыка, преобразованный в попытку угадать моё мнение.

Каждая часть, каждая строчка должна быть подчинена общему замыслу.

Я не против тех или иных решений в работающей программе - можно обсуждать достоинства и недостатки, можно говорить, что одно решение лучше другого, можно иметь разные мнения, спорить и не соглашаться, когда все эти решения являются корректными решениями задачи - это всё будет нормальной ситуацией.

Но против чего я категорически возражаю, так это против бездумности, написания такого кода, который непонятен автору. Не должно быть ни одной непонятной строчки! Пустая программа на C/C++ выглядит так:
Код: (C)
int main()
{
    return 0;
]
Это можно принять как данность и не объяснять - так надо, чтобы программа работала. Но всё остальное, написанное помимо этих 4 строчек, пишется программистом в соответствии с поставленной задачей и потому должно иметь объяснение, ответы на те вопросы, о которых я писал выше. Поэтому я и говорю: начни с main.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
LELECHKA
Участник

by
Offline Offline
Пол: Женский

« Ответ #69 : 08-05-2010 17:18 » 

Dimka, Можно я оставлю пока так:

Код:
#include <fstream.h>
#include <conio.h>
#include <string.h>
#include <stdio.h>
#include <iostream>
#include <math.h>
#include <iomanip.h>
#define MAX 100
#include <stdlib.h>
#define STR2 3
#define FNAME "f:\\furniture.txt\0"

struct Furniture
{
   int Num_Buyer;
   char Addres_Buyer[30];
   char Furniture_Name[30];
   char Furniture_Model[30];
   int Date_Registration;
   int Date_Execution;
};

 int enterChoice();

 void newFile (fstream&);
 void viewFile (fstream&);
 void deleteFile (fstream&);
 void runFile  (fstream&);
 void outputFile  (fstream&);



int main()
{
   fstream My_base;

   char fname[40]=FNAME;
   FILE*in;


   if ((in=fopen(fname, "w+t"))==NULL)
   {
      printf("The file cannot be opened");
      getch();
   }

   int choice;

   while ((choice=enterChoice())!=5)
   {
      switch (choice)
      {
         case 1:
           newFile (My_base);
           break;
         case 2:
           viewFile (My_base);
           break;
         case 3:
           deleteFile (My_base);
           break;
         case 4:
           runFile (My_base);
           break;
         case 5:
           outputFile (My_base);
           break;
         default:
           cerr<<"Incorrect choice"<<endl;
           break;
        }
     My_base.clear();
     }
}

int enterChoice()
{
    cout<<endl<<"Your choise:"<<endl
        <<"1-newFile"<<endl
        <<"2-viewFile"<<endl
        <<"3-deleteFile"<<endl
        <<"4-runFile"<<endl
        <<"5-outputFile"<<endl
        <<"6-the end of the work"<<endl<<"?";

    int menuChoice;
    cin>>menuChoice;
    return menuChoice;
}
void newFile(fstream &writeFromFile)
{
   char fname[40]=FNAME;
   FILE*in;
   int i, j;

   if ((in=fopen(fname, "wt"))==NULL)
   {
      printf("The file cannot be opened");
      getch();
      return;
   }

   Furniture furniture[MAX];

   for (i=0;i<2;i++)
   {
     _flushall();

     printf("\n Num_Buyer: \n");
     scanf("%d",&furniture[i].Num_Buyer);

     printf ("\n Addres_Buyer: \n");
     scanf ("%s", &furniture[i].Addres_Buyer);

     printf ("\n Furniture_Name: \n");
     scanf("%s", &furniture[i].Furniture_Name);

     printf ("\n Furniture_Model: \n");
     scanf("%s", &furniture[i].Furniture_Model);

     printf ("\n Date_Registration: \n");
     scanf("%d",&furniture[i].Date_Registration);

     printf ("\n Date_Execution: \n");
     scanf("%d",&furniture[i].Date_Execution);

     fprintf(in,"\n Num_Buyer: %d\n Addres_Buyer: %s \n Furniture_Name: %s \n Furniture_Model: %s \n Date_Registration: %d \n Date_Execution: %d \n" , furniture[i].Num_Buyer, furniture[i].Addres_Buyer, furniture[i].Furniture_Name,
     furniture[i].Furniture_Model, furniture[i].Date_Registration,furniture[i].Date_Execution);
    }
     printf("\n\n");

   fclose(in);
   getch();
}


void viewFile(fstream &inFurnitureFile)
{
   char fname[40]=FNAME;
   FILE*in;
   int i, j;

   if ((in=fopen(fname, "rt"))==NULL)
   {
      printf("The file cannot be opened");
      getch();
      return;
   }

   Furniture furniture;

   while (!feof(in))
   {
     fscanf(in,"\n Num_Buyer: %d\n Addres_Buyer: %s \n Furniture_Name: %s \n Furniture_Model: %s \n Date_Registration: %d \n Date_Execution: %d \n" , &furniture.Num_Buyer, &furniture.Addres_Buyer, &furniture.Furniture_Name,&furniture.Furniture_Model, &furniture.Date_Registration,&furniture.Date_Execution);
     printf("\n Num_Buyer: %d\n Addres_Buyer: %s \n Furniture_Name: %s \n Furniture_Model: %s \n Date_Registration: %d \n Date_Execution: %d \n", furniture.Num_Buyer, furniture.Addres_Buyer, furniture.Furniture_Name,furniture.Furniture_Model, furniture.Date_Registration,furniture.Date_Execution);
   }
   fclose(in);
   getch();

}

void deleteFile(fstream &deleteFromFile)
{
   char fname[40]=FNAME;
   FILE*in;
   int i,d;


   if ((in=fopen(fname, "w+t"))==NULL)
   {
      printf("The file cannot be opened");
      getch();
      return;
   }

   Furniture furniture[MAX];

   cout<<"Input the date:\n";
   cin>>d;

   fclose(in);
   getch();
}


void runFile  (fstream &outputFromFile)
{
   char fname[40]=FNAME;
   FILE*in;
   int i;



   if ((in=fopen(fname, "w+t"))==NULL)
   {
      printf("The file cannot be opened");
      getch();
      return;
   }

   Furniture furniture[MAX];

   fclose(in);
   getch();
}


void outputFile  (fstream &outputFromFile)
{
   char fname[40]=FNAME;
   FILE*in;
   int i;



   if ((in=fopen(fname, "w+t"))==NULL)
   {
      printf("The file cannot be opened");
      getch();
      return;
   }

   Furniture furniture[MAX];

   fclose(in);
   getch();


}[\code]

« Последнее редактирование: 08-05-2010 17:21 от LELECHKA » Записан

Все можно познать, только не самого себя. (Стендаль)

Мудр не тот, кто знает много, а тот, чьи знания полезны. (Эсхил)

Победа над страхом придает нам силы. (Виктор Гюго)
LELECHKA
Участник

by
Offline Offline
Пол: Женский

« Ответ #70 : 08-05-2010 17:21 » 

Dimka,

Ты говорил, что пользоваться нужно только одной библиотекой, точнее желательно. Получается, что на каждый мой, например,  void newFile (fstream&) в скобках должна быть другая запись с fopen( плюс в каком режиме должен быть открыт файл)? Если да, то я не знаю как это правильно записать.

И по поводу, fseek(), я что-то запуталась. Эту функцию используют, когда работают с двоичным файлом, а у меня текстовый, т.е. мне необходимо изменить мое File*in на File*b и заменить fscanf/fprinf  на  fwrite/fread?
Записан

Все можно познать, только не самого себя. (Стендаль)

Мудр не тот, кто знает много, а тот, чьи знания полезны. (Эсхил)

Победа над страхом придает нам силы. (Виктор Гюго)
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #71 : 08-05-2010 20:34 » 

Цитата: LELECHKA
Ты говорил, что пользоваться нужно только одной библиотекой, точнее желательно. Получается, что на каждый мой, например,  void newFile (fstream&) в скобках должна быть другая запись с fopen( плюс в каком режиме должен быть открыт файл)? Если да, то я не знаю как это правильно записать.
Что именно записать? Не кодом, русским языком скажи, что это такое - то, что ты хочешь записать. То, что ты считаешь проблемой, проблемой не является, потому что в том, о чём ты спрашиваешь, нет никакого смысла в твоей задаче. И всё, что нужно, это увидеть, где смысл есть, а где его нет.

Цитата: LELECHKA
И по поводу, fseek(), я что-то запуталась. Эту функцию используют, когда работают с двоичным файлом, а у меня текстовый, т.е. мне необходимо изменить мое File*in на File*b и заменить fscanf/fprinf  на  fwrite/fread?
Я не сказал "необходимо", я сказал, что двоичный формат более удобен для реализации сортировки, нежели текстовый, и объяснил почему - выбор за тобой. В части замены fscanf/fprintf на fwrite/fread - про такое я говорил, если переходить к двоичному формату. Но вот откуда ты взяла File*in и File*b - это загадка. Что это такое по-твоему? (опять же, русским языком, а не кодом)

P.S. Ситуация патовая - русским языком ты говорить не хочешь, а твой код хочется прокомментировать цитатой из х/ф "Кин-дза-дза": "Очень трудно в язык проникать, когда сразу на двух языках думаете. А этот пацак всё время говорит на языках, продолжения которых не знает!"
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
LELECHKA
Участник

by
Offline Offline
Пол: Женский

« Ответ #72 : 09-05-2010 06:40 » 

Dimka,
Попытаюсь объяснить на русском, что я имею ввиду.
1. Ну вот допустим, мой void newFile (fstream&). Этот пункт меню должен открывать мой файл для ввода/вывода. На данный момент я пытаюсь прописать то же самое, только с помощью fopen. Только не понимаю зачем, наверное смысла нет записывать по-другому.

2. Я ведь работаю с текстовым файлом,  он обозначается как FILE*in, а для того, чтобы работать с файлом в двоичном формате, его необходимо обозначить как FILE*b.
Записан

Все можно познать, только не самого себя. (Стендаль)

Мудр не тот, кто знает много, а тот, чьи знания полезны. (Эсхил)

Победа над страхом придает нам силы. (Виктор Гюго)
Sla
Модератор

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #73 : 09-05-2010 08:05 » 

LELECHKA, потренируйся еще - не получилось.

Записан

Мы все учились понемногу... Чему-нибудь и как-нибудь.
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #74 : 09-05-2010 09:16 » 

LELECHKA, разница между твоим описанием и тем, которое хочется от тебя услышать, в глубине и подробности.

Например, в стандарте языка C++ одному только знаку "," (запятая) посвящено два абзаца на четверь страницы A4 мелким шрифтом английского текста описания! А ты на целую функцию отводишь лишь одно короткое предложение, причём далеко не соответствующее тому, что у тебя написано внутри функции newFile на самом деле. Да, функция newFile делает то, что ты говоришь, но это делается и в других местах твоей программы, а про самое главное, что делает функция newFile, ты вообще не упомянула.

В выражениях:
Код:
void newFile(fstream &);
и
Код:
FILE *in;
на самом деле бездна смысла. Любая функция, любой алгоритм начинается со спецификаций: решаемой задачи, необходимых для решения задачи входных и выходных данных, их способов передачи в памяти, типов данных, допущений о состоянии окружающей функцию "среды" - значений глобальных переменных, состояний файлов и т.п. Я от тебя даже про fstream ничего внятного услышать не могу, а уж про значки "&" и "*" вообще не заикаюсь, хотя это тоже интересно - почему выбран тот или иной значок, за этим тоже должны стоять какие-то соображения, потому что эти значки не для красоты пишутся.

P.S. Алгоритм удаления, который ты прислала мне в привате и мой ответ на твой алгоритм лучше сюда выкладывать. Дело в том, что подобные темы нами могут использоваться для других посетителей - кому-то со сходными проблемами можно будет предложить прочитать эту тему, и, возможно, это поможет. В привате оно будет недоступно. Если не хочешь сейчас, я выложу потом - по окончании. Естественно, информацию личного характера выкладывать не буду.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #75 : 09-05-2010 15:23 » 

Лекция по составлению алгоритмов и спецификаций для простейших случаев Улыбаюсь

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

Как этим пользоваться? Рассмотрим на элементарном примере. Допустим, система - это дверь. Соответственно, она может находиться в двух состояниях: открыта или закрыта. И над ней можно выполнять три действия: открыть или закрыть, а также узнать текущее состояние. Поскольку алгоритм должен переводить систему из одного состояния в другое, для двери возможно составить 2 алгоритма, каждый из которых состоит лишь из 1 действия.

Предусловие А: дверь открыта.
Алгоритм А: закрыть дверь.
Постусловие А: дверь закрыта.

Предусловие Б: дверь закрыта.
Алгоритм Б: открыть дверь.
Постусловие Б: дверь открыта.

Отсюда видно влияние пред- и постусловий на возможность применения алгоритмов. Совершенно очевидно, что открытую дверь нельзя открыть ещё раз, перед этим не закрыв, и нельзя закрыть уже закрытую дверь. Т.е. к предусловию А алгоритм Б просто не подходит - возникнет логическая ошибка при исполнении.

Но алгоритмы могут быть и более сложными, например:

Алгоритм В: закрыть дверь, открыть дверь.
Алгоритм Г: закрыть дверь, открыть дверь, закрыть дверь.

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

Если ослабляется (т.е. уменьшается количество ограничений) предусловие или усиливается (т.е. увеличивается количество ограничений) постусловие - алгоритм должен становиться сложнее, если наоборот - алгоритм можно упростить.

Например, если предусловие "дверь открыта", то более слабое предусловие "дверь открыта или закрыта" или, другими словами, "дверь находится в любом состоянии". Усиление происходит в обратном направлении: от безразличия мы должны перейти к определённости.

Посмотрим, как это влияет на алгоритмы:

Предусловие: дверь открыта или закрыта.
Алгоритм: закрыть дверь.
Постусловие: дверь закрыта.

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

Предусловие: дверь открыта или закрыта
Алгоритм: ЕСЛИ дверь открыта ТО закрыть дверь КОНЕЦ ЕСЛИ
Постусловие: дверь закрыта

Пока что у нас дверь открывалась и закрывалась бессмысленно - не обсуждался вопрос, зачем её открывать или закрывать. Чтобы на такой вопрос получить ответ, систему с дверью нужно поместить в контекст другой системы. Например, система "дверь к врачу". К врачу потому, что такая дверь не бывает постоянно открыта, чтобы не мешать проходу, как это бывает, например, в магазинах, дверь у врача специально предназначена для возможности сохранения врачебной тайны.

В этом новом контексте уже имеет смысл ситуация:

Предусловие: дверь закрыта.
Алгоритм: открыть дверь, закрыть дверь.
Постусловие: дверь закрыта.

Такой алгоритм служит для впускания или выпускания посетителя, и не является ненужным усложнением. Но, как я выше говорил, любой алгоритм должен менять состояние системы. А этого в данной ситуации не видно.

Нужно добавить в систему посетителя. Посетитель умеет входить и выходить и может быть в двух состояниях: снаружи и внутри. К нему можно применить аналогичные рассуждения, что и к двери - подробно расписывать не буду, думаю, это очевидно. Возникает вопрос, как увязать посетителя и дверь между собой.

Попробуем сопоставить состояния:
ЗВ: дверь закрыта и посетитель внутри - возможно;
ЗС: дверь закрыта и посетитель снаружи - возможно;
ОВ: дверь открыта и посетитель внутри - возможно;
ОС: дверь открыта и посетитель снаружи - возможно.
Лишних состояний нет. Если бы мы к двери добавили замок с состояниями отперт и заперт, то очевидно, что состояние, когда дверь открыта и замок заперт хотя и возможно, но бессмысленно, смысл имеет только запертый замок у закрытой двери.

Раз нет лишних состояний, нужно подумать, какие допустимы комбинации действий. Для этого нужно исследовать, как могут меняться состояния, и какие действия при этом выполняются.

Например, если предусловие - ЗВ, а постусловие - ЗС, то возможны алгоритмы:
ЗВ-ЗС-1: посетитель выходит;
ЗВ-ЗС-2: открыть дверь, посетитель выходит, закрыть дверь;
ЗВ-ЗС-3: посетитель выходит, открыть дверь, закрыть дверь;
ЗВ-ЗС-4: открыть дверь, закрыть дверь, посетитель выходит;
и другие более длинные комбинации. Тут здравый смысл говорит, что из всех вариантов подходит только ЗВ-ЗС-2, так как посетитель может войти или выйти лишь через открытую дверь. Но здравый смысл хорошо работает только в очевидных случаях вроде этого, а более сложные и неочевидные случаи могут потребовать больших раздумий, какой из вариантов лучше выбрать - чтобы это решить, нужно очень хорошо понимать, что происходит.

Или, например, если предусловие - ЗВ, а постусловие - ОВ, то возможны алгоритмы:
ЗВ-ОВ-1: открыть дверь;
ЗВ-ОВ-2: посетитель выходит, открыть дверь, посетитель входит;
ЗВ-ОВ-3: открыть дверь, посетитель выходит, посетитель входит;
ЗВ-ОВ-4: посетитель выходит, посетитель входит, открыть дверь;
и другие более длинные комбинации. Здесь уже допустимы как ЗВ-ОВ-1, так и ЗВ-ОВ-3.

Что ещё интересно: посетитель может выполнять своё действие только при состоянии открытой двери. Значит можно сформулировать правило: прежде, чем посетитель выполняет свои действия, дверь нужно открыть. По контексту, поскольку дверь ведёт к врачу, мы договорились, что в конце концов она должна закрываться - это будет в самом конце любого алгоритма.

Посредством формулировки таких утверждений о порядке действий начинают проступать особенности всего множества осмысленных алгоритмов по данной теме. Но чтобы не делать утомительного перечисления всех этих алгоритмов, можно свести их к формуле - для этого понадобятся переменные.

Обозначим Z состояние двери, а Y состояние посетителя. Через ~Z и ~Y обозначим противоположные состояния. Например, если Z - дверь открыта, то ~Z - дверь закрыта, если же Z - дверь закрыта, то ~Z - дверь открыта. Соответственно, формула алгоритмов:

Предусловие: Z
Какой-то алгоритм.
Постусловие: ~Z

подходит как для описания открытия, так и для описания закрытия двери. Или, как говорят, формула инвариантна относительно содержания действия, а её абстрактный смысл - измнение состояния системы на противоположное.

В нашем случае имеется:

Предусловие: Z и Y.
Шаги алгоритма.
Постусловие: дверь закрыта и ~Y.

Шаги алгоритма должны приводить к изменению состояния, описываемого исходным предусловием, чтобы получить окончательное постусловие.

Один шаг
Предусловие: Z
Постусловие: дверь закрыта
Если Y не упоминается, то для этого шага значение переменной не имеет значения.

Другой шаг
Предусловие: дверь открыта и Y
Постусловие: дверь открыта и ~Y.

Теперь попробуем сложить:

Предусловие: Z и Y
   Шаг 1, предусловие: Z
   Шаг 1, постусловие: дверь закрыта
   Шаг 2, предусловие: дверь открыта и Y
   Шаг 2, постусловие: дверь открыта и ~Y
Постусловие: дверь закрыта и ~Y

Как говорилось, в алгоритме каждое постусловие и следующее за ним предусловие не должны друг другу противоречить. Также не должны противоречить внешнее и первое вложенное предусловия, внешнее и последнее вложенное постусловия. Здесь это не соблюдается: постусловие шага 1 противоречит предусловию шага 2, постусловие шага 2 противоречит общему постусловию - значит нужно попробовать переставлять шаги, чтобы максимально уменьшить противоречия.

Предусловие: Z и Y
   Шаг 1, предусловие: дверь открыта и Y
   Шаг 1, постусловие: дверь открыта и ~Y
   Шаг 2, предусловие: Z
   Шаг 2, постусловие: дверь закрыта
Постусловие: дверь закрыта и ~Y

Положение улучшилось: все прежние противоречия устранились. Но появилось новое противоречие между общим предусловием и предусловием шага 1. Перестановка шагов ухудшит положение, значит остаётся лишь одно средство - добавить ещё один шаг, который снимает противоречие.

Предусловие: Z и Y
   Шаг 1, предусловие: Z
   Шаг 1, постусловие: дверь открыта
   Шаг 2, предусловие: дверь открыта и Y
   Шаг 2, постусловие: дверь открыта и ~Y
   Шаг 3, предусловие: Z
   Шаг 3, постусловие: дверь закрыта
Постусловие: дверь закрыта и ~Y

Теперь не осталось противоречий, и можно писать алгоритм. Но можно ещё обратить внимание, что постусловие шага 2 в части Z сильнее, чем предусловие шага 3. Если в конце шага 2 дверь гарантированно открыта, то в начале шага 3 она не может быть открытой или закрытой - она точно открыта. Поэтому мы смело можем усилить предусловие шага 3 и, как в самом начале говорилось, это приведёт к упрощению алгоритма на шаге 3.

Предусловие: Z и Y
   Шаг 1, предусловие: Z
   Шаг 1, постусловие: дверь открыта
   Шаг 2, предусловие: дверь открыта и Y
   Шаг 2, постусловие: дверь открыта и ~Y
   Шаг 3, предусловие: дверь открыта
   Шаг 3, постусловие: дверь закрыта
Постусловие: дверь закрыта и ~Y

Осталось только подставить нужные алгоритмы, которые, записанные в порядке следования, дадут нам общий алгоритм:

Шаг 1, алгоритм: ЕСЛИ дверь закрыта ТО открыть дверь КОНЕЦ ЕСЛИ
Шаг 2, алгоритм: посетитель входит (или посетитель выходит)
Шаг 3, алгоритм: закрыть дверь

Теперь алгоритм можно закодировать на языке C++. Условимся, что состояния описываются переменными (z и y) логического типа (bool), и константа true соответствует открытой двери и посетителю внутри. Договоримся описать алгоритм в отдельной функции, которой будем передавать ссылки на переменные (т.е. если функция будет менять значения переменных, это будет сказываться на других частях программы). Результата у функции нет (тип void). Назовём функцию "пройти" (go).

Вот это всё вышеперечисленно: пред- и постусловия, шаги алгоритма на русском языке, выбор способа кодирования - решения о том, как сказанное на русском языке, будет выражено в коде - вот это всё называется спецификацией. По ней можно совершенно точно написать требуемый участок кода:

Код: (C++)
void go(bool &y, bool &z)
{
   // Шаг 1
   if(!z)
   {
      z = true;
   }

   // Шаг 2
   y = !y;

   // Шаг 3
   z = false;
}

Естественно, хоть сколь-нибудь опытный программист в подавляющем большинстве случаев всё это не расписывает, и такие соображения и доводы приходят к нему автоматически. Начинающим же именно нужно попробовать так подробно порассуждать, пока у них не выработается соответствующий навык мышления.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Sla
Модератор

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #76 : 09-05-2010 15:35 » 

Dimka, Продолжение будет?
Начало

Записан

Мы все учились понемногу... Чему-нибудь и как-нибудь.
LELECHKA
Участник

by
Offline Offline
Пол: Женский

« Ответ #77 : 09-05-2010 16:23 » 


Dimka, можешь сбросить мой алгоритм.
Записан

Все можно познать, только не самого себя. (Стендаль)

Мудр не тот, кто знает много, а тот, чьи знания полезны. (Эсхил)

Победа над страхом придает нам силы. (Виктор Гюго)
Sla
Модератор

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #78 : 09-05-2010 16:32 » 

LELECHKA, мне это напоминает - ну напишите, дядечка!!!


Оффтоп!
Дядечка, здесь потратил не малый труд, чтоб довести до тебя свои знания, разжевал. Так может он еще и сам съест? Так ему вроде и не надо.


По делу. ( я со стороны постороннего наблюдателя)
Dimka, тебя просит элементарных вещей - рассказать СЛОВАМИ, что ты делаешь, без перехода на void  и прочие конструкции кода.



Записан

Мы все учились понемногу... Чему-нибудь и как-нибудь.
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #79 : 09-05-2010 17:00 » 

Sla, продолжение - по обстоятельствам.

А про алгоритм ты не понял, поэтому зря к ней цепляешься. Речь шла про её алгоритм, который она мне в приват отправила. Я на него смотрел-смотрел, думал-думал и разразился Улыбаюсь Вот алгоритм, чтобы было понятно, о чём речь:

Цитата: LELECHKA
Я начну с удаления всех исполненных договоров, предшествующих заданной дате.

1. Открыть файл (в режиме “w+t”). Если попытка открыть файл была безуспешной, вывести сообщение об ошибке.
2. Определить позиции 2 записей: дата исполнения договора и дата оформления договора.
3. Сравнить 2 записи: дата оформления договора и дата исполнения договора.
Если дата исполнения договора=дате оформления, то договор считается исполненным.
Иначе вывести, что исполненных договоров нет.
3. Определить позицию исполненного договора.
4. Затем сравнить 2 следующие записи: дату исполненного договора с заданной датой.
Если дата исполненного договора<заданной, удалить все записи с исполненными       договорами.
Мне не очень нравится то, что я написала.
Я не понимаю, как обозначить исполненный договор? У меня почему-то напрашивается переменная и в то же время, мне кажется что это бессмысленно.
В файле может хранится информация о  нескольких покупателях, а не об одном, поэтому структура должна определятся не как Furniture furniture, а Furniture furniture [MAX], наверное.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Sla
Модератор

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #80 : 09-05-2010 17:11 » 

Я отцепился...

Как по мне, я не знаю даты приведенного тобой послания,
ошибка вот здесь:

исполненный договор, насколько я поняла,это  когда дата исполнения=дате оформления

может вы уже выяснили принцип "исполненности" договора. Но...
А если поставить вопрос - удалить "такой-то" договор. Что изменится?
Записан

Мы все учились понемногу... Чему-нибудь и как-нибудь.
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #81 : 10-05-2010 21:37 » 

В memorize:

Цитата: LELECHKA
Предусловие: файл открыт или закрыт/запись активна или удалена

Предусловие 1: файл открыт или закрыт
Алгоритм 1: ЕСЛИ файл закрыт ТО открыть файл КОНЕЦ ЕСЛИ
Постусловие 1: файл открыт

Предусловие 2: курсор находится на позиции какой-нибудь записи или в конце файла
Алгоритм 2: ЕСЛИ курсор находится на позиции какой-нибудь записи ТО прочитать структуру в позиции курсора и сдвинуть курсор к следующей записи КОНЕЦ ЕСЛИ
Постусловие 2: структура прочтена в позиции курсора

Предусловие 3: структура прочтена  в позиции курсора или курсор находится на позиции какой-нибудь записи
Алгоритм 3: ЕСЛИ структура прочтена в позиции курсора ТО записать структуру в позиции курсора и сдвинуть курсор к следующей записи КОНЕЦ ЕСЛИ
Постусловие 3: структура записана в позиции курсора

Предусловие 4: запись активна или удалена
Алгоритм 4: ЕСЛИ запись активна ТО извлечь дату исполнения договора и дату оформления договора КОНЕЦ ЕСЛИ
Постусловие 4: дата исполнения договора и дата оформления договора извлечены

Предусловие 5: дата исполнения договора <,>,= даты его оформления
Алгоритм 5: ЕСЛИ дата исполнения договора<даты оформления договора ТО извлечь дату исполнения договора КОНЕЦ ЕСЛИ
Постусловие 5: дата исполнения договора извлечена

Предусловие 6: дата исполнения договора (извлеченная) < или > заданной даты
Алгоритм 6: ЕСЛИ дата исполнения договора<заданной ТО удалить текущую запись и сдвинуть курсор на указанную позицию КОНЕЦ ЕСЛИ
Постусловие 6: запись удалена

Постусловие: файл закрыт и запись удалена

Я не уверена в правильности алгоритма 6: прежде, чем удалять запись наверное необходимо узнать позицию курсора, ведь он может находиться не именно в этом месте.
Подчеркнуто то, в чем я не уверена.

Sla, видишь, на лету схватывает! Нет проблем с логичностью, нет проблем с техникой, есть проблема с целеполаганием и предметной областью.

P.S. Но оригинальное мышление, чёрт побери Улыбаюсь Однажды я слышал мнение, что первым языком программирования лучше брать Prolog - тогда мне эта идея показалась не очень хорошей. Но в данном случае это именно то, что нужно - там целеполагание в чистом виде. Жаль, что придётся оставаться с C++. Попробую развивать тему пред- и постусловий, раз так хорошо пошло.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #82 : 13-05-2010 12:31 » 

Вести с невидимого фронта и результаты незримых боёв Улыбаюсь

Попробовали определиться с понятиями файла, позиции в файле и текущей позиции (курсора), записи, поля. А также разобраться с разницей между диском и памятью, почему и в каких случаях нужно копировать данные между памятью и диском. Ещё раз отдельно разобрали, что удалённая запись - это не "дырка в файле" и не "вынутая из колоды карта", а по-прежнему существующая запись, имеющая заранее условленную пометку об удалении, например, пустую строку в имени покупателя.

Последний вариант:
Цитата: LELECHKA
Предусловие: файл открыт или закрыт/запись активна или удалена

Предусловие 1: файл открыт или закрыт
Алгоритм 1: ЕСЛИ файл закрыт ТО открыть файл КОНЕЦ ЕСЛИ
Постусловие 1: файл открыт

Предусловие 2: курсор находится на позиции какой-нибудь записи или в конце файла
Алгоритм 2: ЕСЛИ курсор находится на позиции какой-нибудь записи ТО прочитать структуру в позиции курсора и сдвинуть курсор к следующей записи КОНЕЦ ЕСЛИ
Постусловие 2: структура прочтена в позиции курсора

Предусловие 3: структура прочтена  в позиции курсора или курсор находится на позиции какой-нибудь записи
Алгоритм 3: ЕСЛИ структура прочтена в позиции курсора ТО сохранить структуру в позиции курсора и сдвинуть курсор к следующей записи КОНЕЦ ЕСЛИ
Постусловие 3: структура сохранена в позиции курсора

Предусловие 4: запись активна или удалена
Алгоритм 4: ЕСЛИ запись активна ТО извлечь дату исполнения договора и дату оформления договора КОНЕЦ ЕСЛИ
Постусловие 4: дата исполнения договора и дата оформления договора извлечены

Предусловие 5: дата исполнения договора <,>,= даты его оформления
Алгоритм 5: ЕСЛИ дата исполнения договора<даты оформления договора ТО скопировать дату исполнения договора КОНЕЦ ЕСЛИ
Постусловие 5: дата исполнения договора сохранена

Предусловие 6: дата исполнения договора < или > заданной даты
Алгоритм 6: ЕСЛИ дата исполнения договора<заданной ТО удалить текущую запись и сдвинуть курсор на указанную позицию КОНЕЦ ЕСЛИ
Постусловие 6: запись удалена

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

Поэтому будем двигаться дальше:

Дополнение к лекции

Выше говорилось, что алгоритм должен изменять состояние системы, и вся тройка - предусловие, алгоритм и постусловие - связывается между собой воедино через состояние: предусловие описывает, каково всё в начале, до выполнения алгоритма; алгоритм описывает, что делается, чтобы состояние изменилось; постусловие описывает, как изменилось состояние в конце, после выполнения алгоритма.

Рассмотрим два примера:

Пример 1.
Предусловие: дверь закрыта.
Алгоритм: открыть дверь.
Постусловие: дверь открыта.

Пример 2:
Предусловие: дверь закрыта или открыта
Алгоритм: ЕСЛИ дверь закрыта ТО открыть дверь, посетитель выходит КОН
Постусловие: посетитель снаружи

В обоих примерах предусловие, алгоритм и постусловие не противоречат друг другу. И отсутствие таких противоречий необходимо для правильного алгоритма, но этого мало.

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

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

Как это исправить? Договоримся в самом начале перечислять объекты и их свойства, которые используются в предусловии, и затем проверять, что в алгоритме и постусловии не появились новые и не исчезали имеющиеся в списке объекты и свойства. Перепишем примеры:

Пример 1.
Объекты(свойства): дверь(закрытость)
Предусловие: дверь закрыта
Алгоритм: открыть дверь
Постусловие: дверь открыта

Не изменилось.

Пример 2:
Объекты(свойства): дверь(закрытость), посетитель(местоположение)
Предусловие: дверь закрыта или открыта и посетитель внутри
Алгоритм: ЕСЛИ дверь закрыта ТО открыть дверь, посетитель выходит КОН
Постусловие: дверь открыта и посетитель снаружи

Добавили существенные элементы в пред- и постусловие.
« Последнее редактирование: 13-05-2010 12:33 от Dimka » Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Sla
Модератор

ua
Offline Offline
Пол: Мужской

WWW
« Ответ #83 : 13-05-2010 13:17 » 

Нечестно!!!
Мы бы вам не мешали...
Записан

Мы все учились понемногу... Чему-нибудь и как-нибудь.
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #84 : 13-05-2010 18:32 » 

Цитата: LELECHKA
Предусловие: файл открыт или закрыт/запись активна или удалена

Предусловие 1: файл открыт или закрыт
Алгоритм 1: ЕСЛИ файл закрыт ТО открыть файл КОНЕЦ ЕСЛИ
Постусловие 1: файл открыт

Предусловие 2: курсор находится на позиции какой-нибудь записи или в конце файла
Алгоритм 2: ЕСЛИ курсор находится на позиции какой-нибудь записи ТО прочитать структуру в позиции курсора и сдвинуть курсор к следующей записи КОНЕЦ ЕСЛИ
Постусловие 2: структура прочтена в позиции курсора

Предусловие 3: структура прочтена или сохранена в позиции курсора и курсор находится на позиции какой-нибудь записи
Алгоритм 3: ЕСЛИ структура прочтена в позиции курсора ТО сохранить структуру в позиции курсора и сдвинуть курсор к следующей записи КОНЕЦ ЕСЛИ
Постусловие 3: структура сохранена в позиции курсора и курсор находится на позиции какой-нибудь записи

Предусловие 4: запись активна или удалена
Алгоритм 4: ЕСЛИ запись активна ТО извлечь дату исполнения договора и дату оформления договора КОНЕЦ ЕСЛИ
Постусловие 4: дата исполнения договора и дата оформления договора извлечены

Предусловие 5: дата исполнения договора <,>,= даты его оформления
Алгоритм 5: ЕСЛИ дата исполнения договора<даты оформления договора ТО сохранить дату исполнения договора КОНЕЦ ЕСЛИ
Постусловие 5: дата исполнения договора сохранена

Предусловие 6: дата исполнения договора < или > заданной даты и запись активна
Алгоритм 6: ЕСЛИ  дата исполнения договора<заданной удалить текущую запись и сдвинуть курсор к следующей записи КОНЕЦ ЕСЛИ
Постусловие 6: записи удалены

Постусловие: записи об исполненных договорах удалены и файл закрыт


В алгоритме №6, может нужен цикл,  напишу как я понимаю: если дата исполнения договора<заданной даты, удалять текущие записи до тех пор,  пока все записи, соответствующие условию не будут удалены. Соответственно в Постусловие 6 будет написано: записи удалены. Но оно мне все равно не нравится.
Про цикл ты догадываешься правильно. Но, когда я тебе говорил, что поправить, я специально подчеркнул, что множество записей и одна запись - это разные объекты.

И кроме того, я просил выписывать объекты и их свойства явным образом - этого ты пока не сделала.

Смотрим на самый верхний уровень:

Предусловие: файл открыт или закрыт/запись активна или удалена
Постусловие: записи об исполненных договорах удалены и файл закрыт

Какие тут объекты и их свойства?
« Последнее редактирование: 13-05-2010 18:37 от Sla » Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #85 : 14-05-2010 20:34 » 

Цитата: LELECHKA
Объекты (свойства):  ФАЙЛ (открытость) / СТРУКТУРА ( …)
Предусловие: файл открыт или закрыт/записи об исполненных договорах активны или удалены

Объекты (свойства):  ФАЙЛ (открытость)
Предусловие 1: файл открыт или закрыт
Алгоритм 1: ЕСЛИ файл закрыт ТО открыть файл КОНЕЦ ЕСЛИ
Постусловие 1: файл открыт

Объекты (свойства):  КУРСОР (местоположение) / СТРУКТУРА (…)
Предусловие 2: курсор находится на позиции какой-нибудь записи или в конце файла
Алгоритм 2: ЕСЛИ курсор находится на позиции какой-нибудь записи ТО прочитать структуру в позиции курсора и сдвинуть курсор к следующей записи КОНЕЦ ЕСЛИ
Постусловие 2: структура прочтена в позиции курсора,  курсор находится на позиции какой-нибудь записи

Объекты (свойства):  КУРСОР (местоположение) / СТРУКТУРА (…)
Предусловие 3: структура прочтена или сохранена в позиции курсора и курсор находится на позиции какой-нибудь записи
Алгоритм 3: ЕСЛИ структура прочтена в позиции курсора ТО сохранить структуру в позиции курсора и сдвинуть курсор к следующей записи КОНЕЦ ЕСЛИ
Постусловие 3: структура сохранена в позиции курсора  и курсор находится на позиции какой-нибудь записи

Объекты (свойства):  ЗАПИСЬ (…) / ДАТА (…)
Предусловие 4: запись активна или удалена
Алгоритм 4: ЕСЛИ запись активна ТО извлечь дату исполнения договора и дату оформления договора КОНЕЦ ЕСЛИ
Постусловие 4: дата исполнения договора и дата оформления договора извлечены

Объекты (свойства):  ДАТА (…)
Предусловие 5: дата исполнения договора <,>,= даты его оформления
Алгоритм 5: ЕСЛИ дата исполнения договора<даты оформления договора ТО сохранить дату исполнения договора КОНЕЦ ЕСЛИ
Постусловие 5: дата исполнения договора сохранена

Объекты (свойства):  ДАТА (…) / СТРУКТУРА (…)
Предусловие 6: дата исполнения договора < или > заданной даты
Алгоритм 6: ЕСЛИ  дата исполнения договора<заданной ТО удалять текущие записи до тех пор, пока все записи, соответствующие условию, не будут удалены КОНЕЦ ЕСЛИ
Постусловие 6: записи удалены


Постусловие: записи об исполненных договорах удалены и файл закрыт


Там, где я не могу сформулировать свойства, я ставила многоточие. Изменения я подчеркивала.
Я все еще путаюсь, где у меня 2 объекта, а где один.

Например:


Объекты (свойства):  СТРУКТУРА (…) / ДАТА (…)
Предусловие 4: запись активна или удалена, даты не извлечены
Алгоритм 4: ЕСЛИ запись активна ТО извлечь дату исполнения договора и дату оформления договора КОНЕЦ ЕСЛИ
Постусловие 4: запись активна, дата исполнения договора и дата оформления договора извлечены


Объекты (свойства):  ДАТА (…) / СТРУКТУРА (…)
Предусловие 6: дата исполнения договора < или > заданной даты, запись активна
Алгоритм 6: ЕСЛИ  дата исполнения договора<заданной ТО удалять текущие записи до тех пор, пока все записи, соответствующие условию, не будут удалены КОНЕЦ ЕСЛИ
Постусловие 6: дата исполнения договора < заданной даты, записи удалены

Можно так оставить?
Можно считать, что запись и поле записи - это разные объекты. Но с одной оговоркой. Если меняется значение поля, то, соответственно, меняется и содержание записи (так как поле находится внутри записи, является составной частью записи).


В пункте 5 ты куда-то сохраняешь дату. Куда? И вообще, как я говорил, чтение происходит откуда-то (например, из файла) куда-то (например, в переменную) - в этом случае нужно завести вспомогательную переменную. Тогда результат прочтения будет относиться не к записи ("запись прочтена"), а к содержанию файла в позиции курса и переменной. Текущая запись в файле будет содержать ту же информацию, что и запись в переменной, и именно это тождество информации - лучшее свидетельство успешного прочтения. Аналогично с сохранением, только в обратную сторону. В пункте 4 у тебя фигурируют и поле, и запись, в пункте 5 остаётся одно поле, но при этом операция сохранения "подвисает".

Отсюда же следует ответ по поводу твоих многоточий. Ответь себе на вопрос, в каких операциях у тебя используются даты и структуры, что ты хочешь при выполнении этих операций уточнить, изменить и оставить без изменения? Ответ на это "что?" даст ответ на твой вопрос.

Ещё у меня сохраняется стойкое подозрение к тому, что слова "запись" и "структура" тебе кажутся чем-то разным, хотя я уже дважды говорил, что это одно и то же, и во избежание путаницы настоятельно посоветовал выбрать и использовать какое-нибудь одно слово.

Используй переменные - это хорошие объекты для пред- и постусловий.


Посмотри внимательно на пункт 2. Есть одно замечательное правило: на всякое ЕСЛИ-ТО существует ИНАЧЕ. Т.е. можно так записать:

Предусловие 2: курсор находится на позиции какой-нибудь записи или в конце файла
Алгоритм 2: ЕСЛИ курсор находится на позиции какой-нибудь записи ТО прочитать структуру в позиции курсора и сдвинуть курсор к следующей записи ИНАЧЕ ничего не делать КОН

Т.е. при наличии ЕСЛИ всегда возможны два варианта развития событий. В твоём случае при одном из вариантов ничего не меняется. Постусловие должно подходить для обоих вариантов одновременно. Подумай над своимими постусловиями 2, 3, 4 и 5.


Наконец, по поводу цикла... Я пока не знаю, как к нему тебя подвести, так как ещё не всё разобрано с пред- и постусловиями. Поэтому сделаем иначе. Сначала опишем вспомогательный алгоритм удаления одной записи, а потом будем им пользоваться, когда будем писать цикл.

Объекты: файл(открытость), курсор(местоположение), запись(активность)
Предусловие: файл открыт, курсор находится в позиции записи, запись активна
Вспомогательный алгоритм 1: ?
Постусловие: файл открыт, курсор находится в позиции записи или в конце файла, запись активна или удалена

Попробуй составить шаги алгоритма. Они у тебя уже в основном имеются, нужно только их подставить в правильном порядке и подправить то, о чём у меня сказано выше.


P.S. Складывается впечатление, что происходит информационная перегрузка. Много мелких деталей - в них происходит путаница. И всё из-за того, что отсутствует видение общей цели и стремления к ней. Вместо самостоятельного устремления к получению результата, при котором мелкие вопросы "отваливаются" сами собой, получается, что я будто ставлю рогатки и подпорки - лишь бы удержать движение в нужном направлении, а без этого всё расползается во все стороны. Над этим мне нужно подумать и искать новый подход...
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #86 : 18-05-2010 21:03 » 

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

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

В UML известна Activity Diagram, позволяющая довольно много: обозначить участвующие в алгоритме объекты и показать, какие действия с какими объектами выполняются, обозначить состояния данных между шагами алгоритма. Недостаток её в том, что, во-первых, нужно изучать её графическую нотацию, во-вторых, в ней сложно показать состояние всей системы.

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

Предлагаю за основу взять трассировочную таблицу и расширить её возможностями Activity Diagram.

Например, вывод содержимого файла на экран можно описать так:



В начале идёт заголовок. В первой строке идут названия объектов. Во второй строке - под каждым объектом один или несколько столбцов его свойств.

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

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

При написании циклов используется операция безусловного перехода вида [См. № N], где N - номер строки соответствующего действия. Переход всегда записывается в том столбце, в котором находится действие в строке N.

Для наглядности действия можно выделять, чтобы они не терялись на фоне состояний. Для циклов и условий можно пририсовывать стрелки.


Предлагаю попробовать записать таким способом в начале алгоритм добавления новой записи в конец файла, затем, если получится, попробовать алгоритм удаления.

Предлагаю разделить действия чтения/сохранения и перемещения курсора. По факту в функциях fread и fwrite они совмещены, но это обстоятельство мешает соблюдать принцип одного действия в один момент времени, так как затрагивает сразу многие свойства объектов. В предложенной схеме движение курсора и так меняет как позицию курсора, так и состояние текущей записи. Возможно я не очень хорошо продумал эту часть и можно изобрести какую-то объединяющую сущность... Буду рад предложениям на этот счёт.

P.S. Может будет удобнее составлять таблицу на бумаге от руки карандашом, тогда нужна будет фотография листа или скан.

* alg-tab.PNG (33.95 Кб - загружено 2857 раз.)
« Последнее редактирование: 18-05-2010 21:18 от Dimka » Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Страниц: 1 2 [3]  Все   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines