Какими значениями я должен заполнить свои массивы, чтобы указать пустое пространство?

#c #arrays #c 11

#c #массивы #c 11

Вопрос:

Это скорее вопрос этикета, чем что-либо другое, но при создании новых массивов какое значение, кроме нуля, я должен использовать для обозначения пустого места в массиве? Например:

 int* arr; arr = new int[10];  

Когда я создам новый массив, как в приведенном выше коде, массив будет заполнен десятью нулями. Проблема, с которой я сталкиваюсь, заключается в том, что я хочу использовать подчеркивания при печати массива для обозначения пустых мест, однако у меня также есть нули как часть моего набора данных в массиве. Итак, я должен просто заполнить пустой массив с некоторым произвольным значением, что вряд ли появлюсь в моем наборе данных (like -32000 for example) , и использовать его в качестве индикатора для пустого пространства, или есть какое-то пустое значение, которое я мог бы использовать вместо этого, так что я могу понять то, что стоимость на тот удельный показатель, безусловно, пустое место?

Комментарии:

1. Я почти уверен, что при создании нового массива, как в приведенном выше коде, он не будет заполнен десятью нулями. По крайней мере, не в соответствии со стандартом C .

2. «Нулевое значение» для int , вероятно, равно нулю. Поэтому вы должны выбрать какое-то другое неиспользуемое значение, если это возможно. В противном случае у вас может быть другой массив bool is_used[10] для отслеживания использования,

3. Не существует общепризнанной ценности. Вам нужно будет просмотреть ожидаемый набор данных и выбрать внеполосное значение, значение, которое не может существовать в наборе. Это или иметь флаг состояния, который прилагается к данным, чтобы отметить, является ли конкретное чтение допустимым.

4. в массивах нет пустых мест. Хотя вы можете использовать массив std::optionallt;intgt;

Ответ №1:

То, о чем вы, похоже, спрашиваете, называется стражем-некоторым значением данных, которое имеет особое значение.

Что касается выбора стража, используйте то, что, как вы знаете, не появится, и сделайте его именованной константой. Например, вы можете использовать:

 constexpr int NoValue = std::numeric_limitslt;intgt;::min();  

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

В качестве альтернативы, создайте отдельный массив для хранения этой информации. Для такого массива требуется только один бит на элемент, чтобы указать, является ли значение пустым или нет, и поэтому это означает только частичное увеличение объема памяти, а не расширение вашего типа данных за его пределы int . Этот подход снижает использование памяти в сравнении с локальностью памяти, поскольку данные о «пустоте» не будут храниться рядом со значением в вашем массиве, и это может иметь последствия для кэширования.

Что касается фактического вопроса инициализации: ваш массив неинициализирован и потребует установки значений с std::fill или аналогичных. В противном случае поведение вашей программы не определено, если вы попытаетесь использовать неинициализированное значение. Обратите внимание, что есть особый случай: new int[100]() который приведет к нулевой инициализации памяти. Но вы не можете использовать эту конструкцию для инициализации с любым другим значением.

Рассмотрите возможность использования std::vector , чтобы избежать проблем с управлением памятью и обеспечить инициализацию с ненулевыми значениями без добавления помех в коде:

 std::vectorlt;intgt; arr(10, NoValue);  

Как вы можете видеть, необходимо сделать выбор, который зависит от требований вашей программы и ее входной спецификации. Я надеюсь, что это поможет вам принять более обоснованное решение.

Ответ №2:

должен ли я просто заполнить пустой массив каким-то произвольным значением, которое вряд ли появится в моем наборе данных

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

Однако в тех случаях, когда такого значения нет, или просто для того, чтобы однозначно заявить о своем намерении, канонический способ справиться с этой ситуацией в современном C — использовать std::optionallt;intgt; . Стандартная библиотека-это optional способ превратить любой тип в тип, допускающий обнуление.

Ответ №3:

Пожалуйста, обратите внимание, что вопросы «вкуса», как правило, не одобряются в StackOverflow.

С учетом сказанного, вот мои предпочтения:

Что-то, что не может маскироваться под допустимое значение, например NaN, является хорошим заполнителем. Если это не вариант, то, как вы сказали, значение, которое не будет/не разрешено отображаться в наборе данных, работает.

Комментарии:

1. NaN-это специальное значение с плавающей запятой. Вопрос конкретно касается целых чисел. Что касается NaN, да, это может быть уместно для данных с плавающей запятой, но создает свои собственные проблемы. Не в последнюю очередь потому, что NaN-тестирование отличается от равенства, а значения NaN в целом нарушают все логические и арифметические операторы.

2. Я вижу, как сбивает с толку мой язык. Я имел в виду НаН или что-то вроде Нан. Я также учел, что это не вариант. «Значения NaN в целом нарушают все логические и арифметические операторы» Да, в этом все дело. это будет болезненно очевидно, когда что-то будет сделано с недопустимыми значениями.