Опубликован: 10.04.2015 | Уровень: для всех | Доступ: свободно | ВУЗ: Компания ALT Linux
Лекция 5:

Использование языка Free Pascal для обработки массивов

< Лекция 4 || Лекция 5: 123456 || Лекция 6 >

ЗАДАЧА 5.10. Задан массив вещественных чисел. Перевести все элементы массива в p-ричную систему счисления.

Перед решением всей задачи давайте разберёмся с алгоритмом перевода ве-щественного числа из десятичной в другую систему счисления. Этот алгоритм можно разделить на следующие этапы:

  1. Выделение целой и дробной частей числа.
  2. Перевод целой части числа в другую систему счисления.
  3. Перевод дробной части числа в другую систему счисления.
  4. Объединение целой и дробной частей числа в новой системе счисления.

Алгоритм перевода целого числа в другую систему счисления

Разделить нацело число на основание новой системы счисления. Получим остаток и частное. Остаток от деления будет младшим разрядом числа. Его необходимо будет умножить на 10 в нулевой степени. Если частное не равно нулю, то продолжим деление; новый остаток даст нам следующий разряд числа, который надо будет умножить на десять в первой степени и т. д. Деление будем продолжать до тех пор, пока частное не станет равным 0. Особенностью алгоритма является то, что число формируется в обратном порядке от младшего разряда к старшему, что позволит в один проход собрать число в новой системе счисления.

Алгоритм перевода дробной части числа в другую систему счисления

Умножить дробную часть числа на основание системы счисления. В полученном произведении выделить целую часть числа, это будет старший разряд числа, который необходимо будет умножить на 10^{1}. Дробную часть опять умножить на основание системы счисления. В произведении целая часть будет очередным разрядом (его надо будет умножить на 10^{-2}), а дробную часть необходимо опять умножить на основание системы счисления до получения необходимого количества разрядов исходного числа.

Блок-схема функции перевода вещественного числа N из десятичной системы счисления в другую систему представлена на рис. 5.42.

Обратите внимание, как в блок-схеме и в функции реализовано возведение в степень. В связи с тем, что при переводе целой части числа последовательно используются степени 10, начиная с 0, для формирования степеней десяти вводится переменная q, которая вначале равна 1, а затем в цикле последовательно умножается на 10. При переводе дробной части числа последовательно нужны отрицательные степени 10 : 10^{-1},10^{-2},.... Поэтому при формировании дробной части числа переменная q:=0.1, которая в цикле последовательно делится на 10.

Ниже приведён текст консольной программы решения задачи 5.10 с комментариями.

Блок-схема функции перевода вещественного числа в p-ричную систему счисления

Рис. 5.42. Блок-схема функции перевода вещественного числа в p-ричную систему счисления
{Функция перевода вещественного числа в p-ричную систему счисления.}
{Входные параметры функции: вещественное число N, основание системы}
{счисления - целое число p, kvo - количество разрядов в дробной части}
{формируемого числа.}
function perevod (N: real; P : word; kvo : word ) : real;
var i,N1, ost : word;
	s1, N2, r, s2 : real;
	q : real;
begin
{Если исходное число отрицательно, то для его перевода рекурсивно}
{обращаемся к функции perevod, передавая в качестве параметра модуль}
{числа.}
if N<0 then r:=- perevod ( abs (N),P, kvo )
else
begin
{Выделяем целую N1 и дробную N2 части вещественного числа N.}
	N1:= trunc (N); N2:= frac (N);
	s1 : = 0; s2 : = 0;
{В переменной q будем последовательно хранить степени десяти, вначале}
{туда записываем 1 - десять в 0 степени, а затем в цикле будем}
{последовательно умножать q на 10.}
q : = 1;
{Перевод целой части числа, пока число не станет равным 0.}
	while (N1<>0) do
	begin
{Вычисляем ost - очередной разряд числа - как остаток от деления N1 на}
{основание системы счисления.}
		ost :=N1 mod P;
{Очередной разряд числа умножаем на 10 в степени i и добавляем к}
{формируемому числу s1.}
		s1 := s1+ost * q;
{Уменьшаем число N1 в p раз путем целочисленного деления на p.}
		N1:=N1 div P;
{Формируем следующую степень десятки.}
		q:=q * 1 0;
	end;
{В переменной q будем последовательно хранить отрицательные степени}
{десяти, вначале туда записываем 0.1 - десять в минус первой}
{степени, а затем в цикле будем последовательно делить q на 10.}
	q : = 0.1;
	for i :=1 to kvo do
	begin
{Умножаем дробную часть на 10.}
		N2:=N2* p;
{Вычисляем очередной разряд числа как целую часть от умножения N2 на}
{основание системы счисления. Очередной разряд числа умножаем на 10 в}
{степени i и добавляем к формируемому числу s2.}
		s2 := s2+trunc (N2) * q;
{Выделяем дробную часть от сформированного числа}
		N2:= frac (N2 );
{Формируем очередную отрицательную степень 10.}
		q:=q / 10;
	end;
{Суммируем целую и дробную часть числа в p-ричной системе счисления.}
	r := s1+s2;
end;
	perevod := r;
end;
var C: array [ 1.. 100 ] of real; p, i, n : word;
begin
{Ввод размера массива.}
	Write( ’ n= ’ ); readln ( n );
{Ввод массива.}
	writeln ( ’Массив C ’ );
	for i :=1 to n do read (C[ i ] );
{Ввод системы счисления.}
	writeln ( ’Введите основание системы счисления ’ ); readln ( p );
{Перевод всех элементов массива в другую систему счисления.}
	for i :=1 to n do
	c [ i ] : = perevod (C[ i ], p, 5 );
{Вывод преобразованного массива.}
	writeln ( ’Преобразованный массив C ’ );
	for i :=1 to n do
	write (C[ i ] : 1 : 5, ’   ’ );
end.
Результаты работы консольной программы решения задачи 5.10

увеличить изображение
Рис. 5.43. Результаты работы консольной программы решения задачи 5.10
ЗАДАЧА 5.11. Из массива целых положительных чисел Y удалить 3 последних числа, цифры которых в восьмеричном представлении образуют убывающую последовательность.

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

Заголовок этой функции будет иметь вид:

function vosem (N: word ) : boolean;

На вход функции vosem приходит целое десятичное число (формальный параметр N). Функция возвращает true, если цифры числа в восьмеричном представлении образуют убывающую последовательность, и false в противном случае.

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

Текст функции с комментариями приведён ниже.

function vosem (N: word ) : boolean;
var pr : boolean;
	tsifra, tsifra_s t : word; i : integer;
begin
	i : = 0;
{Предположим, что цифры числа N в восьмеричном представлении образуют}
{убывающую последовательность.}
pr := true;
{Пока число N не равно 0,}
	while N<>0 do
	begin
{Достаём очередной разряд числа в восьмеричной системе.}
		tsifra:=N mod 8;
{Уменьшаем число в 8 раз.}
		N:=N div 8;
		i := i +1;
{Если разряд не первый}
		if i >1 then
{И текущий разряд меньше или равен предыдущему, цифры числа N в}
{восьмеричном представлении не образуют убывающую последовательность}
{(pr:=false) - аварийно покидаем цикл.}
		if tsifra <=tsifra_st then
		begin
			pr := false;
			break;
		end;
	tsifra_st:= tsifra;
end;
vosem:= pr; end;

Алгоритм решения задачи следующий. Перебираем все числа в массиве в обратном порядке. Проверяем, образуют ли цифры текущего элемента массива в восьмеричном представлении убывающую последовательность. Если образуют, то количество таких чисел (k) увеличиваем на 1. Если k \le 3, то удаляем текущий элемент массива.

Создадим визуальное приложение, предназначенное для решения задачи 5.11. Расположим на форме следующие компоненты: три кнопки, три метки, одно поле ввода и две таблицы строк. Расположим их примерно так, как показано на рис. 5.44.

Свойства основных компонентов представлены в таблицах 5.95.10.

Таблица 5.9. Свойства меток, кнопок и текстового поля
Name Caption (Text) Width Visible Left Top
label1 Введите размер массива 153 true 120 46
label2 Исходный массив 110 false 192 96
label3 Преобразованный массив 157 false 192 210
Edit1 7 40 true 288 40
Button1 OK 75 true 376 35
Button2 Удалить числа из файла 185 false 160 448
Button3 Выход из программы 185 false 568 448
Таблица 5.10. Свойства таблиц строк
Name ColCount RowCount Visible FixedCols FixedRows Options.goEditing
StringGrid1 7 1 false 0 0 true
StringGrid2 7 1 false 0 0 false

При запуске приложения видимы метка Label1, поле для ввода размера массива Edit1 и кнопка Button1.

При щелчке по кнопке OK (Button1) из поля ввода Edit1 считывается размер массива и становятся видимыми две другие кнопки, метка label2, таблица строк StringGrid1 для ввода элементов массива. Метка Label1, поле для ввода размера массива Edit1 и кнопка Button1 становятся невидимыми. Окно приложения после щелчка по кнопке OK станет подобным представленному на рис. 5.45.

Форма для решения задачи 5.11

увеличить изображение
Рис. 5.44. Форма для решения задачи 5.11
Окно приложения после щелчка по кнопке ОК

увеличить изображение
Рис. 5.45. Окно приложения после щелчка по кнопке ОК

При щелчке по кнопке Удалить числа из массива происходят следующие действия:

  • считывание массива из StringGrid1;
  • удаление из массива 3-х последних чисел, цифры которых в восьмеричном представлении образуют убывающую последовательность;
  • становятся видимыми метка label3 и таблица строк StringGrid2 для вывода элементов преобразованного массива.

Ниже приведён текст модуля с необходимыми комментариями.

unit Unit1;
{$mode objfpc}{$H+}
interface
uses
	Classes, SysUtils, LResources, Forms, Controls, Graphics,
	Dialogs, StdCtrls, Grids;
{Описание формы.}
type
	{ TForm1 }
	TForm1 = class (TForm)
		Button1 : TButton;
		Button2 : TButton;
		Button3 : TButton;
		Edit1 : TEdit;
		Label1 : TLabel;
		Label2 : TLabel;
		Label3 : TLabel;
		StringGrid1 : TStringGrid;
		StringGrid2 : TStringGrid;
		procedure Button1Click ( Sender : TObject );
		procedure Button2Click ( Sender : TObject );
		procedure Button3Click ( Sender : TObject );
private
	{private declarations}
public
	{public declarations}
end;
type massiv=array [ 1.. 1 0 0 ] of word;
var
	Form1 : TForm1;
	N: word;
	X: massiv;
implementation
{TForm1}
{Функция vosem проверки, образуют ли цифры числа N в восьмеричном}
{представлении убывающую последовательность.}
function vosem (N: word ) : boolean;
var pr : boolean;
	tsifra, tsifra_st : word;
	i : word;
begin
	i : = 0;
{Предположим, что цифры числа N в восьмеричном представлении образуют}
{убывающую последовательность.}
pr := true;
{Пока число N не равно 0,}
	while N<>0 do
	begin
{Достаем очередной разряд числа в восьмеричной системе.}
		tsifra:=N mod 8;
{Уменьшаем число в 8 раз.}
		N:=N div 8;
		i := i +1;
{Если разряд не первый}
		if i >1 then
{и текущий разряд меньше или равен предыдущему, цифры числа N в}
{восьмеричном представлении не образуют убывающую последовательность}
{(pr:=false) - аварийно покидаем цикл.}
		if t s if r a <=t s if r a _ s t then
		begin
			pr := false;
			break;
		end;
		tsifra_st:= tsifra;
	end;
	vosem:= pr;
end;
{Функция удаления из массива X(N) элемента c номером m.}
procedure udal ( var X: Massiv; m: word; var N: word );
var i : word;
begin
	for i :=m to N _1 do
		x [ i ] : = x [ i + 1 ];
	N:=N-1;
end;
{Обработчик щелчка по кнопке ОК.}
procedure TForm1. Button1Click ( Sender : TObject );
begin
{Считываем размер массива из поля ввода.}
	N:= StrToInt ( Edit1. Text );
{Делаем невидимыми первую метку, поле ввода и кнопку ОК.}
	Label1. Visible := False;
	Edit1. Visible := False;
	Button1. Visible := False;
{Делаем видимыми вторую метку и таблицу строк.}
	label2. Visible := True;
	StringGrid1.Visible :=True;
{Устанавливаем количество элементов в таблице строк.}
	StringGrid1.ColCount :=N;
{Делаем видимыми вторую и третью кнопки.}
	Button2. Visible :=True;
	Button3. Visible :=True;
end;
{Обработчик событий кнопки "Удалить числа из массива"}
procedure TForm1. Button2Click ( Sender : TObject );
var k, i : word;
begin
{Считываем массив из таблицы строк.}
	for i :=0 to N -1 do
		X[ i +1]:= StrToInt ( StringGrid1.Cells [ i, 0 ] );
k : = 0;
{Перебираем все элементы массива в обратном порядке.}
	for i :=N -1 downto 0 do
{Если цифры очередного элемента массива в восьмеричном представлении}
{образуют убывающую последовательность,}
		if vosem ( x [ i ] ) then
		begin
{увеличиваем счетчик таких чисел на 1.}
			k:=k+1;
{Если это первое, второе или третье число, удовлетворяющее условию, то}
{удаляем его из массива.}
				if k<=3 then
				udal ( x, i,N);
		end;
{Делаем видимыми третью кнопку и вторую таблицу строк.}
	label3.Visible := True;
	StringGrid2.Visible :=True;
	StringGrid2. ColCount :=N;
{Вывод преобразованного массива.}
	for i :=0 to N _1 do
		StringGrid2. Cells [ i, 0 ] : = IntToStr (X[ i + 1 ] );
end;
{Обработчик кнопки закрытия окна.}
procedure TForm1. Button3Click ( Sender : TObject );
begin
	Close;
end;
initialization
	{$I unit1.lrs}
end.

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

Окно с результатами решения задачи 5.11

увеличить изображение
Рис. 5.46. Окно с результатами решения задачи 5.11

Этой задачей мы заканчиваем раздел, посвящённый обработке массивов, и предлагаем читателю самостоятельно решить несколько задач.

< Лекция 4 || Лекция 5: 123456 || Лекция 6 >
Юрий Шутиков
Юрий Шутиков

По первому тесту выполнил дважды задания. Результат получается правильный (проверял калькулятором). Пишет, что "Задание не проверено" и предлагает повторить. 
 

Евгений Силуков
Евгений Силуков

Еще в декабре выполнил тест №1, а его все так и не проверили.

Юрий Макушин
Юрий Макушин
Россия, Москва, РЭА им. Плеханова, 2004