以下是我最近参加编程考试的一个问题。我和其他学生都没有找到解决问题的方法。教授说这是可能的,但是拒绝告诉我们解决方案是什么。问题:
编写一个过程,其标题为:
void ArrayUpdate( int ??? array, int ??? delAmount, int ??? addAmout)
答案 0 :(得分:2)
创建阵列:
void CreateArray( int*& array, int size )
{
array = new int[ size + 1 ];
array[ 0 ] = size;
}
您可以使用int**
而不是int*&
,但是很难读写。
获取大小:
int ArraySize( int* array )
{
return *array;
}
用法:
int* array;
CreateArray( array, 10 );
//...
for ( int i = 1; i <= ArraySize(array); ++i )
// ...
功能签名:
void ArrayUpdate( int*& array, int delAmount, int addAmout);
答案 1 :(得分:1)
这是我要解决的问题。它与ZDF的代码非常相似,但是它将数组的capacity
添加到簿记中,并通过为调用者提供指向数组中间而不是开始的指针来隐藏和隐藏簿记。这使用户可以将数组用作常规数组,但是如果尝试自己delete
则将崩溃。
在我认为需要更多解释的地方加上了注释。
//Magic numbers are evil.
constexpr int bookkeeping = 2;
constexpr int sizeOff = -2;
constexpr int capOff = -1;
void ArrayUpdate( int *& array, int delAmount, int addAmount)
{
int size;
int capacity;
// can't do jack with a non-existent array, so let's make sure we have one.
if (array != nullptr)
{
size = *(array + sizeOff);
capacity = *(array + capOff);
}
else
{
size = 0;
capacity = 0;
}
if (delAmount > size) // can't delete more than we have.
{
delAmount = size;
// alternative: freak out here. Abort, throw exception, whatever
}
int * to; // track where data goes to
int * temp; // location of new buffer, if resized
bool resized;
int newsize =size + addAmount - delAmount;
if (newsize > capacity)
{
capacity *=2;
if (capacity < newsize)
{
capacity = newsize;
}
temp = new int[capacity+bookkeeping];
to = temp + bookkeeping; // point to where we want data to go:
// after the book-keeping.
resized = true;
}
else
{
to = array;
resized = false;
}
// use std::copy or memcpy here, but since we're not allowed the appropriate
// headers, here comes ol' brute force!
if (delAmount || resized) // need to copy old data around
{
for (int index = delAmount; index < size; index++)
{
*to++ = *(array + index);
}
}
// add new data
for (int count = 0; count < addAmount; count++)
{
if (std::cin >> *to) // always test to make sure you got good input
{
to++;
}
else
{ // Bad input. Clean up
std::cin.clear();
// normally I'd use cin.ignore(numeric_limits<streamsize>::max(), '\n')
// here to kill all the remaining user input, but no <limits>
std::cin.ignore(1000, '\n');
// might also want to just read and discard until you find the
// first whitespace. That's can be done easily by >> to a std::string,
// but no string header allowed.
}
}
if (resized)
{
if (array != nullptr) // normally deleting nullptr is safe, but not when
// you're going to modify it with an offset
{
delete[] (array - bookkeeping);
}
array = temp + bookkeeping; // array hides the extra book-keeping
*(array + capOff) = capacity;
}
if (array != nullptr)
{
*(array + sizeOff) = newsize;
}
}
未经详尽测试。可能是其中的一两个错误。
为完整起见,这是测试代码和一个免费数组例程:
void FreeArray(int * array)
{
delete[] (array - bookkeeping);
}
void printarray(const int * array)
{
int size;
int capacity;
if (array != nullptr)
{
size = *(array + sizeOff);
capacity = *(array + capOff);
}
else
{
size = 0;
capacity = 0;
}
std::cout << "Size: " << size <<"\nCapacity: "<< capacity << '\n';
for (int index = 0; index < size; index++)
{
std::cout << array[index] << ' ';
}
std::cout << std::endl;
}
int main()
{
int * array = nullptr;
printarray(array);
ArrayUpdate(array, 5, 0);
printarray(array);
ArrayUpdate(array, 5, 5);
printarray(array);
ArrayUpdate(array, 5, 5);
printarray(array);
ArrayUpdate(array, 0, 5);
printarray(array);
ArrayUpdate(array, 5, 0);
printarray(array);
}
答案 2 :(得分:0)
如果是“ ???”可以用任何您想要的替换,因此您可以将指向int的指针或指向int的指针传递给函数,等等。
因此,在C ++中,处理内存管理或范围的诀窍是将2个指针存储到数组的开头,再将其存储到数组的结尾:
//a range:
int* limits[2];
int ** array = limits;
然后,如果您在函数内部更改范围的大小,则必须通过引用将其传递:
void ArrayUpdate( int ** array, int delAmount, int addAmout){
int* begin = array[0];
int* end = array[1];
//end so on
}