Поиск пустых значений в несуществующем массиве:
*NL arrpos('probe659', 0) *NL arrpos('$probe659', '')
вернёт позицию 0, т. е. первую позицию массива, хотя, по-хорошему, хотелось бы получать -1, то есть "не найдено".
Неактивен
Неинициализированные переменные и ячейки массивов, числовые и текстовые, имеют значения по умолчанию '' и 0 соответственно.
Если 0 не найден в массиве, то он будет найден сразу за последним элементом массива(в нулевой позиции, если массив пуст), то бишь в первой же неинициализированной ячейке.
При этом стоит учесть то обстоятельство, что массивы неразрывны и "пробелов" между элементами нет: массив располагает свои элементы в ячейках от 0 до N - 1, где N - количество всех существующих элементов массива.
по-хорошему, хотелось бы получать -1, то есть "не найдено"
Оба поведения корректны в своем контексте. Вопрос же заключается в том, какое предпочтительнее для авторов.
Существующий вариант выгоднее тем авторам(A), для которых нет различий между "присвоенным"(инициализированным) значением 0 и "пустым"(неинициализированным), использующим массивы в заранее определенном диапазоне индексов.
Вариант с поиском исключительно инициализированных значений удобнее тем авторам(B), у которых "полезными" считаются значения инициализированные, а "бесполезными" - неинициализированные, при этом длина массива варьируется.
Минус первого варианта для авторов A и B - им придется делать проверку на выход за границы массива при поиске нулевых значений.
Минус второго варианта для авторов A - для работы с массивами им придется инициализировать их нулями. Это противоречит правилу QSP, перенятому из Бэйсика: неинициализированный массив считается заполненным нулями. Придется вводить явное различие между инициализированным значением и неинициализированным(сейчас оно тоже есть, но неявное). С другой стороны, в Бэйсике массивы заранее объявленной длины, поэтому там контекст немного другой.
Отредактировано Nex (06.09.2011 22:56)
Неактивен
Проблем с тем, что содержимое массива внутри интервала автоматически заполняется (или считается заполненным) нулями, нет. Однако ситуация, когда результат поиска возвращает результат, лежащий по сути вне пределов массива (который задал автор), довольно необычна.
Вдогонку к первому примеру код
probe[0]=10 probe[1]=20 probe[2]=30 *NL ARRSIZE('probe') *NL ARRPOS('probe', 0)
вернёт размер массива, равный трём элементам, а позицию нуля — в четвёртом элементе.
Неактивен
Как раз в QSP-то, в отличие Бэйсика, размер массива и не задается!
Я писал об этом в предыдущем сообщении.
Массив считается теоретически бесконечным. Автор при использовании просто пользуется любыми ячейками массива на свое усмотрение.
Кстати, я был неправ насчет "пробелов" - они-таки инициализируются нулевыми значениями, начиная с нулевого индекса. Т.е. такой эксперимент:
probe[1]=20 probe[3]=30 ARRSIZE('probe')
выведет "4"!
Таким образом, весь интервал индексов, между последним инициализированным и нулевым(включительно), будет всегда заполнен как минимум "настоящими" нулями. Эта техника оказалась хитрее, чем я предполагал.
Но нулями он заполняется при присваивании. А как же удаление отдельных элементов через KILLVAR? Но KILLVAR тоже не оставляет пробелов! Как только из массива 1, 2, 3 мы удаляем 2, то получаем массив 1, 3 - два элемента на позициях 0 и 1 соответственно. "Хвост" массива сдвигается влево на 1, сохраняя массив неразрывным.
Раз целостность массивов сохраняется, то, пожалуй, стоит пересмотреть свои выводы.
Неактивен
Nex написал:
Как раз в QSP-то, в отличие Бэйсика, размер массива и не задается!
Я писал об этом в предыдущем сообщении.
Массив считается теоретически бесконечным. Автор при использовании просто пользуется любыми ячейками массива на свое усмотрение.
Ну так я говорю не про указание максимальной размерности массива, а про то, каким этот массив представляет себе автор.
Даже если он учитывает нюансы автоматического заполнения интервалов в массиве, то после выполнения такой конструкции:
probe[3]=30
то есть ручного заполнения четвёртого элемента массива (и первых трёх — в автоматическом режиме), он ожидает, что размер массива будет равен 4. Если же он потом заполнит первые три элемента ненулевыми значениями, размер будет всё также равен 4. Но если он после этого поищет в массиве (ВСЕ элементы которого он же заполнил ненулевыми значениями) значение "0" — QSP вернёт ему позицию несуществующего с точки зрения автора пятого элемента.
Неактивен
Пересмотрел выводы, отредактировал первое сообщение. Оба варианта имеют свои недостатки.
Хорошим решением, теоретически, был бы ввод необязательного параметра, определяющего предполагаемый размер массива. Если указан - ищем значение в указанных пределах по первому способу, если не указан - в существующих элементах массива по второму. Беда в том, что авторам такие тонкости будет очень трудно объяснить.
Неактивен
Nex написал:
Хорошим решением, теоретически, был бы ввод необязательного параметра, определяющего предполагаемый размер массива. Если указан - ищем значение в указанных пределах по первому способу, если не указан - в существующих элементах массива по второму. Беда в том, что авторам такие тонкости будет очень трудно объяснить.
Зачем так усложнять для автора? Не проще всё же в реализации самой функции (на уровне платформы) ввести проверку на размер массива? Например, если найденная позиция больше размера массива — значит, ничего не нашли.
Ведь если автор укажет, что
probe[4]=0 *NL ARRPOS('probe', 0)
то функция отрабатывает вполне корректно и возвращает "4".
Неактивен
Затем, что благодаря отсутствию явного задания длины массива, есть два способа их использования, я об этом писал выше.
Если автор использует массив самым простым способом - задав некую переменную(L), определяющую размер массива, то при заполнении произвольных ячеек внутри выбранного автором диапазона, размер полученного массива запросто может не совпасть с L. И вот тут-то, при поиске нулевых значений, в предложенном тобою варианте мы будем искать не по всей длине L, а лишь по отрезку заполненных элементов. Из-за этого придется явно инициализировать массив, о том, чем это плохо, я тоже писал. Перечитай.
Неактивен
Nex написал:
Затем, что благодаря отсутствию явного задания длины массива, есть два способа их использования, я об этом писал выше.
Если автор использует массив самым простым способом - задав некую переменную(L), определяющую размер массива, то при заполнении произвольных ячеек внутри выбранного автором диапазона, размер полученного массива запросто может не совпасть с L. И вот тут-то, при поиске нулевых значений, в предложенном тобою варианте мы будем искать не по всей длине L, а лишь по отрезку заполненных элементов. Из-за этого придется явно инициализировать массив, о том, чем это плохо, я тоже писал. Перечитай.
Перечитал. В своём описании порядка работы с массивами в QSP ты как-то всё усложнил, смешав как есть и как могло бы быть.
С точки зрения автора всё организовано просто (я не буду говорить про строковые индексы — они не влияют на суть):
Однако, несмотря на "свободную расширяемость" массива, в каждый конкретный момент времени он (массив) имеет вполне определённый фактический размер (который можно получить функцией ARRSIZE), и этот размер автору либо уже известен, либо он его может получить. Так вот, возвращать функцией поиска значение индекса массива, который лежит вне этого диапазона, — на мой взгляд некорректно.
Отсюда и предложение — на уровне платформы ограничить верхний предел обработки массива функцией ARRPOS его фактическим размером, то есть тем значением, которое можно получить функцией ARRSIZE.
Неактивен
Но нулями он заполняется при присваивании. А как же удаление отдельных элементов через KILLVAR? Но KILLVAR тоже не оставляет пробелов! Как только из массива 1, 2, 3 мы удаляем 2, то получаем массив 1, 3 - два элемента на позициях 0 и 1 соответственно. "Хвост" массива сдвигается влево на 1, сохраняя массив неразрывным.
Вот этот нюанс на самом деле напрягает. Грубо говоря, задавая конкретное значение элементу массива, я рассчитываю что оно таким и останется.
Например, я пишу:
probe[4]=10
а потом, поигравшись с killvar пытаюсь поработать с этим элементом, но там неожиданно оказывается другое значение. Пока у меня таких глюков не было, и теперь, зная как это работает, наверное не допущу такой ошибки, но мог бы.
PS Кстати, а если используется строковая индексация? Происходит смещение по индексам, или индекс сохраняется за элементом массива вне зависимости от того, где он находится?
Отредактировано WladySpb (08.09.2011 12:30)
Неактивен
WladySpb написал:
задавая конкретное значение элементу массива, я рассчитываю что оно таким и останется.
Например, я пишу:Код:
probe[4]=10а потом, поигравшись с killvar пытаюсь поработать с этим элементом, но там неожиданно оказывается другое значение. Пока у меня таких глюков не было, и теперь, зная как это работает, наверное не допущу такой ошибки, но мог бы.
Если ты рассчитываешь на неизменность порядка элементов массива, то не нужно удалять элементы — достаточно их просто очищать, вот и всё…
Неактивен
Строковая индексация:
A["a"]="aaa" A["b"]="bbb" A["c"]="ccc"
Имеем:
A[0]="aaa", A["a"]="aaa"
A[1]="bbb", A["b"]="bbb"
A[2]="ccc", A["c"]="ccc"
Далее,
KILLVAR "A", 1
Имеем:
A[0]="aaa", A["a"]="aaa"
A[1]="ccc", A["c"]="ccc"
Т.о., числовые индексы поменялись, но это для нас неважно, т.к. мы пользуемся строковыми.
Что интересно, KILLVAR не поддерживает строковые индексы. Недоработка. Приходится явно указывать соответствующий числовой индекс.
Неактивен
Nex написал:
Что интересно, KILLVAR не поддерживает строковые индексы. Недоработка. Приходится явно указывать соответствующий числовой индекс.
На эту "недоработку" я давно уже пытался обратить внимание.
Пока же для реализации удаления элемента по строковому ключу я пользуюсь такой функцией:
#УдалитьИзМассиваПоКлючу ! Параметры ! 1. 0 - Имя массива (тип: строка) ! 2. 1 - Строковый ключ удаляемого элемента (тип: строка) !---------- dynamic "$<<$ARGS[0]>>[$ARGS[0]] = '!@#$%^del^%$#@!'", $ARGS[1] killvar $ARGS[0], arrpos('$' + $ARGS[0], '!@#$%^del^%$#@!') !---------- --- УдалитьИзМассиваПоКлючу
Суть работы функции:
Неактивен
Переименовал тему "Поиск нуля в несуществующем массиве" в "Особенности работы с массивами в QSP".
Неактивен
Повторяю, есть два способа работы с массивами. Один из них опирается на "реальный размер массива", всегда известный через ARRSIZE, другой - на заданный автором диапазон.
Твое решение подходит только для тех, кто работает по первому способу.
На эту "недоработку" я давно уже пытался обратить внимание.
А кто помешал? Взял бы и обратил внимание, мое или Байта. На форумах ты об этом не писал.
Отредактировано Nex (08.09.2011 15:50)
Неактивен
Nex написал:
Повторяю, есть два способа работы с массивами. Один из них опирается на "реальный размер массива", всегда известный через ARRSIZE, другой - на заданный автором диапазон.
Твое решение подходит только для тех, кто работает по первому способу.
А можно привести код с примером работы по второму варианту (где автор задаёт диапазон), чтобы понимать, чем же это отличается от "реального размера массива"?
Неактивен