Изброеният тип се въвежда в ANSI C, има го и в C++;
синтаксис:
enum [име_на_тип] { списък от стойности} [списък от променливи];
стойностите са идентификатори; подобно на структури можем да дефинираме променливи заедно с описанието на изброения тип;
например:
enum Boolean { true, false} f;
можем да дефинираме променливи отделно (но само ако сме указали име на съответния изброен тип);
enum Boolean i, j; //в C++ enum може да се изпусне;
в C ключовата дума enum може да се изпусне с дефиниция с typedef;
стойностите се интерпретират като целочислени константи и като такива могат да участват в изрази и оператори;
например:
f = false;
if (i!=true)
printf(“Грешка при изчисление!\n”);
компилаторът присвоява на идентификаторите в списъка от стойности цели числа в нарастващ ред, като започва от 0; присвояването се извършва отляво надясно;
например:
f = 0; //също като f = false;
някои компилатори (например Borland C и C++) в такъв случай дават предупреждение; чрез явно преобразуване можем да избегнем предупреждението:
f = (Boolean) 0;
някои компилатори като Borland C и C++ позволяват идентификатор от списъка да бъде инициализиран, като следващите идентификатори получават нарастващи с 1 стойности, освен ако не са инициализирани;
enum counter { start, first, second, tenth = 10, eleventh} c;
компилаторът ще даде стойност 0, 1, 2 на start, first, second и
10, 11 на tenth, eleventh;
в Borland C++ броят байтове, които се разпределят за променлива от изброен тип зависи от стойностите на изброените константи; например, ако всички константи са от тип char, за променливата ще се разпредели 1 байт; в противен случай се използват 2 байта и стойността на променливата от изброен тип ще се интерпретира като int;
enum EXP { a, b, c, d, e, f} Box;
int k = 2;
Box = (enum EXP)(k+1); Box = d;
Box = k+2;//компилаторът дава предупреждение
името на изброения тип, както имената на типове структури и обединения, може да съвпада с имена на променливи в програмата;
typedef enum { Monday = 1, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday} DAYS;
DAYS weekday, *ptr;
int current_day, to_end, from_start;
scanf (“%d”, ¤t_day);
week_day = Sunday; // weekday = (DAYS) 7;
to_end = week_day – current_day;
from_start = Monday;
Текстови и двоични файлове
Текстов файл (поток) – последователност от символи; той може да бъде разделен на редове, като всеки ред е с произволна дължина и завършва със символа за нов ред (‘\n’); всеки символ се съхранява в отделен байт;
Двоичен файл (поток) – последователност от байтове; той съдържа информацията във вида в който тя се съхранява в оперативната памет; при двоичния файл няма преобразуване на данните – само се прави копие, докато при текстовия файл се прави преобразуване на данните преди се запишат (прочетат); с двоичния файл се прави икономия на външна памет и се печели време; обикновено двоичните файлове се използват за съхраняване на данни от тип структура;
обикновено входа и изхода са буферирани; буферът е временна област в паметта, в която се запомнят въвежданите и извежданите данни; при извеждане, когато буферът се запълни, неговото съдържание се предава в блок и процеса на буферизация започва отново; така се ускорява процеса на предаване на данните;
например при въвеждане функцията getchar() чете един символ от буфера след като в него е записан целия въвеждан ред от клавиатурата (т.е. след натискане на Enter); функциите getch() и getche(), с прототипи описани в conio.h, четат директно от клавиатурата; разликата между двете функции е, че getch() не извежда символа на екрана;
при вход и изход от високо ниво, буферите са разположени в областта за динамични данни на потребителската програма;
при вход и изход от ниско ниво, буферите са разположени в работни области на оперативната памет;
всеки път когато започва изпълнението на една програма на C, автоматично се отварят три стандартни файла:
stdin – стандартен файл за вход от клавиатурата;
stdout – стандартен файл за изход на екрана;
stderr – стандартен файл за грешки;
тези стандартни файлове са достъпни чрез указатели, които имат същите имена; по подразбиране при scanf се чете от stdin и при
printf се извежда в stdout;
някои операционни системи позволяват други периферни устройства да се свързват със стандартните файлове – това се указва на ниво операционна система;
етапи при работа с файлове:
-
отваряне на файла
-
обработка
-
четене (компонентите се четат последователно от файла без да се променят)
-
писане (компонентите се записват във файла в реда на тяхното извеждане)
-
актуализация (компонентите се четат от файла и се променя тяхното съдържание)
-
затваряне на файла
9. Текстови файлове. Функции fopen, fclose, getc, putc, fgetc, fputc, ungetc, fscanf, fprintf.
Входът и изходът в C се осъществяват със стандартни функции, описани в stdio.h;
функции, които са описани в stdio.h и са от високо ниво за работа с файлове:
при функциите от високо ниво, програмистът не се грижи за създаването на небходимите буфери, за тяхния размер и т.н.; за работа с файлове се дефинира променлива-указател от тип FILE;
например:
FILE *fp;
типът FILE е дефиниран в stdio.h; това е тип структура, т.е. fp е указател към структура от тип FILE (казваме, че fp е указател към файл); тази структура включва информация за текущата позиция във файла, указатели към свързаните с него буфери и индикатори за грешки или за достигане на край на файла;
функция fopen;
прототип: FILE *fopen (const char *filename, const char *mode);
функцията fopen отваря файла с име filename и като резултат връща указател към отворения файл; filename е име на файл, така както той се задава в операционната система, т.е. fopen прави връзка между името на файла и указателя към файла, който се използва по-късно в програмата;
с параметъра mode се определя как ще се използва този файл;
-
“r” – за четене от файл
-
“w” – за създаване на нов файл
-
“a” – за добавяне към съществуващ файл
-
“r+” – за четене от файл и актуализация
-
“w+” – за създаване на файл и актуализация
-
“a+” – за добавяне към съществуващ файл и актуализация
за работа с текстови файлове, към mode прибавяме ‘t’; например:
“rt”, “wt”, “r+t” “rt+” и т.н.;
за работа с двоични файлове, към mode прибавяме ‘b’; например:
“rb”, “ab”, “a+b” “ab+” и т.н.
функцията fopen връща указател NULL при грешка; ако указател към файл има стойност NULL, това значи, че файлът не е отворен; например:
-
няма място на хард диска
-
писане върху защитена за писане дискета или диск;
-
отваряне на несъществуващ файл за четене;
когато файлът е отворен за актуализация се позволява въвеждане и извеждане; важна особеност в режима на актуализация е, че съответните операции се осъществяват спрямо текущата позиция във файла, т.е. ако е въведен даден запис или елемент за актуализация, преди извеждането му указателят в буфера на файла трябва да се позиционира в началото на този запис или елемент с функцията fseek;
пример:
FILE *fp;
if ( ( fp = fopen (“name”, “w”))==NULL)
printf (“Невъзможно е отварянето на файла!\n”);
във всички функции по-надолу се предполага, че указателят fp е инициализиран чрез fopen (с изключение на случаите когато използваме стандартните файлове);
функция fclose;
прототип: int fclose (FILE *fp);
с помощта на тази функция се затваря файл отворен за буфериран достъп чрез fopen; при това се освобождават всички използвани системни ресурси – буфери, указатели и т.н.; по-важно е, че всички данни, които все още не са записани се записват върху външен носител; не бива да се забравят отворени файлове, тъй като това може да причини загуба на данни, унищожаване на файлове и др.;
ако изпълнението на програмата завършва в главната функция или с функцията exit, автоматично се изпълнява fclose за всички отворени файлове; въпреки това препоръчително е програмистът да затваря всички използвани файлове;
функцията връща като резултат EOF, когато има грешка и 0, ако е изпълнена успешно;
функция getc;
прототип: int getc (FILE *fp);
тази функция връща символа от текущата позиция и увеличава указателят към текущата позиция да сочи към следващия символ от входния поток (файлът сочен от fp); прочетеният символ се преобразува към int без да се отчита при разширението знаковият бит, т.е. символът се интерпретира като unsigned char и се добавят нули при преобразуването; при успешно изпълнение getc връща прочетения символ; при грешка при въвеждането или при достигане на край на файла, функцията връща EOF;
getc(stdin) getchar()
пример:
int c;
while ( (c = getc (fp))!=EOF)
…
функция putc;
прототип: int putc (int c, FILE *fp);
функцията извежда символът c в изходния поток, т.е. във файла, сочен от fp; тя връща изведения символ или EOF при грешка;
putc (c, stdout) putchar()
пример:
char msg[] = “Здравейте!\n”
int i = 0;
while (msg[i])
putc (msg[i++], stdout);
ако функциите getc и putc са реализирани като макроси (например в Borland C++), тогава в стандартната библиотека на компилатора има функции fgetc и fputc, които не са макроси и са еквивалентни на getc и putc;
тяхните прототипи са:
int fgetc (FILE *fp);
int fputc (int c, FILE *fp);
функция ungetc;
прототип: int ungetc (int c, FILE *fp);
тази функция връща обратно символ (например въведен чрез getc) на съответното място във входния поток (сочен от fp); тя се използва когато въвеждаме избирателно само определени символи от файла; функцията връща като резултат върнатия символ при успешно изпълнение или EOF при грешка;
пример: въвеждат се цифри и се формира числото, което е зададено с тези цифри;
int i = 0, ch;
while ( (ch = getchar())!=EOF && isdigit(ch))
i = i*10 + ch – 48;
if (ch!=EOF)
ungetc (ch, stdin); //връщаме символа в буфера на stdin
int isdigit (int ch) е макрос, дефиниран в ctype.h, връща 0, ако ch не е цифра и число различно от 0, ако ch е цифра;
в Borland C++, ако след еднократно изпълнение на getchar или getc се изпълни многократно ungetc, при четенето след това ще се извежда на едно и също място във входния поток (в буфера);
функцията ungetc не е приложима при небуфериран вход;
функция fscanf;
прототип: int fscanf (FILE *fp, const char *format, …);
тази функция има еквивалентно изпълнение на функцията scanf, но чете от произволен входен поток (сочен от fp);
fscanf (stdin) scanf
функция fprintf;
прототип: int fprintf (FILE *fp, const char *format, …);
тази функция има еквивалентно изпълнение на функцията printf, но извежда в произволен изходен поток (сочен от fp);
fprintf (stdout) printf
Сподели с приятели: |