Главная · Поиск книг · Поступления книг · Top 40 · Форумы · Ссылки · Читатели

Настройка текста
Перенос строк


    Прохождения игр    
Demon's Souls |#13| Storm King
Demon's Souls |#12| Old Monk & Old Hero
Demon's Souls |#11| Мaneater part 2
Demon's Souls |#10| Мaneater (part 1)

Другие игры...


liveinternet.ru: показано число просмотров за 24 часа, посетителей за 24 часа и за сегодня
Rambler's Top100
Образование - Керниган, Ричи Весь текст 454.51 Kb

Язык Си

Предыдущая страница Следующая страница
1 ... 20 21 22 23 24 25 26  27 28 29 30 31 32 33 ... 39
качестве своего значения она возвращает число правильно сов-
падающих и присвоенных элементов ввода. Это число может быть

использовано для определения количества найденных элементов
ввода. при выходе на конец файла возвращается EOF; подчерк-
нем, что это значение отлично от 0, что следующий вводимый
символ не удовлетворяет первой спецификации в управляющей
строке. При следующем обращении к SCANF поиск возобновляется
непосредственно за последним введенным символом.
    Заключительное предостережение: аргументы функции SCANF
должны быть указателями. Несомненно наиболее распространен-
ная ошибка состоит в написании

 SCANF("%D", N);

вместо

 SCANF("%D", &N);

     7.5. Форматное преобразование в памяти

    От функции SCANF и PRINTF происходят функции SSCANF и
SPRINTF, которые осуществляют аналогичные преобразования, но
оперируют со строкой, а не с файлом. Обращения к этим функ-
циям имеют вид:

 SPRINTF(STRING, CONTROL, ARG1, ARG2, ...)
 SSCANF(STRING, CONTROL, ARG1, ARG2, ...)

Как и раньше , функция SPRINTF преобразует свои аргументы
ARG1, ARG2 и т.д. В соответствии с форматом, указанным в
CONTROL, но помещает результаты в STRING, а не в стандартный
вывод. KОнечно, строка STRING должна быть достаточно велика,
чтобы принять результат. Например, если NAME - это символь-
ный массив, а N - целое, то

SPRINTF(NAME, "TEMP%D", N);

создает в NAME строку вида TEMPNNN, где NNN - значение N.
    Функция SSCANF выполняет обратные преобразования - она
просматривает строку STRING в соответствии с форматом в ар-
гументе CONTROL и помещает результирующие значения в аргу-
менты ARG1, ARG2 и т.д.эти аргументы должны быть указателя-
ми. В результате обращения

SSCANF(NAME, "TEMP%D", &N);

переменная N получает значение строки цифр, следующих за
TEMP в NAME.

    Упражнение 7-2
    --------------
    Перепишите настольный калькулятор из главы 4, используя
для ввода и преобразования чисел SCANF и/или SSCANF.

     7.6. Доступ к файлам

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

CAT X.C.Y.C

печатает содержимое файлов X.C и Y.C в стандартный вывод.
    Вопрос состоит в том, как организовать чтение из имено-
ванных файлов, т.е., как связать внешние имена, которыми
мыслит пользователь, с фактически читающими данные операто-
рами.

    Эти правила просты. Прежде чем можно считывать из неко-
торого файла или записывать в него, этот файл должен быть
открыт с помощью функции FOPEN из стандартной библиотеки.
функция FOPEN берет внешнее имя (подобное X.C или Y.C), про-
водит некоторые обслуживающие действия и переговоры с опера-
ционной системой (детали которых не должны нас касаться) и
возвращает внутреннее имя, которое должно использоваться при
последующих чтениях из файла или записях в него.
    Это внутреннее имя, называемое "указателем файла", фак-
тически является указателем структуры, которая содержит ин-
формацию о файле, такую как место размещения буфера, текущая
позиция символа в буфере, происходит ли чтение из файла или
запись в него и тому подобное. Пользователи не обязаны знать
эти детали, потому что среди определений для стандартного
ввода-вывода, получаемых из файла STDIO.H, содержится опре-
деление структуры с именем FILE. Единственное необходимое
для указателя файла описание демонстрируется примером:

        FILE *FOPEN(), *FP;

    Здесь говорится, что FP является указателем на FILE и
FOPEN возвращает указатель на FILE. Oбратите внимание, что
FILE является именем типа, подобным INT, а не ярлыку струк-
туры; это реализовано как TYPEDEF. (Подробности того, как
все это работает на системе UNIX, приведены в главе 8).
    Фактическое обращение к функции FOPEN в программе имеет
вид:
       FP=FOPEN(NAME,MODE);

  Первым аргументом функции FOPEN является "имя" файла, кото-
рое задается в виде символьной строки. Второй аргумент MODE
("режим") также является символьной строкой, которая указы-
вает, как этот файл будет использоваться. Допустимыми режи-
мами являются: чтение ("R"), запись ("W") и добавление
("A").
 Если вы откроете файл, который еще не сущетвует, для за-
 писи или добавления, то такой файл будет создан (если это
возможно). Открытие существующего файла на запись приводит к
отбрасыванию его старого содержимого. Попытка чтения несу-
ществующего файла является ощибкой. Ошибки могут быть обус-
 ловлены и другими причинами (например, попыткой чтения из
 файла, не имея на то разрешения). При наличии какой-либо
 ошибки функция возвращает нулевое значение указателя NULL
(которое для удобства также определяется в файле STDIO.H).
  Другой необходимой вещью является способ чтения или за-
писи, если файл уже открыт. Здесь имеется несколько возмож-
ностей, из которых GETC и PUTC являются простейшими.функция
GETC возвращает следующий символ из файла; ей необходим ука-
затель файла, чтобы знать, из какого файла читать. Таким об-
                          разом,

            C=GETC(FP)

помещает в "C" следующий символ из файла, указанного посред-
ством FP, и EOF, если достигнут конец файла.
    Функция PUTC, являющаяся обращением к функции GETC,

           PUTC(C,FP)

помещает символ "C" в файл FP и возвращает "C". Подобно фун-
кциям GETCHAR и PUTCHAR, GETC и PUTC могут быть макросами, а
не функциями.
    При запуске программы автоматически открываются три фай-
ла, которые снабжены определенными указателями файлов. Этими
файлами являются стандартный ввод, стандартный вывод и стан-
дартный вывод ошибок; соответствующие указатели файлов назы-
ваются STDIN, STDOUT и STDERR. Обычно все эти указатели свя-
заны с терминалом, но STDIN и STDOUT могут быть перенаправ-
лены на файлы или в поток (PIPE), как описывалось в разделе
7.2.
    Функции GETCHAR и PUTCHAR могут быть определены в терми-
налах GETC, PUTC, STDIN и STDOUT следующим образом:
#DEFINE GETCHAR() GETC(STDIN) #DEFINE PUTCHAR(C)  PUTC(C,
STDOUT)
При работе с файлами для форматного ввода и вывода можно ис-
пользовать функции FSCANF и FPRINTF. Они идентичны функциям
SCANF и PRINTF, за исключением того, что первым аргументом
является указатель файла, определяющий тот файл, который бу-
дет читаться или куда будет вестись запись; управляющая
строка будет вторым аргументом.

    Покончив с предварительными замечаниями, мы теперь в
состоянии написать программу CAT для конкатенации файлов.
Используемая здесь основная схема оказывается удобной во
многих программах: если имеются аргументы в командной стро-
ке, то они обрабатываются последовательно. Если такие аргу-
менты отсутствуют, то обрабатывается стандартный ввод. Это
позволяет использовать программу как самостоятельно, так и
как часть большей задачи.

  #INCLUDE
  MAIN(ARGC, ARGV)   /*CAT: CONCATENATE FILES*/
  INT ARGC;
  CHAR *ARGV[];
  \(
 FILE *FP, *FOPEN();
 IF(ARGC==1) /*NO ARGS; COPY STANDARD INPUT*/
 FILECOPY(STDIN);
 ELSE
 WHILE (--ARGC > 0)
      IF ((FP=FOPEN(*++ARGV,"R"))==NULL) \(
         PRINTF("CAT:CAN'T OPEN %\N",*ARGV);
         BREAK;
      \) ELSE \(
         FILECOPY(FP);
         FCLOSE(FP);
      \)
  \)
   FILECOPY(FP)  /*COPY FILE FP TO STANDARD OUTPUT*/
   FILE *FP;
   \(
  INT C;
  WHILE ((C=GETC(FP)) !=EOF)
  PUTC(C, STDOUT);
   \)

Указатели файлов STDIN и STDOUT заранее определены в библио-
теке ввода-вывода как стандартный ввод и стандартный вывод;
они могут быть использованы в любом месте, где можно исполь-
зовать объект типа FILE*.они однако являются константами, а
не переменными, так что не пытайтесь им что-либо присваи-
вать.
    Функция FCLOSE является обратной по отношению к FOPEN;
она разрывает связь между указателем файла и внешним именем,
установленную функцией FOPEN, и высвобождает указатель файла
для другого файла.большинство операционных систем имеют не-
которые ограничения на число одновременно открытых файлов,
которыми может распоряжаться программа. Поэтому, то как мы
поступили в CAT, освободив не нужные нам более объекты, яв-
ляется хорошей идеей. Имеется и другая причина для примене-
ния функции FCLOSE к выходному файлу - она вызывает выдачу
информации из буфера, в котором PUTC собирает вывод. (При
нормальном завершении работы программы функция FCLOSE вызы-
вается автоматически для каждого открытого файла).

     7.7. Обработка ошибок - STDERR и EXIT

    Обработка ошибок в CAT неидеальна. Неудобство заключает-
ся в том, что если один из файлов по некоторой причине ока-
зывается недоступным, диагностическое сообщение об этом пе-
чатается в конце объединенного вывода. Это приемлемо, если
вывод поступает на терминал, но не годится, если вывод пос-
тупает в некоторый файл или через поточный (PIPELINE) меха-
низм в другую программу.
    Чтобы лучше обрабатывать такую ситуацию, к программе
точно таким же образом, как STDIN и STDOUT, присоединяется
второй выходной файл, называемый STDERR. Если это вообще
возможно, вывод, записанный в файле STDERR, появляется на
терминале пользователя, даже если стандартный вывод направ-
ляется в другое место.
    Давайте переделаем программу CAT таким образом, чтобы
сообщения об ошибках писались в стандартный файл ошибок.

   "INCLUDE
   MAIN(ARGC,ARGV)  /*CAT: CONCATENATE FILES*/
   INT ARGC;
   CHAR *ARGV[];
   \(
  FILE *FP, *FOPEN();
  IF(ARGC==1)  /*NO ARGS; COPY STANDARD INPUT*/
  FILECOPY(STDIN);
  ELSE
  WHILE (--ARGC > 0)
     IF((FP=FOPEN(*++ARGV,"R#))==NULL) \(
     PRINTF(STDERR,
       "CAT: CAN'T OPEN,%S\N", ARGV);
     EXIT(1);
  \) ELSE \(
     FILECOPY(FP);
  \)
  EXIT(0);
   \)

Программа сообщает об ошибках двумя способами. Диагностичес-
кое сообщение, выдаваемое функцией FPRINTF, поступает в
STDERR и, таким образом, оказывается на терминале пользова-
теля, а не исчезает в потоке (PIPELINE) или в выходном фай-
ле.
    Программа также использует функцию EXIT из стандартной
библиотеки, обращение к которой вызывает завершение выполне-
ния программы. Аргумент функции EXIT доступен любой програм-
ме, обращающейся к данной функции, так что успешное или неу-
дачное завершение данной программы может быть проверено дру-
гой программой, использующей эту в качестве подзадачи. По
соглашению величина 0 в качетсве возвращаемого значения сви-
детельствует о том, что все в порядке, а различные ненулевые
значения являются признаками нормальных ситуаций.

    Функция EXIT вызывает функцию FCLOSE для каждого откры-
того выходного файла, с тем чтобы вывести всю помещенную в
буферы выходную информацию, а затем вызывает функцию _EXIT.
Функция _EXIT приводит к немедленному завершению без очистки
каких-либо буферов; конечно, при желании к этой функции мож-
но обратиться непосредственно.

     7.8. Ввод и вывод строк

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

FGETS(LINE, MAXLINE, FP)

следующая строка ввода (включая символ новой строки) считы-
вается из файла FP в символьный массив LINE; самое большое
MAXLINE_1 символ будет прочитан. Результирующая строка за-
канчивается символом \ 0. Нормально функция FGETS возвращает
LINE; в конце файла она возвращает NULL. (Наша функция
GETLINE возвращает длину строки, а при выходе на конец файла
Предыдущая страница Следующая страница
1 ... 20 21 22 23 24 25 26  27 28 29 30 31 32 33 ... 39
Ваша оценка:
Комментарий:
  Подпись:
(Чтобы комментарии всегда подписывались Вашим именем, можете зарегистрироваться в Клубе читателей)
  Сайт:
 
Комментарии (1)

Реклама