修复尝试修复反转数组时损坏的代码

时间:2014-07-25 02:09:18

标签: c++ arrays

所以我得到了需要修复的代码示例。从我可以收集到的,它需要一个数组,反转它然后计算其中的所有元素。这是代码。

//-------------------------------------------------------------------
void ReverseTheArray( const short *pArrayStart, const int nArrayByteLength )
{

    const short *pArrayEnd = (pArrayStart + nArrayByteLength);

    while(pArrayStart != pArrayEnd)
    {
        short tmp = *pArrayStart;
        *pArrayStart = *pArrayEnd;
        *pArrayEnd = tmp;

        pArrayStart++;
        pArrayEnd--;
    }
}


//-------------------------------------------------------------------
int CountTheArrayContents( const short *pArrayStart, int nNumEntries )
{
    assert(nNumEntries-- > 0);

    int nCount = 0;
    for(unsigned uArrayIndex = nNumEntries; uArrayIndex >= 0; uArrayIndex--)
    {
        nCount += pArrayStart[uArrayIndex];
    }

    return nCount;
}

const short g_nSomeNumbers[] =
{
    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
};

//-------------------------------------------------------------------
int main()
{
    short *pDataArray = new short[10];
    memcpy(pDataArray, g_nSomeNumbers, sizeof(g_nSomeNumbers));

    ReverseTheArray(pDataArray, 10*sizeof(short));
    int nCount = CountTheArrayContents(pDataArray, 10);

    printf("Sum total is %0.02f\n", nCount);

    return 0;
}

我知道问题是什么,但似乎无法找出问题的简单解决方案,不需要重写整个代码。如果任何人都可以阅读此内容并了解如何修复错误,那将非常感激。

我要提一些我认为会导致问题的事情。

ReversTheArray()函数中的所有参数和pArrayEnd变量都是const,但是试图在while循环中进行更改,这会引发错误。 const应该被删除吗?有没有理由将const用于此?

如果删除const,则尝试在CountTheArrayContents()函数中运行for循环时会发生运行时错误,表示未处理的异常并说“访问冲突读取位置0x003DFFFE”。在那一个上画一个完整的空白。

再一次对代码的任何帮助都会非常感激,我也不能感谢你们。

PS。这是创建反向和累积函数的一个挑战,所以我正在寻找代码的修复,而不是删除这两个函数。谢谢

PSS。感谢所有回答的人。我很高兴我这样做了(这是我发布的关于我自己的第一个问题)而且你们都得到了很大的帮助。我必须说我已经学到了很多东西。

2 个答案:

答案 0 :(得分:1)

添加实际长度(以字节为单位)将增加太多,因为指针算法是根据指向的类型大小的单位定义的。也就是说,pArrayEnd变为&pDataArray[10 * sizeof(short)]而不是&pDataArray[10]。在调用反转功能时,您不需要乘以sizeof(short)。或者,您可以在计算nArrayByteLength的初始值时将sizeof(short)除以pArrayEnd

第二个问题是你只分配了10个元素(0..9),这意味着&pDataArray[10]将是数组之外的一个元素。然后,反转功能会尝试将数据分配给此未分配的内存区域,这可能会导致问题。该函数应如图所示初始化pArrayEnd,但紧接着,它应该将pArrayEnd递减1.这样您就不会分配给可能不属于您的内存。在递减pArrayStart == pArrayEnd之前要小心pArrayEnd。另一种测试是确保nArrayByteLength != 0

另一个问题是,如果数组具有偶数个元素,并且您尝试进行反转。如果它具有偶数(如10),则pArrayStart将指向pDataArray[4]pArrayEnd将指向pDataArray[5],并且在分配数据后,{{1}将pArrayStart++指向pArrayStartpDataArray[5]指向pArrayEnd--。那么(6,3),(7,2),(8,1),(9,0),......换句话说,pDataArray[4]永远不会等于pArrayStart这样的案件。相反,您应该确保pArrayEnd

希望这有帮助!

另外,没有使用pArrayStart < pArrayEnd的原因?只是想知道。

修改

可以将重写函数重写为以下内容,这样可以避免std:: reverse宏在执行相同操作时出现问题:

assert

希望int CountTheArrayContents( const short *pArrayStart, int nNumEntries ) { int count = 0; assert(nNumEntries); while (nNumEntries--) count += pArrayStart[nNumEntries]; return count; } 不会溢出。

答案 1 :(得分:1)

如果您要做的只是反转数组的内容并累积结果,std::reversestd::accumulate将完成这一操作(根据@chris的建议)。这是一个示例,它维护动态分配的short*。更好的解决方案是使用std::vectorstd::array

#include <algorithm>
#include <numeric>
#include <stdio.h>
#include <memory.h>

const short g_nSomeNumbers[] =
{
    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
};

int main()
{
    short *pDataArray = new short[10];
    memcpy(pDataArray, g_nSomeNumbers, sizeof(g_nSomeNumbers));

    std::reverse(pDataArray, pDataArray+10);
    int nCount = std::accumulate(pDataArray, pDataArray+10, 0);

    for( size_t i=0; i<10; ++i )
        printf("%d ", pDataArray[i]);
    printf("\n");
    printf("Sum total is %d\n", nCount);

    delete [] pDataArray;

    return 0;
}

打印

9 8 7 6 5 4 3 2 1 0 
Sum total is 45