Механическое удерживание земляных масс: Механическое удерживание земляных масс на склоне обеспечивают контрфорсными сооружениями различных конструкций...
Типы сооружений для обработки осадков: Септиками называются сооружения, в которых одновременно происходят осветление сточной жидкости...
Топ:
Характеристика АТП и сварочно-жестяницкого участка: Транспорт в настоящее время является одной из важнейших отраслей народного хозяйства...
Отражение на счетах бухгалтерского учета процесса приобретения: Процесс заготовления представляет систему экономических событий, включающих приобретение организацией у поставщиков сырья...
Интересное:
Влияние предпринимательской среды на эффективное функционирование предприятия: Предпринимательская среда – это совокупность внешних и внутренних факторов, оказывающих влияние на функционирование фирмы...
Национальное богатство страны и его составляющие: для оценки элементов национального богатства используются...
Аура как энергетическое поле: многослойную ауру человека можно представить себе подобным...
Дисциплины:
2021-03-18 | 54 |
5.00
из
|
Заказать работу |
|
|
После успешного открытия файла программа может осуществлять файловый ввод-вывод. Функции потокового ввода-вывода можно разделить на четыре группы: 1) функции посимвольного ввода-вывода, которые переносят один символ; 2) функции построчного ввода-вывода, которые переносят одну строку; 3) функции форматированного ввода-вывода данных; 4) функции блокового ввода-вывода, которые переносят блоки данных.
3.3 Посимвольный ввод-вывод
Функция посимвольной записи (вывода) в файл имеет прототип:
int fputc(int ch, FILE *fp);
Эта функция помещает символ int ch после преобразования в тип char в открытый поток fp, связанный с файлом. В случае успеха возвращает код записываемого в файл символа, а в случае ошибки или достижения конца файла – EOF.
Пример. Запись символов в открытый для записи файл через поток fp
FILE * fp = fopen (" abc. txt "," w "); // открытие потока для записи
if (fp == NULL){ puts ("ошибка открытия файла"); return -1;}
char s1='Z', str1[]=" Запорожье ",s2;
fputc(s1,fp); // запись символа в файл через поток fp
for(int i=0; i<9; i++)
fputc (str 1[ i ], fp); // запись 9 символов в файл
fputc ('\ n ', fp); // запись символа \ n в файл
printf("Введите символ или Ctrl-Z");
while ((s 2= getchar ())!= EOF)
fputc(s 2,f p); // запись символов в файл
fclose(f p); // закрытие потока
Функция посимвольного чтения (ввода) из файла имеет прототип:
int fgetc(FILE *fp);
Эта функция возвращает символ из открытого потока fp, связанного с файлом, или EOF (–1) в случае ошибки или достижения конца файла.
Пример. Чтение символов из открытого для чтения файла через поток fp
FILE * fp = fopen (" abc. txt "," r "); // открытие потока для чтения
if (fp == NULL){ puts ("ошибка открытия файла"); return -1;}
char z 1, str2[9], z 2;
z 1=fgetc(fp); // чтение символа из файла через поток fp
printf("%c\n", z 1);// вывод на экран прочитанного символа
|
for(int j=0;j<9;j++)
{str2[j]=fgetc(fp); // чтение 9 -и символов из файла
printf("%c",str2[j]);} // вывод на экран cчитанных символов
while((z 2=fgetc(f p))!=EOF) // чтение символов из файла
putc har (z 2);// вывод на экран прочитанных символа
fclose(f p); // закрытие потока
3.4 Построчный ввод-вывод
Функция построчной записи (вывода) в файл имеет прототип:
int fputs(char*string, FILE *fp);
Эта функция переносит байты из строки string в открытый файл через поток fp. Перенос завершается при достижении символа '\0', который в файл не заносится. В случае успеха функция возвращает код последнего записанного в файл символа, а в случае ошибки – EOF. Необходимо следить, чтобы записываемая в файл последовательность символов имела '\0', иначе файл может оказаться неожиданно большим.
Пример. Запись строк в открытый для записи файл через поток fp
FILE * fp = fopen (" abc. txt "," w "); // открытие потока для записи
if (fp == NULL){ puts ("ошибка открытия файла"); return -1;}
char *s1=” Физика ”,*ms1[3]={" ТЕК "," КЕ "," ПТЦА "};
fputs(s1,fp); // з апись строки в файл через поток fp
fputs(" \n ",fp); // з апись строки с \n в файл через поток fp
for (int i=0;i<3;i++)
{fputs(m s1[i],fp); // запись 3 -х строк в файл через поток fp
fputs ("\ n ", fp);}
fclose (fp);// закрытие потока
Функция построчного чтения (ввода) из файла имеет прототип:
char*fgets(char *string,int N,FILE *fp);
Эта функция принимает байты из открытого файла и размещает их по адресу, заданному указателем string. Прием завершается после приема N байт или при получении символа '\n', который тоже передается в строку string. Последним символом является '\0 '. В случае успеха возвращает указатель на строку string, а в случае ошибки или достижения конца файла – NULL –указатель. Для успешного чтения строки из файла надо зарезервировать достаточное место в памяти.
Пример. Чтение строк из открытого для чтения файла через поток fp
FILE * fp = fopen (" abc. txt "," r "); // открытие потока для чтения
if (fp == NULL){ puts ("ошибка открытия файла"); return -1;}
char s2[20], m s2[3][20]; // зрезервируем память
|
fgets(s2,20,fp);// чтение из файла строки, < 20 символов
puts(st2); // вывод на экран прочитанной строки
for(int j =0; j <3; j ++)
{fgets(m s2[ j ],20,fp); // чтение из файла 3 - х строк, <20 сим-в
puts(m s2[ j ]);} // вывод на экран считанных строк
fclose(f p); // закрытие потока
Функция fgets() похожа на функцию gets(). Но функция gets(), получив из стандартного потока (клавиатуры) символ ' \n ' (Enter), преобразует его в ' \0 ' и помещает в строку. Функция fgets(), получив из потока (файла) символ ' \n ', записывает его в строку и еще дописывает символ ' \0 '. Функция fputs() похожа на функцию puts(). Но функция puts() преобразует символ конца строки ' \0 ' в символ ' \n ', выполняет перевод на начало новой строки. Функция fputs(), встретив символ ' \0 ' завершает запись в файл.
Таким образом, если записывать в файл строки без символа ' \n ' в конце строки функцией fputs(), то в файле будет только одна строка. При чтении функцией fgets() строки из файла функция puts() выведет на экран одну суммарную строку. Если записывать в файл строки с символом '\n' в конце, используя функцию fputs(), в файле будет несколько строк с символом ' \n '. При чтении строк из файла функцией fgets() символ ' \n ' преобразуется в символы ' \n ', ' \0 ', а функция puts() выведет на экран строки с символом ' \n ' в конце каждой строки, т.е. между выводимыми строками появятся пустые строки.
Пример. Запись и чтение строк без символа ' \n ' и с символом ' \n '.
#include<stdio.h>
#include<string.h>
Void main()
{ int n =0;
FILE * pf = fopen (" b. txt "," w "); // открытие потока
char st1[]= " Anna ",st2[]= " Ма ria ",st3[20];
// char st1[]= " Anna\n ",st2[]= " Маria\n ",st3[20];
fputs(st1,pf); // запись в файл 4 символов (или 6 символов)
fputs(st2,pf); // запись в файл 5 символов (или 7 символов)
fclose(pf); // размер файла 9 байт (или 13 байт)
pf=fopen("b.txt","r");
while(fgets(st3,20,pf)!=NULL)
{puts(st3); n++;}
printf(" Число строк =%d ",n);
fclose(pf);}
На экран выведется
в первом случае: | во втором случае |
AnnaМаria Число строк=1 | Anna Маria Число строк=2 |
3.5 Форматированный ввод-вывод
Форматированный ввод-вывод данных является частным случаем строкового ввода-вывода. Особенность этого ввода-вывода то, что при переносе данных между файлом через открытый поток и программой происходит преобразование этих данных в соответствии с заданными спецификаторами формата. Спецификаторы формата такие же, как при консольном вводе-выводе.
Функция форматированной записи (вывода) в файл имеет прототип:
|
int fprintf(FILE *fp, char *format [, аргумент ]…);
Эта функция выводит данные с преобразованием по формату в открытый поток fp, связанный с файлом. В случае успеха возвращает число выведенных байтов (символов), а в случае ошибки – EOF.
Пример. Запись чисел в открытый для записи файл через поток fp
FILE * fp = fopen (" abc. txt "," w ");// открытие потока для записи
if (fp == NULL){ puts ("ошибка открытия файла"); return -1;}
int a=5; float b=3.56; long c=50000;
fprintf(fp,"%d %f %ld\n",a,b,c);
int arr[5]={1,2,3,4,5};
float mas[5]={1.1,2.2,3.3,4.4,5.5};
// запись массивов 5 -и чисел типа int, float в файл
for(int i=0;i<5;i++)
fprintf(fp,"%d %f\n",arr[i],mas[i]);
Функция форматированного чтения (ввода) из файла имеет прототип:
int fscanf(FILE *fp, char *format [, указатель ]…);
Эта функция выполняет ввод из открытого файла данных с преобразованием по формату и с занесением в ячейки памяти, определяемые указателями. В случае успеха возвращает число обработанных при вводе полей (спецификаторов) или EOF (–1) в случае ошибки или достижения конца файла.
Пример. Чтение чисел из открытого для чтения файла через поток fp
freopen (" data. txt "," r ", fp); // переоткрытие потока
if (fp == NULL){perror("Входной файл не открыт "); return 1;}
Int n; float f; long l;
fscanf(fp,"%d %f %ld\n",&n,&f,&l);// чтение чисел из файла
printf ("%d %f %ld\n",n,f,l); // вывод чисел на экран
int a [5]; float m [5];
// чтение из файла и вывод на экран массивов из 5-и чисел типа int, float
for(int j=0;j<5;j++)
{fscanf(fp,"%d %f\n",&a[j],&m[j]);
printf("%d %f\n",a[j],m[j]); }
fclose (fp);
3.6 Форматированные вывод в строку и ввод из строки
Не редко возникает необходимость форматированного вывода данных в строку и ввода данных из строки.
Функция форматированного записи (вывода) в строку имеет прототип:
int sprintf(char *buf, char *format [, аргумент ]…);
Эта функция выводит данные с преобразованием по формату в строку buf. Последний символ устанавливается ' \0 '. В случае успеха возвращает число выведенных байтов (символов), а в случае ошибки – EOF.
Функция форматированного чтения (ввода) из строки имеет прототип:
int sscanf(char *buf, char *format [, указатель ]…);
Эта функция вводит из строки данные с преобразованием по формату и помещает их в ячейки памяти, определяемые указателями. В случае успеха возвращает число обработанных при вводе полей или EOF(–1) в случае ошибки.
|
Пример. Запись чисел в строку и чтение чисел из строки
int a 1=10; long b 1=50000; char buf 1[20];
sprintf(buf1,"a1=%d, b1=%ld",a,b);
puts(buf1);// a1=10, b1=50000
float e, pi; char buf2[25]="2. 718281, 3. 141592";
sscanf(buf2,"%f, %f",&e,&pi);
printf("e=%f pi=%f\n",e,pi););//e=2. 718281 pi=3. 141592
int a2; long b2;
sscanf(buf1,"a1=%d, b1=%ld",&a2,&b2);
printf("a2=%d b2=%ld\n",a2,b2); //a2=10 b2=50000
3.7 Блоковый ввод-вывод
Эти функции предназначены для ввода-вывода блоков байт. Блок – это группа рядом расположенных байт, между которыми нет никаких специальных разделителей. Для того чтобы не иметь проблем с символами ' \n ', ' \0 ', блоковый ввод-вывод выполняют в бинарном режиме. За одно обращение можно переносить несколько блоков.
Функция блокового записи (вывода) в файл имеет прототип:
int fwrite(void *ptr, int size, int N, FILE *fp);
Эта функция записывает через поток fp в открытый файл N блоков, размером size байт каждый, из области памяти, определяемой указателем ptr. В случае успеха возвращает число блоков, а в случае ошибки – EOF.
Пример. Запись блоков данных в открытый для записи в двоичном режиме файл через поток fp
FILE *fp=fopen(“abc.txt”,"wb");
if(fp==NULL){puts(" ошибка открытия файла "); return -1;}
struct REC{int a[2]; float b;}; // определение структ.типа
REC str1={1,2, 3.3}; // определение и инициализация структуры
fwrite(&str1,sizeof(REC),1,fp); // запись структуры в файл
REC str2[3]={{3,4, 5.5},{6,7, 8.8},{9,10, 1.1}};
fwrite(str2,sizeof(REC),3,fp);// запись массива структур в файл
fclose (fp);
Функция блокового чтения (ввода) из файла имеет прототип:
int fread(void *ptr,int size,int N,FILE *fp);
Эта функция считывает через поток fp из открытого файла N блоков, размером size байт каждый, в область памяти, определяемой указателем ptr. В случае успеха возвращает число блоков, а в случае ошибки или достижения конца файла – EOF.
Пример. Чтение блоков данных из открытого для чтения в двоичном режиме файла через поток fp
FILE *fp=fopen(“abc.txt”,"rb");
if(fp==NULL){puts(" ошибка открытия файла "); return -1;}
REC str3, str4[3]; // определение структуры и массива структур
fread(&str3,sizeof(REC),1,fp); // чтение структуры из файла
printf("%d %d %f\n",str3.a[0],str3.a[1],str3.b);
fread(str4,sizeof(REC),3,fp);// чтение массива структур из файла
for(int i=0;i<3;i++) // вывод массива структур на экран
printf("%d %d %f\n",str4[i].a[0],str4[i].a[1],str4[i].b);
fclose (fp);
3.8 Произвольный доступ к файлу
При обмене данными с файлом (записи и чтении) – место, куда записывается или считывается информация, определяется указателем записи-чтения. Ранее рассматривались функции обмена с файлом, которые осуществляли последовательный доступ к файлу. В библиотеке языка Си имеются функции, позволяющие выполнить произвольный доступ к файлу, т.е. доступ в любую точку файла.
Функция установки указателя записи-чтения на начало файла имеет прототип void rewind(FILE *fp); Например: rewind(fp);
|
Функция установки указателя записи-чтения в произвольную точку файла имеет прототип:
int fseek(FILE *fp, long offset, int from_where);
Эта функция устанавливает указатель записи-чтения в потоке fp на offset байт вправо или влево. Если o ffset>0, то указатель сдвигается в сторону конца файла, если offset<0, то указатель сдвигается в сторону начала файла. Параметр from_where задает точку отсчета для сдвига: SEEK_SET – сдвиг от начала файла, SEEK_CUR – сдвиг от текущей позиции указателя, SEEK_END – сдвиг от конца файла. В случае успеха функция возвращает 0, иначе – EOF.
Установка указателя записи-чтения левее начала файла считается ошибкой, установка указателя правее конца файла делает значение указателя записи-чтения неопределенным. Например:
// установка указателя записи-чтения через 10байт от начала файла fseek(fp,10L,SEEK_SET);
Функция определения текущего положения указателя записи-чтения имеет прототип: long ftell(FILE *fp);
Эта функция возвращает значение в байтах (тип long) от начала файла до текущего положения указателя записи-чтения файла, открытого через поток fp. В случае ошибки функция возвращает –1L. Например:
long cur=ftell(fp);
Пример. Запись и добавление в файл блоков данных (структур) и чтение одной заданной структуры записанных ранее в файл структур.
#include<stdio.h>
struct REC{unsigned id;char name[20];unsigned mark;};
Int main()
{FILE *out,*in; REC rec;
int flag, sz=sizeof(REC); long len,kol,n;
if((out=fopen("mark.txt","wb"))==NULL)
{perror("Выходной файл не открыт"); return 1;}
do {puts("Введите номер записи, фамилию, оценку");
scanf("%d",&rec.id);
gets(rec.name);
scanf("%d",&rec.mark);
fwrite(&rec,sz,1,out);// запись в файл блока данных
puts("Продолжить ввод? Да-1, Нет-0");
scanf("%d",&flag);
}while(flag);
fclose(out);// закрытие файла
if((in=fopen("mark.txt","rb"))==NULL)
{perror("Входной файл не открыт"); return 2;}
// сдвиг указателя чтения-записи на конец файла
fseek(in,0,SEEK_END);
// определение текущего значения указателя чтения-записи
len=ftell(in);
kol=len/sz; // количество блоков в файле
printf("В файле %d записей\n", kol);
puts("Введите номер записи для чтения:");
scanf("%ld",&n);
if(n>0&&n<=kol)
{fseek(in,(n -1)*sz,SEEK_SET); // установка указателя
// чтения-записи на заданный блок от начала файла
fread(&rec,sz,1,in); // чтение из файла блока данных
printf("%d %s – %d\n",rec.id_rec,rec.name,rec.mark);
}
else puts(" Вне файла!");
fclose(in); // закрытие файла
return 0;}
3.6 Управление файлами и каталогами
В языке С имеются функции для управления файлами и директориями, в BC31 они имеют описания в файле <dir.h>.
Функция создания директория имеет прототип:
int mkdir(const char *path);
Эта функция создает директорий по маршруту, задаваемому строкой, на которую указывает path. В случае успеха функция возвращает 0, иначе –1. Попытка создания корневого директория является ошибкой.
Например:
char *dd="C:\\Common\\Prog";
if(mkdir(dd)!=0) puts("Не могу создать директорий");
Функция удаления директория имеет прототип:
int rmdir(const char * path);
Эта функция удаляет директорий по маршруту, задаваемому строкой path. При успешном удалении директория функция возвращает 0, иначе – 1. Функция выдает ошибку при попытке удалить не пустой или корневой директорий. Например:
char *dd="C:\\Common\\Prog";
if(rmdir(dd)!=0) puts(“Не могу удалить директорий”);
Функция удаления файла описана в заголовочном файле <stdio.h > и имеет прототип:
int remove(const char *filename);
Эта функция удаляет файл с именем, задаваемым строкой filename, при успешном удалении файла возвращает 0. В противном случае возвращает –1 и записывает код ошибки во внешнюю переменную errno (errno=ENOENT – нет файла с таким именем, errno=EACCES – файл только для чтения и т.д.). Например:
char *ff="C:\\Common\\Prog\\lab5.cpp");
if(remove (ff)!=0) puts("Не могу удалить файл");
Функция определения текущего диска имеет прототип:
int getdisk(void);
Эта функция возвращает целое число, определяющее текущий диск. Диску (A:) соответствует значение 0, диску (B:)– 1, диску (C:) – 2 и т.д. Например:
int n=getdisk();
printf(“Текущий накопитель %с:\n”,‘A’+n);
Функция задания текущего диска имеет прототип:
int setdisk(int drive);
Эта функция устанавливает в системе текущий диск, задаваемый параметром drive (0 соответствует диску A:, 1 – диску B:, 2 – диску C: и т.д.) В случае успеха функция возвращает общее число дисков в системе, иначе –1. Например:
int t _ d =4; // диск Е
int n=setdisk(t_d);
printf("Текущий диск %с:\n", ‘A’+t_d);
printf("Всего дисков %d\n", n);
Функция определения текущего директори я для заданного диска имеет прототип:
int getcurdir(int drive, char *dir);
Эта функция записывает в буфер, на который указывает dir, строку текущего директория для диска, задаваемого значением drive. Если значение drive равно 0, то записывается информация о текущем директории текущего диска, если 1 – диска A: и т.д. Функция в случае успеха возвращает 0, иначе ‑ –1. Например:
char inf[40]; int disk=0;
int n=getcurdir(disk,inf);
if(n==0)
printf("Текущий директорий на диске %с %s\n "(disk +’ A ’ -1),inf);
else printf("не могу определить директорий");
Функция задания текущего директория имеет прототип:
int chdir(const char *path)
Эта функция в качестве текущего рабочего директория устанавливает директорий, задаваемый строкой, на которую указывает path. Функция в случае успеха возвращает 0, иначе ‑ –1. Например:
char dir[]=“F:\\Users\\DIR\\data.txt”);
int n=chdir(dir);
if(n!=0) printf(“не могу установить заданный директорий”);
else printf(“Диск %с, текущий директорий %s\n”,dir[0],dir);
Пример. В этом примере создается новый заданный директорий, который затем открывается и в него записывается текстовый файл.
#include<stdio.h>
#include<dir.h>
Int main()
{char namedir[30];
FILE *fp;
puts("Введите имя нового директория по формату F:\\ USERS \\… ");
gets(namedir);
if(mkdir(namedir)!=0) // создание нового директория
{perror("Не могу создать директорий! "); return 1;}
if(setdisk(namedir[0]-'A')==-1)// установка заданного диска
{perror("Не могу установить диск! ");return 2; }
if(chdir(namedir)==-1)// установка заданного директория
{perror("Не могу установить директорий! ");return 3;}
if((fp=fopen("test.txt","w"))==NULL)
{perror("Не могу открыть файл!"); return 4;}
fputs("TEST",fp); // запись строки в файл
fclose(fp); return 0;}
Пример. В этом примере удаляются файл и директорий.
#include<stdio.h>
#include<dir.h>
Int main()
{char namedir[20],namefile[20];
puts("Введите имя директория по формату C:\\ABC");
gets(namedir);
puts(" Введите имя файла "); gets(namefile);
setdisk(namedir[0]-'A');// установка заданного диска
chdir(namedir); // установка заданного директория
if(remove(namefile)==-1) // удаление файла
{perror("Не могу удалить файл!"); return 1;}
if(rmdir(namedir)==-1) // удаление директория
{perror("Не могу удалить директорий!"); return 2;}
return 0;}
4 Многофайловая компиляция
Программы – это обычно совокупность функций. Функции, как правило, размещают в разных файлах, группируя их по каким-либо признакам. В результате для создания конечной программы необходимо их объединить в единое целое.
Напомним, что из всей совокупности функций в программе может быть только одна главная функция main(), которая является точкой входа в программу.
Для объединения функций в одну программу существует несколько механизмов.
Самый простой способ: создать программу из нескольких файлов, используя препроссесорную директиву #include.
Пример.
// файл file1.cpp
extern int b; // описание внешней переменной b
int func2(int,int); // прототип функции func2
int a=5; // определение внешней переменной а
int func1(int c) // определение функции func1
{int f=func2(c,a); // f=30
return f*b; } // 30*10=300
// файл file2.cpp
extern int k; // описание внешней переменной k
int func2(int x, int y) // определение функции func2
{return x*y+k;} // 2*5+20=30
// файл file3.cpp
#include<stdio.h> // подключение библиотечных функций
#include " file1.cpp " // подключение файла file1.cpp
#include " file2.cpp " // подключение файла file2.cpp
int b=10; // определение внешней переменной b
int k=20; // определение внешней переменной k
Void main()
{int d=2,res; res=func1(d);// вызов фукции func1 res=300
printf (“ k =% d res =% d ”, k, res);// вывод результатов на экран
}
В данном примере препроцессор подставил в файл filе3.cpp тексты файлов filе1.cpp и file2.cpp. Переменная a (определена как внешняя в файле filе1), функции func1(), func2() видны и в файле filе3, благодаря работе препроцессора. В файле filе1 для доступа к функции func2() (определена в файле filе2) прописан прототип этой функции. В файлах filе1, filе2 для доступа к переменным b, k (определены как внешние в файле filе3) эти переменные описаны со словом extern.
Поведем некоторые итоги.
1) Функции по определению являются глобальными, и им по умолчанию присваивается класс памяти extern, поэтому функции доступны во всех файлах. Но перед первым использованием функций необходимо записать прототипы, которые необходимы для компилятора.
2) Другие объекты (переменные, массивы, структуры и т.д.) также могут использоваться в файлах, где они не определены. Но они должны быть глобальными, т.е. определены вне функций, и им необходимо присвоить класс памяти extern, если они используются выше своего определения при данном методе создания многофайловой программы.
Каждый объект может быть определен только один раз, но может быть неоднократно описан.
Если использовать в разных файлах одни и те же функции, переменные, то в начале всех файлов необходимо поместить прототипы нужных функций и объявление переменных. Можно поместить прототипы функций, объявления переменных в отдельный файл с расширением .h, и включать этот файл в начало других файлов с помощью оператора #include.
// файл common.h
exrtern int a;
exrtern int b;
exrtern int k;
int func1(int);// прототип функции func1
int func2(int, int);// прототип функции func2
// файл fil е 1.cpp
#include " common.h "
int a=5; // определение внешней переменной а
int func1(int c){int f=func2(c,a);return f*b;}
// файл file2.cpp
#include " common.h "
int func2(int x, int y) {return x*y+k;}
// файл file3.cpp
#include<stdio.h> // подключение библиотечных функций
#include " common.h " // подключение заголовочного файла
#include " file1.cpp " // подключение файла file1.cpp
#include " file2.cpp " // подключение файла file2.cpp
int b=10; // определение внешней переменной b
Void main()
{int d=2,res; res=func1(d+k);
printf(“k=%d res=%d ”,k,res);}
int k=20; // определение внешней переменной k
Фактически оператор подставляет содержимое файла *.h в текущий файл перед тем, как начать его компиляцию. Файл с расширением .h называется файлом заголовков.
Для создания многофайловых программ существует удобный механизм многофайловой компиляции и линковки.
Для этого в ВС-31 необходимо выполнить следующие действия:
1) Разрабатываются и запоминаются отдельно несколько файлов, из которых только один файл с именем main()
2) В главном меню выбирается команда Project, в меню которого выбирается опция Open project, вводится имя проекта с расширением prj. В нижней части окна появится новое окно, а в строке появится опции Add (добавить), Delete (удалить) и др.
3) По команде Add появится список файлов текущего директория, из которого выбираются нужные файлы с расширением .срр. После занесения всех файлов в проект выбирается команда Done (закрыть). В окне проекта будут находиться все файлы, занесенные в проект. Для удаления файлов из проекта пользуются командой Delete (удалить).
4) Далее проект запускается на компиляцию и компоновку (Ctr l +F9), после чего образуется файл с расширением .ехе. Если надо перекомпилировать все файлы проекта (при использовании inline -функций и т.д.) в меню команды Compile выбирается команда Build all.
При разработке некоторой группы функций (для работы с матрицами, с комплексными числами и т.д.) бывает удобно объединить все эти функции в библиотеку функций. Библиотеки также создаются с помощью многофайловой компиляции и имеют расширение .lib.
Для создания библиотеки необходимо:
1) Выбрать команду главного меню Options->Make. В окне After Compiling установить Run librarian->OK.
2) Затем создать проект, включить в него необходимые файлы.
3) Откомпилировать проект, выполнив команду Compile->Make или Compile->Build all. При этом создается файл с расширением. lib.
4) Затем надо создать новый проект. При этом выбирается команда главного Options->Make и в окне After Compiling устанавливается значение Run linker->OK. Задается новое имя проект, и в этот проект включают файл с функцией main(), файл с расширением .lib и другие необходимые файлы, которые не вошли в библиотеку. После компиляции образуется файл с расширением .ехе, который использует функции из библиотеки.
В библиотеку может также включаться и файл с главной функцией main(), но тогда в такую программу будет затруднительно вносить изменения. Поэтому обычно функция main() не входит в библиотеки. Пример.
// файл arith. h
float sum(float, float);
Float sub(float, float);
Float mul(float, float);
// файл sum.cpp
float sum(float a, float b){return a+b;}
// файл sub.cpp
float sub(float a, float b){return a-b;}
// файл mul.cpp
float mul(float a, float b){return a*b;}
Создадим библиотеку, присвоив проекту имя arith.prj и включив в него файлы sum.cpp, sub.cpp, mul.cpp. Откомпилируем этот проект, в результате получим библиотеку arith.lib.
Пример использования библиотеки arith.lib
// файл prog.cpp
#include<stdio.h>
#include " arith.lib "
Int main()
{float c=15.0, d=3.0;
printf(" sum=%f sub=%f mul=%f\n ", sum(c, d), sub(c, d), mul(c, d));
return 0;}
sum=18.0 sub=12.0 mul=45.0
Если исходные файлы предварительно откомпилированы и хранятся в директории в виде объектных файлов (*.obj), то их можно объединить в библиотеку из командной строки, используя утилиту tlib.exe. Эта утилита хранится в директории BC31\bin. Для этого надо набрать в командной строке, например,
f:\users\prog>tlib.exe arith+sum.obj+sub.obj+mul.obj
В результате будет создан библиотечный файл arith.lib, который объединит файлы sum.obj, sub.obj, mul.cpp.
5 Объекты и их атрибуты
Объект в языке С++ – это некоторая поименованная область памяти. Переменная – это частный случай такой поименованной области памяти.
Каждый объект (переменная, массив, указатель, структура, объединение, функция, класс, файл) имеет некоторые атрибуты.
Для объекта задается тип, который: 1) определяет требуемое для объекта количество памяти при ее начальном определении; 2) задает совокупность операций, допустимых для данного объекта; 3) интерпретирует двоичные коды значений при последующих обращениях к объекту; 4) используется для контроля типов для обнаружения случаев недопустимого присваивания.
Кроме типов, для объекта явно или по умолчанию определяются:
§ класс памяти (задает размещение объекта);
§ продолжительность существования объектов и их имен
§ область действия связанного с объектом идентификатора (имени);
§ область видимости объекта;
§ тип компоновки.
Класс памяти определяет размещение объекта в памяти и продолжительность его существования. Класс памяти в общем случае зависит от места расположения объекта в программе. Для явного задания класса памяти при определении (описании) объекта используются или подразумеваются по умолчанию следующие идентификаторы: auto, register, static, extern.
auto – автоматически выделяемая, локальная память. Этот класс памяти всегда присваивается по умолчанию всем объектам, определенным в блоке или функции. Память под такие объекты запрашивается при каждом входе в блок или функцию, где они определены, и освобождается при выходе. При определении автоматических объектов они никак не инициализируются, т.е. их значение сразу не определено.
register – автоматически выделяемая, по возможности регис тровая память. Спецификатор register аналогичен auto, но для размещения значений объектов используются по возможности регистры, а не участки основной памяти. В случае отсутствия регистровой памяти (регистры заняты другими данными) объекты класса register обрабатываются как объекты класса auto.
static – статически выделяемая память. Этот класс памяти присваивается всем объектам, которые определены со спецификатором static. Память для таких объектов выделяется в начале выполнения программы и сохраняется до конца ее выполнения. Такие объекты по умолчанию инициализируются нулями. При явной инициализации значение заносится только первый раз.
extern – глобальная (внешняя) память. Этот класс памяти всегда присваивается по умолчанию всем объектам, определенным вне функций. Память для таких объектов выделяется в начале выполнения программы и сохраняется до конца ее выполнения. Такие объекты по умолчанию инициализируются нулями. По умолчания класс памяти extern имеют функции и все файлы.
Продолжительность существования объектов и их имен определяет период, в течение которого именам в программе соответствуют конкретные объекты в памяти. Три вида продолжительности: локальная (автоматическая), статистическая и динамическая.
Переменные с локальной (автоматической) продолжительностью существования – это объекты с автоматической и регистровой памятью. Они создаются при каждом входе в блок или функцию, где определены, и уничтожаются при выходе.
Объектам со статической продолжительностью существования память выделяется в начале выполнения программы и сохраняется до конца ее выполнения. Это объекты с классом памяти static и extern. По умолчанию статическую продолжительность существования имеют функции и все файлы.
Объекты с динамической продолжительностью существования создаются (получают память) и уничтожаются с помощью явных операций или функций в процессе выполнения программы. Созданный с помощью операции new и функции malloc() объект будет существовать до тех пор, пока память не будет явно освобождена с помощью операции delete или функции free(). Динамическое распределение памяти используется тогда, когда не известно сколько объектов понадобится в программе.
Область действия объекта (имени) – это часть программы, в которой имя объекта может быть использовано для доступа к объекту. Бывает локальная и глобальная область действия. Зависит от того, где и как определены и описаны объекты: в блоке, в функции, в прототипе функции, в файле (модуль), в классе.
Файл является областью действия для всех глобальных объектов, т.е. для объектов, определенных вне любых функций и классов, от точки определения до конца программы. Для доступа к глобальным объектам выше определения их необходимо описать (для функции записать прототип). Если объект определен в блоке или функции, то область его действия – от точки определения до конца блока или функции. Область действия формальных параметров в определении функции – тело функции. Область действия идентификаторов в прототипе функции совпадает с концом прототипа функции.
Объекты с локальной областью действия могут иметь статическую продолжительность существования. Например, если в функции описать переменную static int K, то область действия – локальная (тело функции), а продолжительность существования – статическая.
Область видимости объекта – это часть программы, в которой имя объекта может быть использовано для просмотра значений объекта. Это понятие появилось с возможностью повторных определений идентификатора внутри вложенных блоков (или функций). Чаще всего область действия имени и видимость связанного с ним объекта совпадают. Область видимости может превышать область действия, но наоборот невозможно. Например:
Void main()
{char oper; --- ù
int x=2,y=4,z; |
... |
{int k=5; ––– ù |
int x=3; | |
x+=3.. | |
} ––– û |
…} ––– û
В первом прим
|
|
Индивидуальные и групповые автопоилки: для животных. Схемы и конструкции...
Своеобразие русской архитектуры: Основной материал – дерево – быстрота постройки, но недолговечность и необходимость деления...
Двойное оплодотворение у цветковых растений: Оплодотворение - это процесс слияния мужской и женской половых клеток с образованием зиготы...
Опора деревянной одностоечной и способы укрепление угловых опор: Опоры ВЛ - конструкции, предназначенные для поддерживания проводов на необходимой высоте над землей, водой...
© cyberpedia.su 2017-2024 - Не является автором материалов. Исключительное право сохранено за автором текста.
Если вы не хотите, чтобы данный материал был у нас на сайте, перейдите по ссылке: Нарушение авторских прав. Мы поможем в написании вашей работы!