tags:

views:

127

answers:

9

Here is the code:

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

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

For Character array: (Since we have a NULL character at the end, no problem while iterating)

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

Output: ABCDE

My question is since we say to add NULL character as end of the strings, we rule out such issues! If in case, it is rule to add 0 to the end of integer array, we could have avoided this problem. What say?

+8  A: 

In C++ the best solution is to use a std::vector, not an array. vectors carry their size around with them. The problem with using zero (or any other value) as a an end marker is that of course it can't appear elsewhere in the array. This is not so much of an issue for strings, as we rarely want to print the character with code zero, but it is an issue when using arrays of ints.

anon
I'm ok with using std::vector here. One general question I have. How in vectors, they are able to determine the size of the integer array?
AKN
@AKN They carry the size around as a separate value of some sort.
anon
@AKN the std:vector is not just an array, it's probably a struct which contains an array and an int for length and possibly more.
phkahler
I disagree with this "In C++ the best solution is to use a std::vector". Arrays are part of C++ and are useful in a lot of contexts. Why do you use a vector if there is no need to change the size of the array?
Vicente Botet Escriba
@Vicente Features like easy retrieval of size, checked element access via at(), etc.
anon
Good point for the checked access via at. I will make a proposal to Boost, who know maybe this could result in an addition to the C++0x one day :)You can have the same using an array and the free functions C++0x or Boost.Range xxx::size(arr) and the missing xxx::at(arr,idx) where xxx can be std or boost depending on your constraints.This functional functions are more adapted to generic programming.
Vicente Botet Escriba
+2  A: 

You can certainly decide on your own "sentinel" value to store at the end of your array of integers. If your integers are always expected to be nonnegative, for example, you can use -1 as the sentinel value that marks the end of the array.

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

The char value 0 has special meaning, standardized by convention and practice. The int value 0 does not, so this can't be a general rule. If it works in your specific case, you can go with it. However, in general it is better to just keep track of the length of integer arrays separately, since this works universally. Or use std::vector or a similar container which handles that job for you.

Péter Török
A: 

Use std::vector, like Neil says.

Or do it the iterator way:

int myInt[] ={ 100, 200, 300, 400, 500 };
int *myIntPtr = &myInt[0];
int *myIntPtr_end = myIntPtr + 5;
while(myIntPtr != myIntPtr_end)
  {
  cout<<*myIntPtr<<endl;
  ++myIntPtr;
  }
MadKeithV
Here we see '5' and ofcourse that is the length which we can use directly right! :)
AKN
<b>int *myIntPtr_end = myIntPtr + 5;</b> The pointer *myIntPtr_end is pointing to SOME_JUNK_VALUE after last value. (i.e) after 500. Since for this design flaw, I feel it is not advisable. What say?
AKN
It doesn't matter that it's pointing to junk, as long as you don't dereference the pointer.As for the length of the array - you obviously have it available in your example. If you are talking about pointers-to-arrays with no information about the length, that's something you need to add to your question / description.
MadKeithV
Thanks to your viewpoint Keith.
AKN
+2  A: 

What about using sizeof? http://www.cppreference.com/wiki/keywords/sizeof

Gabriel Ščerbák
Because there is no such thing - your are thinking of sizeof. and this cannot be used once the array has decayed to a pointer.
anon
@Neil Butterworth thank you, that was just an accute case of dislexia:) However, there is nothing said about not being able to access the array. This can be also used further to implement something like boundary checking array template class.
Gabriel Ščerbák
A: 
for(i=0; i < sizeof(myInt); i++ )
{
    cout<<*myIntPtr<<endl;
    myIntPtr++;
}

If you're suggesting your code where myIntPtr is manipulated has no idea of the chunk size it points to, you either have to decide for a magic value in your int array, or restructure your code so that sizeof(myInt) is also available.

Standard C library functions use the latter approach: whenever you need to pass a buffer area through a pointer, you have to pass them its size in the same call.

kostas
Thanks kostas. But sizeof(myInt) will not directly give array size.So instead this can be changed to 'int nIntArrSize = sizeof(myInt)/sizeof(int)'
AKN
+2  A: 

C-strings convention is that a char* finish by a '\0' char. For array or any other C++ container there are other idioms that can be applied. Next follows my preferences

The best way to iterate on sequences is to use the Range-based for-loop included on C++0x

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

If your compiler don't provide this yet, use iterators

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

And if you can not use neither std::begin/end

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

P.S Boost.Foreach emulates the Range-based for-loop on C++98 compilers

Vicente Botet Escriba
Where is std::begin/end defined? Does it come with C++0x?
Christian Ammer
@Christian: Yes, or with Boost.
UncleBens
@Christian Yes this is a new feature of C++ related to Range. Boost.Range include this and much more, simplifying a lot the algorithm on sequences.
Vicente Botet Escriba
+1  A: 

Firstly, we don't "add NULL character" at the end of the string. There's no such thing as "NULL character". We add zero character, which is sometimes called "NUL character". But NULL has absolutely nothing to do with it. NULL is normally used in pointer context and not in character or integer context. Your comparisons like *myCharPtr != NULL or *myIntPtr != NULL will compile (due to the way NULL is defined in C++), but make virtually no sense. If you are looking for a zero character in an array, you can check for it as *myCharPtr != '\0' or as *myCharPtr != 0 or as simply *myCharPtr, but never as *myCharPtr != NULL.

Secondly, the zero character is called zero character for a reason: it is equal to integer zero. Character type in C++ is just a plain integer type after all. The only reason we can use zero character as something special in string context is because it's meaning is reserved for that specific purpose. In general case in integer context reserving zero for that purpose is plainly impossible for obvious reasons: zero is as useful as any other integer value. Yet, if in your specific application integer zero can be used as a reserved value, feel free to use it that way. Or you can use any other integer value for that purpose. But in general case, referring to the question you ask in the title, there's no way to determine the end of an array. It is your responsibility to know where the end is (by knowing the total number of elements or by marking the end with a reserved value of your choice or in some other way). There's no way to determine the end of an array even with strings, because all you can hope for is to find the end of the string, which is not necessarily the end of the array that stores that string.

If you explicitly added a zero to the end of your integer array, your first cycle would happily stop at it. For some reason you explicitly added \0 at the end of your character array (and the second cycle stops), but you didn't add a zero at the end of your integer array (and the first cycle doesn't stop). You are wondering why your first cycle didn't stop at zero? Becuse you didn't put that zero in there. It is that simple.

AndreyT
+1  A: 

Both the ASCII and Unicode standard defines a character with value 0 as the NULL character, not an end-of-array/string marker. It is only C/C++ convention that strings are terminated with this character. Pascal uses a different notation. Also, the NULL character does not necessarily indicated the end of the array that contains the string. There are several Win32 API functions that use double null terminated strings (the open file dialog for one), like this:

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

This is valid C/C++ code, the NULL character does not mean the end of the array.

To adapt this idea of a NULL value to integer arrays means you have to sacrifice one of your integer values. If your data consists of a subset of the set of integers then this isn't a problem but if your data can consist of any integer value, then there is no way to detemine if a given integer is the end-of-array marker or a valid value. In this latter case, your need additional information about the number of elements in the array, either manually or automatically via a std::vector.

Skizz