Как определить конец целочисленного массива при управлении с целочисленным указателем?

Вот код:

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

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

Для Символьного массива: (Так как у нас есть Нулевой символ в конце, никакой проблеме при итерации),

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

Output: ABCDE

Мой вопрос состоит в том, так как мы говорим для добавления Нулевого символа как конца строк, мы исключаем такие проблемы! Если в случае, если, это - правило добавить 0 в конец целочисленного массива, мы, возможно, избежали этой проблемы. Что говорит?

9
задан Georg Fritzsche 29 April 2010 в 09:53
поделиться

9 ответов

Соглашение о C-строках гласит, что символ * заканчивается символом '\ 0'. Для массива или любого другого контейнера C ++ можно применить другие идиомы. Далее следуют моим предпочтениям

. Лучший способ перебора последовательностей - использовать цикл for на основе диапазона, включенный в C ++ 0x

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;
}

PS Boost.Foreach имитирует цикл for на основе диапазона на компиляторах C ++ 98

12
ответ дан 4 December 2019 в 07:04
поделиться

В C ++ лучшим решением является использование std :: vector, а не массива. векторы несут с собой свой размер. Проблема с использованием нуля (или любого другого значения) в качестве конечного маркера заключается в том, что, конечно, он не может появиться где-либо еще в массиве. Это не такая большая проблема для строк, поскольку мы редко хотим печатать символ с нулевым кодом, но это проблема при использовании массивов целых чисел.

11
ответ дан 4 December 2019 в 07:04
поделиться
for(i=0; i < sizeof(myInt); i++ )
{
    cout<<*myIntPtr<<endl;
    myIntPtr++;
}

Если вы предлагаете свой код, в котором используется myIntPtr, не имеет представления о размере блока, на который он указывает, вам нужно либо выбрать магическое значение в массиве int, либо изменить структуру кода так, чтобы sizeof ( myInt) также доступен.

Стандартные функции библиотеки C используют второй подход: всякий раз, когда вам нужно передать буферную область через указатель, вы должны передать им ее размер в том же вызове.

0
ответ дан 4 December 2019 в 07:04
поделиться

Как насчет использования sizeof? http://www.cppreference.com/wiki/keywords/sizeof

3
ответ дан 4 December 2019 в 07:04
поделиться

Значение символа 0 имеет особое значение, стандартизированное соглашениями и практикой. Значение int 0 - нет, так что это не может быть общим правилом. Если это работает в вашем конкретном случае, вы можете пойти с этим. Однако в целом лучше просто отслеживать длину целочисленных массивов отдельно, поскольку это работает универсально. Или используйте std :: vector или аналогичный контейнер, который выполняет эту работу за вас.

1
ответ дан 4 December 2019 в 07:04
поделиться

Используйте std :: vector, как говорит Нил.

Или используйте итератор:

int myInt[] ={ 100, 200, 300, 400, 500 };
int *myIntPtr = &myInt[0];
int *myIntPtr_end = myIntPtr + 5;
while(myIntPtr != myIntPtr_end)
  {
  cout<<*myIntPtr<<endl;
  ++myIntPtr;
  }
0
ответ дан 4 December 2019 в 07:04
поделиться

Вы, конечно, можете выбрать собственное "дозорное" значение , которое будет храниться в конце вашего массива целых чисел. Если предполагается, что ваши целые числа всегда будут неотрицательными, например, вы можете использовать -1 в качестве контрольного значения, которое отмечает конец массива.

int myInt[] ={ 1, 2, 3, 4, 5, -1 };
int *myIntPtr = &myInt[0];
while( *myIntPtr >= 0 )
{
    cout<<*myIntPtr<<endl;
    myIntPtr++;
}
3
ответ дан 4 December 2019 в 07:04
поделиться

Во-первых, мы не «добавляем NULL-символ» в конец строки. Не существует такой вещи, как «NULL-символ». Мы добавляем нулевой символ, который иногда называют «символом NUL». Но NULL не имеет к этому никакого отношения. NULL обычно используется в контексте указателя, а не в символьном или целочисленном контексте. Ваши сравнения вроде * myCharPtr! = NULL или * myIntPtr! = NULL будут компилироваться (из-за того, как NULL определен в C ++), но практически не дают смысл. Если вы ищете нулевой символ в массиве, вы можете проверить его как * myCharPtr! = '\ 0' или как * myCharPtr! = 0 или просто ] * myCharPtr , но никогда как * myCharPtr! = NULL .

Во-вторых, нулевой символ не зря называется нулевым символом: он равен целому нулю. В конце концов, символьный тип в C ++ - это просто целочисленный тип. Единственная причина, по которой мы можем использовать нулевой символ как нечто особенное в строковом контексте, заключается в том, что его значение зарезервировано для этой конкретной цели.В общем случае в целочисленном контексте зарезервировать ноль для этой цели просто невозможно по очевидным причинам: ноль так же полезен, как и любое другое целочисленное значение. Тем не менее, если в вашем конкретном приложении целое число ноль может использоваться как зарезервированное значение, не стесняйтесь использовать его таким образом. Или вы можете использовать для этой цели любое другое целочисленное значение. Но в общем случае, ссылаясь на вопрос, который вы задаете в заголовке, нет способа определить конец массива. Вы обязаны знать, где находится конец (зная общее количество элементов или пометив конец зарезервированным значением по вашему выбору или каким-либо другим способом). Невозможно определить конец массива даже со строками, потому что все, на что вы можете надеяться, - это найти конец строки , которая не обязательно является концом массива, в котором хранится эта строка.

Если вы явно добавите ноль в конец целочисленного массива, ваш первый цикл благополучно остановится на нем. По какой-то причине вы явно добавили \ 0 в конец массива символов (и второй цикл останавливается), но вы не добавили ноль в конец целочисленного массива (а первый цикл не не останавливаюсь). Вам интересно, почему ваш первый цикл не остановился на нуле? Извините, вы не поставили туда этот ноль. Это так просто.

1
ответ дан 4 December 2019 в 07:04
поделиться

Стандарт как ASCII, так и Unicode определяет символ со значением 0 как символ NULL, а не маркер конца массива / строки. Это только соглашение C / C ++, что строки заканчиваются этим символом. Паскаль использует другие обозначения. Кроме того, символ NULL не обязательно указывает на конец массива, содержащего строку. Есть несколько функций Win32 API, которые используют строки с двойным нулем в конце (для одной из них - диалог открытия файла), например:

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

Это допустимый код C / C ++, символ NULL не означает конец массива.

Чтобы адаптировать эту идею значения NULL к целочисленным массивам, вы должны пожертвовать одним из ваших целочисленных значений. Если ваши данные состоят из подмножества набора целых чисел, это не проблема, но если ваши данные могут состоять из любого целочисленного значения, тогда нет способа определить, является ли данное целое число маркером конца массива или допустимое значение. В этом последнем случае вам потребуется дополнительная информация о количестве элементов в массиве вручную или автоматически с помощью std :: vector.

1
ответ дан 4 December 2019 в 07:04
поделиться
Другие вопросы по тегам:

Похожие вопросы: