Используйте исчерпывающие проверки. 


Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Используйте исчерпывающие проверки.



Если переменная должна принимать значения 1|2|3, не следует полагать, что ее значение равно 3, если оно не равно 1 и не равно 2, т.к. возможны ошибки.

Стиль в языках С и Basic

По оценке авторов:

ОВ – весьма важная рекомендация;

В – рекомендация средней важности;

МВ – рекомендация относительно малой важности.

Степень важности рекомендаций определялась на основании оценки их влияния на написание надежной (с минимумом ошибок) программы.

1. (В) Имена. Использовать "паскалевскую" или "венгерскую" нотации.

2. (В) Описатели. Поскольку различные трансляторы языка C отводят данным типа int 2 или 4 байта, использовать для обычных целых тип short, длина элемента которого всегда 2 байта, для длинных целых long – длина всегда 4 байта. Если постановка задачи не требует повышенной точности представления, использовать для данных с плавающей точкой типы float (C) и single (Basic).

3. Литералы.

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

# define TRUE 1

# define FALSE 0

Не следует забывать, что логические данные в программе на языке Basic занимают в памяти 2 байта, значения хранятся в виде true (-1), false (0), а на языке C они занимают в памяти 1 байт и хранятся в виде true (1), false (0).

(В) Старайтесь избегать в тексте программы литералов, заменяйте их символическими константами с помощью директивы #define (язык C).

4. (В) Массивы.

Для языка C следует отметить такие особенности.

Если возможно изменение размеров массивов, определяйте их размеры с помощью директивы #define.

Пример.

#define PAZM 5

float Matrix[PAZM][PAZM];

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

В языке Basic для массивов, размеры которых могут изменяться, при описании используется инструкция dim с пустыми скобками.


Пример.

Dim Matrix() As Single

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

Пример.

ReDim Matrix(1 To 10, 1 To 10)

Такая инструкция в теле процедуры может использоваться многократно. Более подробно синтаксис и область применения инструкции redim будет изложена ниже.

5. (ОВ) В языке C необходимо помнить об особенностях операторов деления / и остатка % при работе с целыми операндами. При делении целого на целое результат всегда целый. Оператор % используйте только для целых операндов.

6. (В) Для логических операторов && и || в языке C вычисление выражения прекращается, как только результат определен, а для аналогичных операторов and и or в языке Basic проверяются оба операнда.

Пример.

Выражение i<100 && x[ i ]<0 при i=100 в языке C примет значение false и выполнение программы продолжится, тогда как в языке Basic вычисление выражения i<100 and x(i)<0 при тех же условиях вызовет ошибку: Subscript out of range (Индекс вне диапазона), поскольку элемента массива x(100) не существует.

7. (ОВ) В языке C при использовании библиотечных функций не забудьте включить файл прототипов.

Пример.

#include <stdio.h>

#include <math.h>

8.(В) Не забывайте об удобных возможностях языка С: многократном присваивании, операторах: ++ -- <знак>=.

9. (ОВ) Ввод-вывод (C):

- при вводе информации функцией scanf в списке данных необходимо использовать оператор нахождения адреса &;

- не забывайте заканчивать ввод данных инструкции scanf клавишей Enter;

- не забывайте заканчивать управляющую строку инструкции printf символом '\n' (перевод на новую строку);

- при неизвестном диапазоне выводимых значений данных с плавающей точкой используйте спецификацию g.

Вопросы для самопроверки и контроля

Вопросы для самопроверки

1. Как разумно размещать инструкции текста программы?

2. Какую роль играют отступы при размещении вложенных инструкций?

3. В чем суть "венгерской" нотации имен?

4. На что, вероятно, указывает предупреждение при трансляции?

5. В чем различие в применении операторов "И" и "ИЛИ" в языках C и Basic?

6. Чем отличается действие оператора деления / в языках C и Basic?

Контрольные вопросы

1. В каких местах нужно осуществлять перенос инструкции, если она не входит в строку?

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

3. Почему нежелательно использовать в программе схожие имена?

4. Зачем нужно явно объявлять все объекты программы?

5. Почему следует избегать инструкций перехода?

6. В чем преимущество работы с массивами в языке Basic?

ДАННЫЕ. ДОПОЛНЕНИЕ

Материал данного раздела содержит информацию о типах и совокупностях данных, специфических для конкретного языка программирования, поэтому ниже рядом с названием раздела в скобках будет указываться принадлежность описываемой конструкции к языку: C (C++) и BBasic.

Перечислимый тип

10.1.1. Тип enum (C)

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

enum <имя_типа>{<имя_элемента>[=<значение>],

[<имя_элемента> [=<значение>]]...};

Пример.

enum spectr{RED, ORANGE, YELLOW, GREEN, BLUE, VIOLET};

 

Затем можно определять переменные этого типа:

[ enum ] spectr color1, color2;

В языке C++ указание ключевого слова enum при объявлении переменных перечислимого типа не является обязательным, если инструкция объявления этого типа записана в программе раньше. Ключевое слово enum является сокращением от enumeration – перечисление.

Запись из примера эквивалентна введению символических констант вида:

# define RED 0

# define ORANGE 1

# define YELLOW 2

# define GREEN 3

# define BLUE 4

# define VIOLET 5

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

Пример.

color1=GREEN; // Допустимо

color2=WHITE; // Ошибка!

Если при объявлении типа символическим константам из списка не задается значений, то первая из них по умолчанию получает значение 0, последующие на 1 больше. Если какой-либо из констант задается значение, а последующим нет, то они получают следующее по порядку целое значение.

Пример.

enum RussianCop{one=1, five=5, ten=10, fifty=50};

enum RussianRoub{One=1, Two, Five=5, Ten=10, Fifty=50, Hundred=100, FiveHundred=500, Thousand=1000};

enum mark{BAD=2, MIDDLE, GOOD, FINE};

Как известно, в языке C не определен логический тип данных, однако он легко вводится с помощью объявления вида: enumbool { false, true };

Фактически разумными при работе с данными перечислимых типов являются только следующие операторы: присваиваниеà color1=VIOLET; и сравнениеà color1==color2.

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

10.1.2. Тип enum (B)

Практически аналогичен такому же типу языка C.

Формат объявления типа:

enum <имя_типа>

<имя_элемента>[=<значение>]

[<имя_элемента>[=<значение>] ]

.......................................................

End enum

Пример.

enum spectr

Red

Orange

Yellow

Green

Blue

Violet

End enum

Объявление переменных имеет вид:

dim color1 as spectr, color2 as spectr

Правила объявления и использования переменных этого типа полностью совпадают с правилами языка C. Имеются только 2 отличия:

- значения переменных и перечисляемых констант относятся к типу long;

- при присвоении переменной значения не из списка констант ошибки не возникает.

10.2. Тип currency (B)

Данные этого типа представляют собой десятичные значения с фиксированной точкой с 15 цифрами в целой части и 4 цифрами – в дробной. Элемент данных занимает в памяти 8 байтов. Диапазон представления:

-922,337,203,685,477.5808 - 922,337,203,685,477.5807.

Литералы данного типа не определены.

Пример объявления переменных.

dim sum1 as currency, TotalSum as currency

Эти данные полезны при денежных расчетах и вычислениях с фиксированной точкой с заданной точностью.

10.3. Тип date (B)

Данные этого типа в памяти представляются специальным форматом с плавающей точкой, точно знать который нет необходимости. Каждый элемент занимает в памяти 8 байтов. Целая часть значения хранит дату, дробная – время. Диапазон представления дат от 1 января 100 года до 31 декабря 9999 года, времени – от 0:00:00 до 23:59:59.

Литералы данного типа заключаются между символами #. Они могут записываться в различных форматах, однако после окончания ввода среда преобразует введенный формат даты/времени в формат, принятый в USA: m/d/yyyy h:mm:ss {AM|PM}, где m - № месяца (1 или 2 цифры в зависимости от значения), d - № дня в месяце (аналогично), yyyy – год, h – час (1 или 2 цифры), mm – минуты, ss – секунды, AM (ante meridiem – до полудня), PM (post meridiem – после полудня) – указатели 12-часовой шкалы.


Пример.

#01 Jan 2001# à #1/1/2001#

#13:03:03# à #1:03:03 PM #

#13/11/2001 5:54:56# à #11/13/2001 5:54:56 AM #

Подобное преобразование может привести к ошибке. Например, запись вида #9/3/2001# будет интерпретироваться как: 3 сентября 2001 года, тогда как, возможно, имелось в виду 9 марта 2001 года (принятый в России краткий формат даты). Поэтому разумно записывать литералы даты/времени как строки. При этом преобразования формата в среде не будет.

Пример.

"09/03/2001 18:34:30" à 9 марта 2001 года 6 часов 34 минут 30 секунд вечера

При выводе значений (печать, экран) используются установленные в пункте НастройкаàПанель управленияàЯзык и стандарты форматы (для даты – краткий, например, 11/03/2001).

Пример объявления переменных.

dim BirthDay as date

С данными этого типа можно манипулировать непосредственно. Например, разницу в датах можно получить так:

dim day1 as date, day2 as date, day3 as integer

day1 = #3/9/1999#

day2 = #3/10/2001#

day3 = day2 - day1

Получим 732 дня.

К дате можно прибавлять дни. Им соответствуют целые значения. Прибавление 1 часа – 1/24, 1 минуты – 1/(24*60), 1 секунды – 1/(24*3600).

Пример.

day2=day1+2 à #3/11/1999#

При преобразовании данных различных типов в тип date значение слева от десятичной точки представляет дату, справа – время. 0 означает полночь, 0.5 – полдень. Отрицательные целые числа представляют даты до 30 декабря 1899 года.

Для облегчения манипуляций с данными типа date имеются следующие библиотечные функции:

Date – возвращает системную дату;

Time – возвращает системное время;

Now – возвращает системные дату и время.

DateAdd (интервал, число, дата) – возвращает дату, отстоящую от дата на число интервалов. Возможные значения аргумента интервал:

- yyyy – год,

- q – квартал,

- m – месяц,

- ww – неделя,

- d – день,

- h – час,

- n – минута,

- s – секунда.

Пример.

DateAdd (" m ", 1, #1/31/2000#) à #02/29/2000#

DateDiff (интервал, дата1, дата2) – возвращает число интервалов между дата2 и дата1. Если дата1 > дата2, возвращается число < 0. Функция имеет 2 необязательных аргумента: первый день недели и первая неделя года и значение интервала = " w – день недели. Употребление этих значений изучить самостоятельно.

Пример.

DateDiff( " d ", #3/9/2000#, #3/10/2001#) à 366

DatePart (интервал, дата) – возвращает заданную интервалом часть дата. Функция также имеет 2 необязательных аргумента: первый день недели и первая неделя года. По умолчанию первым днем недели считается Воскресенье. В примере показано как с помощью символической константы сделать первым днем Понедельник. Аналогичные константы есть и для других дней недели.

Пример.

DatePart (" yyyy ", #3/9/2003#, vbMonday) à 2003 ' vbMonday=2

DatePart (" q ", #3/9/2003#, vbMonday) à 1

DatePart (" m ", #3/9/2003#, vbMonday) à 3

DatePart (" d ", #3/9/2003#, vbMonday) à 9

DatePart (" ww ", #3/9/2003#, vbMonday) à 10

DatePart (" w ", #3/9/2003#, vbMonday) à 7

Day (дата) – возвращает день месяца.

Weekday (дата[, 1-й день недели]) – возвращает порядковый № дня недели.

Month (дата) – возвращает № месяца.

Year (дата) – возвращает год.

Пример.

Day (#3/9/2003#) à 9

WeekDay (#3/9/2003#, 2) à 7

Month (#3/9/2003#) à 3

Year (#3/9/2003#) à 2003

Hour (время) – возвращает целое от 0 до 23 (час аргумента).

Minute (время) – возвращает минуты (0 – 59).

Second (время) – возвращает секунды (0 – 59).

Пример.

Hour (#6:34:30 PM) à 18

Minute (#6:34:30 PM) à 34

Second (#6:34:30 PM) à 30

10.4. Тип void (С)

Так называемый "пустой" тип. Служит для согласования синтаксиса функций, не возвращающих значений или не имеющих аргументов.

Пример.

void putmsg(void){

printf ("Hello, world!\n");

} /* End putmsg */

Этот тип также используется для формирования "универсальных" указателей void *, о которых пойдет речь в другом разделе.

10.5. Подмассивы (сечения) (C)

В языке С можно рассматривать многомерный массив как одномерный, элементами которого являются массивы на 1 меньшей размерности.

Пример.

float sales[3][4][5];

Такой объект можно трактовать как массив с плавающей точкой, состоящий из 3 элементов, каждый из которых является двумерным массивом размером 4*5.

Допустимы следующие обращения к содержимому этого массива:

sales – массив целиком,

sales[ i ] – к i -му подмассиву 4*5,

sales[ i ][ j ] – к элементу с индексами i и j: массив из 5 элементов,

sales[ i ][ j ][ k ] – скалярная величина: собственно элемент массива sales.

Использование сечений иногда весьма удобно, особенно при обращении к процедуре.

Пример. Найти индексы максимальных элементов каждой строки матрицы.

#define M 10

#define N 10

void main(void){

float a[M][N]; int s[M], ind(float [ ], int);

..............

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

s[ i ]=ind(a[ i ], N);// Аргументом функции ind является i -я строка

}

..............

}//End main

int ind(float x[ ], int n){// Параметр есть одномерный массив длиной в строку

int i, k; float y;

y=x[0];

k=0;

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

if (y<x[ i ]){

y=x[ i ]; k=i;

}

}

return k;

} //End ind

10.6. Динамические массивы (B)

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

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

Пример.

dim DinArray() as single

Задание размерности и границ индексов такого массива производится во время выполнения программы инструкцией вида:

redim [ preserve ] <имя_массива>(<выражение>[, <выражение>]...)

Инструкция redim в отличие от инструкции dim является выполняемой. Первое ее использование задает размерность (число измерений), которая не может быть переопределена в последующих инструкциях redim. Эти последующие инструкции могут изменить только границы индексов. Также инструкция redim не может изменить объявленный тип элементов динамического массива.

Пример.

................................

redim DinArray(1 to 10, 4)

................................

redim DinArray(5,5)

При выполнении инструкции redim все значения элементов, которые были заданы ранее, теряются. При этом числовые значения заменяется нулями, строки – пустыми строками (""). Однако, имеется возможность сохранить "старые" значения элементов массива. Это особенно полезно, когда после переопределения размер массива увеличивается. Для этого в инструкции redim необходимо употребить ключевое слово preserve (сохранить). При использовании опции preserve можно изменять только верхнюю границу последнего измерения.

Пример.

redim preserve DinArray(5, 10)

При переопределении динамических массивов весьма удобно употреблять 2 встроенные функции языка Basic:

Lbound (<имя_массива>[, <№ измерения>]) – нижняя граница,

UBound (<имя_массива>[, <№ измерения>]) – верхняя граница.

Пример. Увеличить на 1 границы массива DinArray.

redim DinArray(Ubound(DinArray)+1, Ubound(DinArray, 2)+1)

10.7. Структуры и объединения (C)

Структуры

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

Пример. Структура "Работник" (worker):

- таб. номер;

- Фамилия И.О.;

- должность;

- сумма.

Формат структуры:

struct [<тип_структуры>]{

<список_описаний_элементов>

}[<список_объектов>];

Пример.

struct { // Сведения о звезде

long nom_GC; // Номер по каталогу GC

float mv; // Блеск (звездная величина)

char spectr[5]; // Спектр. класс

double alfa; // Прямое восхождение

double delta; // Склонение

double mu_alfa; // Собственное движение по alfa

double mu_delta; // ------------------- ------------- по delta

char rem[15]; // Особенности (примечания)

} star;

Структура star содержит сведения об одной звезде. Это определение, т.е. под нее выделяется память, объем которой определяется суммарным размером всех элементов, входящих в структуру. В нашем примере он составляет 56 байтов. Пример. Определение нескольких структур одного строения.

struct {

.......

} ref_star, // Опорная звезда

view_star; // Наблюдаемая звезда

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

Пример. Описание типа star.

struct star{

............

};

Определение переменных данного типа:

struct star ref_star, // Опорная звезда

view_star; // Наблюдаемая звезда

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

Примеры.

struct star{

long nom_GC;

float mv;

char spectr[5];

struct { // Подструктура

double alfa;

double delta;

} koord;

struct { // Подструктура

double alfa;

double delta;

} move;

char rem[15];

};

struct data{ // Дата

int day; // День месяца

int month; // Номер месяца

int year; // Год

char month_name[4]; // Название месяца

};

struct form{ // Анкета

char name[15]; // Фамилия И.О.

char address[30]; // Адрес

char post[20]; // Должность

struct data birth_date; // Дата рождения

struct data work_date; // Дата поступления на работу

};


Допустимы массивы структур.

Пример.

struct { /* Сведения о погоде за год */

struct {

double max, min, mid;

} temperature;

struct {

double max, min, mid;

} humidity;

struct {

double max, min, mid;

} pressure;

number_of_observations;

} weather[12];

 

Рекурсивные структуры

Рекурсией, в общем случае, можно назвать правило, позволяющее определить некоторый объект с помощью другого объекта той же структуры. Наиболее распространены рекурсивные функции, простейшим примером которых является формула вычисления факториала: n!=n*(n-1)!

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

Пример.

struct node{

int data;

struct node *next;

};

Здесь в состав структуры включают указатель на структуру того же типа. Такие структуры называют рекурсивными. Их применение будет рассмотрено в курсе "Структуры данных".

Поля битов

До сих пор минимальными адресуемыми элементами программы являлись объекты размером в 1 байт. Примерами таких объектов являлись данные типа char в языке C и типа byte в языке Basic. Однако байт содержит 8 битов (двоичных цифр). Язык C позволяет манипулировать с отдельными битами информации. Такая необходимость возникает, в основном, при программировании аппаратуры, входящей в состав ПК, или программно-аппаратного комплекса. Средством реализации такой возможности является особый вид структуры, имеющий в качестве элементов так называемые поля битов.

Записываются такие структуры следующим образом:

struct {

unsigned [<имя>]: <число битов>;

..........................

}


Пример. Формат регистра состояния ГД RX211.

struct {

unsigned error:1;

unsigned initialize:1;

unsigned addr:2;

unsigned rx02:1;

unsigned:2;/* Hе используются */

unsigned density:1;

unsigned trreg:1;

unsigned enable:1;

unsigned done:1;

unsigned select:1;

unsigned funct:3;

unsigned go:1;

}save_211;

Поле битов без имени нулевой длины вызывает выравнивание последующих полей на границу объявленного типа данных, т.е они располагаются с адреса, кратного 16 для ОС MS DOS и 32 – Windows.

Объединения (смеси)

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

union [<тип>]{

описание элемента 1;

описание элемента 2;

...................;

описание элемента n;

}[<список-элементов>];

Пример.

union {

floa t radius; // Окружность

float side[2]; // Прямоугольник

float triangle[3]; // Треугольник

float point[2]; // Точка

}GeomFig;

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

Заметим, что обобщением понятия объединения является тип данных variant в языке Basic.

Переменные структуры

Переменной называют структуру, в состав которой входит хотя бы 1 смесь.

Пример.

Паспортные данные:

- фамилия и.о.,

- серия,номер,

- дата рождения,

- место рождения,

- национальность,

- прописка,

- семейное положение:холост|женат|разведен,

- переменная часть,

- военнообязанный:да|нет.

 

Общая схема построения такой структуры следующая:

struct {

общие компоненты,

признак активной компоненты (тэг),

union {

переменные компоненты

}<имя>;

........................................................

}<имя структуры>;

Тэгом называют переменную, значение которой определяет, какой элемент объединения занимает память в данный момент.

Пример.

enum sem_pol{holost, genat, razveden};

struct pasport{

char fio[30];

char nomer[12];

struct data birthdate;

char mesto[15];

char nation[15];

char propis[40];

enum sem_pol pr;

union {

/* холост - пусто */

/* женат */

struct {

struct data svadba;

char wife_fio[30];

unsigned chislo_children;

struct {

char name[15];

char pol;

struct data birthdate;

}children[PAZMEP];

}sostav;

/* разведен */

struct data razvod_day;

}sem_sost;

unsigned priziv;

};

10.8. Тип variant (B)

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

dim <имя_переменной> as variant.

Если такой переменной задается числовое значение, то объем памяти под нее составляет 16 байтов, если – строковое, то 22 байта + длина строки. В операторах переменные типа variant ведут себя в соответствии с типом присвоенного значения. Если было присвоено значение типа integer, то переменная работает как целая, если – типа string, то – как строка. Транслятор сам распознает внутренний тип переменной.

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

- данные занимают, в общем случае, больше памяти, чем обычные типы;

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

Например, оператор "+" применим и к числовым, и к строковым данным. В первом случае он выполняет операцию сложения, во втором – сцепление.

Пример.

a="10"

b="11"

a+b à "1011"

b=11

a+b à 21

Если один операнд типа variant содержит числовое значение, а второй – строковое, то второй операнд будет преобразован в число, если это возможно, если нет, то возникнет ошибка Type mismatch (Несогласование типов). При необходимости получения строкового результата нужно использовать оператор "&".

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



Поделиться:


Последнее изменение этой страницы: 2017-02-08; просмотров: 347; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.137.183.14 (0.339 с.)