22333

Ввод и вывод в языке Си: общие концепции. Файлы данных и каталоги файлов. Внутренняя организация и типы файлов

Лекция

Информатика, кибернетика и программирование

h main { FILE stream; if stream = fopen data r == NULL printf Ошибка при открытии файла ; } Имя функции и назначение: fclose закрывает файл предварительно открытый для ввода вывода потоком Формат и описание аргументов: int fclosestream FILE stream; Указатель на открытый файл Возвращаемое значение равно нулю при нормальном завершении операции и EOF в случае возникновения ошибки.h...

Русский

2013-08-04

76 KB

3 чел.

ЛЕКЦИЯ 6

Ввод  и вывод в языке Си: общие концепции. Файлы   данных и каталоги файлов. Внутренняя организация   и типы файлов. Стандартные функции для работы  с               файлами  и  каталогами.  Внешние  устройства как    специальные файлы. Организация обмена  со  стандартными  внешними  устройствами.  Операции ввода/вывода  через  порты  микропроцессоров  Intel    8086/80286.

$ 1. ВВОД И ВЫВОД В ЯЗЫКЕ СИ: ОБЩИЕ КОНЦЕПЦИИ

При разработке и эксплуатации программного обеспечения операции  ввода/вывода играют столь же большую роль, как, например, инструкции  управления  или способы описания оперативных структур данных. Дело в  том, что, с одной стороны, всякая  программа,  лишенная  возможности   общения  с  "внешним миром", оказывается либо недостаточно гибкой по  отношению к наборам обрабатываемых ею данных, либо абсолютно  бесполезной по причине отсутствия возможности сообщить пользователю о результатах своей работы. С другой стороны, во многих прикладных задачах  объемы  перерабатываемой  информации столь велики, что не может   быть и речи о ее одновременном размещении в оперативной памяти ЭВМ и  возникает прямая необходимость в  непрерывной  "подкачке"  данных  в  процессе работы программы. И, наконец, использование одних лишь оперативных структур данных не обеспечивает сохранения информации после   выключения  питания  ЭВМ,  ликвидируя  тем самым возможность ведения  долгосрочных архивов и создания баз знаний.  В современных вычислительных системах внешние устройства, с которыми приходится поддерживать обмен, по выполняемым функциям делятся на две категории. Это,  во-первых,  всевозможные  устройства  для     связи  с оператором ЭВМ, как то интерактивные терминалы и телетайпы,   принтеры, графопостроители, фотонаборные устройства и т. д.  Во-вторых, внешними по отношению к центральной ЭВМ являются накопители

информации  на магнитных носителях, каковыми чаще всего выступают магнитные диски. Две эти категории периферийных устройств принципиально  отличаются тем, что в первом случае передача  данных  на  устройство  осуществляется  последовательным образом (потоком) и носит, как правило, однонаправленный характер. Во втором же  случае  обычно  имеет   место двусторонняя передача информации и достаточно сложная логическая  организация данных на магнитном носителе, поддерживаемая

специальными компонентами операционной системы и прикладными программами.          Одной из основных особенностей языка Си по отношению к большинству других языков программирования высокого уровня является  полное   отсутствие  в нем предопределенных операторов ввода/вывода. Это, однако, ни в коей мере не ограничивает его возможностей по организации   больших наборов данных и управлению периферийным оборудованием,  ибо  все  необходимые  для  этого  средства  предоставляются функциями из  стандартных библиотек языка Си. Более  того,  подобное  отношение  к   операциям ввода/вывода открывает путь к созданию высоко эффективного     и  мобильного  программного  обеспечения,  максимально использующего   возможности операционной системы по поддержанию внешнего обмена.

$ 2. ФАЙЛЫ ДАННЫХ И КАТАЛОГИ. ВНУТРЕННЯЯ ОРГАНИЗАЦИЯ

И ТИПЫ ФАЙЛОВ

Файлами принято называть поименованные наборы данных на внешних    носителях. Совокупность файлов обычно организуется по иерархическому    принципу в виде файлового дерева, чем обеспечивается удобство представления и обработки больших информационных структур.  По  характеру  хранимой  информации различают файлы данных и файлы-каталоги (директории). Первые из них содержат данные, непосредственно  используемые   прикладными программами, включая исходные тексты, объектные и загрузочные  модули  самих  этих программ. Наоборот, содержимое каталогов   составляют указатели на другие файлы и подкаталоги. Прикладные

программы лишены возможности непосредственно вмешиваться в структуру каталогов, а могут делать это лишь опосредованно путем обращения к соответствующим функциям операционной системы.  Тот  каталог,  который    находится на высшем уровне иерархической организации, носит название    корневого каталога.   Логическая  организация файлов данных в каталоги поддерживается    файловой системой, входящей в состав ОС. Основное назначение  файловой системы состоит в том, чтобы отделить пользователя ЭВМ от излишних  деталей внешнего обмена и предоставить ему возможность простого   и гибкого управления большими информационными структурами.  Именами файлов и каталогов в Си-программах, предназначенных для     последующей обработки в среде IBM C/2, могут быть  любые  правильные   имена  в  смысле  операционной  системы  MS DOS. В отдельных случаях   обеспечивается возможность  использования  специальных  метасимволов    для генерации последовательности имен.   В  операционной среде MS DOS не существует какой-либо предопределенной внутренней структуры файлов. Наоборот, всякий  файл  представляет собой простую последовательность байт, каждый из которых может  содержать  либо  правильный код символа ASCII, либо быть произвольной комбинацией двоичных разрядов. Файлы первого типа обычно называют текстовыми файлами и они могут быть  визуализированы,  например,  на  экране  видеотерминала.  Файлы же второго типа, называемые   двоичными файлами, могут содержать внутри себя непечатаемые  символы     или  управляющие последовательности и в общем случае не подлежат визуальному просмотру.  Заметим, однако, что с точки зрения внутренней обработки информации в системе MS DOS, не существует принципиальной  разницы  между  текстовыми  и двоичными файлами, и текстовый режим является основным  при организации обмена информацией. Тем не менее, есть  определенные   отличия  в  интерпретации содержимого файлов некоторыми стандартными   функциями при их использовании в текстовом и двоичном режимах.  Так,  например,  в текстовом режиме комбинация символов CR/LF (hex-коды 0D    и 0A соответственно) преобразуется при вводе в  единственный  символ     LF.  В  процессе  же вывода выполняется обратное преобразование. При    работе в двоичном режиме подобные преобразования не выполняются.

$ 3. СТАНДАРТНЫЕ ФУНКЦИИ ДЛЯ РАБОТЫ С ФАЙЛАМИ

 И КАТАЛОГАМИ

В настоящем параграфе приводятся наиболее употребительные функции управления вводом/выводом из стандартной библиотеки языка Си. По своему функциональному назначению  они  разбиты  на  три  категории:   ввод/вывод потоком, операции обмена низкого уровня и управление файлами  и каталогами. Организация обмена со стандартными внешними устройствами рассмотрена в следующем параграфе.

3.1. Ввод/вывод потоком символов

Функции ввода/вывода потоком  рассматривают  файлы  и  элементы   данных  как последовательности отдельных символов. Они предоставляют    возможность буферизации информации при пересылке, а также  обеспечивают  преобразование  данных в соответствии с заданной спецификацией  формата.   Всякий поток перед обращением к нему должен быть открыт при помощи функции fopen для ввода, вывода или выполнения обеих этих  операций в текстовом или двоичном режиме. Открывая поток, функция fopen     возвращает  указатель  типа FILE, который используется для ссылки на   него во всех операциях ввода/вывода или управления указателем  текущей позиции. После завершения работы с потоком, его следует закрыть,  используя  функцию fclose. В противном случае это сделает операционная система по окончании работы программы.  Операции чтения и записи для потока выполняются, начиная с  текущей  позиции  указателя, смещая последний на соответствующее число  позиций. Используя функцию fseek, указатель можно установить в  произвольную позицию файла перед выполнением очередной операции, а функция rewind позиционирует указатель на начало файла.          Предварительные  описания функций ввода/вывода потоком, а также   определения  соответствующих  констант,  типов и структур помещены в   файл stdio.h, который необходимо включить в программу при помощи директивы препроцессора #include (см. Лекцию 7, $ 4  и  примеры  программ).

         Имя функции и назначение: fopen  -  открывает файл  с  заданным именем для ввода/вывода потоком  Формат и описание аргументов:

              FILE  *fopen(pathname, type)

              const char  *pathname;      /*  Имя открываемого файла  */

              const char  *type;          /*  Тип доступа к файлу     */

Параметр  type  представляет собой строку символов и определяет    характер доступа к файлу:

         "r"  - существующий текстовый файл открыть для чтения

         "w"  - текстовый файл  открыть для записи (в случае существования файла его содержимое разрушается)

         "a"  - текстовый файл  открыть для записи в конец файла (в случае отсутствия файл создается вновь)

         "r+" - существующий файл открыть для чтения и записи

         "w+" - текстовый файл открыть для чтения и записи (в случае существования файла его содержимое разрушается)

Добавление  символа  'b' в конец каждой из этих строк позволяет открыть двоичный файл для выполнения соответствующих операций.  Функция возвращает указатель типа FILE при нормальном  завершении операции и NULL в случае возникновения ошибки.

Пример использования:

                #include  <stdio.h>

                main()

                { FILE  *stream;

                  if ((stream = fopen("data", "r")) == NULL)

                     printf("Ошибка при открытии файла");

                }

Имя функции и назначение: fclose -  закрывает  файл,  предварительно открытый для ввода/вывода  потоком

Формат и описание аргументов:

              int  fclose(stream)

              FILE  *stream;          /*  Указатель на открытый файл  */

Возвращаемое значение равно нулю при нормальном завершении операции и EOF в случае возникновения ошибки. Пример использования:

                      #include  <stdio.h>

                      main()

                      { FILE  *stream;

                        stream = fopen("data", "w+b");

                        ..............................

                        ..............................

                        fclose(stream);

                      }

Имя функции и назначение: feof - проверяет возникновение ситуации  "конец  файла"  при вводе/выводе   потоком

Формат и описание аргументов:

              int  feof(stream)

              FILE  *stream;          /*  Указатель на открытый файл  */

Возвращаемое значение отлично от нуля  при  попытке  чтения  за   пределами файла и равно нулю в противном случае.   Пример использования:

                     #include  <stdio.h>

                     char  string[100];

                     FILE  *stream;

                     void  process(char*);

                     main()

                     { while (!feof(stream))

                          if (fscanf(stream, "%s", string))

                             process(string);

                     }

Имя функции и назначение: fgetc - читает  очередной  символ  из   входного  потока и увеличивает значение указателя

Формат и описание аргументов:

              int  fgetc(stream)

              FILE  *stream;          /*  Указатель на открытый файл  */

Возвращаемое  значение равно коду прочитанного символа при нормальном завершении операции и EOF в случае возникновения ошибки  или   при достижении конца файла.

Пример использования:

          #include  <stdio.h>

          main()

          { char  buffer[81];

            int   i, ch;

            FILE  *stream;

            for (i = 0; i < 80 && (ch = fgetc(stream)) != EOF; i++)

                buffer[i] = ch;

            buffer[i] = '\0'

          }

Имя функции и назначение: fgets  -  читает  строку  символов из   входного потока до первого символа \n   включительно  (но  не более заданного    максимального  количества),  добавляя   нуль-символ в конец прочитанной строки

Формат и описание аргументов:

              char  *fgets(string, n, stream)

              char  *string;          /*  Буфер для размещения про-   */

                                      /*  читанной строки             */

              int   n;                /*  Максимальное количество     */

                                      /*  символов в строке           */

              FILE  *stream;          /*  Указатель на открытый файл  */

Возвращаемое значение равно указателю на строку string при нормальном завершении операции и NULL в случае возникновения ошибки или   при достижении конца файла.

Пример использования:

                    #include  <stdio.h>

                    main()

                    { char  line[100], *result;

                      FILE  *stream;

                      ..................................

                      ..................................

                      result = fgets(line, 100, stream);

                      ..................................

                      ..................................

                    }

Имя функции и назначение: getw - читает из входного потока очередное целое число, заданное в двоичном формате, и  увеличивает  значение   указателя

Формат и описание аргументов:

              int  getw(stream)

              FILE  *stream;          /*  Указатель на открытый файл  */

Возвращаемое  значение равно прочитанному целому числу при нормальном завершении операции и EOF в случае возникновения ошибки  или  при достижении конца файла.

Пример использования:

                        #include  <stdio.h>

                        main()

                        { int   ivalue;

                          FILE  *stream;

                          ......................

                          ......................

                          ivalue = getw(stream);

                          ......................

                          ......................

                        }

                               -------------

Имя функции и назначение: fputc - записывает символ в  выходной   поток и увеличивает значение указателя

Формат и описание аргументов:

              int  fputc(c, stream)

              int   c;                /*  Выводимый символ            */

              FILE  *stream;          /*  Указатель на открытый файл  */

Возвращаемое  значение  равно коду записанного символа при нормальном завершении операции и EOF в случае возникновения ошибки.

Пример использования:

               #include  <stdio.h>

               main()

               { char  buffer[81];

                 int   i;

                 FILE  *stream;

                 .............................................

                 .............................................

                 for (i = 0; i < 81 && buffer[i] != '\0'; i++)

                    fpufc(buffer[i], stream);

                 .............................................

                 .............................................

               }

                               -------------

Имя функции и назначение: fputs  -  копирует строку  символов в    выходной поток

Формат и описание аргументов:

              int  fputs(string, stream)

              const char  *string; /*  Указатель на выводимую строку  */

              FILE        *stream; /*  Указатель на открытый файл     */

Возвращаемое  значение равно коду последнего символа строки при   нормальном завершении операции, нулю для пустой строки и EOF в  случае возникновения ошибки.

Пример использования:

                    #include  <stdio.h>

                    main()

                    { FILE  *stream;

                      ..................................

                      ..................................

                      fputs("This is a string", stream);

                      ..................................

                      ..................................

                    }

                              -------------

Имя функции и назначение: putw - записывает  в  выходной  поток  двоичное представление целого числа и   увеличивает значение указателя

Формат и описание аргументов:

              int  putw(binint, stream)

              int   binint;  /*  Двоичное представление целого числа  */

              FILE  *stream; /*  Указатель на открытый файл           */

Возвращаемое значение равно binint  при  нормальном  завершении  операции и EOF в случае возникновения ошибки.

Пример использования:

                           #include  <stdio.h>

                           main()

                           { FILE  *stream;

                             ...................

                             ...................

                             ...................

                             putw(0347, stream);

                             ...................

                             ...................

                             ...................  

                           }

                               -------------

Имя функции и назначение: fscanf - читает  данные  из  входного  потока  и заносит их в ячейки памяти,   определяемые аргументами функции

Формат и описание аргументов:

              int  fscanf(stream, fstring <, argument ...>)

              FILE        *stream;    /*  Указатель на открытый файл  */

              const char  *fstring;   /*  Строка управления форматом  */

Строка string управления форматом определяет способ интерпретации входных данных. Она может содержать следующие поля:

         -  пробелы, символы табуляции (\t) или перехода на новую строку  (\n), которые позволяют читать без сохранения любые комбинации соответствующих символов из входного потока;

         -  произвольные  печатаемые символы ASCII, кроме знака процента  (%), использование которых позволяет читать без сохранения соответствующие им символы из входного потока;

         - спецификации формата, начинающиеся со знака  процента  (%)  и требующие преобразования прочитанных данных к заданному типу. Аргументы функции fscanf являются указателями на ячейки памяти,  куда  необходимо  поместить прочитанные значения, и должны иметь тот   же самый тип, который задан соответствующими спецификациями в строке   управления форматом.  Всякая спецификация формата в общем случае имеет следующий вид:

                          %<*><width><h|l|L>type

где угловыми скобками (<>) обозначены необязательные элементы конструкции.  Отдельные поля спецификации могут быть символами или числами, задающими конкретный способ преобразования данных при вводе.  Символ преобразования соответствующий полю type, определяет тип   очередного элемента данных, читаемого из входного потока. Этим  элементом  может быть отдельный символ ASCII, строка символов или число  (целое или вещественное). Ниже приведена таблица символов преобразования, имеющих специальное значение в среде IBM C/2, а также  указан   тип отвечающего каждому из них аргумента.

       г==========T===========================T======================¬

       ¦  Символ  ¦  Элемент входного потока  ¦     Тип аргумента    ¦

       ¦==========+===========================+======================¦

       ¦    d     ¦  десятичное целое         ¦  указатель на int    ¦

       ¦----------+---------------------------+----------------------¦

       ¦    D     ¦  десятичное целое         ¦  указатель на long   ¦

       ¦----------+---------------------------+----------------------¦

       ¦    o     ¦  восьмеричное целое       ¦  указатель на int    ¦

       ¦----------+---------------------------+----------------------¦

       ¦    O     ¦  восьмеричное целое       ¦  указатель на long   ¦

       ¦----------+---------------------------+----------------------¦

       ¦    x     ¦  шестнадцатеричное целое  ¦  указатель на int    ¦

       ¦----------+---------------------------+----------------------¦

       ¦    X     ¦  шестнадцатеричное целое  ¦  указатель на long   ¦

       ¦----------+---------------------------+----------------------¦

       ¦    i     ¦  десятичное, восьмеричное ¦  указатель на int    ¦

       ¦          ¦  или шестнадцатеричное    ¦                      ¦

       ¦          ¦  целое                    ¦                      ¦

       ¦----------+---------------------------+----------------------¦

       ¦    I     ¦  десятичное, восьмеричное ¦  указатель на long   ¦

       ¦          ¦  или шестнадцатеричное    ¦                      ¦

       ¦          ¦  целое                    ¦                      ¦

       ¦----------+---------------------------+----------------------¦

       ¦    u     ¦  десятичное целое без     ¦  указатель           ¦

       ¦          ¦  знака                    ¦  на unsigned int     ¦

       ¦----------+---------------------------+----------------------¦

       ¦    U     ¦  десятичное целое без     ¦  указатель           ¦

       ¦          ¦  знака                    ¦  на unsigned long    ¦

       ¦----------+---------------------------+----------------------¦

       ¦ e, f, g, ¦  вещественное число       ¦  указатель на float  ¦

       ¦   E, G   ¦                           ¦                      ¦

       ¦----------+---------------------------+----------------------¦

       ¦    c     ¦  символ ASCII             ¦  указатель на char   ¦

       ¦----------+---------------------------+----------------------¦

       ¦    s     ¦  строка символов          ¦  указатель на массив ¦

       ¦          ¦                           ¦  элементов типа char ¦

       ¦----------+---------------------------+----------------------¦

       ¦    p     ¦  значение вида xxxx:yyy,  ¦  указатель на длин-  ¦

       ¦          ¦  где x и y есть шестнад-  ¦  ный указатель (тип  ¦

       ¦          ¦  цатеричные цифры         ¦  far) неопределенно- ¦

       ¦          ¦                           ¦  го типа             ¦

       L==========¦===========================¦======================-

Символ звездочка (*), возможно входящий в спецификацию формата,  заставляет  систему  обмена проигнорировать очередной элемент данных   заданного типа во входном потоке. Необязательное поле width представляет собой положительное  десятичное  число, задающее максимальное количество символов, читаемых   их входного потока и интерпретируемых в соответствии со спецификатором type.  Дополнительные спецификаторы h, l и L могут  быть  использованы   для  модификации типа аргумента, определенного полем type. Их действие распространяется лишь на длину соответствующего аргумента (short    или long).    Возвращаемое функцией fscanf значение равно  количеству  прочитанных  и  преобразованных  в соответствии с заданным форматом полей    входного потока. При попытке чтения за пределами файла функция возвращает значение EOF.

Пример использования:

                     #include  <stdio.h>

                     main()

                     { char   sym, string[81];

                       int    ival;

                       long   lval;

                       float  fval;

                       FILE   *stream;

                       .............................

                       .............................

                       stream = fopen("data", "r");

                       fscanf(stream, "%c", &sym);

                       fscanf(stream, "%s", string);

                       fscanf(stream, "%d", &ival);

                       fscanf(stream, "%ld", &lval);

                       fscanf(stream, "%f", &fval);

                       .............................

                       .............................

                     }

                               -------------

Имя функции и назначение: fprintf - записывает  форматированные    данные в выходной поток

Формат и описание аргументов:

              int  fprintf(stream, fstring <, argument ...>)

              FILE        *stream;    /*  Указатель на открытый файл  */

              const char  *fstring;   /*  Строка управления форматом  */

Строка fstring управления форматом определяет способ преобразования  данных при выводе. Она может включать в себя обычные символы,  копируемые в выходной поток, Esc-последовательности (см. Лекцию 2, $

    3) и спецификации формата, начинающиеся со знака процента (%).  Аргументы функции fprintf  являются  простыми  переменными  или   указателями, задающими набор выводимых значений. Всякая спецификация формата в общем случае имеет следующий вид:

                  %<flags><width><.precision><h|l|L>type

где угловыми скобками (<>) обозначены необязательные элементы конструкции.  Отдельные поля спецификации могут быть символами или числами, задающими конкретный способ преобразования данных при выводе. Символ  преобразования,  соответствующий  полю type, определяет  тип очередного элемента данных, записываемого в выходной поток. Этим  элементом может быть отдельный символ  ASCII,  строка  символов  или   число (целое или вещественное). Ниже приведена таблица символов преобразования, имеющих специальное значение в среде IBM C/2.

    г==========T======================T================================¬

    ¦  Символ  ¦       Аргумент       ¦         Формат вывода          ¦

    ¦==========+======================+=============================== ¦

    ¦   d, i   ¦  целое число         ¦  десятичное целое со знаком    ¦

    ¦----------+----------------------+--------------------------------¦

    ¦     u    ¦  целое число         ¦  десятичное целое без знака    ¦

    ¦----------+----------------------+--------------------------------¦

    ¦     o    ¦  целое число         ¦  восьмеричное целое без знака  ¦

    ¦----------+----------------------+--------------------------------¦

    ¦     x    ¦  целое число         ¦  шестнадцатеричное целое без   ¦

    ¦          ¦                      ¦  знака, использующее "abcdef"  ¦

    ¦----------+----------------------+--------------------------------¦

    ¦     X    ¦  целое число         ¦  шестнадцатеричное целое без   ¦

    ¦          ¦                      ¦  знака, использующее "ABCDEF"  ¦

    ¦----------+----------------------+--------------------------------¦

    ¦     f    ¦  вещественное число  ¦  вещественное число со знаком  ¦

    ¦          ¦                      ¦  с фиксированной точкой        ¦

    ¦----------+----------------------+--------------------------------¦

    ¦   e, E   ¦  вещественное число  ¦  вещественное число со знаком  ¦

    ¦          ¦                      ¦  в экспоненциальной форме      ¦

    ¦----------+----------------------+--------------------------------¦

    ¦   g, G   ¦  вещественное число  ¦  вещественное число со знаком  ¦

    ¦          ¦                      ¦  в экспоненциальной форме или  ¦

    ¦          ¦                      ¦  с фиксированной точкой в за-  ¦

    ¦          ¦                      ¦  висимости от величины порядка ¦

    ¦----------+----------------------+--------------------------------¦

    ¦     c    ¦  символ ASCII        ¦  отдельный символ              ¦

    ¦----------+----------------------+--------------------------------¦

    ¦     s    ¦  указатель типа char ¦  строка символов               ¦

    L==========¦======================¦================================-

Символы,  занимаюшие поле flags в строке формата, позволяют управлять размещением выводимой информации в пределах поля,  заданного  параметром  width, а также определяют способ вывода чисел со знаком. Так, знак минус (-) в этом случае  требует  выравнивания  печатаемых   символов  по левой границе поля width (по умолчанию производится выравнивание по правой границе), а знак плюс (+)  заставляет  выводить     со  знаком  (+  или -) как положительные, так и отрицательные числа.  Дополнительный флаг в виде знака номера (#) может использоваться для    вывода начального нуля в восьмеричном формате и пары  0x  или  0X  в    шестнадцатеричном  формате, а также для обязательной печати десятичной точки при выводе вещественных чисел даже  при  нулевом  значении  поля precision.  Параметр  width является целым положительным десятичным числом,  определяющим минимальное количество позиций, отводимых под соответствующий элемент данных в выходном потоке. Если количество символов в     выводимом значении меньше width, то  осуществляется  его  расширение   пробелами слева или справа в зависимости от значения поля flags. Для   замены пробелов на нули необходимо снабдить параметр width префиксом   нуль (0). При отсутствии этого параметра в строке формата он автоматически получает некоторое стандартное значение.          Целочисленный положительный параметр precision определяет минимальное  количество  печатаемых  цифр в записи целого числа (при использовании символов преобразования i, d, u, o, x или X), количество   цифр справа от десятичной точки при печати вещественных чисел  (преобразование по форматам f, e, E, g или G) или максимальное количество символов в строке (при выводе по формату s). В случае отсутствия,   этот  параметр заменяется некоторым стандартным значением, зависящим   от типа выводимого элемента данных.    Дополнительные спецификаторы h, l и L могут  быть  использованы    для задания длины выводимого аргумента (short или long).  Возвращаемое функцией fprintf значение равно количеству напечатанных символов.

Пример использования:

      #include  <stdio.h>

      #define  MAX  100

      main()

      { int    i;

        float  length[MAX], width[MAX];

        FILE   *printer;

        ..............................................................

        ..............................................................

        ..............................................................

        printer = fopen("prn", "w");

        fprintf(printer, "\t\t\t*** Результаты расчета ***\n\n");

        for (i = 0; i < MAX; i++)

           fprintf(printer, "%3d  length = %6.3f,  width = %6.3f\n",

                                                 length[i], width[i]);

        ..............................................................

        ..............................................................

        ..............................................................

      }

                               -------------

Имя функции и назначение: fseek - перемещает  указатель текущей    позиции файла

Формат и описание аргументов:

              int  fseek(stream, offset, origin)

              FILE  *stream;         /*  Указатель на открытый файл   */

              long  offset;          /*  Смещение в байтах от origin  */

              int   origin;          /*  Начальная позиция указателя  */

Эта  функция перемещает указатель, связанный с открытым файлом,   на offset байт вперед или назад относительного заданного  параметром    origin  начала отсчета. Последний может быть одной из следующих символических констант, определенных в файле stdio.h:

               SEEK_SET     -     начало файла

               SEEK_CUR     -     текущая позиция указателя

               SEEK_END     -     конец файла

Заметим, что допустимым является позиционирование указателя за пределами конца файла, однако его перемещение за начало файла приводит  к   ошибке.  Возвращаемое значение равно нулю при нормальном завершении операции и отлично от нуля в противном случае.

Пример использования:

                 #include  <stdio.h>

                 main()

                 { int   result;

                   FILE  *stream;

                   stream = fopen("data", "r");

                   .....................................

                   .....................................

                   .....................................

                   result = fseek(stream, 0L, SEEK_SET);

                   .....................................

                   .....................................

                   .....................................

                 }

                               -------------

Имя функции и назначение: rewind - устанавливает указатель  текущей позиции на начало файла

Формат и описание аргументов:

              void  rewind(stream)

              FILE  *stream;          /*  Указатель на открытый файл  */

Эта функция не возвращает никакого значения в точку вызова.

Пример использования:

               #include  <stdio.h>

               main()

               { int   dat_1 = 1, dat_2 = 7, dat_3, dat_4;

                 FILE  *stream;

                 stream = fopen("data", "w+");

                   /*      Запись данных в файл       */

                 fprintf(stream, "%d %d", dat_1, dat_2);

                   /*  Установка указателя на начало  */

                 rewind(stream);

                   /*        Считывание данных        */

                 fscanf(stream, "%d %d", &dat_3, &dat_4);

                 ........................................

                 ........................................

                 ........................................

               }

                               -------------

3.2. Операции ввода/вывода низкого уровня

Функции ввода/вывода низкого уровня осуществляют обмен с файлами или периферийными устройствами путем прямого обращения к соответствующим функциям операционной системы (системным вызовам).  Они  не  предоставляют  возможности буферизации информации при пересылке и не   обеспечивают преобразования данных из внутреннего  машинного  представления в текстовый формат.  Перед обращением к существующему файлу его необходимо предварительно  открыть при помощи функции open для ввода, вывода или выполнения обеих этих операций в текстовом  или  двоичном  режиме.  Новый   файл  может  быть  создан путем использования функции creat. Обе эти     функции возвращают  в  точку  вызова  целочисленный  параметр  (file    handle), который следует использовать для ссылки на открытый файл во   всех  последующих  операциях ввода/вывода низкого уровня или при управлении указателем текущей позиции. После завершения работы с  файлом,  его нужно закрыть путем вызова функции close. В противном случае это сделает операционная система по окончании работа программы.          Операции чтения и записи низкого уровня  выполняются  функциями  read и write соответственно начиная с текущей позиции указателя. Используя функцию lseek, указатель можно установить в произвольную позицию  файла перед выполнением очередной операции ввода/вывода. Проверка выхода за конец файла осуществляется функцией eof.  Предварительные описания функций  ввода/вывода  низкого  уровня     помещены в файл  io.h.  Кроме  этого,  файлы  fcntl.h, sys\types.h и   sys\stat.h содержат определения символических констант, используемых     отдельными  функциями. Для нормальной работы программы все эти файлы    необходимо включить в ее исходный текст при помощи директивы препроцессора #include (см. Лекцию 7, $ 4 и примеры программ).  Более полную информацию о  вводе/выводе  низкого  уровня  можно     найти в руководстве Language Reference, входящем в стандартный комплект поставки компилятора IBM C/2.

3.3. Управление файлами и каталогами

При  разработке  отдельных прикладных программ и тем более системного программного обеспечения могут оказаться  полезными  предоставляемые  операционной системой дополнительные возможности управления структурой каталогов и изменения имен существующих файлов. Соответствующие операции реализуются специальными функциями, входящими в  состав библиотеки языка Си, что позволяет избежать непосредственного   обращения к системным функциям ОС. В этом разделе приведены  краткие   сведения  о  некоторых функциях рассматриваемой группы. Их

предварительные описания помещены в стандартные  файлы  stdio.h  и  direct.h     (конкретно см. примеры использования отдельных функций), которые при     необходимости следует включить в исходный текст программы, используя     директиву препроцессора #include.

Имя функции и назначение: remove - удаляет файл с заданным именем

Формат и описание аргументов:

              int  remove(pathname)

              const char  *pathname; /*  Полное имя удаляемого файла  */

Возвращаемое значение равно нулю при нормальном завершении операции  и  -1  в случае отсутствия в каталоге файла с заданным именем  или запрете на его удаление (read-only file).

Пример использования:

                #include  <stdio.h>

                main()

                { int  result;

                  .......................................

                  .......................................

                  .......................................

                  result = remove("c:\\myfile");

                  if (result == -1)

                     printf("Ошибка при удалении файла");

                  .......................................

                  .......................................

                  .......................................

                }

                               -------------

Имя функции и назначение: rename - изменяет  имя  существующего   файла или каталога

Формат и описание аргументов:

              int  rename(oldname, newname)

              const char  *oldname;             /*  Старое имя файла  */

              const char  *newname;             /*  Новое имя файла   */

Эта функция, переименовывающая существующие файлы  и  каталоги,  позволяет также перемещать отдельные файлы из одного каталога в другой  путем изменения их полных имен. В то же время, операции перемещения файлов между различными устройствами и целых каталогов не  являются допустимыми. Возвращаемое значение равно нулю при нормальном завершении операции  и отлично от нуля в случае возникновения ошибки (неверное задание имени файла oldname, существование файла с именем newname  или     отсутствие  возможности создать файл с таким именем, попытка перемещения отдельных файлов с одного устройства на другое и т. д.).

Пример использования:

          #include  <stdio.h>

          main()

          { int  result;

            .....................................................

            .....................................................

            .....................................................

            result = rename("c:\\programs\myprog", "c:\\myprog");

            .....................................................

            .....................................................

            .....................................................

          }

                               -------------

Имя функции и назначение: chdir - изменяет текущий каталог

Формат и описание аргументов:

              int  chdir(pathname)

              char  *pathname;      /*  Имя нового текущего каталога  */

Возвращаемое значение равно нулю при нормальном изменении текущего каталога и -1 в случае возникновения ошибки.

Пример использования:

                           #include  <direct.h>

                           main()

                           { ................

                             ................

                             ................

                             chdir("..\\..");

                             ................

                             ................

                             ................

                           }

                               -------------

Имя функции и назначение: mkdir - создает новый каталог

Формат и описание аргументов:

              int  mkdir(pathname)

              char  *pathname;         /*  Имя создаваемого каталога  */

Возвращаемое значение равно нулю при нормальном завершении операции и -1 в противном случае.

Пример использования:

                     #include  <direct.h>

                     main()

                     { int  result;

                       .............................

                       .............................

                       result = mkdir("b:\\newdir");

                       .............................

                       .............................

                     }

                               -------------

Имя функции и назначение: rmdir - удаляет существующий каталог

Формат и описание аргументов:

              int  rmdir(pathname)

              char  *pathname;           /*  Имя удаляемого каталога  */

Удаляемый  этой  функцией каталог должен быть пустым и не может   являться текущим или корневым каталогом.   Возвращаемое значение равно нулю при нормальном завершении операции и -1 в случае возникновения ошибки.

$ 4. ВНЕШНИЕ УСТРОЙСТВА КАК СПЕЦИАЛЬНЫЕ ФАЙЛЫ. ОРГАНИЗАЦИЯ

ОБМЕНА СО СТАНДАРТНЫМИ ВНЕШНИМИ УСТРОЙСТВАМИ

В  операционной  среде  MS  DOS всевозможные внешние устройства     последовательного доступа (терминалы, устройства печати,  графопостроители  и т. д.) рассматриваются как специальные файлы. Это обстоятельство играет чрезвычайно важную роль с точки зрения гибкого и эффективного управления этими устройствами и общей технологии  организации  ввода/вывода.  Действительно, для того, чтобы передать данные   на какое-либо внешнее устройство, достаточно записать их в некоторый     стандартный файл, используя, например, обычные функции  ввода/вывода   потоком  символов. При этом нет необходимости знать в деталях технические характеристики этого устройства, ибо все они известны  операционной системе, в состав которой входят соответствующие программные   драйверы.  Связь имен специальных файлов с конкретными внешними устройствами обычно устанавливается на уровне базовой системы ввода/вывода (BIOS).  Запуская в работу какую-либо программу, операционная система MS  DOS автоматически открывает пять стандартных файлов, ориентированных

    на выполнение операций ввода/вывода потоком. Эти файлы имеют предопределенные имена и характерные режимы доступа, приведенные в следующей таблице.

     г=============T=================================T=================¬

     ¦  Имя файла  ¦           Устройство            ¦  Режим доступа  ¦

     ¦=============+=================================+=================¦

     ¦   stdin     ¦  стандартное устройство ввода   ¦     чтение      ¦

     ¦             ¦  (обычно клавиатура терминала)  ¦                 ¦

     ¦-------------+---------------------------------+-----------------¦

     ¦   stdout    ¦  стандартное устройство вывода  ¦     запись      ¦

     ¦             ¦  (обычно экран терминала)       ¦                 ¦

     ¦-------------+---------------------------------+-----------------¦

     ¦   stderr    ¦  стандартное устройство для со- ¦     запись      ¦

     ¦             ¦  общений об ошибках (обычно эк- ¦                 ¦

     ¦             ¦  ран терминала)                 ¦                 ¦

     ¦-------------+---------------------------------+-----------------¦

     ¦   stdaux    ¦  стандартное вспомогательное    ¦  чтение/запись  ¦

     ¦             ¦  устройство (обычно устройство, ¦                 ¦

     ¦             ¦  подключенное по последователь- ¦                 ¦

     ¦             ¦  ному интерфейсу COM1)          ¦                 ¦

     ¦-------------+---------------------------------+-----------------¦

     ¦   stdprn    ¦  стандартное устройство печати  ¦     запись      ¦

     L=============¦=================================¦=================-

Предопределенные  имена специальных файлов по существу являются   указателями на структуру FILE и их допустимо использовать  на  месте   параметра stream во всех функциях ввода/вывода потоком (см. $ 3 настоящей лекции). Так, например, для печати сообщения на экране терминала  достаточно  воспользоваться функцией fprintf, задав в качестве   ее первого парметра имя stdout:

           fprintf(stdout, "Это стандартное устройство вывода");

С другой стороны, ввод символа, поступившего от клавиатуры  терминала,  можно  выполнить при помощи функции fgetc, адресовав ее к стандартному устройству ввода stdin:

                            sym = fgetc(stdin);

Заметим, однако, что не все операции, определенные для  обычных   файлов, имеют смысл для стандартных устройст ввода/вывода. Например,   следующее обращение к функции fscanf

                      fscanf(stdout, "%d", &intval);

не является допустимым, ибо стандартное устройство вывода  не  может    быть использовано в качестве устройства ввода. Ошибочным также будет   обращение к функции fseek при любом указатели на специальный файл.   Для удобства работы со стандартными устройствами stdin и stdout   в  состав библиотеки языка Си дополнительно включены функции, специально ориентированные на обмен с этими  устройствами.  Их  имена  во   многом  схожи с именами рассмотренных в $ 3 функций ввода/вывода

потоком и приведены в следующей таблице.

    г===============T======================T===========================¬

    ¦  Имя функции  ¦      Назначение      ¦  Эквивалентное обращение  ¦

    ¦===============+======================+===========================¦

    ¦  getch()      ¦  читает  очередной   ¦                           ¦

    ¦               ¦  символ от клавиа-   ¦            нет            ¦

    ¦               ¦  туры терминала без  ¦                           ¦

    ¦               ¦  эха на экране       ¦                           ¦

    ¦---------------+----------------------+---------------------------¦

    ¦  fgetchar()   ¦  читают  очередной   ¦   fgetc(stdin)            ¦

    ¦  getchar()    ¦  символ со стандар-  ¦                           ¦

    ¦               ¦  тного  устройства   ¦                           ¦

    ¦               ¦  ввода               ¦                           ¦

    ¦---------------+----------------------+---------------------------¦

    ¦  fputchar(s)  ¦  записывают символ   ¦   fputc(s, stdout)        ¦

    ¦  putchar(s)   ¦  s  на стандартное   ¦                           ¦

    ¦               ¦  устройство вывода   ¦                           ¦

    ¦---------------+----------------------+---------------------------¦

    ¦  gets(str)    ¦  читает строку сим-  ¦   fgets(str, 256, stdin)  ¦

    ¦               ¦  волов str со стан-  ¦                           ¦

    ¦               ¦  дартного устройст-  ¦                           ¦

    ¦               ¦  ва ввода            ¦                           ¦

    ¦---------------+----------------------+---------------------------¦

    ¦  puts(str)    ¦  копирует  строку    ¦   fputs(str, stdout)      ¦

    ¦               ¦  символов str  на    ¦                           ¦

    ¦               ¦  стандартное  уст-   ¦                           ¦

    ¦               ¦  ройство вывода      ¦                           ¦

    ¦---------------+----------------------+---------------------------¦

    ¦  scanf(...)   ¦  читает форматиро-   ¦   fscanf(stdin, ...)      ¦

    ¦               ¦  ванные данные  со   ¦                           ¦

    ¦               ¦  стандартного уст-   ¦                           ¦

    ¦               ¦  ройства ввода       ¦                           ¦

    ¦---------------+----------------------+---------------------------¦

    ¦  printf(...)  ¦  записывает форма-   ¦   fprintf(stdout, ...)    ¦

    ¦               ¦  тированные данные   ¦                           ¦

    ¦               ¦  на стандартное ус-  ¦                           ¦

    ¦               ¦  тройство вывода     ¦                           ¦

    L===============¦======================¦===========================-

Каждая  из  упомянутых здесь функций семантически подобна соответствующей ей общей функции и имеет те же самые аргументы, исключая   указатель на структуру FILE. Их предварительные описания также помещены в файл stdio.h (кроме описания функции getch(),  которое  находится в файле conio.h).

$ 5. ОПЕРАЦИИ ВВОДА/ВЫВОДА ЧЕРЕЗ ПОРТЫ МИКРОПРОЦЕССОРОВ

Intel 8086/80286

Все  периферийные устройства и внешняя память подключены к системной шине микро-ЭВМ через специальные интерфейсы. Каждый такой интерфейс имеет набор встроенных регистров,  называемых  портами  ввода/вывода, через которые центральный процессор и память взаимодействуют с соответствующими внешними устройствами. Одни порты предназначены  для  буферирования  данных  и называются буферными портами или     портами данных. Другие служат для хранения  информации  о  состоянии    устройства или интерфейса и носят название портов состояния. Третьи,   называемые  портами управления, используются для получения команд от   центрального процессора.

         В некоторых компьютерах адреса памяти и портов включены в  единое  адресное пространство и все команды с обращением к памяти могут   обращаться и к портам. В системах же построенных на  базе  микропроцессоров  Intel  8086/80286  допускается  организация  двух адресных  пространств: памяти и ввода/вывода. В этом случае всякий порт  снабжается индивидуальным номером, однозначно идентифицирующим его среди     всего множества выходных портов.   Стандартная  библиотека компилятора IBM C/2 предоставляет пользователям две функции с именами inp() и outp(), осуществляющие  

прямой  обмен информацией с портами микропроцессора. Возможность выполнения операций ввода/вывода столь низкого уровня необходима при разработке программных драйверов устройств, однако она может  оказаться  полезной и при подготовке прикладных программ, требующих взаимодействия с периферийным оборудованием в реальном масштабе времени. Предварительные описания функций inp() и outp() помещены в файл conio.h.

Имя функции и назначение: inp - читает один информационный байт  через входной порт с заданным номером

Формат и описание аргументов:

              int  inp(port)

              unsigned  port;          /*  Номер опрашиваемого порта  */

Пример использования:

          #include  <conio.h>

          main()

          { char      result;

            unsigned  port = 0x64;

            result = inp(port);

            printf("Содержимое порта 64H равно %0x\n", (int)result);

          }

Имя функции и назначение: outp - записывает один информационный   байт в выходной порт с заданным номером

Формат и описание аргументов:

              int  outp(port, value)

              unsigned  port;              /*  Номер выходного порта  */

              int       value;             /*  Выводимое значение     */

Возвращаемое функцией outp значение равно параметру value.

Пример использования:

                         #include  <conio.h>

                         main()

                         { unsigned  port = 0x64;

                           outp(port, 0x03);

                         }


 

А также другие работы, которые могут Вас заинтересовать

47543. Методические указания. Менеджмент 102.5 KB
  Управление персоналом : учебное пособие Н. Психология делового общения : учебное пособие Г. Психология конфликта : учебное пособие Н. Деловое общение : учебное пособие сост.
47545. Методические рекомендации.Организация обслуживания в общественном питании 500.5 KB
  Характеристика проектируемого предприятия Составление меню проектируемого предприятия Сервисная деятельность предприятия Маркетинговая деятельность предприятия
47548. ДЕРЖАВНА АТЕСТАЦІЯ ВИПУСКНИКІВ 282.5 KB
  Для бакалаврів надані рекомендації щодо виконання випускної атестаційної роботи державний іспит та кваліфікаційної дипломної роботи надана інформація щодо майбутнього вступу до магістратури. Структура та зміст дипломної роботи. Порядок захисту дипломної роботи. Критерії оцінки дипломної роботи.
47549. Методические рекомендации. Международные отношения 1.11 MB
  В пособии даны рекомендации необходимые студентам при прохождении производственной и преддипломной практик написания отчетов по практикам а также для обобщения и анализа собранных материалов и написания дипломной работы. Целью проведения преддипломной практики является закрепление навыков полученных в период производственной практики а также сбор анализ и обобщение материалов для написания дипломной работы. Перед студентами в период прохождения практики ставятся следующие задачи: – изучение структуры организации в которую...
47550. Финансы и кредит. Методические указания 437 KB
  Выбор темы дипломной работы Формулировка названия дипломной работы План дипломной работы Последовательность оформления дипломной работы и подготовка к ее защите