Стандартная библиотека libc

advertisement
Стандартная библиотека libc
Введение: что такое библиотека?
Библиотека – набор объектных файлов объединенных в один
файл
Заголовки используемых функций включаются в программу с
помощью директивы #include
Когда программа использует библиотечную функцию,
компоновщик находит ее и добавляет в программу
Подключение библиотеки
gcc prog.c −lm
−lm – ключ транслятора (−l) и «короткое имя» библиотеки: (m)
полное имя – libm.a, а короткое строится по правилам:
lib + короткое имя + {.a или .so}
можно подключить библиотеку указав полный путь:
cc prog.c /usr/lib/libm.a
Обзор стандартной библиотеки C
Стандартная библиотека C (libc) имеет 24 заголовочных файла
файл
<assert.h>
<ctype.h>
<errno.h>
<float.h>
<limits.h>
<locate.h>
<math.h>
<setjmp.h>
<signal.h>
<stdarg.h>
<stddef.h>
<stdio.h>
<stdlib.h>
<string.h>
<time.h>
описание
определяет макрос assert() – проверка условия
функции классификации символов
идентификация ошибок и сообщения об ошибках
параметры типов с плавающей точкой
параметры переменных целых типов
функции связанные с локализацией
элементарные математические функции
нелокальные (дальние) переходы
обработка сигналов
функции с произвольным числом аргументов
часто используемые константы и типы данных
система ввода/вывода
функции общего назначения
функции обработки строк (C-strings)
работа с временем и датой
Библиотека файлового ввода-вывода (file IO)
Порядок работы с файлами
1
Файл «открывается»: создаётся универсальное устройство
ввода-вывода называемое поток (stream)
2
Производится обмен информацией между программой и файлом:
с точки зрения программы происходит чтение данных из потока
(или запись в поток)
3
Файл «закрывается»; при нормальном завершении программы
main() (или exit()) все открытые файлы закрываются; при
аварийном завершении (или вызове abort()) файлы не
закрываются и информация может быть потеряна
В языке С файлом может быть все что угодно, начиная с дискового
файла и заканчивая терминалом или принтером.
Потоки
Бинарный поток – поток данных «как есть», без изменений
Текстовой поток – поток символов собранных в «строки»
(”\n“ в конце строки); в текстовом потоке может происходить
преобразование некоторых символов
При работе с файлами используют указатель на структуру типа FILE
Указатель на файл
#include <stdio.h>
FILE * fp;
Структура FILE содержит информацию как о файле так и о
связанном с ним потоке
Внимание
Пользуйтесь только указателями
Никогда ничего не меняйте в этой структуре
Стандартные потоки (создаются автоматически):
extern FILE * stdin;
extern FILE * stdout;
extern FILE * stderr;
Text terminal
Display
Keyboard
std
out
stderr
n
stdi
Program
Концепция буферизации
Небуферизованный поток – запись/чтение производится
символ за символом
Построчная буферизация – запись/чтение в буфер, передача
из буфера по приходу символа перевода строки
Полная буферизация – запись/чтение в файл тогда, когда
буфер полностью заполнен; размер буфера выбирается исходя из
задачи
Стандартные потоки:
stdin – всегда буферизован
stderr – всегда небуферизован
stdout – поток буферизован построчно если вывод на терминал,
иначе полная буферизация
Открытие файла: fopen()
прототип функции определен в <stdio.h>:
FILE * fopen(const char* fname, const char* mode);
открывает файл, имя которого задается параметром fname и
связывает с ним поток
параметр mode задает режим в котором файл будет открыт:
mode действие
r
открыть текстовый файл для чтения
w
создать текстовый файл для записи, а если файл уже
существует переписать
a
+
дописать в конец текстового файла
открыть файл для обновления (для чтения и записи);
ставится после r,w,a
создать бинарный поток;
ставится после r,w,a или r+,w+,a+
b
Закрытие файла: fclose()
Прототип функции:
int fclose(FILE * fp);
fclose() закрывает поток; fp – указатель полученный от ранее
вызванного fopen()
все данные из буфера записываются в файл
в случае успеха возвращает ноль
при ошибке возвращает EOF (end-of-file); причину ошибки можно
выяснить с помощью функции ferror()
Внимание
Рекомендуется вызывать fclose() в явном виде, так как количество
одновременно открытых файлов в системе ограниченно
Чтение-запись одного символа: getc(), putc()
Прототипы:
int getc(FILE* fp);
int putc(int ch, FILE* fp);
/* Чтение символа */
/* Запись символа */
fp – указатель полученный от fopen()
ch – записываемый символ (putc)
обе функции возвращают целое значение
считанного/записанного символа
в случае ошибки возвращают EOF
getc() возвращает EOF по достижению конца файла
(более точную информацию даст функция feof())
putchar(c) то же самое, что и putc(c,stdout)
getchar(c) то же самое, что и getc(stdin)
Пример: вывод содержимого файла на экран
начало . . .
#include <stdio.h>
#include <stdlib.h>
. . . продолжение
int main(int argc, char *argv[]) {
FILE *fp;
char ch;
if( argc != 2 ) {
printf("No file name.\n");
exit(1);
}
fp=fopen(argv[1], "r");
if( fp == NULL ) {
printf("Error open file\n");
exit(1);
}
ch = getc(fp);
while( ch != EOF ) {
putchar(ch);
ch = getc(fp);
}
fclose(fp);
}
return 0;
Проверка на ошибки
Внешняя переменная errno
#include <errno.h> /* define volatile int errno; */
Переменная errno содержит:
в начале работы программы ноль
если при вызове библиотечной функции произошла ошибка –
номер ошибки
Функция strerror()
#include <string.h>
char * strerror(int errno);
функция возвращает строку, содержащую системное сообщение
об ошибке, связанной со значением errno
Функция perror()
#include <stdio.h>
void perror(const char* str);
функция преобразует errno в строку и записывает её в stderr
str – дополнительное сообщение
printf(" initial value of errno = %d\n",errno);
double a = -1.2;
double b = sqrt(a);
if( errno != 0 ) {
printf(" after sqrt() errno = %d\n",errno);
printf(" strerror msg: %s\n",strerror(errno));
perror(" perror msg");
}
initial value of errno = 0
after sqrt() errno = 33
strerror msg: Numerical argument out of domain
perror msg: Numerical argument out of domain
Работа с ошибками ввода-вывода
int ferror(FILE * stream)
возвращает ненулевое значение (true) если в stream произошла
ошибка
Пример: if( ferror(fp) ) perror("Error in file");
int feof(FlLE * stream)
возвращает ненулевое значение (true) если дошли до конца
stream
void clearerr(FILE * stream)
обнуляет индикатор конца файла и индикатор ошибок для
потока stream
Функции ввода-вывода
Функции аналогичные функциям printf() и scanf():
Xформатный ввод-вывод в файл
int fprintf(FILE *stream, const char format, ...)
int fscanf(FILE *stream, const char format, ...)
Xформатный ввод-вывод в С-string
int sprintf(char *buf, const char *format, ...);
int sscanf(const char *buf, const char *format, ...);
Ввод-вывод блоков данных (неформатированный)
size_t fread(void *ptr, size_t size, size_t nobj, FILE *stream);
size_t fwrite(const void *ptr, size_t size, size_t nobj,
FILE *stream);
ptr – указатель на область памяти (например массив), которая
записывается (fwrite()) или считывается (fread()) из файла
nobj – число элементов в буфере
size – размер одного элемента в байтах
Обе функции возвращают количество прочитанных/записанных
элементов
size_t – беззнаковый целый тип (оператор sizeof возвращает
именно этот тип); применяется для задания размера объекта.
Печать: printf("%zu\n",sizeof(int) );
Пример: запись бинарных данных в файл
#include <stdio.h>
#include <stdlib.h>
int main(void) {
FILE *fp;
double d = 12.23;
int i = 101;
long l = 123023L;
if( (fp=fopen("test.dat", "wb+")) == NULL ) {
perror(" Error open file");
exit(1);
}
fwrite(&d, sizeof(double), 1, fp);
fwrite(&i, sizeof(int), 1, fp);
fwrite(&l, sizeof(long), 1, fp);
. . . и их последующее чтение.
rewind(fp); // rewind the ’fp’ back to its beginning
fread(&d, sizeof(double), 1, fp);
fread(&i, sizeof(int), 1, fp);
fread(&l, sizeof(long), 1, fp);
printf("%f %d %ld\n", d, i, l);
fclose(fp);
}
return 0;
Output:
12.230000 101 123023
Перенаправление потоков
stdout → файл:
B ./a.out > output.dat ⇒ вывод программы записать
в файл output.dat
B ./a.out >>output.dat ⇒ дописать в конец файла
файл → stdin
B ./a.out < input.dat ⇒ чтение из файла input.dat
чтение из файла input.dat и вывод в файл output.dat:
B ./a.out < input.dat > output.dat
stdout + stderr → файл
B ./a.out > output.dat 2 > &1
B ./a.out >& output.dat
# POSIX
# simplified non-POSIX
Конвейер (pipe)
B program1 | program2
вывод программы-1 перенаправляется на вход программы-2:
stdout(program1) → stdin(program2)
Цепочка: B Program1 | Program2 | Program3
stdout3
3
err
d
t
Text terminal s
Display
Keyboard
stderr2
std
err
1
Program 3
stdout2 ⇒ stdin3
Program 2
stdout1 ⇒ stdin2
Program 1
stdin1
Download