10. Расширение и примеры
С каждой переменной связан ее класс. С некоторыми упрощениями
можно сказать, что если в декларации не указан класс, то переменная,
объявленная внутри функции, имеет класс auto, а переменная,
объявленная вне функции - класс extern. Разница между ними
заключается в том, что переменная класса auto создается заново перед
каждым вызовом функции и перестаёт существовать после окончания
выполнения функции, в то время, как переменная класса extern
существует все время выполнения программы. Другой важной особенностью
переменных класса extern является то, что, если в программе существует
несколько объявлений некоторой переменной с атрибутом extern и только
одно объявление этой переменной без атрибута extern, находящееся вне
функции, то все эти объявления относятся к этой переменной.
Переменные класса static существуют все время выполнения
программы, но если они объявлены внутри функции, то они становятся
доступны только при выполнении этой функции. В декларациях класса
static и в тех декларациях переменных класса extern, в которых нет
слова extern, можно присваивать начальные значения.
-1Функции с переменным числом аргументов-0
Функцию с переменным числом аргументов можно объявить перед
первым вызовом этой функции, а в заголовке определения,
непосредственно после скобки, замыкающей список параметров, должно
стоять слово auto. Если эти условия соблюдены, то каждый вызов функции
будет неявно дополнен аргументом типа (int), указывающим, сколько байт
заняли все аргументы функции, включая и новый аргумент. Следует
отметить, что аргументы вычисляются в порядке их выступления в вызове
и записываются в память в порядке убывания адресов. В частности,
результатом функции max является максимум переданных ей аргументов
типа (int):
int
max (Count) auto
int Count;
{
int argc, *argv, max;
argc = (Count >> 1)-1;
argv = Count + argc;
max = -32768;
while (argc--)
if (*argv-- > max)
max = argv[1];
return max;
}
-1UWAGA-0: Этого нет в базовом языке.
-1Команда inline-0
В системе Hisoft Вы имеете возможность вставлять в свою программу
на Си фрагменты в машинных кодах с помощью команды inline. Аргументами
этой команды могут быть произвольные выражения, в частности,
16-ричные литералы 0хdd. Принято, что первый аргумент в пределах 0-255
генерирует один байт кода, а каждый последующий - два байта кода.
В файле stdio.lib команда inline используется для определения ряда
графических функций:
cls ()
{
inline (0xCD, 0xD6B);
}
-1UWAGA-0: Этого нет в базовом языке.
-1Примеры-0
1.Определение функции для вычисления абсолютной величины аргумента
типа (int).
int
abs (Par)
int Par;
{ return Par < 0 ? -Par: Par }
2.Определение функции для вычисления максимального элемента массива с
элементами типа (int):
int
max (Arr, Len)
int Len, Arr[];
{
int Val;
Val = -32768;
while (Len--)
if (Arr[Len]>Val)
Val = Arr[Len];
return Val;
}
3.Определение функции для подсчета числа единичных бит в аргументе
типа (int):
int
count (Bits)
unsigned Bits;
{
int Tally
for (Tally = 0; Bits; Bits >>=1)
Tally+ = Bits&1;
return Tally;
}
4.Определение функции ,аргументом которой является адрес памяти, а
результатом - данное типа (char), находящееся по этому адресу:
сhar
peek (Addr)
unsigned Addr;
{
typedef char *ChrPtr;
return *cast(ChrPtr)Addr;
}
5.Определение функции poke для записи данных типа (char) по адресу
Addr:
poke (Addr, Data)
unsigned Addr;
char Data;
{
typedef char *ChrPtr;
*cast(ChrPtr)Addr = Data;
}
6.Определение функции сравнения последовательностей знаков:
int
strcmp (Src, Trg)
char *Src, *Trg;
{
while (*Src == *Trg++)
if (!*Src++) return 0;
return *Src > Trg[-1] ? 1: -1;
}
7.Определение функции для создания данного типа (int) из
последовательности цифр:
int
atoi (Src)
char *Src;
{
int Chr, Val;
Val = 0;
while ((Ch = *Src++) == ' ')
Val = 10*Val+Chr - '0';
return Val;
}
8.Используя функции динамического управления памятью (calloc и free),
описанные в приложении С, создать строковый редактор, позволяющий
создавать текст, строки которого нумеруются числами без знака.
Принять, что ввод строки требует ввода числа и текста строки. Если
текст строки отсутствует (пусто), то строка игнорируется. Если
отсутствуют и число и текст, то на монитор выводятся все строки
текста. Каждая введенная строка должна оканчиваться знаком ENTER, а
текст - знаком EOF (SS + I).
#include "stdio.h"
typedef struct Str{
struct Str *next;
int lab;
}LIST;
typedef LIST *ListPtr;
typedef char *CharPtr;
LIST head = {NULL};
main ()
{
extern LIST *find();
int num, del;
char line[81];
LIST *pos;
num = 0;
do {
if (!num)
display();
else {
pos = find(num);
if (pos->next&&pos->next->lab == num)
delete (pos);
if (del! = 'n') {
getLine (line,81);
insert (pos, num, line);
}
}
getNumber (&num, &del);
}
LIST*
find (num)
int num;
{
LIST *ref;
ref = &head;
while (ref->next&&ref->next->lab < num)
ref = ref->next;
return ref;
{
delete (pos)
LIST *pos;
{
LIST *ptr;
ptr = pos->next;
pos->next = ptr->next;
free(cast(CharPtr)ptr);
}
getLine (ptr, max)
char *ptr;
int max;
{
int i, c;
for (i=0;
i < max-1&&(c=getchar()) != 'n';
i++) *ptr++ = c;
if (c != 'n')
while (getchar() != 'n');
*ptr = ' ';
}
int
length (line)
char *line;
{
int len;
len=0;
while (*line++)
len++;
return len;
}
insert (pos, num, line)
LIST *pos;
int num;
char line[];
{
LIST *ptr, *ref;
int size;
size=sizeof(ListPtr)+sizeof(int)+length(line)+1;
if (ptr=cast(ListPtr)callof(1,size)) {
ref=pos->next;
pos->next=ptr;
ptr->next=ref;
ptr->lab=num;
fill(cast(CharPtr)(ptr+1),line);
} else
printf ("Zignorowano:-brak pamieci");
}
display ()
{
LIST *ref;
ref=head.next;
while (ref) {
printf ("%3d%sn", ref->lab, cast(CharPtr)(ref+1));
ref=ref->next;
}
}
fill (ref, line)
char *ref, *line;
{
while (*ref++=*line++);
*ref=' ';
}
getNumber (num, del)
int *num, *del;
{
int c, val;
val=0;
while ((c=getchar())>='0'&&c<='9')
val=10*val+c-'0';
*num=val;
*del=c;
}
#include ? stdio.lib ?
9.Создать программу для вывода на экран содержимого файла TEXT.DOC:
#define EOF (-1);
typedef int FILE;
main ()
{
int Chr;
FILE *input, *fopen();
if ((input=fopen("TEXT.DOC","r"))!=NULL)
while ((Chr=getc(input)) != EOF)
putchar (Chr);
}
10.Программа копирования строки с клавиатуры на принтер:
typedef int FILE;
#define EOF (-1)
main ()
{
FILE *STREAM;
int Chr;
while ((Chr=getchar() != EOF)
putc (Chr, cast(STREAM)3);
}
Приложение В. Редактор Hisoft
Директивы редактора имеют вид:
Dn1,n2,t1,t2;
-где D-однобуквенная директива, n1 и n2 - целые числа 1 ... 32767,
t1 и t2 - записи не более 20 символов каждая. Некоторые параметры
могут быть опущены. В этом случае они принимают значение
соответствующих параметров предыдущей директивы.
Если система Hisoft находится в режиме компиляции, то для вызова
редактора необходимо нажать EDIT (CS+1), а затем клавишу ENTER. Для
окончания редактирования и вызов компилятора используется директива
С, а для выхода в Basic - директива В.
-1Директива I (insert) Im,n-0
Директива служит для инициации автоматической нумерации строк
текста. Непосредственно после ее выполнения на экране появится число
m. После нажатия ENTER ввод строки с этим номером заканчивается, а на
экране в новой строке появится число m+n, соответствующее номеру
следующей строки. Для прекращения действия директивы I нажмите EDIT.
-1Директива L (list) Lm,n-0
Директива служит для вывода на экран строк текста n ... m.
По умолчанию m=1, а n=32767. Если весь текст не умещается на экране,
то он выводится порциями по 10 строк. Размер порции вывода может быть
изменен директивой К. Для выхода из директивы необходимо нажать
EDIT.
-1Директива K (Chunk) Lm-0
Директива устанавливает порцию вывода из m строк для директивы L.
-1Директива W (Write) Wm,n-0
Вывод на принтер. Для прерывания печати - BREAK.
-1Директива S (Set) S,,d-0
Изменение сепаратора аргументов директив. По умолчанию
сепаратором является запятая, но можно установить любой другой знак.
-1Директива V (View) L-0
Вывод на экран аргументов n1, n2, t1, t2, использованных в
последней выполненной директиве; вывод адресов начала и конца буфера
текста.
-1Директива D (Delete) Dm,n-0
Удаление строк от m до n. D10,10 или D10 - удаление только 10-ой
строки.
-1Директива N (Renumber) Nm,n-0
Перенумерация: первая строка имеет номер m, последующие n+m.
-1Директива Р (Put) Pm,n,t-0
Запись во внешнюю память, как в файл с именем t, строк программы
от m до n.
-1Директива G (Get) G,,t-0
Ввод из внешней памяти как из файла с именем t текста программы.
Введенный текст размещается непосредственно за уже отредактированным,
а его строки автоматически нумеруются с дискретностью 10.
-1Директива С (Compiler) C-0
-1Директива B (Basic) B-0
Для возврата в Си - PRINT USR 25200.
-1Директива F (Find) Fm,n,f,s-0
Поиск в отрезке m...n строки с наименьшим номером, содержащей f.
После этого выполняется директива Е. Найденный текст может быть заменен
на текст s, если использовать поддирективу s.
-1Директива Е (Edit) Em-0
Неявное выполнение этой директивы происходит при компиляции
программы, содержащей ошибочную строку m. В этом случае на экран
выводится сообщение об ошибке, а по нажатию EDIT неявно выполняется
директива Em. При нажатии любой другой клавиши вызывается компилятор.
Редактирование строки осуществляется с помощью однозначных
поддиректив.
* поддиректива => (CS+8)
Если к моменту использования этой поддирективы вся итоговая
строка была выведена на экран, то к строке добавляется введенный
символ, в противном случае вводится следующий знак итоговой строки;
* поддиректива <= (CS+5)
Стирание на экране последнего знака итоговой строки и сдвиг
курсора вправо;
* поддиректива ENTER
Перенос в итоговую строку оставшихся символов исходной, окончание
редактирования и замена в тексте исходной строки на итоговую;
* поддиректива Q (Quit)
Окончание редактирования без изменения исходной строки;
* поддиректива R (Replace)
Игнорирование итоговой строки и повторение редактирования;
* поддиректива L (List)
Перенос в итоговую строку оставшихся символов исходной и установка
курсора на начало итоговой строки. Как-будто итоговая становится
исходной, а новая итоговая - пустой;
* поддиректива К (Kill)
Если на экран выведена вся итоговая строка, то при выполнении
поддирективы удаляется ближайший символ исходной строки, в противном
случае удаляется знак, под которым находится курсор в итоговой строке;
* поддиректива Z (Zeroize)
Пропуск всех символов итоговой строки, начиная от символа под
курсором и всех последующих символов - еще не рассмотренных -
исходной;
* поддиректива I (Insert)
Изменение вида курсора с L на * и переход в режим, при котором
символы, введенные с клавиатуры, вводятся непосредственно в итоговую
строку. В этом режиме ошибки устраняются DELETE. Выход из режима по
нажатию ENTER.
* поддиректива X (External)
Перенос в итоговую строку оставшихся символов исходной, вывод на
экран всей итоговой строки и неявное выполнение поддирективы I;
* поддиректива C (Chang)
Изменение вида курсора с L на + и переход в режим, при котором
символы, введенные с клавиатуры, непосредственно вводятся в итоговую
строку. Если в момент ввода такого символа на экран выведена вся
итоговая строка, то веденные символы размещаются в конце строки, а
следующий знак исходной строки опускается. В противном случае вводимый
символ замещает находящийся под курсором символ исходной строки и
неявно выполняется поддиректива =>. Выход из этого режима по ENTER.
* поддиректива F (Final)
Поддиректива выполняется после неявного выполнения директивы E,
вызванного выполнением директивы F. При этом организуется поиск
следующего участка, содержащего текст f, который был указан в
предварительно выполненной директиве F. Следует помнить, что поиск
текста осуществляется в границах, определенных в директиве F;
* поддиректива S (Substitute)
Замена найденного текста f текстом s и неявное выполнение
поддирективы F. Поиск текста должен быть инициирован выполнением
директивы или поддирективы F.
Приложение С. Некоторые библиотечные функции
Арифметика, знаковые операции и конверсии
Функция max; (stdio.h)
int max (count) auto
int count;
Функция min; (stdio.h)
int min (count) auto
int count;
Функция abs; (stdio.lib)
int abs(p)
int p;
Функция sign; (stdio.h)
int sign (p)
int p;
Результатом функции является данное величиной -1, 0 или 1 в
зависимости от знака аргумента
Функция peek; (stdio.lib)
char peek (addr)
unsigned addr;
Возвращает данное типа (char), хранящееся по адресу addr.
Функция poke; (stdio.lib)
poke (addr, ch)
unsigned addr;
int ch;
Функция tolower; (встроенная)
char tolower (c)
char c;
Результатом функции является данное типа (char). Если с
заглавная буква, то результат - соответствующая малая. В
остальных случаях - символ, равный с.
Функция toupper; (встроенная)
char toupper (c)
char c;
Функция обратная tolower.
Функция atoi; (stdio.lib)
int atoi (str)
char *str;
Преобразование последовательности символов, указанных str в данные
типа (int). Если последовательность начинается с целого числа, то
результатом является это число, в противном случае - 0.
Сортировка
Функция qsort; (stdio.lib)
qsort (ptr, cnt, size, fun)
char *ptr;
int cnt, size;
int (*fun)();
Сортировка данных, являющихся массивом из cnt элементов, первый байт
которого указан str. Размер элементов определен size, а сравнивающая
функция - fun. Функция, связанная с параметром fun, должна быть
подобрана так, чтобы для ее элементов elm1 и elm2 результатом вызова:
(*fun)(&elm1,&elm2)
было данное типа (int) величиной -1,0 или 1 в соответствии с:
-1 если elm1elm2;
Преобразование символьных последовательностей
Функция strcat; (stdio.lib)
char *strcat (first, second)
char *first, *second;
Удлинение последовательности символов, указанных first, на длину
последовательности second (т.е. присоединение second к first).
Результат функции - данное типа (*char), указывающее на первый знак
последовательности first.
Функция strcmp; (stdio.lib)
int strcmp (src, trg)
char *src, *trg;
Сравнение последовательности знаков, указанных src и trg, и доступ к
данному типа (int), определяющему результат сравнения. Данное имеет
величину 0 -если последовательности равны, положительную - если первая
последовательность больше второй или отрицательную, если первая меньше
второй. Сравнение идет до конца последовательности или до первого
несравнения.
Функция strcpy; (stdio.lib)
char *strcpy (dst, src)
char *dst, *src;
Копирование последовательности, указанной src, в область памяти,
указанную dst.
Функция strlen; (stdio.lib)
unsigned strlen (str)
char *str;
Доступ к данному типа (int) равному числу знаков последовательности,
указанной str.
Управление оперативной памятью
Функция calloc; (stdio.lib)
char *calloc (n, size)
unsigned n, size;
Выделение области памяти, предназначенной для размещения n объектов
размером size каждый и доступ к указателю на эту область. Если
выделение области невозможно, то результат - NULL.
Функция free; (stdio.lib)
free (ptr)
char *ptr;
Освобождение области памяти, выделенной функцией calloc. Аргумент
функции представляет собой указатель на эту область.
Функция swap; (встроенная)
swap (pArea, qArea, len)
char *pArea, *qArea;
unsigned len;
Обмен местами содержимого двух областей памяти длиной len байт,
указанных pArea и qArea.
Функция move; (встроенная)
move (dst, src, len)
char *dst, *src;
unsigned len;
Копирование области памяти длиной len, указанной src, в область,
указанную dst.
Операции ввода/вывода
Функция gets; (stdio.lib)
char gets (str)
char *str;
Размещение в области памяти, указанной str, последовательности
символов, получаемой из стандартного файла ввода. Выполнение функции
заканчивается при получении знака 'n' (ENTER). Вместо него в ЗУ
записывается знак с кодом 0. Результатом функции является указатель на
первый знак поля памяти.
Функция puts; (stdio.lib)
puts (str)
char *str;
Вывод в стандартный файл вывода последовательности символов, указанных
str. Необходимо, чтобы последним знаком был знак с кодом 0.
Функция fgets; (stdio.lib)
char *fgets (str, n, inp)
char *str;
int n;
FILE *inp;
Размещение в поле памяти, указанном str, не более чем n знаков,
получаемых из файла, указанного inp. Выполнение функции заканчивается
при размещении n-1 знака или при получении знака 'n'. После этого в
поле размещается дополнительный знак с кодом 0. Результатом функции
является указатель на первый знак поля или знак NULL, если файл
пустой.
Функция fputs; (stdio.lib)
fputs (str, out)
char *str;
FILE *out;
Вывод в файл, указанный out, последовательности знаков, указанных str,
оканчивающейся символом с кодом 0.
Генерация случайных чисел
Функция rand ; (stdio.lib)
int rand()
Функция srand (s); (stdio.lib)
int s;
Переустановка генератора случайных чисел.
Графика и звук
Функция plot; (stdio.lib)
plot (on, x, y)
int on,x, y;
Индикация на экране пикселя с координатами х, y и с цветом paper, если
on=0, или ink, если on=1.
Функция line; (stdio.lib)
line (on, dx, dy)
int on, dx, dy;
Вычерчивание отрезка прямой от текущей позиции, установленной функцией
plot, до точки, удаленной на dx, dy. On определяет цвет.
Функция paper; (stdio.lib)
paper (color)
int color;
Функция ink; (stdio.lib)
ink (color)
int color;
Функция cls; (stdio,lib)
cls()
Функция beep; (stdio.lib)
beep (time, tone)
int time, tone;
Tone - частота в Hz, time - длительность 1/10 s.
Приложение D. Сообщения об ошибках
Error-0 missing 'x'
отсутствие ожидаемого знака
Error-1 RESTRICTION: not implemented
неизвестный тип данных
Error-2 bad character constant
ошибка в символьном литерале
Error-3 not a prerocessor command
ошибочная директива препроцессора
Error-4 LIMIT: macro buffer full
определение отменяет само себя
Error-5 can only define identifiers as macros
ошибочная директива препроцессора
Error-6 RESTRICTION: macros may not have parametrs
ошибочная директива препроцессора
Error-7 cannot open file
отсутствие файла с данным именем
Error-8 RESTRICTION: cannot nest includes
включенный файл содержит директиву включения другого файла
Error-9 missing while
ошибка в команде do
Error-10 not in loop or switch
неправильное использование команды break
Error-11 not in loop
неправильное использование команды continue
Error-12 not in switch
команды case или default неправильно использованы
Error-13 LIMIT: too many case satements
слишком много case
Error-14 multiple default statments
более чем один default
Error-15 goto needs a label
отсутствие метки в команде goto
Error-16 multiple use of identifier
совпадение метки и идентификатора
Error-17 direct execution not possible
некорректное использование директивы препроцессора
Error-18 LIMIT: name table full
слишком много типов данных
Error-19 LIMIT: too many types
слишком много типов данных
Error-20 duplicate declaration - type
двойное объявление
Error-21 duplicate declaration - storage class
двойное объявление
Error-22 LIMIT: global symbol table full
Error-23 LIMIT: too much global data
слишком много переменных вне объявления функции
Error-24 duplicate declaration
двойное объявление
Error-25 LIMIT: local symbol table full
слишком много переменных в функции
Error-26 this variable was not in parametr list
переменная не была упомянута в списке параметров
Error-27 undefined variable
Error-28 bad function return type
ошибочное выражение в команде return
Error-29 no arrys of functions
использован массив функций
Error-30 LIMIT: expression too complicated
Error-31 LIMIT: expression too complicated
слишком сложное выражение
Error-32 bad type combination
некорректный аргумент операции
Error-33 bad operand type
некорректный аргумент операции
Error-34 need an lvalue
использовано не l-выражение
Error-35 not a defined members of a structure
имя не идентифицирует поля
Error-36 expected a primary here
использовано не первичное выражение
Error-37 undefined variable
обращение к не объявленной переменной
Error-38 need a type name
не использовано имя типа
Error-39 need a constant expression
использовано не константное выражение
Error-40 can only call functions
в вызове не использовано имя функции
Error-41 does not follow ? properly
неправильное использование 3х-аргументного оператора
Error-42 destination must be an lvalue
использовано не l-выражение
Error-43 need a:to follow ?
неправильное использование 3х-аргументного оператора
Error-44 need a pointer
не использован указатель
Error-45 illegal parametr type
некорректный параметр функции
Error-46 RESTRICTION: not implemented
неизвестный тип данных
Error-47 cannot use this operator
неизвестный тип данных
Error-48 bad declaration
ошибка в объявлении
Error-49 storage class not valid
ошибка в объявлении
Error-50
Error-51 duplicate declaration of structure tag
двойная декларация признака
Error-52 use a predeclared structure for parameters
объяви структурный тип после функции
Error-53 structure cannot contain itself
структура не может содержать саму себя
Error-54 bad declarator
ошибка в объявлении
Error-55 missing ) in function declaration
отсутствие () в объявлении функции
Error-56 bad formal parameter list
ошибка в объявлении функции
Error-57 type should be function
неизвестный тип результата функции
Error-58
Error-59
Error-60 LIMIT: no more memory
Error-61 RESTRICTION: use assignment to initialize
некорректное присвоение начальных данных
Error-62-63 cannot initialize this
некорректное присвоение начальных данных
Error-64 too much initialization data
слишком много начальных данных