Не могу открыть файл : No such file or directory — КиберПедия 

Механическое удерживание земляных масс: Механическое удерживание земляных масс на склоне обеспечивают контрфорсными сооружениями различных конструкций...

Типы сооружений для обработки осадков: Септиками называются сооружения, в которых одновременно происходят осветление сточной жидкости...

Не могу открыть файл : No such file or directory

2021-03-18 54
Не могу открыть файл : No such file or directory 0.00 из 5.00 0 оценок
Заказать работу

После успешного открытия файла программа может осуществ­лять файловый ввод-вывод. Функции потокового ввода-вывода можно разделить на четыре группы: 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 - Не является автором материалов. Исключительное право сохранено за автором текста.
Если вы не хотите, чтобы данный материал был у нас на сайте, перейдите по ссылке: Нарушение авторских прав. Мы поможем в написании вашей работы!

0.242 с.