您不应该这样使用sizeof(originalarray)/sizeof(int)
。它仅适用于静态声明的数组(大小在编译时已知)。您必须将尺寸和它一起传递。您为什么不只从数组中制作一个vector
并传递它呢?
我正在编写一个合并排序函数,现在我只是在使用一个测试用例数组(没有输入-暂时是静态的)。我不知道如何将数组作为参数传递。现在是我的代码:
//merge sort first attempt
#include <iostream>
#include <algorithm>
#include <vector>
int mergeSort(int[]);
int main() {
int originalarray[] = { 1, 3, 5, 7, 9, 2, 4, 6, 8, 10 };
mergeSort(originalarray[]);
}
int mergeSort(int[] originalarray) {
int num = (sizeof(originalarray) / sizeof(int));
std::vector < int > original(num);
if (num > 2) {
return num;
}
// Fill the array using the elements of originalarray
// This is just for demonstration, normally original will be a parameter,
// so you won't be filling it up with anything.
std::copy(originalarray, originalarray + num, original.begin());
// Create farray and sarray of the appropriate size
std::vector < int > farray(num / 2);
std::vector < int > sarray(num - farray.size());
// Fill those using elements from original
std::copy(original.begin(), original.begin() + farray.size(), farray.begin());
std::copy(original.begin() + farray.size(), original.end(), sarray.begin());
mergeSort(farray);
mergeSort(sarray);
}
请注意,此mergeSort函数不起作用,因为我还没有弄清楚如何合并它们(这是我的任务)。我想在处理这两个向量之前先对它们进行排序,但由于需要将数组作为参数传递,因此我无法对其进行编译。我不理解指针,所以如果这是解决方案,我的借口就是无知。我现在正在学习编程,将C ++作为第一语言,并且对语言的功能只有基本的了解。感谢您的帮助。
要稍微扩展一下,请记住C ++数组是exactly C数组。因此,您所拥有的只是一块内存的地址,该内存声称(不保证)是某物的数组。
好的,我们再扩展一点。
C(因此是C ++)实际上没有这样的“数组”。它所具有的只是地址,指针。因此,当您将某个东西做成“数组”时,真正发生的是告诉编译器某个变量代表一个地址。
在C中区分declaration和definition是很有用的。在声明中,您只是在给一个名称和类型指定名称;在定义中,您实际上是在分配空间。
所以,如果我们先定义一个数组,如
int ar[100];
这意味着我们要告诉编译器我们要100个int
的空间,我们希望将其全部分配到一个块中,并且我们将使用名称ar
。 sizeof
运算符提供了类型或对象使用的字节数,因此我们的数组ar
将占用100×sizeof(int)
个字节。在大多数计算机上,这将是400个字节,但因计算机而异。
如果我们定义一个变量
int * ar_p; // using '_p' as a reminder this is a pointer
我们正在为将包含地址的变量定义空间。它的大小将为sizeof(int*)
,通常为4或8,但在某些计算机上可能会是2到16之间的任何值,在某些不太可能很快会出现的计算机上。
数组的名称为ar
。编译器将该名称转换为地址,因此我们可以使用[
ar_p = ar ; // THIS WORKS
现在,为了方便起见,我们的数组ar
恰好从内存中的位置1000开始。
该名称ar
确实not没有为其分配任何空间;就像一个常数,一个数字。因此,您无法撤消该任务
ar = ar_p ; // THIS WON'T WORK
出于同样的原因,您不能说
1000 = ar_p ; // THIS WON'T WORK EITHER
即,您不能更改1000的值。(在早期版本的FORTRAN中,由于复杂的原因,此技巧仍然有效。这是一个错误。在尝试调试程序之前,您从未活过。其中“ 2”的值为3。)
C中的数组始终基于零,也就是说,第一个索引始终为零。其他任何索引只是使用索引计算的地址。因此,ar[0]
只是地址1000加0字节的偏移量,即1000。ar[1]
是1000加上int
大小的1倍,因此next int结束。实际上,在C语言中总是如此。
这称为数组引用
。[当我们使用语法*ar_p
时,我们告诉编译器将事物AT包含在ar_p
中包含的地址处。 `。
这称为取消引用指针
。如果我们说
ar_p = ar;
然后
*ar_p
和ar[0]
指的是同一件事。
[当我们说ar[0]
时,我们告诉编译器我们想要的东西在ar
中的0字节地址处。 ar[1]
是从int
开始的一个地址ar
或4个字节。因此,*(ar_p+3)
与ar[3]
指的是同一事物。 (我们需要括号,因为我们想先在地址中添加3,然后再查看内容。*ar_p+3
首先获取ap_p
所指向的内容,然后再添加3。)
事实是,C不知道或不太在乎数组的大小。如果我来做ar[365]
,编译器将愉快地生成代码以查看单元格1000+(365×sizeof(int)
)。如果在您的数组中,那很好,但是如果只是随机内存,那也很好。 C不在乎。
((记住C来自电话公司。“我们不在乎;我们不必。我们是电话公司。”)
所以,现在,我们知道了一些规则,我已经将其移至此处。将“≡”读作“等同于”或“等同于”。
您可以依赖的内容:
foo(TYPE t[])
≡foo(TYPE * t)
由于C不知道指针与数组之间的区别,因此可以声明其中之一。定义函数时,可以编写
void foo(int[] ar){
或
void foo(int* ar){
并获得完全相同的效果。
t[i]
≡*(t+i)
以上。可以在任何位置编写ar[i]
的地方,都可以用*(ar+i)
代替。 (实际上有一个奇怪的附带情况可以解决这个问题,但您不会像初学者那样碰到它。)
TYPE *t
,(t+i)
将等于t
加i*sizeof(TYPE)
的地址也在上面解释了这一点。当您像ar[42]
这样索引到数组时,这意味着您希望从起始地址开始到第42位。因此,如果您使用的是int
,那么您需要将int
的宽度移动42倍,也就是说sizeof(int)
。
现在,这就是所有C,并且由于C ++被定义为C的“一种”,所以C ++也都适用。除外
TYPE
是用户定义的类型,该类型会使operator[]
和operator*
超载。在C ++中,您可以决定要定义一个与其他任何类型一样工作的新类型,但是您可以更改该语言执行特定操作的方式。因此,程序员can
您不应该这样使用sizeof(originalarray)/sizeof(int)
。它仅适用于静态声明的数组(大小在编译时已知)。您必须将尺寸和它一起传递。您为什么不只从数组中制作一个vector
并传递它呢?
附带说明:
sizeof
将在编译时进行翻译。因此,不可能知道作为参数传递的数组的大小。 我看到你加入了<vector>
。我建议您不要使用所有数组,而只使用vector
类。您可以看到有关如何使用STL容器的示例,例如vector
here。
尽管将符号传递给函数时,它们会衰减为指向数组第一个元素的指针。因此,您的sizeof
无法正常工作。
当您传递数组时,最好传递数组大小,以便您知道在哪里停止。将其添加为附加参数。
除了以上所有答案之外,您可能还想从c-faq.com上检查阵列上的问题和答案:http://c-faq.com/aryptr/index.html
不幸的是,要完全按照C或C ++的方式进行操作非常困难。您可以像这样传递固定大小的数组:
int mergeSort(int originalarray[20])
{
// do something
}
但是,数组的大小不是由数字定义的,而是由初始化列表中元素的数量定义的。
在您的情况下要做的事情(尽管这确实是错误的事情)是分两个步骤进行:
int originalarray[] = {1, 3, 5, 7, 9, 2, 4, 6, 8, 10}; const size_t arraySize = sizeof originalarray / sizeof originalarray[0]; int mergeSort(int array[arraySize]) { // do something }
太糟糕了,它不会做您需要做的事情:将数组传递给这样的函数会复制数组,而排序的重点就是更改原始数组。
实际上,如果不了解“指针”的概念,您将无法再进一步。
您真正需要开发的功能应该是这样的:
int originalarray[] = {1, 3, 5, 7, 9, 2, 4, 6, 8, 10}; const size_t arraySize = sizeof originalarray / sizeof originalarray[0]; int mergeSort(int *array, const size_t size) { // do something } mergeSort(&(originalArray[0]), arraySize);
换句话说,将指针传递给第一个元素和元素数。
或者,您可以处理向量。向量将两个相同的东西(指向第一个元素和大小的指针)封装在一个称为“对象”的实体中。另外,它可以为您管理内存,因此您可以根据需要扩展元素的数量。这是C ++的方式。太糟糕了,您无法像数组一样使用{...}初始化向量。
当您相信仅使用std :: vector就足够了时,您似乎同时使用了动态分配的数组和向量。
首先,将输入数组更改为std :: vector,并用输入数据填充它。
int main() { std::vector<int> originalarray; for (int data = 1; data <= 10; data++) { originalarray.push_back(data); } mergeSort(originaldata); }
现在,重要的是声明您的mergesort函数以引用对std :: vector的引用。
int mergeSort(std::vector<int>& originalarray) { // The rest of your code, note that now you are passing // in your array for sorting, so you can continue with your code to split // the vector into farray and sarray // then call sort on your halves. mergeSort(farray); mergeSort(sarray); // I'm guessing at this point you'd write code to combine your farray sarray, and // put it back into originalarray...don't forget to clear original array first! }
只是一个注释,看起来您不是在进行就地排序,因此,由于要复制大量数据,因此希望您的排序需要一段时间。
您不应该这样使用sizeof(originalarray)/sizeof(int)
。它仅适用于静态声明的数组(大小在编译时已知)。您必须将尺寸和它一起传递。您为什么不只从数组中制作一个vector
并传递它呢?
我看到你加入了<vector>
。我建议您不要使用所有数组,而只使用vector
类。您可以看到有关如何使用STL容器的示例,例如vector
here。
尽管将符号传递给函数时,它们会衰减为指向数组第一个元素的指针。因此,您的sizeof
无法正常工作。
除了以上所有答案之外,您可能还想从c-faq.com上检查阵列上的问题和答案:http://c-faq.com/aryptr/index.html
不幸的是,要完全按照C或C ++的方式进行操作非常困难。您可以像这样传递固定大小的数组:
当您相信仅使用std :: vector就足够了时,您似乎同时使用了动态分配的数组和向量。