Добавил:
ivanov666
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Прикладное программирование на CC++ с нуля до мультимедийных и сетевых приложений
.pdf
Функции 41
Здесь сначала описана главная функция, а затем функция STEP. Поскольку естественный порядок описания функций нарушен, мы должны информировать функцию main о том, что где-то в программе описана функция
STEP, которую следует использовать. Нужно объявить (декларировать) ее.
Как видно из примера, делается это очень просто. Функция STEP имеет тип
double, и ее объявляют в main вместе с описаниями переменных этого типа.
Для того чтобы система могла отличить объявление переменной от объявления функции, после имени функции в описании ставят круглые скобки.
Функция STEP от двух аргументов: õ (вещественного типа) и n (целого
типа), как легко убедиться, возвращает n-ю степень числа õ для неотрицательных целых n. Главное, на чем следует остановиться, это то, что в теле
функции STEP нам пришлось описать две дополнительные переменные — i è
s, после чего изготовленная нами функция стала совсем похожей на уже совсем родную нам главную функцию main. Мы упоминали о том, что переменные, описанные внутри функции, являются локальными. Они «живут»
только в этой функции и для других функций не существуют. В этой связи
имена локальных переменных в разных функциях вполне могут совпадать.
Переменная õ1 в функции Ì не имеет никакого отношения к переменной õ1
в функции Ð так же, как Миша, живущий в квартире 56, это вовсе не то же
самое, что Миша, живущий в квартире 65. Совсем иное дело — глобальные
переменные, описанные в программе вне функций. Такие переменные (и
константы) «живут» во всех функциях, описанных после глобальных переменных. Такие объекты видны из любой функции программы. Изменение
значения глобальной переменной, сделанное в одной из функций программы, немедленно отобразится на ее значении во всех остальных функциях.
Продолжая нашу аналогию, можно сказать, что Александр Сергеевич Пушкин — он и есть Пушкин и для квартиры 56, и для квартиры 65, и если президентом на выборах стал господин Буш, то он стал президентом и для штата
Техас, и для штата Флорида.
Правда, и здесь возможны особенности. А что, если в некой семье с нестандартным воображением родившегося ребенка назвали А. С. Пушкин? Когда в этой семье говорят о Пушкине, то кого имеют в виду? В житейской ситуации, по-видимому, в этом случае требуются дополнительные пояснения.
В С ничего такого не нужно. Существует следующее правило: если имя глобальной переменной совпадает с именем локальной для некоторой функции
переменной, то внутри этой функции операции с этим именем относятся к
локальному объекту. Так, например, изменение локальной переменной никак
не отразится на значении глобальной переменной с тем же именем. Наоборот,
изменение глобальной переменной проявится во всех функциях, где такое
имя не описано, а там, где описана ее локальная «тезка», с последней ничего
не произойдет.
Мы говорили пока о типизированных функциях, вычисляющих одно значение и возвращающих это значение в качестве значения функции. Возможен, однако, и другой вариант использования функций, когда требуется определить и передать в программу несколько значений. В некоторых языках про
граммирования такие программные модули носят название процедур.
-

42 Глава 1. Язык программирования С
Типичная для этого варианта задача — преобразование координат. Допустим,
нам нужно создать функцию, которая принимает в качестве аргументов полярные координаты точки ρ è ϕ и передает в вызывающую эту функцию программу декартовы координаты точки Õ è Ó, вычисляемые по формулам
X =ρ ϕcos( ),Y =ρ ϕsin( )
.
Один из способов решения такой задачи состоит в передаче вычисленных
значений в вызывающую программу в виде глобальных переменных:
#include<stdio.h>
#include<math.h>
#define Pi 3.1415927
double X,Y;
void decart(double r,double f)
{ double pil80=Pi/180;
X=r*cos(f); Y=r*sin(f); }
void main()
{double rr.ff;
scanf("%lf %If'",&rr.&ff);
decart(rr,ff);
printf("%lf %lf",X,Y); }
Прежде всего, поясним новый элемент программы, появившийся в третьей строке. Мы уже говорили, что конструкции, начинающиеся символом #,
являются инструкциями препроцессору. Такие инструкции предписывают
системе еще до начала компиляции произвести над программой некоторые
предварительные действия. Так, инструкция #include предписывает подключить к программе соответствующий заголовочный файл. По инструкции
#define ÀAÀ ÂÂÂ препроцессор просматривает весь текст программы и везде,
где встречается фрагмент ÀÀÀ, производится его замена на фрагмент ÂÂÂ.
Подчеркнем, что замена делается именно в тексте еще до компиляции программы. Необходимость в использовании этой препроцессорной инструкции
возникает только в особых случаях, с которыми, однако, читателю, возможно,
придется столкнуться, что и побудило нас включить эту конструкцию в программу.
Функция decart в данной программе не возвращает никакого значения и
поэтому имеет тип void. В теле функции описана локальная переменная pil80,
которая получает значение, используемое для преобразования углов из градусной меры в радианную. Использование здесь локальной переменной явно
нецелесообразно. Автор сознательно допустил это для того, чтобы читатель
сам попробовал сделать необходимые корректировки. Передача в главную
функцию вычисленных в decart значений осуществляется с помощью глобальных переменных Õ è Y.
Передача результатов вычислений из одной функции в другую через глобальные переменные является не единственным и иногда и не лучшим способом. Альтернативой может быть передача значений по адресам, с использованием указателей. Начнем с того, что напомним — функция, приняв значения
своих аргументов, работает не непосредственно с этими аргументами,асих

Функции 43
копиями. Так, если вы попытаетесь в теле функции изменить значение аргумента, то, выйдя из функции, обнаружите, что эти изменения в вызывающей
функцию программе никак не отразились. Однако эту особенность можно
обойти, если аргументы, которые вы хотите изменить, задать через их адреса.
Теперь, если с ними обращаться по правилам работы с указателями, то можно
передавать значения из функции в функцию по адресам, без использования
глобальных переменных.
Продемонстрируем эти возможности на той же задаче, которую реализовала предыдущая
const double pil80=3.1415927/180;
void DECART(double r,double f,double *x,double*y)
{ *x=r*sin(f*pil80); *y=r*cos(f*pil80); }
void main()
{double r,f,x,y;
scanf("%lf %lf",&r,&f);
DECART(r,f,&x,&y);
printf("%lf %1f",x,y); }
программа. Сейчас она будет выглядеть следующим образом:
Для начала мы оптимизировали определение значения pi180. Теперь оно
стало вещественной константой, которая не может и не должна меняться нигде в программе. Кроме того, сразу задано ее числовое значение через деление
пифагорова числа на 180. Эта операция делается в программе один раз, что и
является наиболее оптимальным.
Функция DECART имеет четыре аргумента. Два первых — обычные переменные типа double, а третий и четвертый — указатели на double. Тело функции состоит из двух выражений присваивания. Первое из них следует понимать так: «По адресу, указанному третьим аргументом функции, записать значение, равное произведению первого аргумента на синус второго аргумента,
умноженного на значение константы pi180». Аналогичную сентенцию можно
сочинить и для второго выражения присваивания.
В главной функции описаны четыре вещественные переменные: r, f, õ, ó.
Значения первых двух вводятся с консоли и далее используются как «входные» параметры в функции DECART. Значения õ è ó формируются в результате работы этой функции. Поскольку на месте двух последних аргументов
должны стоять указатели, мы написали в вызове функции DECART &x è &ó.
Изложенные только что представления позволят нам окончательно разобраться с функцией scanf. Вспомним, что инициализируемую с консоли переменную мы снабжали символом & перед ее именем. Сейчас стало понятным,
почему это необходимо. Функция scanf должна изменить значение вводимой
переменной — единственная возможность сделать это без привлечения глобальных объектов заключается в использовании указателей. Именно по этой
причине аргументом функции scanf является не сама переменная, а ее адрес.
Продолжим изучение функций уже на достаточно сложном примере с
многократным последовательным вызовом нескольких функций. Заметим, что
читатель, «не обремененный» некоторыми знаниями из высшей математики,
будет вынужден пропустить следующий пример.

44 Глава 1. Язык программирования С
Рассмотрим вполне реальную задачу приближенного вычисления определенного интеграла по методу трапеций. Формула трапеций может быть представлена в следующей форме:
Здесь
h
ba
=
b
f x dx h
( ) ...
∫
a
−
,
y fx
= (),x a ih
ii
n
⎛
=
⎜
⎝
yy
+
0
n
++++
2
=+
i
yy y
12
⎞
⎟
n
⎠
.
.
Суть метода трапеции состоит в том, что интервал интегрирования разбивается на n малых равных между собой отрезков длиной h. На каждом из этих
отрезков подынтегральная площадь заменяется трапецией, площадь которой
вычисляется по известной формуле. Точность вычисления интеграла зависит
от числа разбиений n. Можно, увеличивая n, достичь желаемой относительной точности. Мы в нашей программе будем поступать следующим образом.
Вычислим интеграл при n разбиениях — получим значение J
снова вычислим интеграл — получим значение J
JJ
−
nn
êà
2
, ãäå ε — заданная точность, то процесс удваивания n продол-
>
J
2
ε
n
. Если относительная ошиб-
2n
. Удвоим n è
n
жается. Рано или поздно (если интеграл «хороший») желаемая точность будет
достигнута. А теперь составим программу, которая вычисляет конкретный ин-
теграл, например
b
3
x
:
dx
∫
3
a
double a.b;
double FUNC(double x)
{ return x*x*x/3.; }
double trap(double a,double b,int n)
{ int i=l;
double h=(b-a)/n,t=0.5*(FUNC(a)+FUNC(b));
for(;i<n;) t+=
return t*h; }
double integral(double eps)
{ int n=4,z;
double a0=trap(a,b,4),al;
do
{al=trap(a,b,n+=n);
z=fabs (al-a0) >fabs (a1) *eps;
a0=al; } while(z);
return al; }
void main()
{ double epsilon;
printf("a="); scanf("%lf",&a);
printf("b="); scanf("%lf'",&b);
printf("eps="); scanf("%lf",&epsilon);
printf("INTEGRAL=%lf",integral(epsilon)); }
;
PUNC(a+h*i++);
Описаны две глобальные переменные à è b, которым будут присвоены
значения пределов интегрирования. Функция FUNC предназначена для вычисления значений подынтегрального выражения. Не составляет труда изме
-

Функции 45
нить конкретную функцию x3/З на любую другую. Функция trap реализует
формулу трапеций для разбиения интервала интегрирования от à äî b на n отрезков. Три эти величины являются аргументами функции. Функция integral
выполняет вычисление интеграла по методу трапеций с заданной точностью.
Параметр eps определяет эту точность. Рекомендуется внимательно рассмотреть тело функции и убедиться в том, что здесь действительно реализован алгоритм достижения заданной точности.
Все три функции возвращают вещественные значения и используются в
главной функции. В последней с консоли вводятся пределы интегрирования и
точность. Функция печати вызывает функцию integral, которая вызывает
функцию trap, которая, в свою очередь, обращается к функции FUNC. Такие
многократные, вложенные друг в друга вызовы функций являются типичными структурами алгоритмических языков программирования.
Рассмотрим еще один пример на использование «самодельной» функции
без параметров. В этом примере мы познакомимся с еще одним генератором
случайных чисел, описанным в заголовочном файле stdlib.h. Эта функция называется random, имеет аргумент типа int и возвращает целое случайное число
из диапазона от 0 до N – 1, ãäå N — значение аргумента функции. С помощью
этой функции изготовим генератор вещественных случайных чисел в диапазоне от 0 до 1. В главной функции генератор будет использован для заполнения
вещественного массива случайными числами:
#include<stdlib.h>
const double g=l./31999.;
double RN()
{ return random(32000)*g; }
void main()
{ int i=0; double a[10];
while(i<10) printf("%lf\n" ,a[i++]=RN()); }
Легко видеть, что функция RN, которой не нужны аргументы, с использованием заготовленной глобальной константы g реализует генерацию случайной величины в нужном диапазоне. Обратим внимание на то, что в главной
программе производится печать очередного элемента массива, который прямо
в функции печати и получает значение.
Следующая функция заполняет n первых элементов массива случайными
целыми в диапазоне от 0 до 9:
void initarray(int *name. int n)
{do *(name+- -n)=random(10); while(n); }
Эта функция может быть использована, например, в следующей главной
функции:
void main()
{ int mass[100],k;
printf("ЗАПОЛНИТЬ K="); scanf("%d",&k);
initarray(mass,k);
printf("ЭЛЕМЕНТОВ МАССИВА\п");
while(k) printf("%d\n",mass[- -k]);}

46 Глава 1. Язык программирования С
Последний вопрос, который мы рассмотрим в отношении функций, связан с использованием имен функций в качестве аргументов функций. Сразу
обратимся к примеру программы:
double function1(double x)
{ return (x+3.2)*(x-4.7); }
double function2(double x)
{ return (x*x-3.*x-.2)*7.4; }
double minimum(double a,double b.int n,double func(double))
{double h=(b-a)/n,g=1e32,min=func(a); int i=l;
while(i<=n) if(g=func(a+h*i++))<min) min=g;
return min; }
void main()
{ printf("MINIMUM function1=%e\n
MINIMUM functioii2=%e",
minimum(-10.0,+10.0,1000,function1),
minimum(-10.0,+10.0,1000,function2)); }
Две первые функции в программе вычисляют значения некоторых алгебраических выражений — полиномы второй степени от x. Функция minimum возвращает значение, полученное с некоторой точностью, доставляющее минимум функции с именем func. Интервал [àb], на котором находится минимум,
разбивается на n отрезков и на конце каждого отрезка с координатой à+h*i
проверяется, имеет ли функция значение, меньшее по сравнению с предыдущим значением. Разобраться более детально с поиском минимума читателю
предлагается самостоятельно. Нас сейчас интересует оформление функции
minimum. Она имеет четыре параметра, три из которых — обычные аргументы: à
è b — концы интервала, n — число разбиений интервала. Четвертый параметр
является именем функции, с которой предстоит работать функции minimum.
Пока конкретный вид функции func не задан — func является формальным именем, а фактическое имя будет задаваться только в главной функции. Для того
чтобы компилятор «понял», что последний аргумент есть имя функции, после
имени стоят скобки, а для того чтобы компилятор «знал», что формальная
функция имеет один аргумент типа double, в скобках стоит название типа. Обратите внимание, что после названия типа нет имени аргумента. Кроме того,
необходимо указать и тип формальной функции. В нашем случае это double. Теперь обратимся к главной функции. Она дважды вызывает функцию minimum.
Первый раз в качестве фактического имени использовано имя function1, à âòîðîé ðàç — function2. При этом указывается только имя функции без скобок и
аргументов. Таким образом, используя в качестве аргументов формальные имена функций, можно создавать универсальные функции, обеспечивающие вызовы различных конкретных функций.
Файлы
До сих пор возможности общения наших программ с окружающим миром
были весьма ограничены. Мы могли только вводить данные в программу с
консоли и выводить их на экран. Теперь наша задача состоит в том, чтобы

Файлы 47
научиться записывать результаты работы программы на диск и считывать данные с диска в программу.
Как известно, любые данные хранятся на магнитных носителях информации (магнитных дисках) в виде файлов. Представляя файл как «папку» с информацией, что дословно и соответствует английскому слову file, мы должны
освоить процедуры открытия и закрытия этих «папок» и процедуры чтения и
записи файлов.
Сразу начнем со следующей программы:
void main()
{ int i;
FILE *f;
f=fopen("one.dat","w");
for(i=l; i<15; i++) fprintf(f,"%d\n",i);
fclose(f); }
Здесь мы впервые столкнулись с еще одним типом данных. Название этого типа FILE (пишется именно заглавными буквами, что для С нехарактерно).
Переменная f имеет отношение к этому новому типу. Поскольку она фигурирует в описании со стоящей перед ней звездочкой, многоопытный читатель
сделает вывод о том, что f является указателем. Так оно и есть, и указывает
этот указатель на файл. Иными словами, f является адресом начала файла.
Пока, однако, этот указатель не инициализирован, не привязан ни к какому
конкретному файлу. Инициализация указателя на файл (мы будем использовать также термин «файловая переменная») производится одновременно с открытием файла, предоставлением файла в распоряжение данной программе.
Открытие файла производится функцией fopen и выглядит как выражение
присваивания:
ИмяФайловойПеременной=fореn("Строка1", "Строка2");
Эта процедура действительно является присваиванием, поскольку функция fopen, возвращающая адрес файла, который она открывает, имеет тип
FILE*. Функция имеет два аргумента. Строка1 задает имя открываемого файла. В DOS полное имя файла состоит, как правило, из собственно имени и
расширения, разделенных точкой. В нашем примере открывается файл
one.dat. Строка2 состоит из буквы, показывающей, для каких операций открывается файл. Возможны следующие варианты:
•
«r» — файл открывается для чтения из него информации (read);
•
«w» — файл открывается для записи информации (write);
•
«a» — файл открывается для дозаписи информации в конец файла
(append).
Буква w предполагает создание нового файла с указанным в Строке1 именем. Будьте внимательны: если на диске в рабочем каталоге уже существовал
файл с таким именем, то его открытие для записи приведет к безвозвратной
(и, вероятно, безвременной) утрате старого файла.
Данная программа создает новый файл и записывает в него 14 целых чи
сел от 1 до 14. Каждое число записывается в новую строку. Функция записи в
-

48 Глава 1. Язык программирования С
ôàéë fprintf весьма похожа на знакомую вам функцию печати на экран printf.
Разница состоит в том, что сразу за открывающей скобкой пишется файловая
переменная, а далее после запятой все полностью совпадает с правилами
оформления печати на экран. Информация, записанная в файл, выглядит
точно так, как и на экране. В этом можно убедиться, просмотрев созданный
файл с помощью любого текстового редактора, в частности, и из системы
TURBO Ñ. Поработав с папкой, вы, наверное, ее закрываете. Это же следует
сделать и с файлом. Функция закрытия файла fclose имеет в качестве аргумента имя файловой переменной. Можно отметить, что в случае успешного, как
говорят военные — штатного, завершения программы все открытые файлы
закрываются автоматически. Тем не менее, мы настоятельно рекомендуем вызывать функцию fclose сразу после того, как программа завершила работу с
соответствующим файлом.
Теперь напишем программу, которая читает данные из файла. Считаем,
что на диске существует файл one.dat, созданный предыдущей программой:
void main()
{ int i,j=10.k;
FILE *pp;
Pp=fopen("one.dat","r");
for(i=0; i<j; i++)
{ fscanf(pp,"%d",&k);
printf("%d\n",k); }
fclose(pp); }
В программе файл one.dat открывается для чтения. В цикле с помощью
функции чтения из файла fscanf в переменную k из этого файла читается очередное число, и его значение выводится на экран. После чтения десяти чисел
файл закрывается, и программа завершает работу.
Функция fscanf также похожа на функцию ввода с клавиатуры scanf. В ней
на первом месте стоит указатель на файл. С оформлением форматной строки
дело обстоит несколько сложнее. Прежде всего, нужно знать, что если в форматной строке стоит некий символ, то вы должны быть уверены, что текущая
позиция читаемого файла содержит именно этот символ. Например, если в
форматной строке стоит \n, то и в файле в этот момент находится символ перехода на новую строку. В этой связи рекомендуется, по крайней мере, на
первых порах, вообще не писать в форматной строке ничего, кроме форматных выражений. Избегайте даже пробелов. Учитывая эти тонкости, разработчики системы позаботились о том, чтобы функция fscanf в какой-то степени
сама разбиралась с размещением записей в файле. Как бы ни размещались
числа: каждое в своей строке, группами в строках, все в одной строке — вы
просто пишете подряд столько форматных выражений, сколько нужно прочитать чисел (или символов). Не обращайте внимание на то, как расположены
данные в файле. Можете считать, что они все записаны подряд в строчку.
Нормально сформированный файл всегда имеет последним символом
признак конца файла EOF (end of file). Существует специальная функция feof,
имеющая аргументом файловую переменную, которая показывает, достигнут

Файлы 49
ли конец файла. Для более ясного представления о работе функции feof представим файл в виде киноленты, которая прокручивается так, что после очередного чтения данных следующий кадр устанавливается в «файловое окно».
В качестве кадра надо понимать очередной байт, записанный в файл. В самом
последнем кадре файла и находится признак конца файла EOF. Если после
очередного чтения из файла в «файловом окне» оказался признак конца, то
при вызове функции feof она возвращает 1, иначе конец файла не достигнут,
и функция возвращает 0.
Рассмотрим новую стандартную функцию int getc(FILE *f). Как видно из
такого ее формального определения, функция getc возвращает целое число и
имеет своим аргументом указатель на файл. Функция читает из файла очередной символ (байт) и возвращает его код (значение). Обратим внимание на то,
что читается один байт, а возвращаемое значение конвертируется в тип int,
занимающий два байта.
Функция int putc(int ñ,FILE *f) записывает в очередную позицию файла
символ, код которого задан первым аргументом. Первый аргумент имеет тип
int, a при записи в файл значение конвертируется в тип char. Таким образом,
на месте первого параметра может находиться как код символа, так и сам
символ. Функция возвращает код записанного символа, что может быть использовано в программе.
Теперь уместно, безотносительно к текущей теме — файлам, рассмотреть
еще несколько полезных функций. Функция int getch(void), нам уже знакомая,
читает символ, скажем так, из стандартного файла ввода/вывода. А стандартным файлом назовем консоль. Следовательно, функция вводит символ с клавиатуры. До сих пор мы пользовались этой функцией для того, чтобы сохранить открытым рабочий экран до нажатия любой клавиши. Это действительно важное приложение функции, но ее основным назначением является
передача в программу символа, считываемого с клавиатуры.
Функция int putch(int ñ), наоборот, передает символ, заданный своим аргументом, в стандартный файл ввода/вывода. А чтобы перестать испытывать
терпение читателя, то автор будет вынужден сказать по-простому: функция
печатает на экран символ — свой аргумент.
В некоторых реализациях систем программирования, в частности, в
TURBO С, вы можете встретить модификации этих функций getchar, putchar,
getche и putche. Эти разновидности описанных выше функций отличаются ре-
жимом работы, в том числе буферизацией или не буферизацией ввода. Сказав
эти загадочные слова, автор этим и ограничится, отослав любопытного читателя к справочной системе TURBO C++ и к литературе.
Наряду с чтением и записью одиночных символов существуют функции
чтения и записи строк, как для консоли, так и для файлов. Эти функции имеют имена gets, puts, fgets è fputs.
Функция char* gets(char* s) читает строку символов с клавиатуры (до нажатия клавиши ввода) и помещает ее в память, начиная с адреса s. При этом в
качестве аргумента функции целесообразно использовать имя описанного в
программе символьного массива, в который будет помещена прочитанная с
консоли строка.

50 Глава 1. Язык программирования С
Функция int puts(const char* s) может иметь своим аргументом указатель
на символ — имя символьного массива или непосредственно строку символов
в кавычках. Строка или массив выводится на экран.
Из файла может быть прочитана или в файл может быть записана строка.
Первую из этих задач выполняет функция char* fgets(char*, int, PILE* ). Она
читает из файла, на который указывает последний аргумент, очередную строку, записывает ее в память по адресу, на который указывает первый аргумент.
При этом читается количество символов, не превышающее значения второго
аргумента, уменьшенного на единицу. В конец записанной в память строки
автоматически добавляется признак конца строки \0. Сама функция, в соответствии с ее типом char*, возвращает адрес начала строки.
Следующая программа, текст которой будем считать находящимся в файле re.ñ, построчно читает сама себя и выводит на экран длины строк:
#include<stdio.h>
#include<string.h>
void main()
{ FILE *f;
char *p;
int length;
f=fopen("re.c","r");
while(!feof(f))
{fgets(p,256,f);
length=strlen(p);
printf("%d\n",length); }}
Ограничитель длины читаемой строк здесь выбран равным 256, поскольку
в редакторе TURBO Ñ недопустимы строки длиннее 255 знаков. Можно обойтись без переменной length и использовать в цикле while единственное выражение printf(«%d\n»,strlen(fgets(p,256,f))). Обратите внимание на то, что мы не
пытались описать в программе символьный массив, в который записывается
очередная строка. Вместо этого мы создали только указатель ð íà char — адрес
начала строки. Так поступать вполне допустимо, хотя душа автора этому непроизвольно противится, поскольку при этом конкретная область памяти под
строку, казалось бы, не выделяется. В реальной программе автор описал бы
массив ð[256] и после этого спал бы по ночам спокойным сном, чего и читателю желает.
Функция int fputs (char*, FILE*) записывает в файл, указанный последним
аргументом, строку, расположенную по адресу, указанному первым аргументом. Возвращается количество записанных символов.
Если выполняются строковые операции со стандартным файлом ввода/вывода, то есть с консолью, то используются функции char* gets (char*) è
int puts(const char*). Наверное, уже нет нужды пояснять, что является аргументами этих функций и какие значения эти функции возвращают.
Широкие возможности программисту предоставляет так называемый прямой доступ к файлу. Используя нашу аналогию файла с кинолентой, можно
сказать, что прямой доступ к файлу позволяет устанавливать файловое окно на
любой заданный кадр. Установка очередной позиции осуществляется функци
-
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
