Автокликер Clickermann :: Форум
Основной раздел => Ошибки => Topic started by: Vint on July 09, 2014, 10:59:53 AM
-
Переменная содержащая массив не передаётся в качестве параметра для подпрограммы.
От массива остаётся нулевой элемент.
LOGCLEAR
SUB(LOG_ARR, $ARR_LOG)
LOGWRITE ("Размер массива: ",ARRSIZE($ARR_LOG))
FOR($INARR,$INARR<ARRSIZE($ARR_LOG))
LOGWRITE ("[",$INARR,"] = ",$ARR_LOG[$INARR])
END_CYC
LOGWRITE (" ")
END_SUB
ARRPUSH($arr, 5)
ARRPUSH($arr, 6)
ARRPUSH($arr, 7)
ARRPUSH($arr, 8)
LOGWRITE ("Настоящий размер ", ARRSIZE($arr))
LOGWRITE ("Подпрограмма:")
LOG_ARR($arr)
Лог:
11:59:33 Настоящий размер 4
11:59:33 Подпрограмма:
11:59:33 Размер массива: 1
11:59:33 [0] = 5
11:59:33
-
В данном скрипте происходит следующее...
1 часть - Здесь наращивается до бесконечности массив $arr, и выводится размер этого массива в лог.
ARRPUSH($arr, 5)
ARRPUSH($arr, 6)
ARRPUSH($arr, 7)
ARRPUSH($arr, 8)
LOGWRITE ("Настоящий размер ", ARRSIZE($arr))
LOGWRITE ("Подпрограмма:")
LOG_ARR($arr)
2 часть - Здесь вызывается описанная ранее подпрограмма LOG_ARR($arr) с параметром, отличным от параметра в описании подпрограммы. Происходит всего лишь запись в лог - "Размер массива: 1".
LOG_ARR($arr)
3 часть - А подпрограмма SUB(LOG_ARR, $ARR_LOG) с параметром, хоть и описана, но больше нигде в скрипте не используется с этим параметром, переменная $ARR_LOG всегда будет иметь значение 0. А в лог выводится "Размер массива: ",ARRSIZE($ARR_LOG), всегда равный единице.
SUB(LOG_ARR, $ARR_LOG)
LOGWRITE ("Размер массива: ",ARRSIZE($ARR_LOG))
FOR($INARR,$INARR<ARRSIZE($ARR_LOG))
LOGWRITE ("[",$INARR,"] = ",$ARR_LOG[$INARR])
END_CYC
LOGWRITE (" ")
END_SUB
Или я чего то не понял, или это развод...
-
Или я чего то не понял, или это развод...
Ты не понял.
В чём состоит развод?
В данном скрипте происходит следующее...
1 часть - Здесь наращивается до бесконечности массив $arr, и выводится размер этого массива в лог.
Почему до бесконечности? Это пример для демонстрации набросан на коленке. И т.к. предназначается не новичкам то не указан HALT и прочая лабуда.
2 часть - Здесь вызывается описанная ранее подпрограмма LOG_ARR($arr) с параметром, отличным от параметра в описании подпрограммы...".
Как может быть параметр отличный. У нас параметры позиционные, а не именованные. Там при передаче вообще могло стоять число без всякого имени. ???
Мы передаём в подпрограмму ЗНАЧЕНИЕ параметра, а не его имя. В подпрограмме, в заголовке, значение присваивается переменной.
...переменная $ARR_LOG всегда будет иметь значение 0...
3. тоже неправильно, т.к. неправильно второе.
Переменная $ARR_LOG не имеет значение 0 она имеет значение
[0]-го элемента массива,
в данном примере 5
-
Ну очевидно что в подпрограмме применять массив в качестве параметра нельзя. Это не ошибка. Просто это не реализовано пока что.
Передается только одна строка, нужно указать её
LOGCLEAR
SUB(LOG_ARR, $ARR_LOG)
LOGWRITE ("Размер массива: ",ARRSIZE($ARR_LOG))
FOR($INARR,$INARR<ARRSIZE($ARR_LOG))
LOGWRITE ("[",$INARR,"] = ",$ARR_LOG[$INARR])
END_CYC
LOGWRITE (" ")
END_SUB
ARRPUSH($arr, 5)
ARRPUSH($arr, 6)
ARRPUSH($arr, 7)
ARRPUSH($arr, 8)
LOGWRITE ("Настоящий размер ", ARRSIZE($arr))
LOGWRITE ("Подпрограмма:")
LOG_ARR($arr[2])
HALT
Лог
16:30:46 Настоящий размер 4
16:30:46 Подпрограмма:
16:30:46 Размер массива: 1
16:30:46 [0] = 7
16:30:46
-
А почему тогда так работает?
LOGCLEAR
ARRPUSH($arr, 5) // Создаем массив из четырех элементов
ARRPUSH($arr, 6)
ARRPUSH($arr, 7)
ARRPUSH($arr, 8)
LOGWRITE ("Размер массива = ", ARRSIZE($arr)) // Проверяем размер массива
//--------------------------------
SUB(LOG_ARR, $arr)
ARRPUSH($arr, 9) // Добавим элементов в массив
ARRPUSH($arr, 10)
ARRPUSH($arr, 11)
LOGWRITE ("Действия с параметром подпрограммы: (вывод в лог значений элементов массива)")
FOR($INARR,$INARR<ARRSIZE($arr))
LOGWRITE ("[",$INARR,"] = ",$arr[$INARR]) // Выводим в лог значения элементов массива
END_CYC
END_SUB
//--------------------------------
LOG_ARR($arr)
LOGWRITE (STRCONCAT("Новый размер массива = ", ARRSIZE($arr), " (т.к.локальные переменные подпрограммы (параметры) при этом будут уничтожены).")) // Повторно проверяем размер массива
HALT // Полная остановка выполнения скрипта (это я для себя)
-
при вызове саба с ключом(переменной) представляющей массив, она переиницилизируется в локальную переменную.
Зачем вообще нужно передавать массив в вызов саба, если внутри саба ваш заранее инициилизированый массив и так будет доступен, ведь в кликермане все переменные изначально публичны/глобальны.
-
Я и не говорю что это ошибка. Но в том виде как оно сейчас не есть хорошо. Я в курсе что тоже самое при выводе массива в лог.
Передавать нужно конечно не здесь. Это пример. Передавал я в саб в инклюде у которого свои имена переменных. Вся идея из-за этого провалилась. Помнить и использовать имена переменных в стандартных удобных инклюдах когда есть передача параметров не есть хорошо.
-
Дело тут в том что нельзя просто так скопировать массив
ARRPUSH($arr, 5)
ARRPUSH($arr, 6)
ARRPUSH($arr, 7)
ARRPUSH($arr, 8)
$arr2 = $arr // получим не копию а всего лишь одно значение
LOGWRITE ("размер ", ARRSIZE($arr2))
HALT
Тоже самое происходит и при передаче параметра
-
Это я знаю. Я и предлагал давно сделать копирование массивов простым присваиванием. Ответили, что скопировать в цикле не проблема.
Оно то не проблема, но ведь потянуло ещё несколько неприятностей.
Вот и рекомендую чтобы имя массива отдельно тоже означало/ссылалось на сам массив не только как аргументы функций.
Сейчас имя без индекса используется только внутри своих+поисковых функциях.
-
Не знаю на сколько актуально, и заранее извиняюсь за археологию, но даже при одной мысли о массовом использовании нечто подобного, сразу хочется ударить себя молотком по пальцам ;D
Зачем вообще нужно передавать массив в вызов саба, если внутри саба ваш заранее инициилизированый массив и так будет доступен, ведь в кликермане все переменные изначально публичны/глобальны.
Всё же не кошерно везду и всюду работать с глобальными переменными.
По этому в голову пришел примерно следующий костыль:
1) Перед передачей массива в процедуру преобразовывать его в строку(с разделителями, которые точно не будут попадатся в виде элементов массива)
2) Передавать в процедуру уже строку
3) В процедуре эту строку парсить по разделителям в массив и уже дальше с ним работать
В коде это должно выглядеть примерно так
SUB(ArrSmpl, $LocalString)
STRSEPARATE($LocalString,"_",$LocalArray) //парсим сроку в УЖЕ локальный массив по заранее заданному разделителю
FOR($i=0, $i < ARRSIZE($LocalArray))
LOGWRITE($LocalArray[$i]) //ну и дальше можно работать с элементами массива как нам удобно
END_CYC
END_SUB
$GlobalArray[0] = 1 //инициализируем переменные
$GlobalArray[1] = 2
$GlobalArray[2] = 3
$GlobalArray[3] = 4
$GlobalArray[4] = 5
$string = ""
FOR($i=0, $i < ARRSIZE($GlobalArray)) //запихиваем элементы массива в строку
$string = STRCONCAT($string,$GlobalArray[$i],"_") //разделителем в данном случае выступает нижнее подчеркивание
END_CYC
ArrSmpl($string)
HALT
По идее, аналогичным способом можно и возвращать массивы из процедур. Надеюсь кому-то будет полезным.
-
Уже давно есть GETVAR/SETVAR
SUB(_ARR_OUTPUT, $_arrName, $_strName, $_start, $_stop, $_step)
$_stop = $_stop*$_step
WHILE($_start*$_step <= $_stop)
SETVAR($_strName, STRCONCAT(GETVAR($_strName), GETVAR(STRCONCAT($_arrName, "[", $_start, "]"))))
INC($_start, $_step)
END_CYC
END_SUB
STRSEPARATE("0,1,2,3,4,5,6,7,8,9", ",", $arr)
$output_str = ""
_ARR_OUTPUT("$arr", "$output_str", ARRSIZE($arr)-1, INT(ARRSIZE($arr)/2), -1) // Заполнение строки в обратном порядке половиной массива
PRINT($output_str)
HALT
-
Уже давно есть GETVAR/SETVAR
Прикольное решение. Но всё равно это как-то ненормально. Действие же простое, зачем такие костыли. Ни в одном языке подобного не видел. Не говоря уж проотерю скорости на этих циклах преобразования.
Пока возьмём на заметку, но просим сделать нормальную передачу массивов (и присваивание заодно).
-
Это я знаю. Я и предлагал давно сделать копирование массивов простым присваиванием.
Пока возьмём на заметку, но просим сделать нормальную передачу массивов (и присваивание заодно).
Так уже все есть - ARRCONCAT
На деле это будет как-то так (не совсем то что требовалось, но работать должно быстро и без лишних заморочек):
LOGCLEAR
SUB(LOG_ARR)
LOGWRITE ("Размер массива: ",ARRSIZE($ARR_LOG))
FOR($INARR,$INARR<ARRSIZE($ARR_LOG))
LOGWRITE ("[",$INARR,"] = ",$ARR_LOG[$INARR])
END_CYC
LOGWRITE (" ")
END_SUB
ARRPUSH($arr, 5)
ARRPUSH($arr, 6)
ARRPUSH($arr, 7)
ARRPUSH($arr, 8)
LOGWRITE ("Настоящий размер ", ARRSIZE($arr))
LOGWRITE ("Подпрограмма:")
ARRCONCAT ($ARR_LOG, $arr)
LOG_ARR()
halt
23:18:07 Настоящий размер 4
23:18:07 Подпрограмма:
23:18:07 Размер массива: 4
23:18:07 [0] = 5
23:18:07 [1] = 6
23:18:07 [2] = 7
23:18:07 [3] = 8
23:18:07
-
Уже давно есть GETVAR/SETVAR
Да, тоже решение. Но как по мне - обращатся к элементам массива через array[index] всё же поудобней чем через конструкции GETVAR/SETVAR.
В прочем, описанный ранее мною способ подходит только для передачи данных "в". Для возвращения значений, вообще любых и массивов в частности, "из" процедуры без GETVAR/SETVAR не обойтись.
Так уже все есть - ARRCONCAT
На деле это будет как-то так (не совсем то что требовалось, но работать должно быстро и без лишних заморочек):
В данном примере всёравно процедура обращается к глобальной переменной. Суть темы же в том, чтобы передавать массив в процедуру параметром.
p.s. А что за функция ARRCONCAT такая? В версии 4.13 об ней не слова нету в справке.