">
Информатика Программирование
Информация о работе

Тема: Работа с массивами

Описание: Постановка задачи. Однородные структуры данных. Массивы и матрицы. Реализация массивов в языках программирования. Возможность задания нижнего значения индекса. Интерфейс программы. Прокомментированный текст. Алгоритмизация.
Предмет: Информатика.
Дисциплина: Программирование.
Тип: Курсовая работа
Дата: 22.08.2012 г.
Язык: Русский
Скачиваний: 6
Поднять уникальность

Похожие работы:

МИНИСТЕРСТВО ОБРАЗОВАНИЯ И НАУКИ

РОССИЙСКОЙ ФЕДЕРАЦИИ

МОСКОВСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ

ТЕХНОЛОГИЙ И УПРАВЛЕНИЯ им. К.Г. РАЗУМОВСКОГО

ФИЛИАЛ в г. ВЯЗЬМЕ СМОЛЕНСКОЙ ОБЛАСТИ

КУРСОВАЯ РАБОТА

Дисциплина: «Программирование на ЯВУ»

Тема: «Работа с массивами»

Специальность: «Автоматизированные системы обработки информации и управления»

Форма обучения: Очная

Курс: 2

Студент:

Преподаватель:

2012

Содержание

Введение

Постановка задачи2

Однородные структуры данных. Массивы и матрицы.

Интерфейс программы3

Прокомментированный текст программы6

Алгоритмизация

Заключение

Список литературы10

Введение

C# (произносится Си-Шарп) - это новый язык программирования от компании Microsoft. Он входит в новую версию Visual Studio - Visual Studio.NET. Кроме C# в Visual Studio.NET входят Visual Basic.NET и Visual C++. Одна из причин разработки нового языка компанией Microsoft - это создание компонентно-ориентированного языка для новой платформы .NET. Другие языки были созданы до появления платформы .NET, язык же C# создавался специально под эту платформу и не несет с собой груза совместимости с предыдущими версиями языков. Хотя это не означает, что для новой платформы это единственный язык. Еще одна из причин разработки компанией Microsoft нового языка программирования - это создание альтернативы языку Java. Как известно, реализация Java у Microsoft не была лицензионно чистой - Microsoft в присущей ей манере внесла в свою реализацию много чего от себя. Компания Sun, владелица Java, подала на Microsoft в суд, и Microsoft этот суд проиграла. Тогда Microsoft решила вообще отказаться от Java, и создать свой Java-подобный язык, который и получил название C#. Если перевести слова NET Runtime на русский язык, то мы получим что-то вроде «Среда выполнения». Именно вы этой среде и выполняется код, получаемый в результате компиляции программы написанной на C#. NET Runtime основын не на ассемблере (т. е. не на коде, родном для процессора), а на некотором промежуточном коде. Отдаленно он напоминает виртуальную Java машину. Только если в случае Java у нас был только один язык для виртуальной машины, то для NET Runtime таких языков может быть несколько. Теоретически программа для среды NET Runtime может выполняться под любой операционной системой, в которой NET Runtime установлена. Но на практике пока единственная платформа для этого - это Windows. Учитывая перечисленные достоинства языка С#, он был выбран мною для решения поставленной задачи.

Постановка задачи.

Заполнить матрицу А(N,N) числами натурального ряда в последовательности, указанной на рисунке и найти их сумму. Вывести матрицу на печать. Предусмотреть возможность открытия файла с диска и сохранения файла на диск.



Однородные структуры данных. Массивы и матрицы.

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

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

Давайте сначала посмотрим, как реализованы массивы в некоторых языках программирования. Будем рассматривать Fortran, Algol60, Basic, PL/I, C, Pascal. Выбор именно этих языков продиктован тем, что в них видны практически все варианты реализации понятия массива.

Реализация массивов в языках программирования

Язык Fortran. Один из первых ввел в обиход понятие массива. Первые версии языка позволяли организовывать только числовые массивы. Впрочем, и сам язык появился как средство описания вычислительных задач математики (FORTRAN=FORmula TRANslation). Более поздние версии языка значительно расширили понятие массива.

Массивы в языке Fortran могут иметь произвольное количество индексов, или размерностей. Однако конкретные трансляторы могут накладывать ограничения. Изменить размер однажды созданого массива невозможно. Первый элемент массива всегда имеет индекс 1. Примеры описания массивов:

DIMENSION A(30)

REAL B(50)

INTEGER C(10,20,30)

Примеры обращения к массивам:

DO 5 I=1,20

5 C(5,I,10)=A(i)+B(I+10)*4

Однако этими простыми примерами не исчерпываются все возможности работы с массивами в языке Fortran. Дело в том, что Fortran, не допуская динамические массивы, тем не менее позволяет указывать размерность вычисляемую в ходе выполнения программы. Это возможно при передаче массива в процедуру или функцию. Пример:

SUBROUTINE NEG(A,N)

INTEGER A(N)

DO 1 I=1,N

1 A(I)=-A(I)

END

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

SUBROUTINE NEG(A,N)

INTEGER A(1)

DO 1 I=1,N

1 A(I)=-A(I)

END

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

Язык PL/I. Задумывался как язык для решения задач ВСЕХ типов. Обладает огромной гибкостью. Но эта гибкость привела к существенному усложнению синтаксиса языка, что отразилось на времени компиляции. Кроме того поддержка времени выполнения оказалась очень громоздкой. Большое число неявных преобразований типов данных и соглашений затрудняло отладку и написание программ. Поэтому мало кто знал и тем более использовал все возможности этого языка. А возможности были впечатляющими, для своего времени. Динамические массивы, структуры, процедурный тип данных, перехват исключительных ситуаций, работа с битами, гибкий ввод-вывод, вырезки из массивов. Не удивительно, что он составил серьезную конкуренцию Fortran. Однако, с исчезновением, по крайней мере в нашей стране, компьютеров серии ЕС (IBM), этот язык канул в лету. Тогда как Fortran, безусловно утратив свои былые позиции, нашел свою нишу на персональных компьютерах.

Поскольку PL/I практически мертвый язык, я не буду сильно вдаваться в подробности работы с массивами в этом языке. Одной из уникальных возможностей, так и не появившихся в других языках, была возможность формирования вырезок из массивов. Насколько эта возможность была важна сказать трудно. Я не видел ни одной программы, где бы эта возможность использовалась. Разновидность вырезок есть в языке Algol68, но это тема отдельного и очень долгого разговора. Приведу пример описания массивов на языке PL/I:

DECLARE A(50) FIXED(5);

DECLARE B(30) FLOAT;

Язык Algol60. Язык легенда. Предназначеный больше для описания алгоритмов, чем для практического применения, этот язык опередил свое время по богатству возможностей и логичности построения. Основной проблемой этого языка было отсутствие стандартизованности ввода-вывода. Кроме издания огромного количества алгоритмов, язык нашел и практическое применение. Причем во многих странах даже более широкое, чем Fortran.

Наиболее важным и заметным, с точки зрения массивов, является возможность задания нижнего значения индекса. Массивы, передаваемые в качестве параметров в процедуры, можно описывать без указания размерности. Поскольку язык Algol60 ввел понятие блока begin..end, в котором можно описывать свои внутренние переменные, описание массивов с вычисляемыми границами индексов не вызывает затруднений. Приведу комплексный пример:

real procedue pr(a,n);

value n; integer n;

array a;

begin

real array b[-n:n];

real r;

integer i,j;

for i:=-n step 1 until n do

for j:=-n step1 until n do

b[i]:=b[i]+a[i,j];

end j;

end i;

for i=-n step 1 until n do

if b[i]>0 then r:=r+b[i];

end i;

pr:=r;

end pr;

Этот пример не более чем способ показать основные правила работы с массивами в языке Algol60.

Язык Pascal. Был разработан Н.Виртом как язык для обучения программированию. Базовым языком послужил Algol60. Все сложные и неоднозначные конструкции Algol были выброшены. Были добавлены недостающие элементы, такие как пользовательские типы данных. Процедуры и методы ввода-вывода стали частью стандарта языка. В результате получился компактный, наглядный и надежный язык программирования. Достаточно быстро Pascal стал популярен не только как язык обучения, но и как язык прикладного программирования. Дальнейшим развитием языка Pascal стали языки Modula и Oberon. Эти языки менее известны, в первую очередь из-за того, что Pascal был поддержан фирмой Borland. Кроме трансляторов Turbo Pascal и Borland Pascal эта фирма выпустила продукт, который стал бестселлером. Речь идет о Delphi. Правда Pascal в продуктах Borland давно перестал быть Pascal Вирта, теперь это Object Pascal, но основные идеи остались прежними. Modula и Oberon не получили такой поддержки от крупных разработчиков трансляторов, а жаль.

program test;

const

Size=30;

type

Color=(Red,Green,Blue);

var

CrtPixels : array [0..Size] of Color;

i : integer;

begin

for i:=0 to Size do begin

case i mod 3 of

0: CrtPixels[i]:=Red;

1: CrtPixels[i]:=Green;

2: CrtPixels[i]:=Blue;

end;

end;

end.

Этот пример очень простой. Да сложнее и не требуется. Видно, что работа с массивами в языке Pascal очень похожа на работу с массивами в языке Algol60. Есть и отличия. Это первый пример, в котором массив не числовой, а определяемого пользователем перечислимого типа. И тем не менее работа с таким массивом не отличается от работы с обычным массивом целых чисел. Это важный момент.

Стандарт языка, предложенный Виртом, не допускал создания динамических массивов. Это было сделано намеренно. Однако массивы переменного, или, по крайней мере вычисляемого размера, были необходимы при написании серьезных программ. Естественно это было реализовано в коммерческих трансляторах. Так в Borland Pascal можно объвить массив, при описании функции, как array of без указания размера, но с обязательным указанием типа. Получить значения нижнего и верхнего индксов можно функциями Low и High. Более того, можно указать факт передачи массива без указания не только размеров, но и типа. Использовать такой параметр в функции можно только с помощью явного приведения типа.

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

Язык Basic. Язык для начинающих, так он по крайней мере задумывался. В оригинале, простой язык программирования, интерпретируемый а не транслируемый, требующий минимальной поддержки и минимальных ресурсов, соответственно предоставляющий минимум средств для написания программы. Любимый язык фирмы Microsoft и самого Билла Гейтса. Ведь именно с интерпретатора этого языка начинал Билл, успешная реализация которого и послужила причиной создания фирмы Microsoft.

В понимании Microsoft язык Basic вовсе не простейший язык, а мощный современный язык программирования, включающий в себя поддержку объектноориентированного подхода, OLE, средств визуального проектирования. Это Visual Basic.

Оригинальный Basic допускал только однобуквенные переменные. Массивы были только статические, и только одномерные. Причем если объявлялся массив без указания размерности, то считается, что массив состоит из 10 элементов. При развитии языка первыми ликвидированными ограничениями стали длинна имен переменных и количество индексов массива. В дальнейшем, при активном участии Microsoft стали допустимы и динамические массивы. Нижнее значение индекса фиксированно, и равно 0.

DIM Arr[30,30]

DIM Matrix()

REDIM Matrix(30,10,30)

FOR I=30 TO 0 STEP -1

Matrix[I,0,I]=I

Arr[I,I]=Matrix[I,I,I]

NEXT

Как видно, возможно не только указывать, что массив динамический, но еще и на ходу менять количество индексов.

Язык С. Один из самых популярных языков программирования, особенно в варианте С++. Большую свободу самовыражения дает только Assembler. Несмотря на то, что им пугают начинающих программистов, достаточно простой язык. К тому же чрезвычайно мощный, компактный и выразительный. Не зря его используют даже для написания операционных систем, например Unix и Windows. Позволяет программисту контролировать абсолютно все. Однако именно эта возможность и требует учитывать все тонкости и детали, например управления памятью. Небрежность оборачивается трудноуловимыми ошибками.

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

Чем же различаются массивы и указатели, кроме семантики? Вот далеко не полный список отличий. Для многомерных массивов нельзя просто объявить указатель, а затем использовать его с индексами. Почему, станет понятным после знакомства с реализацией массивов. Нельзя освободить память из-под массива, определенного с явным указанием размерностей. В языке С++ для массива, при создании, вызываются конструкторы для всех элементов, а при уничтожении, деструкторы для всех элементов. Для указателя таких вызовов не производится.

Позволю себе не углубляться дальше в тонкости языков С и С++, так как эта статья совсем о другом. Скажу лишь, что нижняя граница индексов массивов в языке С всегда 0.

#include

void func(int* a) {

int* b;

int c[10,5];

int d[]={1,2,3,4,5};

int i;

b=malloc(10*sizeof(int));

for(i=0; i<10; i++) {

a[i]=d[i/2]*i;

*(b+i)=a[i];

c[i,i]=a[i]+d[i/2];

}

free(b);

}

Обратите внимание на *(b+i), это эквивалент b[i], и демонстрирует возможность смешивания указателей и массивов.

Физическая реализация массивов

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

Не во всех языках возможно выполнение всех этих операций, не все операции кажутся очевидными. Например, создание и уничтожение массива. В языке Fortran эти операции нельзя выполнить явно. Но массивы тем не менее создаются и уничтожаются, автоматически, при входе в процедуру и при выходе из нее. (Собственно в Fortran IV массивы, как впрочем и локальные переменные процедур и функций, зачастую размещаются на этапе трансляции программы в статических областях памяти. При этом о создании и уничтожении массивов речи идти, естественно, не может. Однако, если компилятор размещает локальные переменные в стеке, то он просто обязан создавать и уничтожать массивы во время выполнения программы.)

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

Основой работы с массивами является доступ к отдельным элементам. Физически, массивы располагаются в оперативной памяти. Значит для доступа к элементу массива достаточно получить адрес этого элемента в памяти. Оперативная память представляет собой набор последовательно пронумерованых байт. По существу это одномерный массив байт. Элементы массива в языках высоко уровня могут занимать более одного байта. Кроме того массивы могут быть многомерными. Таким образом, для доступа к конкретному элементу массива в языке высоко уровня, необходимо решить задачу отображения этого массива на одномерный массив байт. Поверьте, это звучит страшнее, чем есть на самом деле.



Сначала определимся с понятиями. В оперативной памяти компьютера, кроме массивов, находятся и другие данные, а так же код программы и код операционной системы. Иначе говоря, массив занимает только часть памяти. Адрес памяти, с которого начинается массив, называется базовым адресом массива. Мы будем обозначать это base. Размер элемента массива будем обозначать как size. На рисунке изображен массив, элементы которго занимают по два байта. Нижняя граница индекса будет обозначаться low(), например нижняя граница индекса i будет выглядеть так, low(i). Соответственно верхняя граница будет обозначаться как high(). Сам массив будем обозначать как array.

Начнем разбираться с одномерных массивов с нижней границей индекса равной 0. Очевидно, что array[0] будет располагаться по адресу base. Следующий элемент, array[1], будет иметь адрес base+size. И так далее, array[2] расположиться по адресу base+size+size=base+2*size. В общем виде это можно записать так:

array[i]=base+i*size

Если допустить, что нижняя граница индекса не 0, то формула немного усложнится, оставаясь тем не менее простой и очевидной:

array[i]=base+(i-low(i))*size

Для неверящих формулам выполним проверку. Пусть у нас есть массив, нижняя граница индекса которого -5, а верхняя 5. Итак:

array[-5]=base+(-5+5)*size=base
array[-4]=base+(-4+5)*size=base+size

Видно, что формулы дают правильные результаты.

Теперь попробуем разобраться с двумерными массивами. При этом мы сразу наталкиваемся на вопрос "какой индекс изменяется первым?". Порядок изменения индексов не важен с точки зрения языка высокого уровня, но важен с точки зрения вычисления адреса элемента. Те из Вас, кто изучал в институте язык Fortran, наверняка помнят задачи, в которых требовалось вывести на печать содержимое массива. Хитрость заключалась в том, что первый индекс соответствовал номеру строки, а второй номеру столбца. В языке Fortran при указании имени массива в операторе ввода-вывода, напрмер в операторе PRINT, первым изменяется первый индекс. В результате массив (его еще называли матрицей) печатается повернутым на 90 градусов. Решение было простое, использовать неявные циклы. Другие решения не принимались. Несмотря на явно учебный характер тех задач они показывали одну важную, и не всегда очевидную, проблему. Проблему переносимости данных через внешние носители. Если Ваша программа, на Вашем любимом языке программирования, выводит многомерный массив да диск, а другая программа, возможно даже на машине с другой архитектурой, читает этот массив, то Вы должны или явно указывать последовательность вывода каждого элемента массива, или быть уверены, что правила изменения индексов многомерного массива одинаковы в обоих случаях. Кстати, проблема последовательности передачи элементов информации очень важна при работе в сетях.



Однако вернемся к массивам. На рисунке показана разница в размещении элементов массива [3,2] в зависимости от того, какой индекс изменяется первым. Вычисление адреса элемента в обоих случаях выполняется одинаково. Для наглядности рассуждений примем, что первым изменяется второй индекс, то есть сначала в памяти размещаются элемены первой строки, затем второй, и так далее. Будем рассматривать массив array[i,j]. Адрес каждого элемента в строке будет вычисляться по тем же формулам, что и для одномерного массива. Для вычисления адреса начала каждой строки нам потребуется знать, сколько памяти занимает одна строка. Очевидно, что каждая строка является одномерным массивом (это кстати объясняет, почему многомерные массивы часто рассматриваются как массивы массивов) и занимает

(high(j)-low(j)+1)*size

байт оперативной памяти. Первая строка двумерного массива начинается с адреса base, вторая с адреса base+(high(j)-low(j)+1)*size. Значит формулу для вычисления адреса элемента двумерного массива можно получить из формулы для одномерного массива. Нужно только заменить base на приведенное выше выражение, с учетом номера строки

array[i,j]=base+(i-low(i))*(high(j)-low(j)+1)*size+(j-low(j))*size

Желающие могут упростить выражение вынеся size за скобки. Проверим формулу для массива [2,3]. При этом индекс i будет изменяться от 0 до 1, а j от 0 до 2, т.е. low(i)=0, high(i)=1, low(j)=0, high(j)=2. Пусть каждый элемент занимает по два байта, т.е. size=2.

a[0,0]=base+(0-0)*(2-0+1)*2+(0-0)*2=base
a[0,1]=base+(0-0)*(2-0+1)*2+(1-0)*2=base+2
a[0,2]=base+(0-0)*(2-0+1)*2+(2-0)*2=base+4
a[1,0]=base+(1-0)*(2-0+1)*2+(0-0)*2=base+6
a[1,1]=base+(1-0)*(2-0+1)*2+(1-0)*2=base+8
a[1,2]=base+(1-0)*(2-0+1)*2+(2-0)*2=base+10

Как видно, результаты получились правильными. Для случая, когда первым изменяется первый индекс, формула сохраняется, поменяются лишь переменные i и j

array[i,j]=base+(j-low(j))*(high(i)-low(i)+1)*size+(i-low(i))*size

Массивы размерностью 3 ничего нового не привносят. Формула остается прежней, только base заменяется на выражение, учитывающее количество двумерных массивов и их размер. Напомню, что трехмерный массив можно рассматривать как одномерный массив двумерных массивов. Аналогично и четырехмерный массив можно рассматривать как одномерный массив трехмерных массивов. И так далее. Формулы приводить не буду. Попробуйте написать их сами.

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

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

На контроле индексов остановлюсь подробнее. Эта возможность есть далеко не во всех языках и компиляторах. Иногда контроль можно включить или выключить, для всей программы или ее части. Контроль индексов может сильно замедлить Вашу программу. Действительно, для статических массивов эта операция требует дополнительно по два сравнения на каждый индекс. Для динамических массивов, кроме того, требуется обращение к массиву с границами индексов. Так что может иметь смысл использовать контроль индексов только на этапе отладки программы. Можно так же запретить контроль индексов для критичной по времени части программы, например для внутренних циклов.

Использование идеологии массивов для организации баз данных

И в заключение хочу продемонстрировать Вам универсальность описаных здесь подходов, методов и формул к, казалось бы, совершенно посторонним темам. В качестве примера возьмем файлы dBase III (dbf) и применим к ним методы работы с массивами. Думаете не возможно? Вы ошибаетесь!

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

Длина заголовка может быть разной, но ее можно определить при открытии файла базы. Из заголовка так же определяется длина записи. Первая запись в базе имеет номер 1, то есть low=1. Этих данных для нашего примера достаточно. Забудем, на время, об удаленных записях, о необходимости корректировки полей в заголовке, при изменении или добавлении записей в базе. Осталось напомнить, что мы можем прочитать дисковый файл с любого байта, и любое количество байт. А теперь пример:

int dBase; /* Дескриптор файла базы */

int base; /* Длина заголовка базы в байтах */

int size; /* Длина записи базы в байтах */

int i; /* Номер записи */

int addr; /* Адрес записи в файле */

char* record; /* Собственно запись базы */

/*

Открываем базу и получаем дескриптор файла, длину заголовка

и длину записи.

*/

. . . . .

/*

Выделяем память для хранения записи в оперативной памяти

*/

record=malloc(size);

/*

Считываем пятую запись базы

*/

i=5;

addr=base+(i-1)*size;

lseek(dBase,addr,SEEK_SET);

read(dBase,record,size);

/*

Изменяем запись

*/

. . . . .

/*

Записываем измененую запись обратно

*/

lseek(dBase,addr,SEEK_SET);

write(dBase,record,size);

/*

Освобождаем занимаемую записью оперативную память

*/

free(record);

/*

Закрываем базу

*/

. . . . .

Не правда ли, все очень просто. Если добавить коррекцию заголовка базы при ее изменении и контроль ошибок, то получится вполне работоспособный набор функций для работы с dbf файлами. Если приложить еще немного усилий, то можно написать набор классов С++ для работы с базами dBase III. Причем это будет работать гораздо быстрее, чем обработка таких баз через ODBC, а места занимать гораздо меньше. Кстати, у меня есть набор таких классов. Он написан году так в 94, и предназначался для программистов переходящих на С++ с CLIPPERа. Как показала практика, эти классы существенно облегчили такой переход. Причем они используются и сейчас (2007 год). Исходные тексты этих классов не привожу сознательно. Написать их не сложно, достаточно пары дней, а в качестве упражнения еще и очень полезно.

Интерфейс программы. 

Рис. 1. Вид главного окна.



Рис. 2. Главное окно после обработки.



Рис. 3. Окно открытия файла с диска.



Рис. 4. Окно сохранения файла на диск.



Рис. 5. Окно предварительного просмотра.

Прокомментированный текст программы.

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Linq;

using System.Text;

using System.Windows.Forms;

using System.IO;

namespace WindowsFormsApplication1

{

public partial class Form1 : Form

{

public Form1()

{

InitializeComponent();

}

private void toolStrip1_ItemClicked(object sender, ToolStripItemClickedEventArgs e)

{

}

private void saveToolStripButton_Click(object sender, EventArgs e) //процедура сохранения файла на диск

{

string s = richTextBox1.Text;

if (saveFileDialog1.ShowDialog() == DialogResult.OK)

{

StreamWriter sw = new StreamWriter(saveFileDialog1.FileName);

sw.WriteLine(s);

sw.Close();

}

}

private void newToolStripButton_Click(object sender, EventArgs e) // процедура очистки экрана, создания нового документа

{

richTextBox1.Clear();

printToolStripButton.Visible = false; //сделать кнопку печати невидимой

saveToolStripButton.Visible = false; //сделать кнопку сохранения невидимой

}

private void openToolStripButton_Click(object sender, EventArgs e)

{

string s = "";

if (openFileDialog1.ShowDialog() == DialogResult.OK)

{

StreamReader sr = new StreamReader(openFileDialog1.FileName);

s = sr.ReadToEnd();

richTextBox1.Text = s;

sr.Close();

printToolStripButton.Visible = true; //сделать кнопку печати видимой

saveToolStripButton.Visible = true; //сделать кнопку сохранения видимой

}

}

int [,] a=new int [11,11]; // Описать массив

private void numericUpDown1_ValueChanged(object sender, EventArgs e)

{

printToolStripButton.Visible = true; //сделать кнопку печати видимой

saveToolStripButton.Visible = true; //сделать кнопку сохранения видимой

richTextBox1.Clear(); // очистка

int n = (int)numericUpDown1.Value; // прочитать размерность

int i = 0; // индекс строки

int j = 0; // индекс столбца

int p = 1; // записываемое число

int pr = n - 2; // от левого нижнего угла вправо

int lev = 0; // от нижнего правого угла вверх

int niz = n - 1; // от верхнего правого угла влево

int verh = 1; // от верхнего левого угла вниз

int sum = 0;

int k = 0;

for (k = 1; k <= n / 2; k++) // количество витков

{

for (j = lev; j <= pr; j++) // заполенние крайней нижней строки

{ a[niz, j] = p; sum = sum + p; p++;

}

for (i = niz; i >= verh; i--) // заполнение крайней правой строки

{ a[i, pr + 1] = p; sum = sum + p; p++;

}

for (j = pr + 1; j >= lev + 1; j--) // заполнение крайней верхней строки

{ a[verh - 1, j] = p; sum = sum + p; p++; }

for (i = verh - 1; i <= niz - 1; i++) // заполнение крайней левой строки

{ a[i, lev] = p; sum = sum + p; p++;

}

pr--; lev++; verh++; niz--;

}

//Заполнить центр

if (n % 2 != 0) { a[n / 2, n / 2] = p; sum = sum + p;

}

//Вывод массива

string s = "";

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

{

s = "";

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

{

s = s + a[i, j].ToString() + (char)9; ;

}

richTextBox1.AppendText(s + " ");

}

richTextBox1.AppendText("Сумма=" +sum.ToString()); // Вывод суммы

}

private void printToolStripButton_Click(object sender, EventArgs e) // процедура предварительного просмотра перед печатью

{

printPreviewDialog1.PrintPreviewControl.Zoom = 1.0;

printPreviewDialog1.ClientSize = Screen.PrimaryScreen.Bounds.Size;

printPreviewDialog1.ShowDialog();

}

private void printDocument1_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e) // процедура внешнего вида текста для печати

{

e.Graphics.DrawString(richTextBox1.Text, this.Font, Brushes.Black, new PointF(20, 20));

}

}

}

Алгоритмизация

Заключение

Список литературы

1. Попов А.А. Программирование и основы алгоритмизации, Программирование на языках высокого уровня. – М., МГУТУ, 2004.

2.Епанешников А., Епанешников В. Delphi 4. Среда разработки: Учебное пособие. - М.:Диалог-МИФИ,1999.

3.Фаронов В.В. Delphi 4. Учебный курс. – М.: «Нелидж», 1999.

4.Учебник по Delphi 7 для начинающих.