C++ для начинающих работа с бинарными файлами
Код C++ Записать число в бинарный файл. Прочитать число из бинарного файла
=================
#include //Для очистки экрана
#include //Для работы с клавиатурой
#include //Для работы с файловыми потоками
void main ()
system ( “CLS” ); //Очистка экрана
int y = 0 ; // Y будем записывать в файл
int x = 0 ; //X будем считывать из файла
cout > y ; //Вводим число, которое нужно сохранить в файл
ofstream out ( “C://1.txt” , ios :: binary | ios :: out ); //Открываем файл в двоичном режиме для записи
out . write ((char*)& y ,sizeof y ); //Записываем в файл число y
out . close (); //Закрываем файл
ifstream in ( “C://1.txt” , ios :: binary | ios :: in ); //Открываем файл в двоичном режиме только для чтения
in . read ((char*)& x ,sizeof x ); //Читаем оттуда информацию и запоминаем её в X
in . close (); //Закрываем файл
cout //Показываем X после изменения
system( “PAUSE” );
>
====================
Уверен, что кого-то могут смутить страшные строчки этого небольшого кода. Не беспокойтесь, он не так страшен, каким может казаться.
Для записи в файл использована команда ofstream, для чтения из файла использована команда instream
У обеих команд внутри скобок одинаковая конструкция.
Если вы присмотритесь к тому, что внутри скобок, то заметите во время записи в файл и во время чтения из файла там изменилась только одна буква, точнее одна переменная, над которой проводится действие.
Во время записи в файл, мы записывали в файл значение y и вот этот самый y стоит в первом случае.
Во время чтения информации, мы считывали информацию в x и вот этот самый x стоит во втором случае.
Про режимы открытия файлов можно почитать тут
Пример работы с текстовым файлом можно почитать тут
Возможно вы уже читали, возможно вам говорили, возможно вы вообще не знали, но когда приходится записывать структуру или класс в файл, то внутри структуры может быть очень много информационных полей и при записи структуры в файл в текстовом режиме придется записывать каждый элемент структуры, а это отнимет много времени. Вот при записи структуры в бинарный файл можно записать всю структуру целиком и сразу.
Код C++ Запись объекта структуры в бинарный файл. Чтение объекта структуры из бинарного файла
============================
#include //Для работы с клавиатурой
#include //Для работы с файлами
#include //Для очистки экрана
//Наша структура
struct MyStruct
char * Name ;
int size ;
>;
void main ()
system ( “CLS” ); //Очистка экрана
MyStruct X , Y ; //Создали два объекта соответствующие нашей структуре
//Например объект X имеет такие параметры
X . Name = “МЕДВЕД” ; //
X . size = 100 ; //
//Открываем файл для записи в бинарном режиме
ofstream out ( “C://2.txt” , ios :: binary | ios :: out );
out . write ((char*)& X ,sizeof X ); //Записываем объект X в открытый нами файл
out . close (); //Закрываем открытый файл
//Открываем файл только для чтения, открываем в бинарном режиме
fstream in ( “C://2.txt” , ios :: binary | ios :: in );
in . read ((char*)& Y ,sizeof Y ); //Считываем информацию в объект Y
in . close (); //Закрываем открытый файл
//Показываем объект Y по его составным частям
cout cout
Если посмотреть на первый пример, где записывалось число и этот, где структура, то при записи файла и чтения файла легко увидеть однообразие. Так вот и получается, что в бинарный файл можно записать любой объект такой короткой инструкцией.
Для тех кому интересен пример записи класса в бинарный файл и чтение класса из бинарного файла, то вот. Я думаю, что тех кого эта часть интересует уже должны быть знакомы с классами. Я выкладывал немного материала, но это намного дальше чем расположена эта тема.
Код C++ Запись объекта класса в бинарный файл. Чтение объекта класса из бинарного файла
======================
#include
#include
#include
class MyClass
int z ; //Недоступен ничему кроме своего класса
public:
int x ;
int y ;
MyClass () < z = 100 ;>; //Инициализация z с помощью конструктора
void showZ () < cout ; //Метод класса, отображает на экране значение z
>;
void main ()
system( “CLS” );
MyClass A , O ; //Создаем два объекта
//Задаем параметры объекту A и записываем его в файл
A . x = 50 ;
A . y = 60 ;
O . x = 0 ; //Инициализируем параметры объекта О в нули. Будем читать его из файла
O . y = 0 ;
ofstream out ( “C://1.txt” , ios :: binary | ios :: out ); //Открыли для записи в бинарном режиме
out . write ((char*)& A ,sizeof A ); //Записали объект А в открытый файл
out . close (); //Закрыли открытый файл
ifstream in ( “C://1.txt” , ios :: binary | ios :: in ); //Открыли для только для чтения в бинарном режиме
in . read ((char*)& O ,sizeof O ); //Считали информацию в объект О
in . close (); //Закрыли открытый файл
cout //Вывели два доступных поля объекта О на экран
O . showZ (); // С помощью метода класса отобразили z из объекта О на экране
system( “PAUSE” );
>
Узнаем адрес объекта X и приводим объект Х к однобайтовому типу
=======================================================
in . read ((char*)& Y ,sizeof Y ); //Считываем информацию в объект Y
Узнаем адрес объекта Y и кладем в объект Y каждый новый прочитанный байт.
Инструктируем, что нам в объект Y нужно положить sizeof Y байт
=======================================================
Все статьи всего этого блога созданы и пока еще создаются одним человеком. Благодаря читателям в статьях исправляются ошибки и неточности .
Я выкладываю всё бесплатно и для того, чтоб вы могли разобраться. Но я трачу много сил и много времени. Если вы считаете нужным и цените мой труд, то можете отблагодарить материально
можно пополнить счет телефона
МТС (РОССИЯ) +7 (981) 857-10-21
или кошельки WebMoney
R375024497470
E149319127674
Z301246203264
Работа с бинарными файлами на Си
Задание такое: есть бинарный файл, содержащий целые положительные и отрицательные числа. Из него нужно удалить самое большое и самое маленькое. Я смог найти эти числа и добавить в файл, но придумать, как их, наоборот, удалить, у меня не получается. Пожалуйста, помогите
#include #include #include #include #include /* Изменение файла в соответствии с заданием */ void edit_file(char *filename); /* вывод содержимого бинарного файла на экран */ void out_file(char *filename); int main(int n_arg, char *arg[]) < system("chcp 65001"); // смена кодировки, если файл в кодировке utf-8 system("cls"); char *file_name; FILE *fin, *fout; //Чтение аргументов программы if (n_arg >1) < file_name = (char*)malloc(sizeof(arg[1])); file_name = arg[1]; >else < file_name = (char*)malloc(sizeof(char)*20); //Если аргументы не заданы ввод названия файла пользователем. //Тут ограничение на название файла 20 символов. printf("Введите имя файла: "); if (!fgets(file_name, 20, stdin))< printf("\nИмя файла введено неверно"); return 1; >; file_name[strlen(file_name)-1] = '\0'; > printf("Исходный файл:\n"); out_file(file_name); edit_file(file_name); printf("Измененный файл:\n"); out_file(file_name); printf("\n"); system("pause"); return 0; > void out_file(char *filename) < // вывод содержимого файла на экран int n = 0; FILE *fin; fin = fopen(filename, "rb"); if(!fin) < printf("Невозможно открыть бинарный файл\n"); system("pause"); exit(0); >while(fread(&n, sizeof(n), 1, fin)) < printf("%5d", n); >fclose(fin); > void edit_file(char *filename) < // изменение содержимого файла int n = 0, max=INT_MIN, min=INT_MAX; FILE *fin; fin = fopen(filename, "r+b"); if(!fin) < printf("Невозможно открыть бинарный файл\n"); system("pause"); exit(0); >rewind(fin); //сдвигаем все элементы на 1 while(fread(&n, sizeof(n), 1, fin)) < if (n >max) max=n; //проверяем максимум if (n < min) min=n; //проверяем минимум >//записываем максимум fwrite(&max, sizeof(n), 1, fin); //записываем минимум fwrite(&min, sizeof(n), 1, fin); fclose(fin); printf("\n\nФайл изменен\n"); >
Отслеживать
задан 29 апр 2021 в 16:34
Listopad02 Listopad02
1,198 1 1 золотой знак 6 6 серебряных знаков 21 21 бронзовый знак
P.S. ссылка на Repl с кодом и бинарным файлом: replit.com/@Listopad02/exercise-3#main.c
29 апр 2021 в 16:37
Удалить алгоритм: 1. читаем потом обрабатываем, готовим данные к записи. 2. перемещаем указатель в ноль lseek. 3. Пишем. fwrite 4. Обрезаем лишнее ftruncate (stackoverflow.com/questions/873454/how-to-truncate-a-file-in-c). 5. Закрываем файл
29 апр 2021 в 16:48
Из-за того что вы не переместили указалеть в ноль, но дочитали файл до конца перед записью — запись происходит в конец файла (append получилось). Без truncаte будет в файле «старый хвост» болтаться, т.е два хвоста получится.
29 апр 2021 в 16:50
@nick_n_a , я если правильно понял, выход для меня сейчас — только создание нового бинарного файла, и запись туда, так?
29 апр 2021 в 17:01
Ну как крайний случай — так можно, я бы делал с lseek + truncate. О нашёл аналог truncate chsize Возможно chsize(fileno(file),размер) сработает.
29 апр 2021 в 17:09
1 ответ 1
Сортировка: Сброс на вариант по умолчанию
Функции работы с файлами не предусматривают «удаление» куска. Файл представлен как «неразрывная лента». В ленту можно писать, можно перемещаться по массиву влево вправо. Можно делать его короче. С файлом нужно работать где-то так же как и с одним обычным массивом типа char array[] без дополнительных удобств, только длинну можно менять.
Так как явно вырезать кусок файла нельзя, то делается «косвенное» вырезание. Для файла применимы следующие операции. Open открытие. Close — закрытие. Seek — перемещение. Read чтение. Write — запись. Trunc — обрезание. Я бы выделил три алгоритма перезаписи файла.
Trunc в разных системах запысывается по-разному. Я использовал _chsize из io.h. Но что бы она работала, пришлось взять файловый дескриптор используя fileno, и текущую позицию файла, используя ftell. Итого получилось _chsize(fileno(f),ftell(f)); . В WINAPI можно использовать SetEndOfFile , у unix ф-ция ftruncate cкорее всего.
-
Простейший алгоритм будет такой: Open, Read, обработка, Seek(0), Write(весь файл), Truncate. Т.е.
#include //. FILE *fin; fin = fopen(filename, "r+b"); // . fseek(fin,0,0); fwrite(новый файл); // Записываем весь буфер с новыми данными _chsize(fileno(f),ftell(f)); // truncate установим размер файла fclose(f);
при записи, не обязательно записывать всё одним куском. Вы можете поставить цикл, и записать все элементы кроме удалённых последовательно.
-
Что бы не лопатить весь файл, можно например удалить строку 2 из файла. Создаём файл, записываем в него 1 2 3 4 через возврат каретки. Удалить строку номер 2 можно так (код не идеальный, для примера как выкинуть кусок файла с from по to)
#include #include int main(int n_arg, char *arg[]) < FILE* f = fopen("1.txt","r+b"); // Нет проверки char myfile[4096]; int size = fread(myfile,1,4096,f); // Читаем весь файл int from=0, to=0, i; // Поиск первого символа 13 for (i=0;i// Поиск второго символа 13 for (i=from;i if ((from !=0) && (to !=0)) < fseek(f,from,0); // Оставляем начало файла по from без изменений fwrite(myfile + to,size - to, 1, f); // Записывам изменившуюся часть файла _chsize(fileno(f),ftell(f)); // Обрезаем старый "хвост" >fclose(f);
bool MoveInFile(FILE * f, long from, long to, int size) < char buffer[256]; // Или задать нужный размер отличный от 256, или делать динамический буфер if (size >sizeof(buffer)) return false; fseek(f,from,0); fread(buffer,1,size); // Прочли кусок в буфер fseek(f,to,0); fwrite(buffer,1,size); // Записали прочитаный кусок в другую позицию return true; >
Алгоритм сложный — приводить полностью не буду. Тем более что при значительно больших кусках эту ф-цию прийдётся сильно усложнить — разбить один MoveInFile на несколько таких, что бы каждый кусок поместился в буфер. Это делают в крайних случаях.
- Нужно помнить, что такие операции пригодны при размере файла где-то до 10. 100 МБайт, и то при размере выше 1Мб будут проблемы. Если куски мелкие — могут быть проблемы с быстродействием. Так же может возникнуть проблема — где и как получить нужное колличество ОЗУ. В x86 приёдется брать память мелкими кусками. При работе с большими файлами — нужно писать кусками не менее 4096 байт, желательно кусками не меньше чем размер кластера файловой системы, и желательно выравнивать обращения по этим границам. Если раньше 4096 было стандартно, думаю скоро перейдём на 8192 байта. Поэтому при работе с файлами более 1 Мб часто используют классы/библиотеки кеширования.
- При работе с файлами свыше 4Гб прийдётся использовать seek64 или что-то подобное.
- Желательно учитывать littel-indian/big-indian иначе можно поймать UB.
- Иногда желательно делать fflush перед закрытием, или в случае если вы делаете логирование.
P.S. Ваш алгоритм не подходит для работы с файлами соовсем. Потому что нужно заранее знать какой вид будет иметь выходной файл. Теоретически можно вычислить позицию первого и второго удаляемого куска, но, т.к. вы не храние файл в памяти — можно сделать перемещение по алгоритму 3 через MoveInFile. Но это будет сильно сложно для вас, но и к тому же сильно нерационально, т.к. ради одного-двух удалений прийдётся сделать несколько перезаписей файла. Этот алгоритм выгодно использовать только если соовсем не хватает памяти для метода 1,2 и файл более 1Мб (на глаз). Я думаю лучше вам лучше вычитать всё, и сделать по алгоритму 1.
Как работать с бинарным файлом в с
В С++ нет типа byte , а вместо типа byte используют тип char . Согласно правилам языка С++ , тип char оказывается наименьшей единицей информации. Из-за этого восприятие нами ситуации в целом немного искажается, ведь мы видим char* , а на самом деле это как byte*
В наших компьютерах используется такая модель памяти, где одна ячейка занимает 1 байт. А один символ char гарантировано, как утверждают в стандарте, должен залезать в эту ячейку. Поэтому, в зависимости от ситуации, тип char можно трактовать или как символьный тип, или как байтовый тип.
- Файлы, хранящие последовательность байтов, называют бинарными файлами.
Это связано с тем, что байт делится на биты, а биты представляют собой двоичные цифры. Слово бинарный переводится как двоичный .
Чтобы мы могли записать какое-нибудь значение в бинарном представлении, нам нужно для начала вывести это бинарное представление, а чтобы записалось правильное количество байт, нужно явно указывать это количество. Это выглядит приблизительно следующим образом:
Так мы делаем строку байтов для того, чтобы отдать потоку, открытому в двоичном режиме
Так мы ограничиваем число уходящих в поток байтов нужным числом
Здесь есть аналогия с символьным массивом, но поскольку у нас не символьная строка, а байтовая строка, то ограничение происходит не нуль-символом, а явным указанием числа числа байт. В зависимости от заявленного для переменной типа переменная может занимать от одного до нескольких байт в памяти компьютера, и при записи переменных мы должны внимательно следить, чтобы число байтов, указываемое нами, строго било с числом байт, занимаемых переменной в памяти. Мы переносим байты из памяти в файл. Чтобы байты переносились как именно байты, мы интерпретируем переменную как строку байтов.
Приблизительно такие ужасы у нас происходят при записи в бинарном формате данных в файл.
Для того, чтобы правильно читать данные из файлов, хранящих данные в бинарном виде, нужно знать общую структуру хранения внутри файла. В нашем случае структура хранения внутри файла весьма проста: в файле хранится два числа, одно целое, одно дробное. Т. е. нужно знать, что хранится внутри файла, и в каком порядке оно хранится. Чтобы получить возможность читать данные, хранимые внутри файлов, нам нужно подключить заголовочный файл fstream и использовать тип ifstream или тип fstream . Я буду использовать первый.
//clang Работа с бинарными файлами Чтение Листинг #2
#include
using namespace std ;
const char * FName = «C:\\FromC\\1.txt» ; //Путь к файлу
int x = 0 ; //Переменные
double y = 0 ;
/*НАЧАЛО РАБОТЫ С ФАЙЛОМ*/
ifstream in ( FName , ios : : binary ) ;
in . read ( ( char * ) &x, sizeof(x)); //перенос байтов из файла в «х»
in . read ( ( char * ) &y, sizeof(y)); //перенос байтов из файла в «y»
/*КОНЕЦ РАБОТЫ С ФАЙЛОМ*/
cout < < x < < '\n' < < y < < '\n' ;
Всё очень напоминает запись в файл, только происходит обратный процесс. Опять же, мы следим за числом цепляемых байтов и переносим их из файла в память компьютера.
- ifstream — специальный тип, объекты которого выполняют роль файловых переменных, читающих файлы.
- ofstream — специальный тип, объекты которого выполняют роль файловых переменных, записывающих файлы.
Для того, чтобы вам проще было работать с бинарными файлами, нужно запомнить две простые истины:
- Выводите строку байтов
- Следите за размерами
На самом деле для компьютеров нет различия между бинарными и текстовыми файлами, это различие существует только из-за нашего восприятия мира. Вы легко можете прочитать самый простейший текстовый файл при бинарном подходе, при этом вам текст будет точно так же понятен, как он понятен и сам по себе, в блокноте. Текстовые файлы — это только-лишь частный случай бинарных файлов. Просто создайте какой-нибудь текстовый файл в удобном месте (нежелательно, чтобы путь к текстовому файлу содержал символы русского алфавита). Например, я создам файл » C:\MyFiles\text.txt «, в этот файл запишу какой-то текст. Советую сначала не использовать русские символы, потому что у некоторых из вас могут быть трудности с кодировками, а я объяснить решения не смогу. В общем, пишу в текстовый файл текст: » Hello, my file! » и сохраняю этот файл. Теперь я буду читать этот файл в бинарном режиме.Вы можете записать в файл несколько строчек.
//clang Работа с бинарными файлами Чтение текстового файла Листинг #3
using namespace std ;
const char * FName = «C:\\MyFiles\\text.txt» ; //Путь к файлу
char S [ 255 ] = < >; //Символьный массив в 255 символов
/*НАЧАЛО РАБОТЫ С ФАЙЛОМ*/
ifstream in ( FName , ios : : binary ) ;
in . read ( ( char * ) &S, sizeof(S)); //перенос байтов из файла в «х»
//in.read((char*)S, sizeof(S)); //в случае с массивом можно и так
/*КОНЕЦ РАБОТЫ С ФАЙЛОМ*/
cout < < S < < '\n' ;
Тут вам как и в обычном случае: нужно заполнять байтовую строку байтами, получаемыми из файла, и следить за числом передаваемых байт. Только нужно сделать дополнительное обнуление символьного массива, чтобы при выводе на экран к полученному из файла тексту не прилипал мусор.
Подводный камень, который может вас ждать в ближайшем будущем — это попытка записать в файл значение, на которое ссылается указательная переменная. В случае работы с указателями в файл будет записываться не значение, с которым связана указательная переменная, а сама указательная переменная. Поэтому не записывайте в файл указательные переменные, если вы не записываете адреса памяти. А адреса памяти вам вряд ли придётся записывать в файл, потому что работа с адресами памяти в полномочиях операционной системы. Вам нужно или сразу записывать значения не указательного характера, или переводить указательный вариант в вариант неуказательный. Будьте особенно осторожны, если вам надо записывать данные, связанные с указательными переменными.
Похожие темы:
Дальше совсем новичкам можно пока не читать, а просто принять к сведению. В бинарные файлы можно быстро и легко сохранять объекты тривиальных, т. е. простых по своему строению, классов и читать в объекты подходящих классов данные из таких бинарников.
Работа с текстовыми и бинарными файлами
В главе рассмотрен классический способ работы с файлами в C/C++, использующий библиотеку stdio.h и доступ к данным через структуру FILE. Альтернативный современный механизм работы с файлами в языке C++ на основе потоков и библиотек , , будет изучен в следующей главе.
Базовые функции для работы с файлами описаны в библиотеке stdio.h. Вся работа с файлом выполняется через файловую переменную-указатель на структуру типа FILE, определённую в стандартной библиотеке:
Открыть файл можно функцией fopen, имеющей два параметра:
(char *имя_файла, char *режим_доступа)
Параметр имя_файла может содержать относительный или абсолютный путь к открываемому файлу. Приведём примеры его значений:
- • «data.txt” — открывается файл с именем data.txt из текущей папки. Следует понимать, что, при запуске исполняемого файла приложения не из IDE, текущая папка — та, где находится исполняемый файл. При отладке в IDE папка может быть иной, например, в Visual Studio при открытом консольном решении с именем Console, содержащем одноимённый проект, файл следует разместить в папке Console/Console, а при запуске исполняемого файла не из IDE — в папке Console/Debug;
- • » f: my. dat» — открывается файл my. dat из головной папки диска f : Так как обратный слеш ‘V в C/C++ является служебным символом, при записи пути к файлу его нужно удваивать.
Имя файла также может быть запрошено у пользователя: char buf[80];
printf («пВведите имя файла:»);
Параметр режим_доступа определяет, какие действия будут разрешены с открываемым файлом. Примеры его возможных значений:
- • » rt» — открывается для чтения текстовый файл;
- • «г+Ь» — открывается для произвольного доступа (как чтения, так и записи) бинарный файл;
- • «at» — открывается текстовый файл для добавления данных в конец файла;
- • «w» — открывается файл для новой записи без указания того, текстовый он или бинарный.
По факту указание режима доступа «Ь» или «t» не накладывает каких-либо ограничений на методы, которые будут применяться для чтения или записи данных.
После открытия файла следует обязательно проверить, удалась ли эта операция. Для этого существует два основных подхода:
- 1) использовать стандартный обработчик ошибок terror ([1,с. 76-77]);
- 2) сравнить указатель, который вернула f open, с константой NULL (nullptг) стандартной библиотеки.
Во втором случае код может быть таким:
fp = fopen («text.txt»,»r+b»);
//Обработка ситуации «He удалось открыть»
Пример 1. Приложение проверяет, удалось ли открыть файл из текущей папки, имя файла запрашивается у пользователя (код для Visual Studio).
printf («пВведите имя файла:»);
fflush (stdin); gets (buf);
fp = fopen (buf,»r+b»);
printf («пне удалось открыть файл»);
exit (1); //Выйти с кодом завершения 1
fflush(stdin); getchar(); return 0;
Функции, возвращающие указатель, в том числе fopen, считаются небезопасными в ряде новых компиляторов, например в Visual Studio 2015. Если их использование приводит не к предупреждению, а к генерации ошибок, есть два основных способа решения проблемы:
1. В соответствии с рекомендациями компилятора, заменить старые названия функций на их безопасные версии, например strcpy на strcpy_s и fopen на fopen_s. При этом может измениться и способ вызова функций, например,
FILE *out = fopen_s(«data.txt» , «wt»);
2. В начале файла (до всех #include) указать директиву
Если используется предкомпиляция, то можно определить этот макрос в заголовочном файле stdaf х. h.
Выбор способа чтения или записи данных зависит от того, какой должна быть структура файла.
Если файл форматированный, т.е. является текстовым и состоит из лексем, разделённых стандартными разделителями
- (пробел, табуляция, перевод строки), обмен данными с ним можно выполнять следующими методами:
- • f scanf — для чтения;
- • fprintf — для записи.
Первым параметром этих функций указывается файловая переменная, в остальном работа совпадает со стандартными scanf и printf.
Пример 2. Файл text.txt в текущей папке приложения имеет следующий вид:
Прочитаем его как последовательность вещественных чисел.
FILE *fp = fopen ( «text.txt»,»г»);
printf (» He удалось открыть файл»);
if (feof(fp)) break;
//обработка очередного значения a
При работе с форматированными файлами важно учитывать следующие моменты:
1. Функции семейства scanf возвращают целое число -количество значений, которые успешно прочитаны в соответствии с указанным форматом. В реальных приложениях эту величину следует проверять в коде:
//не удалось получить одно значение
2. На «восприятие» программой данных может влиять установленная в приложении локаль. Например, если до показанного кода выполнен оператор
результат работы кода может измениться (для русской ло-кали разделителем целой и дробной части числа является запятая, а не точка).
- 3. Очередное чтение данных изменяет внутренний файловый указатель. Этот указатель в любой момент времени, пока файл открыт, показывает на следующее значение, которое будет прочитано. Благодаря этому наш код с бесконечным while не зациклился.
- 4. Код показывает, как читать из файла заранее неизвестное количество значений. Это позволяет сделать стандартная функция feof (проверка, достигнут ли конец файла; вернёт не ноль, если прочитано всё).
- 5. Распространённый в примерах из Интернета код вида
//обработка числа a
под Windows может породить неточности при интерпретации данных. Например, этот код может прочитать как последнее значение завершающий перевод строки в файле, благодаря чему последнее прочитанное значение удвоится.
Пример 3. В качестве примера форматной записи в файл сохраним массив а из 10 целочисленных значений в файле с именем result.txt по 5 элементов в строке:
FILE *fp=fopen ( «result.txt»,»wt»);
puts («He удалось открыть файл!»);
> void DrawWindow (WINDOW w) < //Нарисовать окно w char c[]=; window (1,1,80,25); textbackground(w.back); textcolor(w.color); gotoxy (w.xl-1,w.yl-1); cprintf ("%c",c[0]);