380 likes | 611 Views
Входно/изходни операции. Въвеждането и извеждането на данни се осъществява чрез входно/изходни функции. В езика C не съществуват входно/изходни оператори. Функциите биват два вида: а. функции за работа с файлове на високо ниво (буфериран вход/изход);
E N D
Входно/изходни операции • Въвеждането и извеждането на данни се осъществява чрез входно/изходни функции. • В езика C не съществуват входно/изходни оператори. • Функциите биват два вида: а. функции за работа с файлове на високо ниво (буфериран вход/изход); б. функции за работа с файлове на ниско ниво (небуфериран вход/изход). • Файл • Входно/изходната система позволява работа с различни входно/изходни устройства: терминали, дискови управляващи устройства, магнитни ленти. • Всяко устройство се разглежда като логическо устройство, което е наречено поток.
Действителното физическо устройство е наречено • файл. • Файлът в Cможе да бъде дисков файл, терминал, • принтер. • При операцията отваряне се осъществява връзка • между логическото устройство (поток) и • физическото устройство. • Файлът се позиционира в началото си (индикаторът • на позицията се инициализира). • Всяка операция четене или запис води до нарастване • на индикатора за позицията. • При операцията затваряне се прекъсва връзката • между потока и файла. • Указател към файл • Всеки поток, свързан с файл, има структура за • управление на файла FILE, която е дефинирана в • stdio.h.
Указателят към файл е указател към информацията, която дефинира името, състоянието и текущата позиция на файла. FILE *fp; • EOF се използва за маркиране край на файл и има стойност -1. Видове файлове а) Текстов файл Текстовият файлпредставлява последователност от символи, като всеки символ се съхранява в отделен байт. Текстовият файл може да бъде разделен на редове, като всеки ред е с произволна дължина и завършва със символа за нов ред ’\n’. б) Двоичен (бинарен) файл Двоичният файл съдържа двоичното представяне на данните.
Той е последователност от байтове, които точно • съответстват на байтовете във външното • устройство. • В текстовите файлове съответствието не е точно: • например символът „нов ред“ може да се • конвертира в последователност от два символа • „връщане в началото на текущия ред“ и • „преминаване на нов ред“. • Най-често двоичният файл се използва за • съхранение на структури. • Етапи при работа с файлове • а) Отваряне на файла – осъществява се връзка между абстрактния файл и физическото устройство. • б) Обработка – обмен на данни (запис, четене, актуализация). • в) Затваряне на файла – преустановяване на връзката между файла и физическото устройство.
Функции за работа с файлове на високо ниво
Пример: Отваряне и затваряне на файл #include <stdio.h> #include <stdlib.h> int main () { FILE *fp; fp=fopen("test.txt", "r"); /* Отваряне на текстов файл за четене */ if(fp==NULL) /* Проверка за съществуване на файла */ { printf("Файлът не може да бъде отворен.\n"); exit(1);/* Прекъсване изпълнението на програмата */ } /* със статус 1 - грешка*/ /* Обработка на компонентите на файла */ fclose(fp); /* Затваряне на файла */ return 0; }
Пример: Слепване на текстови файлове #include <stdio.h> /* Копира символ по символ от файла f2 във файла f1. */ void filecopy(FILE *f1, FILE *f2); /* Въвежда символи от клавиатурата и ги записва в текстов файл с име filename, докато се въведе край на файл (Ctrl/Z). Връща указател към създадения файл или NULL.*/ FILE *writefile(char *filename); /* Чете от текстов файл с указател fp и име filename и изобразява съдържанието му върху екрана. */ void readfile(FILE *fp, char *filename); /* Към файла f1 с име fname1 долепя файла f2 с име fname2 и връща указател към новосъздадения файл, чието име е fname3. */ FILE *fileconcat(FILE *f1, char *fname1, FILE *f2, char *fname2, char *fname3);
void main () { FILE *text1, *text2, *text3; char name1[81], name2[81], name3[81]; printf("Въведи име на файл => "); gets(name1); text1=writefile(name1); printf("Въведи име на файл => "); gets(name2); text2=writefile(name2); printf("Слепване на файлове\n"); printf("Въведи име на файл => "); gets(name3); text3=fileconcat(text1, name1, text2, name2, name3); readfile(text3, name3); }
/* Копира символ по символ от файла f2 във файла f1. */ void filecopy(FILE *f1, FILE *f2) { int ch; while((ch=fgetc(f2)) != EOF) /* Четене на символ от f2 до достигане на края му */ fputc(ch, f1);/* Запис на символа във f1 */ }
/* Въвежда символи от клавиатурата и ги записва в текстов файл с имеfilename, докато се въведе край на файл (Ctrl/Z). Връща указател към създадения файл или NULL. */ FILE *writefile(char *filename) { FILE *fp; int ch; fp=fopen(filename, "w"); /* Отваряне на текстов файл за запис*/ if(fp==NULL) /* Проверка за създаване на файла*/ printf("Файлът не може да бъде създаден.\n"); else { printf("Въведи символи. За край - Ctrl/Z.\n"); fflush(stdin); /* Изчистване на входния буфер*/ filecopy(fp, stdin); /* Копиране от клавиатурата stdin във fp*/ fclose(fp); /* Затваряне на файла */ } return(fp); }
/* Чете от текстов файл с указател fp и име filename и изобразява съдържанието му върху екрана. */ void readfile(FILE *fp, char *filename) { int ch; fp=fopen(filename, "r");/* Отваряне на текстов файл за четене */ if(fp==NULL) /* Проверка за съществуване на файла*/ printf("Файлът не може да бъде отворен.\n"); else { filecopy(stdout, fp); /* Копиране от fp върху екрана stdout*/ fclose(fp); /*Затваряне на файла*/ } }
/* Към файла f1 с име fname1 долепя файла f2 с име fname2 и връща указател към новосъздадения файл, чието име е fname3. */ FILE *fileconcat(FILE *f1, char *fname1, FILE *f2, char *fname2, char *fname3) { FILE *f3; f1=fopen(fname1, "r"); /* Отваряне на f1 за четене */ f2=fopen(fname2, "r"); /* Отваряне на f2 за четене */ f3=fopen(fname3, "w"); /* Отваряне на f3 за запис */ if(f1==NULL || f2==NULL || f3==NULL) /* Проверка за отварянето на файловете */ printf("Файлът не може да бъде отворен.\n"); else { filecopy(f3, f1);/* Копиране на f1 въвf3 */ filecopy(f3, f2); /* Копиране на f2 във f3 */ fclose(f1); /* Затваряне на f1*/fclose(f2); /* Затваряне на f2*/fclose(f3); /* Затваряне на f3*/ } return(f3); }
Алгоритъм за Актуализация • Отваряне на файла за актуализация • Проверка за съществуване на файла • Докато не е достигнат края на файла 3.1. Четене на данни от файла 3.2. Ако данната съвпада с търсената данна 3.2.1.Позициониране на файла една позиция назад 3.2.2.Актуализиране на данните 3.2.3.Запис на актуализираните данни във файла 3.2.4.Затваряне на файла 3.2.5. Изход с индикатор „успешна актуализация“ • Затваряне на файла • Изход с индикатор „неуспешна актуализация“
Пример: Данните за студенти включват: факултетен номер, име, специалност, група и успех. Да се напишат функции за: 1) въвеждане на студент; 2) отпечатване на данните за студент; 3) запис на данните за студентите от факултет в двоичен файл; 4) четене на данните от двоичен файл и отпечатване на данните за факултета; 5) изчисляване на среден успех на дадена студентска група; 6) смяна на специалността на студент с даден факултетен номер. В програмата въведете данните за факултет в двоичен файл FЕТТ.dat, отпечатайте данните за студентите от факултета, изчислете и отпечатайте средния успех на група 79, сменете специалността на студент с факултетен номер 1234567, който отива в специалност ЕТ.
#include <stdio.h> #include <string.h> struct student { int facN; /* факултетен номер */ char name [20]; /* име */ char spec [20]; /* специалност */ int gr; /* група */ float uspeh; /* успех */ }; typedef struct student stud; stud enter (void); void print (stud s); FILE *writeFile (char *fname); int readFile (FILE *fp, char *fname); float sredenUspeh (FILE *fp, char *fname, int grupa); int update (FILE *fp, char *fname, int searchFacN, char *newSpec);
int main() { FILE *binary; float sredno; binary = writeFile ("FЕTT.dat"); printf("Списък на студентите от ФETT\n"); readFile (binary, "FETT.dat"); sredno=sredenUspeh(binary, "FETT.dat", 79); printf("Среден успех на група 79=%5.2f\n",sredno); if(update(binary, "FETT.dat",1234567, "ET")) printf("Успешна актуализация\n"); else printf ("Неуспешна актуализация\n"); return 0; }
/* Въвеждане на студент */ stud enter (void) { stud s; printf ("Факултетен номер: "); scanf ("%d", &s.facN); fflush (stdin); printf ("Име: "); gets(s.name); printf ("Специалност: "); gets(s.spec); printf ("Група: "); scanf("%d", &s.gr); printf ("Успех: "); scanf ("%f", &s.uspeh); return (s); } /* Отпечатване на данните за студент */ void print (stud s) { printf ("%10d %-20s %-20s %5d %5.2f\n", s.facN, s.name, s.spec, s.gr, s.uspeh); }
/* Запис на данните за студентите от факултет в двоичен файл */ FILE *writeFile (char *fname) { FILE *fp; stud s; int n, i; fp = fopen (fname, "wb"); if (!fp) return NULL; printf ("Брой студенти: "); scanf ("%d", &n); printf ("Въведете данни за студентите.\n"); for (i=0; i<n; i++) { s=enter(); fwrite (&s, sizeof (stud), 1, fp); } fclose (fp); return (fp); }
/* Четене на данните от двоичен файл и отпечатване на данните за факултета */ int readFile (FILE *fp, char *fname) { stud s; fp = fopen (fname, "rb"); if (!fp) return 0; while (fread (&s, sizeof (stud), 1, fp) == 1) print (s); fclose (fp); return (1); }
/* Изчисляване на среден успех на дадена студентска група */ float sredenUspeh (FILE *fp, char *fname, int grupa) { stud s; float sr=0.0; int broj=0; fp = fopen (fname, "rb"); if (!fp) return 0; while (fread (&s, sizeof (stud), 1, fp) == 1) if (s.gr==grupa) { broj++; sr+=s.uspeh; } fclose (fp); if(broj==0) return 0; else return (sr/broj); }
/* Смяна на специалността на студент с даден факултетен номер */ int update (FILE *fp, char *fname, int searchFacN, char *newSpec) { stud s; fp = fopen (fname, "r+b"); if (!fp) return 0; while (fread (&s, sizeof (stud), 1, fp) == 1) if (s.facN==searchFacN) {fseek (fp, ftell (fp) – sizeof (stud), SEEK_SET); strcpy(s.spec, newSpec); fwrite (&s, sizeof (stud), 1, fp); fclose (fp); return (1); } fclose (fp); return (0); }
Предпроцесор • Предпроцесорът е програма, която управлява процеса на компилация, с което езикът C се доближава до асемблерните езици. • Препроцесорът използва директиви. Директива #define • Макроопределение – дефинира идентификатор и низ, като навсякъде в програмата заменя идентификатора (името на макроса) с низа. #defineидентификатор низ • идентификатор – представлява име на макрос • низ - това е последователност от символи; може да бъде константа, израз
Примери: #define MAXINT 32767 #define PI 3.141592 #define NULL ’\0’ #defineMSG ”Програма на C\n” #defineLONG_MSG ”Това е пример за дълго съобщение, \което не се побира на един ред” • Макроопределение с аргументи(дефиниране на функция като макрос) – навсякъде в програмата заменя идентификатора с низа и формалните аргументи в низа – с фактическите аргументи. #defineидентификатор(списък_от_аргументи) низ • списък_от_аргументи - идентификатор1, . . .
Примери: #defineMAX(a, b) ((a)>(b) ? (a) : (b)) #define ABS(a) (a)<0? -(a) : (a) printf(MSG); printf(”max(10, 20) = %d\n”, MAX(10, 20)); printf(”abs(-100) = %d\n”, ABS(-100)); Директива #undef – премахва предварително дефиниран макрос. #undefидентификатор #undef PI Директива #error – принуждава компилатора да спре компилацията и да изведе съобщение за грешка. #errorсъобщение_за_грешка • съобщение_за_грешка не се затваря с кавички (”)
Директива #include – инструктира компилатора да прочете допълнителен файл към основния файл. #include<име_на_файл> - файлът се търси в стандартния каталог #include”име_на_файл” - файлът се търси в указания каталог(потребителски библиотеки) Някои заглавни фалове, съдържащи описание на стандартни функции stdio.h – Входно/изходни функции conio.h – Функции за управление на екрана math.h – Математически функции string.h – Функции за работа с низове ctype.h – Функции за работа със символи stdlib.h - Функции с общо предназначение (търсене, сортировка)
Директиви за условна компилация • #ifdefиме_на_макрос текст на програма на C #else текст на програма на C #endif • #ifndefиме_на_макрос текст на програма на C #endif • #ifконстантен_израз текст на програма на C #elif константен_израз текст на програма на C #else текст на програма на C #endif
Пример: #define SIZE 100 #if SIZE>99 printf(”Компилация за масив с брой елементи по-голям от 99\n”); #else printf(”Компилация за малък масив\n”); #endif Директива #line- променя номера на следващия ред в програмата и името на файла за компилация. #lineконстанта[[”име_на_файл”]] Константа - положително цяло число, новият номер на реда име_на_файл - новото име на файла; ако се пропусне, името на файла не се променя
Пример: #line 100/* Променя номера на следващия ред */ int main () /* Ред 100 */ { /* Ред 101 */ printf(”Директива line\n”); /* Ред 102 */ return 0; /* Ред 103 */ } /* Ред 104 */