Methods_AP_LABS_II
.pdfВиводить символ с у потік stream (записує у файл). У випадку успіху
повертає с, у випадку помилки - EOF.
int fputs(const char *s, FILE *stream)
Ввиводить рядок s у потік. У випадку успіху повертає ненегативне ціле,
у випадку помилки EOF.
Лістинг 6.1
#include <stdio.h> #include <stdlib.h> int main()
{
FILE *fp;
char buffer[256];
fp=fopen ("file.dat","r") ; //відкриваємо файл для
читання |
|
if(!fp) |
|
puts("Помилка відкриття файлу " ) else |
|
{ |
|
while(fgets(buffer,255,fp)!=NULL) |
//поки не |
кінець |
|
//файлу, |
|
уводимо рядок |
|
fputs(buffer, stdout) ; |
//виводимо |
на екран |
|
fclose(fp); |
|
}
return(0);
}
6.1.4 Виведення у файл
Найбільш поширеною функцією для виведення даних у файл є функція
fprintf() з наступним синтаксисом
int fprintf (FILE * stream, const char * format, ...)
з параметрами:
–stream — вказівник на структуру FILE, отриманий при відкритті файлу.
–format — форматна строка. Довільний рядок, що може містити специфікатори формату наступного вигляду
%[flags][width][.precision][length]specifier
Найважливішим є поле specifier, яке визначає тип та формат даних, що буде записано у файл (таблиця 6.3).
|
|
|
Таблиця 6.3 |
|
|
Поле specifier |
|
|
|
|
|
Поле |
|
Що буде виведено/прочитано |
Приклад |
specifier |
|
|
|
|
|
|
|
c |
|
Символ |
А |
|
|
|
|
d або i |
|
Ціле число зі знаком |
-234 |
|
|
|
|
f |
|
Число з плаваючою точкою |
34.32 |
|
|
|
|
s |
|
Рядок С |
Hello, World! |
|
|
|
|
u |
|
Ціле без знаку |
123 |
|
|
|
|
Можливі значення інших полів є наступними (таблиці 6.4-6.7). |
|||
|
|
|
Таблиця 6.4 |
|
|
Поле flags |
|
|
|
|
|
Поле flags |
Опис |
|
|
|
|
|
|
- |
|
Вирівнювання вліво. За замовчуванням — вправо. |
|
|
|
||
‘ ‘ |
Якщо знак не відображається, перед числом вставляється |
||
|
|
пробіл. |
|
|
|
|
|
0 |
|
Використати нулі замість пробілів при вирівнюванні вліво. |
|
|
|
|
|
|
|
|
Таблиця 6.5 |
|
|
|
Поле width |
|
|
|
|
Поле |
|
|
Опис |
width |
|
|
|
|
|
|
|
число |
|
Мінімальна кількість символів при виведенні значення. У випадку, |
|
|
|
коли значення менше цього числа, результат доповнюється |
|
|
|
пробілами. |
|
|
|
|
|
‘ ‘ |
|
Якщо знак не відображається, перед числом вставляється пробіл. |
|
|
|
|
|
|
|
|
Таблиця 6.6 |
|
|
|
Поле precision |
|
|
|
|
Поле |
|
Опис |
|
.precision |
|
||
|
|
|
|
.число |
|
Для d, i, u — мінімальна кількість знаків, що буде виведено. |
|
|
|
|
Якщо результат менше цього числа, поле вирівнюється нулями |
|
|
|
зліва. |
|
|
|
Для f — кількість знаків після точки. |
|
|
|
Для s — максимальна кількість символів на виході. |
|
|
|
|
|
|
|
Таблиця 6.7 |
|
|
|
Поле length |
|
|
|
|
Поле |
|
Опис |
|
length |
|
|
HАргумент інтерпретується як short int або unsigned short int (для i, d, u)
l |
Аргумент інтерпретується як long int або unsigned long int (для i, d, |
u)
LАргумент інтерпретується як long double (для f)
Уякості інших аргументів вказуються значення, що будуть виведені у відповідності до визначеного форматного рядку.
Приклад 6.1.
fprintf(stdout, “%3.1f”, 3.141) // вивести число PI з точністю 1 знак після коми, 3.1
Функція fprintf() повертає число символів, що було записано в файл.
Для читання інформації з файлу використовується функція з наступним
синтаксисом
int fscanf (FILE * stream, const char * format, ...)
зпараметрами:
–stream — вказівник на структуру FILE, отриманий при відкритті файлу;
–format — форматний рядок. Це довільний рядок, що може містити специфікатори формату виду [=%[*][width][modifiers]type=],
де
* |
Дані будуть прочитані, але не будуть записані у відповідний |
|
аргумент. |
|
|
width |
Максимальне число символів, що буде прочитано в поточній |
|
операції. |
|
|
modifiers |
Те ж саме, що і length в fprintf() |
|
|
type |
Тип змінної, що буде прочитано. Те ж, що і specifier у fprintf(). |
|
Підтримуються c, d, f, s, u. |
|
|
Інші аргументи можуть змінюватись в залежності від форматного рядку. Вони визначають послідовність адрес змінних, у які будуть зчитані дані з файлу.
Лістинг 6.2. Прочитати з файла test.in 2 числа і записати їх суму в файл test.out.
#include <cstdio> #include <cstdlib>
int main()
{
using namespace std;
const char
*input = "test.in", *output = "test.out";
int a, b;
// Відкрити вхідний файл тільки для читання
FILE * in = fopen(input, "r"); if(!in)
{
perror(input); return -1;
}
//Прочитати 2 цілих числа if(fscanf(in, "%d %d", &a, &b) != 2)
{
printf("Не можу прочитати 2 цілих числа з файлу.\n"); return -2;
}
//Відкрити вихідний файл для запису
FILE * out = fopen(output, "w"); if(!out)
{
perror(output); return -3;
}
// Записати суму чисел у вихідний файл
if(fprintf(out, "%d", a + b) != 1) // не вірно так писати, т.я. fprintf()
повертає кількість записаних у файл символів
{
printf("Не можу записати суму у файл.\n"); return -4;
}
return 0;
}
Іноді виникає необхідність прочитати або записати у файл складний тип даних, для якого не визначено окремих символів форматування
(наприклад, структуру або масив). Для цього використовують бінарні файли та функції
size_t fread (void * ptr, size_t size, size_t count, FILE * stream); //
Читання з файлу
size_t fwrite (const void * ptr, size_t size, size_t count, FILE * stream); // Запис в файл
з наступними параметрами:
–ptr — вказівник на масив, що буде прочитано з файлу або записано в файл;
–size — розмір елементу масиву в байтах;
–count — кількість елементів в масиві;
–stream — вказівник на структуру FILE, отриманий при відкритті файлу.
Функція fread() (fwrite()) повертає кількість прочитаних (записаних)
елементів.
Приклад 6.2. Читання та запис заголовку бінарного файлу:
// Заголовок бінарного файлу struct {
int version; char name[20]; int data_size;
} header;
FILE* input = fopen(“test.hdf”, “r+b”)
// Прочитати заголовок з бінарного файлу if(!fread(&header, sizeof header, 1, input))
{
printf(“Не можу прочитати заголовок!”); exit(-1);
}
printf(“%d”, header.version); header.version++;
// Записати заголовок в бінарний файл if(!fwrite(&header, sizeof header, 1, input))
{
printf(“Не можу записати заголовок!”); exit(-2);
}
Для переміщення в рамках файлу (переміщення вказівника поточної позиції) використовується функція
int fseek (FILE * stream, long int offset, int origin)
з параметрами:
–stream — вказівник на структуру FILE, отриманий при відкритті файлу;
–offset — зсув відносно origin;
–origin — позиція, відносно якої відраховується offset. Цей параметр
може приймати наступні значення:
SEEK_SET — початок файлу;
SEEK_CUR — поточна позиція в файлі;
SEEK_END — кінець файлу.
Функція повертає 0, якщо переміщення було успішним.
Наприклад,
fseek(f, 20, SEEK_SET); // Перемістити вказівник у файлі на 20
байт
Для того, щоб отримати поточну позицію у файлі використовують
функцію
long int ftell ( FILE * stream), де stream — вказівник на структуру
FILE, отриманий при відкритті файлу.
Наприклад, знайти розмір файлу можна наступним чином.
FILE* f = fopen(“test.txt”, “r”); fseek(f, 0, SEEK_END); long size = ftell(f);
Закрити файл можна за допомогою функції int fclose (FILE * stream) з
параметром stream — вказівник на FILE, що закривається.
Приклад:
fclose(in);
6.1.5 Потоки С++
Більш сучасний підхід для роботи з файлами з’явився у стандарті мови С++. В даному підході використовуються потоки введення/виведення
ifstream та ofstream.
Потоки ifstream та ofstream є класами (class). Більш докладно класи, їх властивості та основні принципи використання будуть розглядатися в учбовому курсі Програмування -2. Об’єктно-орієнтоване програмування.
Важливим є те, що операції та функції, які застосовні до стандартних потоків введення/виведення cin та cout (ЛР №1), можна використовувати також і при роботі з ifstream та ofstream.
Відкрити файл можна при створенні потоку:
ifstream ( const char * filename, mode);
ofstream ( const char * filename, mode);
або за допомогою відповідних їх методів
void open ( const char * filename, mode); void open ( const char * filename, mode);
з наступними параметрами:
–filename — імя файлу, наприклад /etc/passwd;
–mode — режим доступу до файлу.
У |
стандарті С++ визначено наступні режими доступу до файлу |
(таблиця 6.8): |
|
|
Таблиця 6.8 |
|
Режими доступу |
|
|
app |
Доступ для додавання нової інформації. При виводі інформація |
|
додається в кінець файлу. |
|
|
ate |
Перемістити вказівник файлу в кінець. |
|
|
binary |
Режим доступу до бінарного файлу. |
|
|
in |
Доступ для читання. |
|
|
out |
Доступ для запису. |
|
|
trunc |
Створити пустий файл для читання та запису. Якщо файл вже існує, |
|
його вміст стирається. |
|
|
Режими доступу можуть поєднуватися за допомогою оператора ‘або’
(|). Наприклад, режим ios::binary | ios::in визначає доступ тільки для читання
бінарного файлу.
Приклад 6.3
//Відкрити файл для читання ifstream in1(“test.in”);
//Те ж, з використанням функції open() ifstream in2;
in2.open(“test.in”);
//Відкрити файл для запису
ofstream out1(“test.out”);
// Те ж, з використанням функції open() ifstream out2;
out2.open(“test.out”);
Потоки ifstream та ofstream дозволяють використовувати модифікатори (endl, width, setf, hex) та методи (getline()), що визначені також і для потоків cin та cout (див. ЛР № 1). Наприклад, записати ціле число в шістнадцятковій системі в файл можна наступним чином.
ofstream o(“test.txt”); o << hex << 1234;
Лістинг 6.3.
// Прочитати 2 числа з вхідного файлу та записати в вихідний файл їх суму
#include <iostream> #include <fstream>
int main()
{
using namespace std;