Хрестоматия по программированию на Си в Unix


Работа с файлами. Хрестоматия по программированию на Си в Unix - стр. 6


RWptr += прочитанное_или_записанное_число_байт;

При открытии файла указатель стоит на начале файла: RWptr=0. При записи файл если надо автоматически увеличивает свой размер. При чтении - если мы достигнем конца файла, то read будет возвращать "прочитано 0 байт" (т.е. при чтении указатель чтения не может стать больше размера файла).

  • Аргумент сколькоБайт имеет тип unsigned, а не просто int:

    int n = read (int fd, char *адрес, unsigned сколькоБайт); int n = write(int fd, char *адрес, unsigned сколькоБайт);

    Приведем упрощенные схемы логики этих сисвызовов, когда они работают с обычным дисковым файлом (в UNIX устройства тоже выглядят для программ как файлы, но иногда с особыми свойствами):

  • m = write(fd, addr, n);

    если( ФАЙЛ[fd] не открыт на запись) то вернуть (-1); если(n == 0) то вернуть 0; если( ФАЙЛ[fd] открыт на запись с флагом O_APPEND ) то RWptr = длина_файла; /* т.е. встать на конец файла */ если( RWptr > длина_файла ) то заполнить нулями байты файла в интервале ФАЙЛ[fd][ длина_файла..RWptr-1 ] = '\0'; скопировать байты из памяти процесса в файл ФАЙЛ[fd][ RWptr..RWptr+n-1 ] = addr[ 0..n-1 ]; отводя на диске новые блоки, если надо RWptr += n; если( RWptr > длина_файла ) то длина_файла = RWptr; вернуть n;

    m = read(fd, addr, n);

    если( ФАЙЛ[fd] не открыт на чтение) то вернуть (-1); если( RWptr >= длина_файла ) то вернуть 0; m = MIN( n, длина_файла - RWptr ); скопировать байты из файла в память процесса addr[ 0..m-1 ] = ФАЙЛ[fd][ RWptr..RWptr+m-1 ]; RWptr += m; вернуть m;

    Найдите ошибки в фрагменте программы:

    #define STDOUT 1 /* дескриптор стандартного вывода */ int i; static char s[20] = "hi\n"; char c = '\n'; struct a{ int x,y; char ss[5]; } po; scanf( "%d%d%d%s%s", i, po.x, po.y, s, po.ss); write( STDOUT, s, strlen(s)); write( STDOUT, c, 1 ); /* записать 1 байт */

    Ответ: в функции scanf перед аргументом i должна стоять операция "адрес", то есть &i. Аналогично про &po.x и &po.y. Заметим, что s - это массив, т.е. s и так есть адрес, поэтому перед s операция & не нужна; аналогично про po.ss - здесь & не требуется.

    В системном вызове write второй аргумент должен быть адресом данного, которое мы хотим записать в файл. Поэтому мы должны были написать &c (во втором вызове write).

    Ошибка в scanf - указание значения переменной вместо ее адреса - является довольно распространенной и не может быть обнаружена компилятором (даже при использовании прототипа функции scanf(char *fmt, ...), так как scanf - функция с переменным числом аргументов заранее не определенных типов). Приходится полагаться исключительно на собственную внимательность!




    - Начало -  - Назад -  - Вперед -



    Книжный магазин