Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Костюк - Основы программирования

.pdf
Скачиваний:
134
Добавлен:
30.05.2015
Размер:
1.3 Mб
Скачать

201

/*11*/ – попытка чтения из первого файла 1000 байт в массив X, k – количе­

ство прочитанных байт ;

/*12*/ – запись во второй файл k байт из массива X; /*13*/ – увеличение счетчика числа прочитанных байт;

/*15*/ – закрытие файлов; /*16*/ – вывод длины файла.

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

Программа (Б.2) выполняет действия, аналогичные тем, которые описаны в про­ грамме (3.20), и, кроме того, производит дополнительные проверки.

Конец примера.

Пример Б.3. Программа сортировки слиянием линейного списка. Пусть описа­ ние структуры для элемента списка имеет вид:

struct el{int s; struct el *p;};

(Б.3)

Вспомогательная функция (Б.2) слияния двух непустых упорядоченных по воз­ растанию линейных списков реализует на Си алгоритм (3.24).

 

 

void slist(struct el *p11, struct el *p22,

 

struct el **p3)

 

{struct el *p4,*p1,*p2;

 

p1=p11; p2=p22;

 

if (p1->s<=p2->s)

 

{*p3=p1; p4=p1; p1=p1->p;}

 

else {*p3=p2; p4=p2; p2=p2->p;}

(Б.4)

while ((p1!=NULL)&&(p2!=NULL))

if (p1->s<=p2->s)

 

{p4->p=p1; p4=p1; p1=p1->p;}

 

else {p4->p=p2; p4=p2; p2=p2->p;}

 

if (p1!=NULL) p4->p=p1;

 

} else p4->p=p2;

 

В функции slist первые два параметра входные: p11 – указатель на начало первого списка, p22 – указатель на начало второго списка. Третий параметр p3 – выходной: после выполнения процедуры он будет являться указателем на начало объединенного списка, причем в функцию он передается по ссылке (поэтому в его описании имеется две звездочки). Функция конструирует выходной список из эле­ ментов двух входных списков, поэтому после ее исполнения входные списки пере­ стают существовать.

Функция (Б.5) реализует на Си рекурсивный алгоритм сортировки слиянием ли­ нейного списка (4.7).

202

 

 

void sortlist(struct el **p, int n)

 

{struct el *p1, *p2;

 

int k,i;

 

if (n>1)

 

{k=n/2; p1=*p;

 

for (i=1;i<=k-1;i++) p1=p1->p;

(Б.5)

p2=p1->p; p1->p=NULL; p1=*p;

 

sortlist(&p1,k); sortlist(&p2,n-k);

 

} }slist(p1,p2,p);

 

В функции sortlist первый параметр – указатель на начало списка сортиру­ емых элементов – в функцию передается по ссылке. Второй параметр задает количе­ ство элементов списка. Функция конструирует упорядоченный список из элементов входного списка.

Программа (Б.6) вначале вводит количество сортируемых чисел, затем сами эти числа и формирует из них линейный список. После этого с помощью вызова функции sortlist элементы списка упорядочиваются. В конце программы упорядоченные

элементы выводятся. Полный текст программы должен включать директивы:

#include <stdlib.h>

#include <stdio.h>

а также описание структуры (Б.3) и функции (Б.4) и (Б.5).

void main(void)

{int i,n,v;

struct el *p1, *p2, *p3;

scanf("%d",&n); /*ввода числа элементов n*/ p1=malloc(sizeof(struct el)); p2=p1;

/*создан 1–й элемент будущего списка*/

for(i=0;i<n;i++)

 

/*ввод в цикле*/

 

{scanf("%d",&v);

/*элементов и формирование*/

 

p2->s=v;

/*из них списка*/

(Б.6)

if(i<n-1)

/*если не последний элемент списка*/

{p3=malloc(sizeof(struct el));

/*то создание*/

 

}}p2->p=p3; p2=p3; /*еще одного элемента списка*/

 

p2->p=NULL; /*обнуление последней ссылки в списке*/

 

sortlist(&p1,n);

/*вызов функции сортировки списка*/

 

p2=p1;

/*вывод в цикле элементов списка*/

 

while(p2!=NULL)

 

{printf("%d ",p2->s); p2=p2->p;}

 

 

203

}

Конец примера.

Пример Б.4. Программа численного интегрирования произвольной функции од­ ной переменной f (x) на интервале [a, b] методом трапеций путем деления интерва­ ла на n равных частей. Функция интегрирования Integr реализует алгоритм (3.28) из примера 3.25.

float Integr(float (*f)(float), float a, float b, int n)

{int i; float d,s;

s=(f(a)+f(b))/2; d=(b-a)/n; for(i=1;i<n;i++)

s=s+f(a+i*d); }return s*d;

Пусть в программе имеются следующие описания интегрируемых функций:

float f1(float x)

{return exp(sqrt(x));} float f2(float x)

{return sqrt(exp(x));}

(Б.7)

(Б.8)

Пусть также функции занумерованы числами 1 и 2. Тогда программа (Б.9) вводит номер подинтегральной функции, границы интервала и количество частей деления интервала, после чего вычисляет интеграл вызовом функции Integr и выводит вы­ численное значение интеграла. Ее текст должен содержать директивы:

#include <stdio.h>

#include <math.h>

void main(void)

 

 

{float y, a, b; int i,n;

 

 

const float (*f[])(float)={f1,f2};

 

/*описание константного массива функций*/

 

scanf("%d%d%f%f%d",&i,&a,&b,&n);

(Б.9)

y=Integr(f[i-1],a,b,n);

/*ввод входных данных*/

 

/*вычисление интеграла*/

 

printf("%10.5f",y);

/*вывод результата*/

 

}

 

 

204

Конец примера.

Пример Б.5. Пусть программа вводит целое n, после чего генерирует и выводит все возможные перестановки чисел от 1 до n. Генерация перестановок осуще­ ствляется рекурсивным алгоритмом (4.8), который реализован в виде функции per, алгоритм (Б.10). В ней используются глобальные массивы P и R и переменная n.

Перестановка заносится в массив P, начиная с нулевого элемента. В программе (Б.11) в описании массива P указано 20 элементов, поэтому нельзя вводить n > 20 и генерировать перестановки с большим числом элементов.

void per(int k) /*функция генерации перестановок*/

{int i,j; for(i=1;i<=n;i++)

if(R[i]==0)

{P[k]=i; R[i]=1;

if(k==n-1) /*вывод сгенерированной перестановки*/

{for(j=0;j<n;j++)printf(”%3d”,P[j]);

(Б.10)

}printf(”\n”); /* переход к новой строчке вывода*/

 

else per(k+1);

 

 

}R[i]=0;

 

 

 

}

 

 

 

 

 

 

#include <stdio.h>

/*библиотека ввода-вывода*/

 

int n,P[20],R[21]; /*описание глобальных переменных*/

 

void main()

 

 

 

{int i;

 

/*ввод n*/

(Б.11)

scanf(”%d”,&n);

 

for(i=1;i<=n;i++) R[i]=0; /*обнуление массива R */

 

}per(0);

/*вызов функции генерации перестановок*/

 

Конец примера.

Пример Б.6. Программа, вычисляющая определитель квадратной матрицы. Вы­ числение определителя осуществляется функцией Det, которая реализует алгорит­

мы (7.16)–(7.20).

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

205

описанной константой eps. При обращении к элементам матрицы в выражениях

приводится явное вычисление индекса. Так, чтобы обратиться к элементу матрицы Aij в тексте программы записывается: *(A+i*n+j). В функции Det используется

глобальная константа eps, описание которой может иметь вид: const eps=1e-6;

 

 

float Det(int n, float *A)

{int i=0, r=n, p=1, v, j, k; float z;

 

while (i<r)

/*выбор ведущего элемента*/

 

{v=i;

 

for (j=i+1;j<n;j++)

 

 

if (abs(*(A+j*n+i))>abs(*(A+v*n+i))) v=j;

 

if (abs(*(A+v*n+i))<eps) r=i;

 

else

/*перестановка строк*/

 

{if (v!=i)

 

{p=-p;

 

 

for (j=i;j<n;j++)

 

 

{z=*(A+i*n+j); *(A+i*n+j)=*(A+v*n+j);

 

} }*(A+v*n+j)=z;

/*вычитание строк*/

(Б.12)

for (k=i+1;k<n;k++)

 

{z=*(A+k*n+i)/ *(A+i*n+i);

 

}for (j=i;j<n;j++)*(A+k*n+j)-=z* *(A+i*n+j);

 

}i=i++;

 

 

}

/*вычисление определителя*/

 

if (r<n-1) z=0;

 

else

/*по треугольной матрице*/

 

{z=p**A; for (i=1;i<n;i++) z*=*(A+i*n+i);}

 

}return z;

 

 

Ниже приведена главная программа, вызывающая функцию Det.

void main()

{float y, *M; int i, j, n;

scanf("%d",&n); /*ввод размера матрицы*/

 

 

206

 

 

 

 

 

M=malloc(n*n*sizeof(float)); /*выделение памяти*/

 

for(i=0;i<n;i++)

/*ввод элементов матрицы*/

 

 

for(j=0;j<n;j++)

 

(Б.13)

 

scanf("%f",M+n*i+j);

/*вычисление определителя*/

 

 

y=Det(n,M);

 

 

printf("%10.5f",y);

/*вывод результата*/

 

 

}free(M);

/*освобождение памяти*/

 

В программе (Б.13) вначале вводится размер матрицы n, после чего динамиче­ ски выделяется память для n2 элементов матрицы и производится построчно ввод всех n2 элементов. Далее с помощью вызова функции Det вычисляется значение определителя, которое затем выводится. В конце программы выделенная для матри­ цы память освобождается.

В тексте программы (Б.13) должно быть описание функции (Б.12), а также дирек­ тивы препроцессора:

#include <stdio.h>

#include <stdlib.h>

Конец примера.

Приложение В Таблицы кодов ASCII

В.1 Основная таблица ASCII

В таблице код символа вычисляется как сумма номера строки (от 0 до 15) и чис­ ла, которым помечен столбец. Например, код символа '<' равен 12+48=60. Основ­

ная таблица ASCII содержит символы с кодами от 0 до 127, для их записи достаточно 7 бит. При записи кода в байт (8 бит) старший бит полагается равным нулю.

0

16

32

48

64

80

96

112

0

 

 

 

0

@

P

p

1

 

 

!

1

A

Q

a

q

2

 

 

"

2

B

R

b

r

3

 

 

#

3

C

S

c

s

4

 

 

$

4

D

T

d

t

5

 

 

%

5

E

U

e

u

6

 

 

&

6

F

V

f

v

7

 

 

7

G

W

g

w

8

 

 

(

8

H

X

h

x

9

 

 

)

9

I

Y

i

y

10

 

 

*

:

J

Z

j

z

11

 

 

+

;

K

[

k

{

12

 

 

,

<

L

\

l

|

13

 

 

-

=

M

]

m

}

14

 

 

.

>

N

^

n

~

15

 

 

/

?

O

_

o

 

Коды от 0 до 31 соответствуют специальным управляющим символам, код 32 имеет символ пробела, код 127 – символ del (удаление).

208

В.2 Кодовая таблица 866 (MS DOS)

Вторая часть таблицы ASCII содержит символы с кодами от 128 до 255, при за­ писи кода в байт (8 бит) старший бит равен единице. В варианте для MS DOS содер­ жатся русские буквы, символы псевдографики (которые можно использовать для оформления таблиц), а также ряд других символов.

 

128

144

160

176

192

208

224

240

0

А

Р

а

р

Ё

1

Б

С

б

с

ё

2

В

Т

в

т

Є

3

Г

У

г

у

є

4

Д

Ф

д

ф

Ї

5

Е

Х

е

х

ї

6

Ж

Ц

ж

ц

Ў

7

З

Ч

з

ч

ў

8

И

Ш

и

ш

º

9

Й

Щ

й

щ

10

К

Ъ

к

ъ

11

Л

Ы

л

ы

12

М

Ь

м

ь

13

Н

Э

н

э

¤

14

О

Ю

о

ю

15

П

Я

п

я

 

209

В.3 Кодовая таблица 1251 (MS Windows)

Вторая часть таблицы ASCII содержит символы с кодами от 128 до 255, при за­ писи кода в байт (8 бит) старший бит равен единице. В варианте для MS Windows наряду с русскими буквами содержится ряд других символов.

 

128

144

160

176

192

208

224

240

0

Ђ

ђ

 

º

А

Р

а

р

1

Ѓ

Ў

±

Б

С

б

с

2

ў

І

В

Т

в

т

3

ѓ

Ј

і

Г

У

г

у

4

¤

ґ

Д

Ф

д

ф

5

Ґ

µ

Е

Х

е

х

6

‌‌‌

Ж

Ц

ж

ц

 

 

 

‌‌‌

 

 

 

 

 

 

 

 

|

 

 

 

 

 

7

§

·

З

Ч

з

ч

8

Ё

ё

И

Ш

и

ш

9

©

Й

Щ

й

щ

10

Љ

љ

Є

є

К

Ъ

к

ъ

11

«

»

Л

Ы

л

ы

12

Њ

њ

¬

ј

М

Ь

м

ь

13

Ќ

ќ

Ѕ

Н

Э

н

э

14

ћ

ћ

®

ѕ

О

Ю

о

ю

15

Џ

џ

Ї

ї

П

Я

п

я

Литература

По языкам Паскаль и Си существует необъятное число книг и учебников. Ин­ тересны книги автора языка Паскаль Н. Вирта [4, 12] и автора языка Си Д. Ритчи [14]. Книга [19] посвящена языку Си++, который является объектно-ориен­ тированным развитием Си. Для практической работы на компьютере потребуются книги или руководства по конкретному транслятору и операционной системе. Напри­ мер, для работы с транслятором Turbo Pascal можно использовать какую-либо из книг по языку и транслятору [10, 11, 20], а для работы с транслятором Turbo С –

книгу [17].

 

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

[1,

4, 7, 8, 9]. Проблемы технологии программирования обсуждаются в книгах

[2, 6,

12, 16]. О рекуррентных последовательностях и алгоритмах см. в [1, 4, 5]. Об алго­ ритмах сортировки и поиска см. в [5, 14, 17]. О рекурсивных алгоритмах и бэктрекин­ ге см в. [1, 17]. Алгоритмы контекстного поиска имеются в [5, 15, 18]. Алгоритмы с графами имеются в [18]. Вычислительные алгоритмы линейной алгебры см., напри­ мер, в [3, 21].

1.Абрамов С. А. Математические построения и программирование. – М.: Наука, 1978. – 192 с.

2.Брукс Ф. П. мл. Как проектируются и создаются программные комплексы. Ми­ фический человеко-месяц: Пер. с англ. – М.: Мир, 1979. – 159 с.

3.Вержбицкий В.М. Основы численных методов. – М.: Высшая школа, 2002. – 840 с.

4.Вирт Н. Систематическое программирование. Введение: Пер. с англ. – М.: Мир, 1977. – 184 с.

5.Вирт Н. Алгоритмы + структуры данных = программы: Пер. с англ. – М.: Мир, 1985. – 406 с.

6.Гласс Р. Руководство по надежному программированию: Пер. с англ. – М.: Мир, 1982. – 280 с.

7.Грис Д. Наука программирования: Пер. с англ. – М.: Мир, 1984. –416 с.

8.Дал У., Дейкстра Э., Хоор К. Структурное программирование: Пер. с англ. – М.: Мир, 1975. – 245 c.

9.Дейкстра Э. Дисциплина программирования: Пер. с англ. – М.: Мир, 1978. – 275 c.

10.Епанешников А. М., Епанешников В. А. Программирование в среде Turbo Pascal 7.0. – 3-е изд., стер. – М: "ДИАЛОГ-МИФИ", 1995. – 288 с.