Упаковка последовательности нулей
В качестве примера рассмортим программу, которая упаковывает массив положительных вещественных чисел, " сворачивая" последовательности подряд идущих нулевых элементов. Формат упакованной последовательности следующий :
-последовательность ненулевых элементов кодируется целым счетчиком (типа int), за которым следуют сами элементы ;
-последовательность нулевых элементов кодируется отрицательным значением целого счетчика ;
-нулевое значение целого счетчика обозначает конец последовательности ;
-пример неупакованной и упакованной последовательностей : 2.2, 3.3, 4.4, 5.5, 0.0, 0.0, 0.0, 1.1, 2.2, 0.0, 0.0, 4.4 и 4, 2.2, 3.3, 4.4, 5.5, -3, 2, 1.1, 2.2, -2, 1, 4.4, 0
В процессе упаковки требуется подсчитывать количество подряд идущих нулей. При этом в выходной последовательности запоминается место расположения последнего счетчика - также в виде указателя. Смена счетчика происходит, если текущий и предыдущий элементы относятся к разным последовательностям (комбинации " нулевой - ненулевой" и наоборот).
//------------------------------------------------------bk44-01.cpp
void pack(int *p, double v[], int n)
{
int *pcnt=p++; // Указатель на последний счетчик
*pcnt=0;
for (int i=0; i<n; i++)
{ // Смена счетчика
if (i!=0 && (v[i]==0 && v[i-1]!=0) ||
v[i]!=0 && v[i-1]==0))
{ pcnt=p++; *pcnt=0; }
if (v[i]==0)
(*pcnt)--; // -1 к счетчику нулевых
else
{
(*pcnt)++ ; // +1 к счетчику ненулевых
*((double*)p)++ = v[i];
}
}
*p++ = 0;
}
Функция распаковки не в пример проще :
//------------------------------------------------------bk44-02.cpp
int unpack(int *p, double v[])
{ int i=0,cnt;
while ((cnt = *p++)!=0) // Пока нет нулевого счетчика
{
if (cnt< 0) // Последовательность нулей
while(cnt++!=0)
v[i++]=0;
else // Ненулевые элементы
while(cnt--!=0) // извлечь с преобразованием
v[i++]=*((double*)p)++;
} // типа указателя
}