Решение практических задач на Паскале. Выпуск 1


Уважаемые подписчики! Извиняюсь за долгое (мягко говоря) молчание

Семестр выдался, однако ... И, тем не менее, начинаю.

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

  1. У меня набрались кое-какой опыт решения задач, который может заинтересовать и других. Я по образованию физик, который  настоящее время занимается математическим моделированием полупроводниковых технологий и приборов.
  2. В основном я отвечаю на вопросы в Гостевой книге сайта, посвященного программированию на Паскале. И, естественно, заметил, что вопросы стали повторяться. Отсюда вывод: те ответы, для которых нужно место, или показались просто интересными, давать здесь. В этой рассылке.
  3. Естественно, что и здесь можно задавать любые вопросы относительно семейного положения, алгоритмов, размера приданного дочери и программирования в Паскале.

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

Write('Введите значение какой-нибудь фигни');
ReadLn(Fignja);
А тем не менее, производя расчеты с помощью ЭВМ удобно, чтобы вся информация, необходимая для вычислений, содержалась в отдельном файле, из которого Ваша программа ее считывает.

Причин несколько:

  1. Работая в диалоговом режиме, то есть вводя числа с клавиатуры по запросу программы, Вы существенно замедляете работу ЭВМ.
  2. Трудно исправить введенные числа.
  3. Если нужно повторить расчеты, изменив только одно число из многих, приходится вводить все.
  4. Нелегко бывает вспомнить, какие значения параметров задавали в предыдущий раз.
Как работать с файлами, написано уже немало. Писал на эту тему и наш Олег Чарышкин. Его статьи можно найти в архиве нашей рассылки

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

Решим для определенности задачу: рассчитать значения некоторой функции в заданных пределах и с заданным шагом. Результаты записать в в виде таблицы в файл. (Когда я решал подобные задачи на Паскале, я пришел к разумному выводу, что одна и та же программа не должна и считать и отображать. Гораздо удобнее разделить функции. Отображать график функции, записанной в виде таблицы в текстовый файл, должна программа отдельная программа).

Код простенькой "решающей" программы. Пояснения в виде комментариев и ниже:

program Solv001;
uses CRT;
var
 inFileName: String;
 outFileName: String;
 a, b, h: Real;

TYPE
  TMyFunction = function (xx: Real): Real;  
{Такой тип переменной, ее в Паскале называют "процедурным типом"
 позволит одной процедурой рассчитывать графики 
 различных функций}

function ReadParams: Boolean;
const
  space = ' ';
var
  F_TEXT: Text;
begin
  ReadParams:=False; {Это значение по умолчанию}
  Assign(F_Text, inFileName); 
  {$I-} Reset(F_Text); {$I+}
  if IOResult <> 0 then begin
    WriteLn('Не могу открыть файл ', inFileName);
    ReadKey;
  end;
  {При чтении тоже могут быть ошибки. Например, поставьте вместо 
   "англоязычной" разделительной точки "русскоязычную" запятую или 
   букву}
  {$I-}
  ReadLn(F_Text, a, b, h, outFileName);
  {$I+}
  if IOResult <> 0 then begin
   WriteLn('Произошла ошибка при чтении данных из файла', inFileName);
   Exit;
  end;
  {В outFileName будет занесено все, что идет после числа, в том числе и пробелы.
   Их надо удалить}
  While pos(space, outFileName) <> 0 do
    delete(outFileName, pos(space, outFileName), 1);
  Close(F_Text);    {Закрывать файл лучше самому}
  ReadParams:=True  {Вот теперь-то и ставим сигнал "Все прошло нормально" }
end;

{Рассчет и вывод}
procedure CalcAndOut(Left, Right, Step: Real; Func: TMyFunction);
var t: Text;
begin
 Assign(t, outFileName);
 Rewrite(t);
 while Left < Right do begin
  WriteLn(t, Left,'  ', Func(Left));
  Left:=left + Step;
  if Left > Right then Left := Right;
 end;
 Flush(t);
 Close(t);
 WriteLn('Расчет и вывод в файл ',outFileName,' закончены')
end;

{Эту функцию будем рассчитывать}
function MySin(x: Real): Real; far;
begin
  MySin:=12*sin(3*x)
end;

BEGIN
  ClrScr;
  if ParamCount = 0 then begin
    WriteLn(' Программе нужно передать параметр: имя файла с данными');
    WriteLn(' ПРИМЕР ЗАПУСКА:');
    WriteLn(' >Solv001.exe solv.dat');

    WriteLn('Для продолжения нажите любую клавишу ...');
    ReadKey;
    WriteLn('Нет, нет, только не эту!');
    Halt(1);
  end;
  inFileName:=ParamStr(1);
  if NOT ReadParams then begin
   WriteLn('Нужно имя существующего файла');
   ReadKey; Halt(1)
  end;
  CalcAndOut(a, b, h, MySin);
END.
Когда запускаете программу из среды разработки программ Borland Pascal, то значение параметра следует задать с помощью меню Run/Parameters...

Если исполняемый файл запускаете в Windows, то значение параметра, файла с исходными данными следует указать в ярлыке, на закладе "Программа".

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

Можно предложить 3 простых варианта организации файла данных. Для этого чтение исходных данных вынесено в отдельную функцию булевского типа. Я назвал ее ReadParams. Тело этой функции я буду менять, показывая другие алгоритмы чтения исходных данных. Эта функция возвращает значение ИСТИНА, если все удалось прочитать правильно, и ЛОЖЬ - если произошла какая-то ошибка

Варианты такие:

  1. все параметры в одной строке - рассмотрен здесь;
  2. исходные данные содержат комментарии;
  3. исходные параметры содержатся в отдельных строках.

 

ВАРИАНТ №1

Числа располагаются в одной строке в определенном порядке. Например:
0.5   100   5.1  out.DAT
что должно означать:

Считать все эти данные можно одним оператором ReadLn:

ReadLn(F_TEXT, a, b, h, outFileName);
Именно это и сделано в примере, который показан выше.

Одна проблема - в outFileName будут считаны лишние пробелы, что для DOS недопустимо. Я удалил их с помощью стандартной функции POS

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

 

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


Вопросы и предложения присылайте Борису

К стати, а Вы знаете, что у нас имеется рассылка, посвященная самым новым и нужным шпаргалкам для студентов и школьников?

Hosted by uCoz