我遇到了一个问题,同时实现一个循环缓冲区,必须偶尔对齐。连接阵列
说我有两个阵列,leftArr
和rightArr
。我想将右边的数组移动到byteArr
,将左边的数组移动到byteArr
+右边数组的长度。 leftArr
和rightArr
都大于byteArr
,并且rightArr
大于leftArr
。 (这与rotating a circular buffer并不完全相同,因为左侧阵列不需要从byteArr
开始)。虽然左右阵列不重叠,但存储在byteArr
处的组合阵列可与当前阵列重叠,存储在leftArr
和rightArr
。从byteArr
到rightArr + rightArrLen
的所有内存都可以安全地写入。一个可能的实现是:
void align(char* byteArr, char* leftArr, int leftArrLen, char* rightArr, int rightArrLen) {
char *t = malloc(rightArrLen + leftArrLen);
// form concatenated data
memcpy(t, right, rightArrLen);
memcpy(t + rightArrLen, left, leftArrLen);
// now replace
memcpy(byteArr, t, rightArrLen + leftArrLen);
free(t);
}
但是,我必须完成这与恒定的内存复杂性。
我有什么到目前为止是这样的:
void align(char* byteArr, char* leftArr, int leftArrLen, char* rightArr, int rightArrLen)
{
// first I check to see if some combination of memmove and memcpy will suffice, if not:
unsigned int lStart = leftArr - byteArr;
unsigned int lEnd = lStart + leftArrLen;
unsigned int rStart = rightArr - byteArr;
unsigned int rEnd = rStart + rightArrLen;
unsigned int lShift = rEnd - rStart - lStart;
unsigned int rShift = -rStart;
char temp1;
char temp2;
unsigned int nextIndex;
bool alreadyMoved;
// move the right array
for(unsigned int i = 0; i < rEnd - rStart; i++)
{
alreadyMoved = false;
for(unsigned int j = i; j < rEnd - rStart; j-= rShift)
{
if( lStart <= j + rStart - lShift
&& j + rStart - lShift < lEnd
&& lStart <= (j + rStart) % lShift
&& (j + rStart) % lShift < lEnd
&& (j + rStart) % lShift < i)
{
alreadyMoved = true;
}
}
if(alreadyMoved)
{
// byte has already been moved
continue;
}
nextIndex = i - rShift;
temp1 = byteArr[nextIndex];
while(rStart <= nextIndex && nextIndex < rEnd)
{
nextIndex += rShift;
temp2 = byteArr[nextIndex];
byteArr[nextIndex] = temp1;
temp1 = temp2;
while(lStart <= nextIndex && nextIndex < lEnd)
{
nextIndex += lShift;
temp2 = byteArr[nextIndex];
byteArr[nextIndex] = temp1;
temp1 = temp2;
}
if(nextIndex <= i - rShift)
{
// byte has already been moved
break;
}
}
}
// move the left array
for(unsigned int i = lStart; i < lShift && i < lEnd; i++)
{
if(i >= rEnd - rStart)
{
nextIndex = i + lShift;
temp1 = byteArr[nextIndex];
byteArr[nextIndex] = byteArr[i];
while(nextIndex < lEnd)
{
nextIndex += lShift;
temp2 = byteArr[nextIndex];
byteArr[nextIndex] = temp1;
temp1 = temp2;
}
}
}
}
此代码工作的情况下lStart = 0, lLength = 11, rStart = 26, rLength = 70
但在情况lStart = 0, lLength = 46, rStart = 47, rLength = 53
失败。我可以看到的解决方案是添加逻辑来确定何时已经移动了右数组中的一个字节。虽然这对我来说可能是可行的,但我想知道是否有一个简单的解决方案来解决这个问题,该问题的运行具有不断的内存复杂性,而且没有额外的读写操作?
这里的一个程序来测试的实现:
bool testAlign(int lStart, int lLength, int rStart, int rLength)
{
char* byteArr = (char*) malloc(100 * sizeof(char));
char* leftArr = byteArr + lStart;
char* rightArr = byteArr + rStart;
for(int i = 0; i < rLength; i++)
{
rightArr[i] = i;
}
for(int i = 0; i < lLength; i++)
{
leftArr[i] = i + rLength;
}
align(byteArr, leftArr, lLength, rightArr, rLength);
for(int i = 0; i < lLength + rLength; i++)
{
if(byteArr[i] != i) return false;
}
return true;
}
那么'leftArr'和'rightArr' _always_指向_somewhere_到以'byteArr'开头的同一个内存块? – chux
我建议你发布一个(小)数据输入和输出的例子,如你所期望的那样工作,而另一个则没有。 –
看起来代码可能以'void foo(char * byteArr, unsigned lStart,unsigned rStart,unsigned leftArrLen,unsigned rightArrLen)开始;' – chux