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




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


Составьте программу, которая строит график функции sin(x) на отрезке от 0 до 2*пи. Учтите такие вещи: соседние точки графика следует соединять отрезком прямой, чтобы график выглядел непрерывным; не забывайте приводить double к int, т.к. координаты пикселов - целые числа.

Напишите функцию, которая заполняет в массиве байт count бит подряд, начиная с x-ого бита от левого края массива:

байт 0 | байт 1 7 6 5 4 3 2 1 0 | 7 6 5 4 3 2 1 0 : биты в байте

0 1 2 3 4 5 6 7 | 8 9 10 11 12 13 14 15 : x

========================== x=2, count=11

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

Ответ (причем мы заполняем биты не просто единицами, а "узором" pattern):

void horizLine(char *addr,int x,int count,char pattern){ static char masks[8] = { 0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01 }; /* индекс в этом массиве равен числу 0-битов слева */ register i; char mask; short lbits, rbits; /* число битов слева и справа */ short onebyte; /* единственный байт ? */ addr += x/8; /* в байте 8 бит */ mask = masks[ lbits = x & 7 ]; /* x % 8 */ if( count >= (rbits = 8 - lbits)){ count -= rbits; onebyte = 0; }else{ mask &= ~masks[ lbits = (x+count) & 7 ]; onebyte = 1; } /* Первый байт */ *addr = (*addr & ~mask) | (pattern & mask); addr++; /* Для pattern==0xFF можно просто * *addr++ |= mask; * поскольку (a &~m)|(0xFF & m) = (a &~m) | m = * (a|m) & (~m|m) = (a|m) & 0xFF = a | m * Почему здесь нельзя написать *addr++ = (*addr...) ? * Потому, что ++ может быть сделан ДО вычисления * правой части присваивания! */ if(onebyte) return; /* Средние байты */ for(i = count/8; i > 0; --i) *addr++ = pattern; /* mask==0xFF */ /* Последний байт */ if((lbits = count & 7) == 0) return; /* последний байт был полным */ mask = ~masks[lbits]; *addr = (*addr & ~mask) | (pattern & mask); }

Заметим, что для быстродействия подобные алгоритмы обычно пишутся на ассемблере.




Содержание  Назад  Вперед