Что нового

автоматическое дополнение двумерного массива

running-frag

why me?
Сообщения
441
Репутация
60
допустим есть
Код:
Local $data[1][3]

как нам добавить вот такое
Код:
$data[2][1] = ""
$data[2][2] = ""
$data[2][3] = ""

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

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
running-frag,
Попробуйте так.
Код:
#include <Array.au3>

Dim $aArray[1][3] = [['Test00', 'Test01', 'Test02']]
$sString = 'Test1'
For $i = 1 To 10
	ConsoleWrite($sString & @LF)
	_ArrayAdd2D($aArray, $sString)
	_ArrayDisplay($aArray, $i & ' (10)')
	$sString &= '|Test' & $i + 1
Next

Func _ArrayAdd2D(ByRef $a_Array, $s_Value, $s_Delim = '|')
	Local $i_UBound_1D, $i_UBound_2D, $i_UBound_Value, $a_Value, $s_LastString, $i_End

	If UBound($a_Array, 0) <> 2 Then Return SetError(1, 0, -1)
	If Not IsString($s_Value) Then Return SetError(2, 0, -1)
	$i_UBound_1D = UBound($a_Array)
	$i_UBound_2D = UBound($a_Array, 2)
	$a_Value = StringSplit($s_Value, $s_Delim, 2)
	$i_UBound_Value = UBound($a_Value)
	$i_End = $i_UBound_Value - 1
	If $i_UBound_Value > $i_UBound_2D Then
		$i_End = $i_UBound_2D - 1
		For $i = $i_UBound_2D To $i_UBound_Value - 1
			$s_LastString &= $a_Value[$i] & $s_Delim
		Next
		$s_LastString = StringTrimRight($s_LastString, 1)
	EndIf
	ReDim $a_Array[$i_UBound_1D + 1][$i_UBound_2D]
	For $i = 0 To $i_End
		$a_Array[$i_UBound_1D][$i] = $a_Value[$i]
	Next
	If $s_LastString Then
		$a_Array[$i_UBound_1D][$i_UBound_2D - 1] &= $s_Delim & $s_LastString
	EndIf
	Return $i_UBound_1D
EndFunc   ;==>_ArrayAdd2D
Или так.
Код:
#include <Array.au3>

Dim $aArray[1][3] = [['Test00', 'Test01', 'Test02']]
Global $sString = 'Test1'
For $i = 1 To 10
	ConsoleWrite($sString & @LF)
	_ArrayAdd2D_1($aArray, $sString)
	_ArrayDisplay($aArray, $i & ' (10)')
	$sString &= '|Test' & $i + 1
Next

Func _ArrayAdd2D_1(ByRef $a_Array, $s_Value, $s_Delim = '|')
	Local $i_UBound_1D, $i_UBound_2D, $i_UBound_Value, $a_Value

	If UBound($a_Array, 0) <> 2 Then Return SetError(1, 0, -1)
	If Not IsString($s_Value) Then Return SetError(2, 0, -1)
	$i_UBound_1D = UBound($a_Array)
	$i_UBound_2D = UBound($a_Array, 2)
	$a_Value = StringSplit($s_Value, $s_Delim, 2)
	$i_UBound_Value = UBound($a_Value)
	If $i_UBound_Value > $i_UBound_2D Then
		ReDim $a_Array[$i_UBound_1D + 1][$i_UBound_Value]
	Else
		ReDim $a_Array[$i_UBound_1D + 1][$i_UBound_2D]
	EndIf
	For $i = 0 To $i_UBound_Value - 1
		$a_Array[$i_UBound_1D][$i] = $a_Value[$i]
	Next
	Return $i_UBound_1D
EndFunc   ;==>_ArrayAdd2D_1
 
Автор
R

running-frag

why me?
Сообщения
441
Репутация
60
да оно, работает спасибо, другими словами нам нужно "затереть существующий и воссоздать новый"

у меня не получалось это всё дело из за Local, у меня бОльшая часть переменных именно такая, отсюда вопрос чем (на практике) отличается Dim от Local?
ну то что они не Global я понял, тем что если есть Global $var тогда при Dim $var мы перезапишем значение $var? а в случае Local $var даст ошибку, так? вот этом у меня путанница :(


Добавлено:
Сообщение автоматически объединено:

а вот эта строка самая интересная
Код:
ReDim $a_Array[$i_UBound_1D + 1][$i_UBound_2D]

в $a_Array у нас что? "хэндл" (ссылка на массив как в питоне)? немного не ясно как пересоздаётся "внешний" массив $aArray (вне функции _ArrayAdd2D ())
 
Автор
R

running-frag

why me?
Сообщения
441
Репутация
60
так что никто не знает? :( по прежднему не ясно два пред. поста
 

Garrett

Модератор
Локальный модератор
Сообщения
3,999
Репутация
967
running-frag [?]
по прежднему не ясно два пред. поста
Что конкретно неясно?

[?]
в $a_Array у нас что? "хэндл" (ссылка на массив как в питоне)?
Нет не handle. Это размерность массива, то есть массив инициализируется заново с новой размерностью.
Код:
$i_UBound_1D = UBound($a_Array)
$i_UBound_2D = UBound($a_Array, 2)
ReDim $a_Array[$i_UBound_1D + 1][$i_UBound_2D]
 

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4,020
Репутация
626
running-frag [?]
в $a_Array у нас что? "хэндл"
типа того. если обратишь внимание на определении функции,
Код:
Func _ArrayAdd2D_1(ByRef $a_Array, $s_Value, $s_Delim = '|')

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

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Global - объявление глобальных переменных, т.е. эти переменные действительны в любое время и в любом месте кода, в том числе и в функциях. Сохраняются на все время работы кода или до тех пор, пока вы сами их не уничтожите.

Local - объявление локальных переменных. Используется только внутри функций. Такие переменные действительны только внутри той функции, в которой были объявлены, и будут автоматически уничтожены после выхода из этой функции.

Если Local стоит не внутри функции, а в теле основного кода, то это эквивалентно Global, но является плохим стилем написания кода.

Dim - объявление массива. Т.к. массивы могут быть объявлены с помощью Global и Local, то, чтобы избежать путаницы, не рекомендуется использовать Dim там, где можно обойтись без этого.

ReDim - Изменение длины ранее созданного массива. При этом данные, которые находились в массиве сохраняются (если, конечно, длина массива увеличивается, а не уменьшается).

Код:
; Это глобальные переменные, к ним можно обращаться в лубом месте кода
Global $A = 0
Global $B = 10

Func MyFunc()
	
	Local $C[2] = [$A, $B] ; $C объявлена как массив и содержит значения глобальных переменных $A и $B
	
	...
	
	$C = 0 ; Нет массива, $C = 0
	
	...
	
	Dim $C[2] = [$A, $B] ; $C опять стала массивом
	
	...
	
	ReDim $C[3] ; Увеличиваем длину массива с 2 до 3, при этом значения первых двух ячеек массива не изменились, т.е. $C[0] = $A и $C[1] = $B

	$C[2] = $A + $B ; Присваиваем третьей ячейки массива какое-нибудь значение
	
	...
	
EndFunc
 

gregaz

AutoIT Гуру
Сообщения
1,166
Репутация
299
На офф. сайте и др. полно готовых ф-ий.
Вот пример простой универсальной ф-ии __ArrayAdd

Код:
#include <Array.au3>

Dim $avArray[5][3] = [ _
[5, 20, 8], _
[4, 32, 7], _
[3, 16, 9], _
[2, 35, 0], _
[1, 19, 6]]

$vValue="a|b|c"

_ArrayDisplay($avArray)
__ArrayAdd($avArray, $vValue)
_ArrayDisplay($avArray)

; #FUNCTION# ====================================================================================================================
; Name...........: _ArrayAdd
; Description ...: Adds a specified value at the end of an existing array. Also will add a delimited string to a 2D array.
; Syntax.........: _ArrayAdd(ByRef $avArray, $vValue)
; Parameters ....: $avArray - Array to modify
;                  $vValue  - Value to add
; Return values .: Success - Index of last added item
;                  Failure - -1, sets @error
;                  |1 - $avArray is not an array
;                  |2 - $avArray is not a 1 or 2 dimensional array
;                  |3 - $vValue has too many subitems
; Author ........: Jos van der Zande <jdeb at autoitscript dot com>
; Modified.......: Ultima - code cleanup, BrewManNH - 2D array support
; Remarks .......:
; Related .......: _ArrayConcatenate, _ArrayDelete, _ArrayInsert, _ArrayPop, _ArrayPush
; Link ..........:
; Example .......: Yes
; ===============================================================================================================================
Func __ArrayAdd(ByRef $avArray, $vValue, $sSeparator = "|")
	If Not IsArray($avArray) Then Return SetError(1, 0, -1)
	If UBound($avArray, 0) > 2 Then Return SetError(2, 0, -1)
	Local $avValue = StringSplit($vValue, $sSeparator)
	If Not @error Then
		ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $avValue = ' & $avValue & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console
		$iSubMax = $avValue[0]
		If $iSubMax <> UBound($avArray, 2) Then Return SetError(3, 0, 0)
	EndIf
	If UBound($avArray, 0) = 1 Then
		Local $iUBound = UBound($avArray)
		ReDim $avArray[$iUBound + 1]
		$avArray[$iUBound] = $vValue
		Return $iUBound
	Else
		Local $iUBound = UBound($avArray)
		ReDim $avArray[$iUBound + 1][$iSubMax]
		For $i = 0 To $iSubMax - 1
			$avArray[$iUBound][$i] = $avValue[$i + 1]
		Next
		Return $iUBound
	EndIf
EndFunc   ;==>_ArrayAdd


Источник : http://www.autoitscript.com/forum/topic/131676-modified-version-of-the-standard-arrayau3-include-file/
 
Автор
R

running-frag

why me?
Сообщения
441
Репутация
60
Yashied [?]
Local - объявление локальных переменных. Используется только внутри функций. Такие переменные действительны только внутри той функции, в которой были объявлены, и будут автоматически уничтожены после выхода из этой функции.Если Local стоит не внутри функции, а в теле основного кода, то это эквивалентно Global, но является плохим стилем написания кода.Dim - объявление массива. Т.к. массивы могут быть объявлены с помощью Global и Local, то, чтобы избежать путаницы, не рекомендуется использовать Dim там, где можно обойтись без этого.
всё равно не могу понять, надо время поиграться с этим, мозг пережуёт я переиначу вопрос :(

как использывать Global это понятно
внутри функциях я использую Local (это нормально?)
если мы используем Local для того что б обьявить массив внутри фукнции это нормально?
Dim используется только для массивов?

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


если обобщить то получается что Dim используется только для массивов, а всё остальное Global + Local так?


Kaster [?]
то увидишь, что $a_Array передается по указателю. все остальные переменные просто копируются в локальное окружение. то есть если ты внутри функции изменишь $s_Value то за пределами функции с этой переменной ничего не произойдет. а вот если изменишь $a_Array то изменения коснутся и той переменной, которую передаешь.
бинго! спасибо уяснил (т.е. как в питоне) передаётся ссылка на переменные (массив) которые находятся ВНЕ функции, всё стало на свои места (с этим разобрался)
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
running-frag сказал(а):
если обобщить то получается что Dim используется только для массивов, а всё остальное Global + Local так?

Если обобщить, то получается так: любые переменные (и массив в том числе) нужно объявлять с помощью Global или Local, а Dim и ReDim используются только для ранее объявленных переменных. Первая создает массив для любой переменной, вторая - переразмеривает уже созданный массив.

running-frag сказал(а):
бинго! спасибо уяснил (т.е. как в питоне) передаётся ссылка на переменные (массив) которые находятся ВНЕ функции, всё стало на свои места (с этим разобрался)

Это только, если стоит ByRef перед переменной в заголовке функции. В противном случае, весь массив будет скопирован во внутренний стек функции и $a_Array будет ссылаться уже на новый массив. Следовательно, любые изменения массива будут действовать только в пределах этой функции. При выходе из функции, ее стек уничтожается, и все локальные переменные, соответственно, тоже будут уничтожены. Есть еще вариант Const ByRef, это аналогично ByRef, но только при попытке изменить массив внутри функции будет ошибка.

Кстати, структуры всегда передаются в функцию как ByRef, независимо от того, указана она или нет, стоит ли Const или нет.

Код:
$tData = DllStructCreate('dword')

ConsoleWrite(DllStructGetData($tData, 1) & @CR)

_MyFunc($tData)

ConsoleWrite(DllStructGetData($tData, 1) & @CR)

Func _MyFunc($tData)
	DllStructSetData($tData, 1, 1)
EndFunc
 
Автор
R

running-frag

why me?
Сообщения
441
Репутация
60
разобрался кажись :smile: спасибо
по поводу ByRef тоже сообразил но не стал постить, и так уже раза 4 редактировал старый пост :rofl:

спасибо всем
 

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4,020
Репутация
626
Yashied [?]
Есть еще вариант Const ByRef, это аналогично ByRef, но только при попытке изменить массив внутри функции будет ошибка.
непонятно, зачем передавать такой массив в функцию :smile:
на других языках массивы передаются по указателю для объявления процедур, то есть когда при выполнении кода возвращается не значение а проделываются манипуляции. это экономит память, т.к. не создается лишняя структура. а вот зачем передавать массив по указателю, если с ним в дальнейшем не работать, не знаю :smile:

хотя, предположу, что по той же причине, экономия памяти, а Const для защиты от изменений самим собой :D
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Kaster сказал(а):
...а Const для защиты от изменений самим собой :D

Или для защиты от изменений какими-либо UDF.
 
Автор
R

running-frag

why me?
Сообщения
441
Репутация
60
Код:
Local $_ini = "string"
...	
	$_ini = IniReadSection ($sFile_overview, "icon") ; тут впереди должен быть Dim (т.к. функция отдаёт массив)


правильно понял? и второй вариант
Код:
Local $_ini

	$_ini = IniReadSection ($sFile_overview, "icon") ; а тут должен быть Dim?
 

AZJIO

Меценат
Меценат
Сообщения
2,874
Репутация
1,194
running-frag
Функции (IniReadSection, StringSplit, WinList, ProcessList, StringRegExp и т.д.), которые возвращают массив в переменную, которую не обязательно объявлять с помощью Dim, так как с помощью Dim нужно определить размер массива, но функции сами его задают при выполнении. Насколько я понял Dim всего лишь пересоздаёт пустой массив с новым размером если он был уже объявлен с помощью Global или Local.
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
running-frag

В AutoIt все переменные имеют тип Variant, т.е. не имеют постоянного типа. В любой момент можно из массива сделать строку и наоборот. Поэтому, как они будут объявлены в Global или Local не имеет особого значения, это нужно только для инициализации.

Для проверки того или иного типа есть ряд функций типа IsArray(), IsString(), IsInt() и т.д. Если в описании функции сказано, что она возвращает массив, то, если не произошло ошибки, и нужно с этой переменной работать как с массивом.

Код:
Global $Var = 0 ; Целочисленный тип

...

$Var = StringLeft('0|1|2|3|4', 5) ; Строковый тип

...

$Var = StringSplit($Var, '|') ; Массив

...

$Var = $Var[0] / 3 ; Вещественный тип

...

$Var = Floor($Var) ; опять целочисленный тип
 
Верх