使用整数指针操作时如何确定整数数组的结尾?

时间:2010-04-29 09:16:39

标签: c++ pointers

以下是代码:

int myInt[] ={ 1, 2, 3, 4, 5 };
int *myIntPtr = &myInt[0];
while( *myIntPtr != NULL )
{
    cout<<*myIntPtr<<endl;
    myIntPtr++;
}

Output: 12345....<junks>..........

For Character数组:(因为我们最后有一个NULL字符,迭代时没问题)

char myChar[] ={ 'A', 'B', 'C', 'D', 'E', '\0' };
char *myCharPtr = &myChar[0];
while( *myCharPtr != NULL )
{
    cout<<*myCharPtr<<endl;
    myCharPtr++;
}

Output: ABCDE

我的问题是,因为我们说要添加NULL字符作为字符串的结尾,我们排除了这些问题! 如果是这样的话,规则是在整数数组的末尾添加0,我们可以避免这个问题。怎么说?

11 个答案:

答案 0 :(得分:12)

C字符串约定是由'\ 0'字符完成的char *。对于数组或任何其他C ++容器,还有其他可以应用的习语。接下来是我的偏好

迭代序列的最佳方法是使用C ++ 0x中包含的基于范围的for循环

int my_array[] = {1, 2, 3, 4, 5};
for(int& x : my_array)
{
  cout<<x<<endl;
}

如果您的编译器尚未提供此功能,请使用迭代器

for(int* it = std::begin(array); it!=std::end(array); ++it)
{
  cout<<*it<<endl;
}

如果你不能既不使用std :: begin / end

for(int* it = &array[0]; it!=&array[sizeof(array)]; ++it)
{
  cout<<*it<<endl;
}

P.S Boost.Foreach在C ++ 98编译器上模拟基于范围的for循环

答案 1 :(得分:11)

在C ++中,最好的解决方案是使用std :: vector,而不是数组。矢量随身携带它们的大小。使用零(或任何其他值)作为结束标记的问题当然是它不能出现在数组的其他地方。对于字符串来说,这不是一个问题,因为我们很少想要使用代码零打印字符,但在使用整数数组时这是一个问题。

答案 2 :(得分:3)

您当然可以决定将自己的"sentinel" value存储在整数数组的末尾。例如,如果您的整数总是预期为非负,则可以使用-1作为标记数组末尾的标记值。

int myInt[] ={ 1, 2, 3, 4, 5, -1 };
int *myIntPtr = &myInt[0];
while( *myIntPtr >= 0 )
{
    cout<<*myIntPtr<<endl;
    myIntPtr++;
}

答案 3 :(得分:3)

答案 4 :(得分:1)

char值0具有特殊含义,按惯例和惯例标准化。 int值0没有,因此这不是一般规则。如果它适用于您的具体情况,您可以使用它。但是,通常最好只分别跟踪整数数组的长度,因为这可以普遍使用。或者使用std::vector或类似的容器为您处理该工作。

答案 5 :(得分:1)

首先,我们不在字符串的末尾添加“NULL字符”。没有“NULL character”这样的东西。我们添加字符,有时称为“NUL字符”。但是NULL与它完全无关。 NULL通常用于指针上下文,而不是字符或整数上下文。您的*myCharPtr != NULL*myIntPtr != NULL之类的比较将会编译(由于在{+ C ++中定义NULL的方式),但实际上没有任何意义。如果您要在数组中查找零字符,可以将其检查为*myCharPtr != '\0'*myCharPtr != 0或仅*myCharPtr,但绝不会*myCharPtr != NULL

其次,零字符被称为零字符,原因是:它等于整数零。毕竟,C ++中的字符类型只是一个普通的整数类型。我们可以将零字符用作字符串上下文中的特殊内容的唯一原因是因为它的含义是为特定目的而保留的。一般情况下,在整数上下文中为此目的保留零显然是不可能的,原因很明显:零与任何其他整数值一样有用。但是,如果在您的特定应用程序中,整数零可以用作保留值,请随意使用它。或者,您可以使用任何其他整数值来实现此目的。但一般情况下,参考标题中提出的问题,无法确定数组的结尾。您有责任知道结束的位置(通过了解元素的总数或通过使用您选择的保留值或以其他方式标记结尾)。即使使用字符串也无法确定数组的结尾,因为您可以希望找到字符串的结尾,这不一定是存储该字符串的数组的结尾。

如果你明确地在整数数组的末尾添加了一个零,那么你的第一个循环将很乐意停止它。出于某种原因,您在字符数组的末尾明确添加了\0(并且第二个循环停止),但是您没有在整数数组的末尾添加零(并且第一个循环不会停止)。你想知道为什么你的第一个周期没有停在零?因为你没有把那个零放在那里。就这么简单。

答案 6 :(得分:1)

ASCII和Unicode标准都将值为0的字符定义为NULL字符,而不是数组结束/字符串标记。字符串以此字符终止只是C / C ++约定。 Pascal使用不同的表示法。此外,NULL字符不一定表示包含该字符串的数组的结尾。有几个Win32 API函数使用双空终止字符串(一个打开文件对话框),如下所示:

"one\0two\0three\0" // there's an implicit '\0' appended in C/C++

这是有效的C / C ++代码,NULL字符并不代表数组的结尾。

为了使NULL值的这种想法适应整数数组意味着你必须牺牲一个整数值。如果您的数据由整数集的一个子集组成,那么这不是问题,但如果您的数据可以包含任何整数值,那么无法确定给定的整数是数组的结尾标记还是有效值。在后一种情况下,您需要手动或通过std :: vector自动获取有关数组中元素数量的其他信息。

答案 7 :(得分:0)

使用std :: vector,就像Neil说的那样。

或者以迭代器方式执行:

int myInt[] ={ 100, 200, 300, 400, 500 };
int *myIntPtr = &myInt[0];
int *myIntPtr_end = myIntPtr + 5;
while(myIntPtr != myIntPtr_end)
  {
  cout<<*myIntPtr<<endl;
  ++myIntPtr;
  }

答案 8 :(得分:0)

for(i=0; i < sizeof(myInt); i++ )
{
    cout<<*myIntPtr<<endl;
    myIntPtr++;
}

如果您建议操作myIntPtr的代码不知道它指向的块大小,您必须决定int数组中的魔术值,或者重构代码以便sizeof(myInt)也可以。

标准C库函数使用后一种方法:每当需要通过指针传递缓冲区时,就必须在同一个调用中传递它们的大小。

答案 9 :(得分:0)

为任何数组创建结束指针的一般方法如下:首先使用sizeof(array)/sizeof(array[0])确定数组中的元素数。请注意,sizeof出现两次,因为它返回项目的大小(以字节为单位)。因此对于静态数组,这是数组的大小除以数组中元素的大小。然后指向数组的结束指针是array+number_of_elements。所以这应该有效:

int myInt[]={1, 2, 3, 4, 5};
int myIntNumElements = sizeof(myInt) / sizeof(myInt[0]);
int *myIntEnd = myInt + myIntNumElelents;

for (int *myIntPtr = myInt; myInt != myIntEnd; myIntPtr++)
  {
    cout << *myIntPtr << endl;
  }

现在有一些警告:

  • 结束指针指向阵列结束后的位置!所以*myIntPtr返回垃圾,而不是数组中最后一个元素的值。
  • 这仅适用于常规静态数组!对于容器,请使用beginend成员函数和迭代器。
  • 此方法适用于任何版本的C ++。但是,如果您使用的是C ++ -11或更高版本,建议在for语句中使用std::beginstd::end函数,如下所示:

    for (int *myIntPtr = std::begin(myInt); myIntPtr != std::end(myIntPtr); myIntPtr++)

  • 除了其他答案之外,还应考虑此方法。哪个是最好的是上下文问题。

答案 10 :(得分:0)

使用sizeof()可以解决问题

int arr[] = {10, 20};                                                                                                                                                               
int *p = arr;                                                                                                                                                                       
int loop = sizeof(arr);                                                                                                                                                                                                                                                                                                                                                 

while (loop) {                                                                                                                                                                             
   cout<<*p++<<endl;                                                                                                                                                          
   loop-=sizeof(int);                                                                                                                                                           
}