Как проверить, «установлен» ли в c - PullRequest
6 голосов
/ 05 сентября 2010

Если я выделю массив C следующим образом:

int array[ 5 ];

Затем установите только один объект:

array[ 0 ] = 7;

Как проверить, все ли ключи (array[1], array[2],…) хранят значения? (В данном случае, конечно, это не так.)

Есть ли такая функция, как PHP isset()?

if ( isset(array[ 1 ]) ) ...

Ответы [ 6 ]

6 голосов
/ 05 сентября 2010

В Си нет таких вещей, как содержимое статического массива всегда "установлено".Однако вы можете указать какое-то специальное значение, чтобы представить, что оно не инициализировано, например,

// make sure this value isn't really used.
#define UNINITIALIZED 0xcdcdcdcd

int array[5] = {UNINITIALIZED, UNINITIALIZED, UNINITIALIZED, UNINITIALIZED, UNINITIALIZED};

array[0] = 7;

if (array[1] != UNINITIALIZED) {
   ...
6 голосов
/ 05 сентября 2010

Вы не можете

Там все значения не определены (то есть случайны).

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

int array[ 5 ] = {};

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

int array[ 5 ]   = {};  // Init all to 0
int isSet[ 5 ]   = {};  // Init all to 0 (false)

int getVal(int index)          {return array[index];}
int isSet(int index)           {return isSet[index];}
void setVal(int index,int val) {array[index] = val; isSet[index] = 1; }
2 голосов
/ 06 сентября 2010

Я не знаю php, но здесь происходит одна из двух вещей

  • массив php на самом деле является хеш-картой (это делает awk)
  • массив php заполняется обнуляемыми типами

в любом случае существует значимое понятие "не установлено" для значений массива. С другой стороны, массив c встроенного типа всегда имеет значение some в каждой ячейке. Если массив неинициализирован и является автоматическим или был размещен в куче, эти значения могут быть случайными, но они существуют.

Чтобы узнать поведение php:

  • Реализуйте (или найдите библиотеку с умом) и используйте вместо этого хеш-карту в массиве.
  • Сделать массив структур, включающих поле isNull.
  • Инициализировать массив некоторым часовым значением во всех ячейках.
2 голосов
/ 05 сентября 2010

В C все элементы будут иметь значения (мусор) во время выделения.Таким образом, вы не можете иметь функцию, подобную той, которую вы запрашиваете.

Однако вы можете по умолчанию заполнить ее некоторыми стандартными значениями, такими как 0 или INT_MIN, используя memset (), а затем написать код isset ().

1 голос
/ 06 сентября 2010

Мне нравится подход, состоящий в том, чтобы создать 2 массива, один для обозначения битового массива, какие индексы массива установлены, а другой, содержащий фактические значения. Даже в тех случаях, когда вам не нужно знать, установлен ли элемент в массиве или нет, это может быть полезной оптимизацией. Обнуление массива битов 1 бит на элемент происходит намного быстрее, чем инициализация массива 8 байт на элемент, равного size_t, особенно если массив будет оставаться разреженным (в основном незаполненным) в течение всего времени жизни.

Один практический пример, где я использовал этот трюк, - функция поиска подстроки, использующая таблицу пропуска плохих символов в стиле Бойера-Мура. Таблица требует 256 записей типа size_t, но необходимо заполнить только те, которые соответствуют символам, которые фактически появляются в строке иглы. 1 КБ (или 2 КБ на 64-битной) memset будет преобладать в использовании ЦП в случае очень коротких поисков, что приведет к тому, что другие реализации будут вынуждены обходить эвристику, независимо от того, будет ли использоваться таблица. Но вместо этого я оставил таблицу пропусков неинициализированной и использовал 256-битный битовый массив (всего 32 байта для подачи в memset), чтобы указать, какие записи используются.

1 голос
/ 05 сентября 2010

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

Вы также можете использовать указатели. Вы можете использовать нулевые указатели для представления данных, которые еще не были назначены. Я сделал пример ниже:

int * p_array[3] = {NULL,NULL,NULL};
        p_array[0] = malloc(sizeof(int));
        *p_array[0] = (int)0;
        p_array[2] = malloc(sizeof(int));
        *p_array[2] = (int)4;
        for (int x = 0; x < 3; x++) {
            if (p_array[x] != NULL) {
                printf("Element at %i is assigned and the value is %i\n",x,*p_array[x]);
            }else{
                printf("Element at %i is not assigned.\n",x);
            }
        }

Вы можете создать функцию, которая выделяет память и устанавливает данные, и другую функцию, которая работает как функция isset в PHP, протестировав для вас NULL.

Надеюсь, это поможет вам.

Редактировать: Убедитесь, что память освобождена после того, как вы закончили. Другая функция может использоваться для освобождения определенных элементов или всего массива.

Я использовал указатели NULL прежде, чтобы показать, что данные еще не созданы или должны быть воссозданы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...