Извините, ничего не найдено.

Не расстраивайся! Лучше выпей чайку!
Регистрация
Справка
Календарь

Вернуться   forum.boolean.name > Программирование игр для компьютеров > Blitz3D > Полезные функции

Полезные функции Выкладываем полезные функции, чтоб не изобретать велосипед заново...

Ответ
 
Опции темы
Старый 10.08.2012, 14:36   #1
Жека
Дэвелопер
 
Регистрация: 04.09.2005
Адрес: Красноярск
Сообщений: 1,376
Написано 491 полезных сообщений
(для 886 пользователей)
Возвращение нескольких результатов из функции + Разбиение строки по символу

Метод №1: использование глобальных массивов.

У этого метода есть ограничение, о котором ниже, но для простых каких-то задач сгодится.
Как альтернатива - свои списки (упрощённые) использовать (может допишу с ними пример сделал, ниже по теме "метод №2").

Была задачка разбить строку на подстроки по знаку-разделителю. Я захотел вернуть массив строк.
Просто через "Return mas" блитц не умеет. Поэтому я сделал глобальный массив для хранения результатов работы функции.

;инфа для возврата значений из функций
Dim RETVAL_STR$(0)
Global RETVAL_COUNT%

;smb - 1 символ типа запятой
Function fnSplitString(s$,smb$=",")
	Local size% = Len(s)
	Local cnt% = 0, k%
	;сначала находим количество символов-разделителей
	For k% = 1 To size
		If(Mid(s,k,1) = smb) Then cnt = cnt + 1
	Next
	RETVAL_COUNT = cnt+1 ;запоминаем размер
	Dim RETVAL_STR(cnt) ;расширяем до нужного размера
	If(cnt = 0)
		RETVAL_STR(0) = s
		Return
	EndIf
	;теперь снова проходим, заполняя глобальный массив
	Local val$ = "", char$, ind% = 0
	For k% = 1 To size
		char = Mid(s,k,1)
		If(char = smb)
			RETVAL_STR(ind) = val
			val = ""
			ind = ind+1
		Else
			val = val + char
			If(k = size) Then RETVAL_STR(ind) = val ;последнюю подстроку тоже
		EndIf		
	Next
End Function
На оптимальность работы функции я не претендую, мне нужно от неё парсить параметры в строчках типа
130,30,30
в момент загрузки уровня.

Пример использования:
fnSplitString("100,exit,-7")
For k% = 0 To RETVAL_COUNT-1
	DebugLog("RETVAL_STR("+k+") = "+RETVAL_STR(k))
Next
Теперь о грустном. Вот это работать будет криво или загнётся:
Local s1$ = "0,0;1,0;1,1;0,1", s2$
fnSplitString(s1, ";") ;сначала разбиваем по точке-с-запятой
For k% = 0 To RETVAL_COUNT-1
	DebugLog("RETVAL_STR("+k+") = "+RETVAL_STR(k))
	fnSplitString(RETVAL_STR(k),",") ;теперь по запятой
	For i% = 0 To RETVAL_COUNT-1
		DebugLog("RETVAL_STR_2("+i+") = "+RETVAL_STR(i))
	Next
Next
Очередной вызов функции затрёт массив, который используется в другом месте.

Последний раз редактировалось Жека, 13.08.2012 в 08:23. Причина: Поправил мелочи, назвал это метод №1
(Offline)
 
Ответить с цитированием
Старый 10.08.2012, 15:09   #2
Hartmann1
AnyKey`щик
 
Регистрация: 24.06.2012
Сообщений: 16
Написано 5 полезных сообщений
(для 6 пользователей)
Ответ: Возвращение нескольких результатов из функции + Разбиение строки по символу

Сообщение от Жека Посмотреть сообщение
	Dim RETVAL_STR(cnt) ;расширяем до нужного размера
	If(cnt = 0)
		Dim RETVAL_STR(0)
		RETVAL_STR(0) = s
		Return
	EndIf
Зачем еще раз "Dim RETVAL_STR(0)" делаешь, если cnt и так будет 0? И Dim с нулем удаляет массив, нужно Dim 1 делать.

Сообщение от Жека Посмотреть сообщение
If(k = size) Then RETVAL_STR(ind) = val ;последнюю подстроку тоже
Это вообще вынести из цикла, причем без условия "If(k = size)"

Переменная k не определена как Local.

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

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

ЗЫ
По коду еще, мне кажется для длинных строк будет эффективнее сделать авторазмер массива ( как например в С++ std::vector, каждый раз в два раза ), нежели сначала делать предрасчет.
Правка: забыл что в блице нет ReDim и новый Dim удаляет старые данные.

Ну и в крайнем случае можно банки использовать, неудобно конечно что встроеного PokeString нету.
(Offline)
 
Ответить с цитированием
Старый 10.08.2012, 18:26   #3
Жека
Дэвелопер
 
Регистрация: 04.09.2005
Адрес: Красноярск
Сообщений: 1,376
Написано 491 полезных сообщений
(для 886 пользователей)
Ответ: Возвращение нескольких результатов из функции + Разбиение строки по символу

Сообщение от Hartmann1 Посмотреть сообщение
Зачем еще раз "Dim RETVAL_STR(0)" делаешь, если cnt и так будет 0? И Dim с нулем удаляет массив, нужно Dim 1 делать.
Нифига не удаляет, я проверял. Лишний дим забыл убрать, спасибо, сначала хотел ветку елсе делать.
Это вообще вынести из цикла, причем без условия "If(k = size)"
Можно.
Переменная k не определена как Local.
Некритично.
Как вариант можно передавать через параметры функции статические массивы, просто заранее определить максимальный размер, некрасиво конечно, но как вариант.
Вот про это подробнее, пожалуйста, если это не из серии забыл что речь о блитце.

Спасибо за комменты
(Offline)
 
Ответить с цитированием
Старый 10.08.2012, 19:30   #4
Hartmann1
AnyKey`щик
 
Регистрация: 24.06.2012
Сообщений: 16
Написано 5 полезных сообщений
(для 6 пользователей)
Ответ: Возвращение нескольких результатов из функции + Разбиение строки по символу

Сообщение от Жека Посмотреть сообщение
Нифига не удаляет, я проверял.
Как ты проверял?
Сообщение от Жека Посмотреть сообщение
Некритично.
Тем не менее твой код может заюзать какой-нить невнимательный нуб, у которого окажется глобальная k (и не такие бывают же
Сообщение от Жека Посмотреть сообщение
Вот про это подробнее, пожалуйста, если это не из серии забыл что речь о блитце.
А чего подробнее, через параметры можно передавать массивы с квадратными скобками, статические которые. В твоем случае будет
fnSplitString(s$,smb$=",",strings$[константный размер])
Только вот я не подумал что передавать-то туда нужно такого же размера массив Короче лучше банки юзать.
А еще лучше хранить данные в бинарном виде
(Offline)
 
Ответить с цитированием
Сообщение было полезно следующим пользователям:
Жека (11.08.2012)
Старый 11.08.2012, 07:48   #5
Жека
Дэвелопер
 
Регистрация: 04.09.2005
Адрес: Красноярск
Сообщений: 1,376
Написано 491 полезных сообщений
(для 886 пользователей)
Ответ: Возвращение нескольких результатов из функции + Разбиение строки по символу

Сообщение от Hartmann1 Посмотреть сообщение
Как ты проверял?
Dim a$(0)
a(0) = "hi world!"
DebugLog(a(0))
пашет отличненько-с (я сам удивился, но раз оно так, то что поделать?)

Глобальная К - опасно, сам такое не сделаю, но всё же полезно при написании кода на экспорт людям.

"Массивы с квадратными скобками" - для данного примера не сгодятся, но на будущее припомню.
(Offline)
 
Ответить с цитированием
Старый 11.08.2012, 13:04   #6
Hartmann1
AnyKey`щик
 
Регистрация: 24.06.2012
Сообщений: 16
Написано 5 полезных сообщений
(для 6 пользователей)
Ответ: Возвращение нескольких результатов из функции + Разбиение строки по символу

Сообщение от Жека Посмотреть сообщение
Dim a$(0)
a(0) = "hi world!"
DebugLog(a(0))
пашет отличненько-с (я сам удивился, но раз оно так, то что поделать?)
Глянул справку и точно ведь, я забыл что в блице выделяется на 1 элемент больше чем указано
Кстати -1 тоже корректный размер, и судя по тому что доступ к нулевому элементу вызывает "index out of bounds", память освобождается.
(Offline)
 
Ответить с цитированием
Старый 13.08.2012, 08:47   #7
Жека
Дэвелопер
 
Регистрация: 04.09.2005
Адрес: Красноярск
Сообщений: 1,376
Написано 491 полезных сообщений
(для 886 пользователей)
Ответ: Возвращение нескольких результатов из функции + Разбиение строки по символу

Метод №2: использование связных списков

Здесь пример использования подобия связного списка для возвращения неограниченного числа параметров из функции.

;создание списка с параметрами - головной узел
Function fnRetValCreate.TRetVal(s$="", i%=0, f#=0)
	Local rv.TRetVal = New TRetVal
	rv\root = rv
	rv\sVal = s
	rv\iVal = i
	rv\fVal = f
	Return rv
End Function

;добавление нового результата
Function fnRetValAdd.TRetVal(retval.TRetVal, s$="", i%=0, f#=0)
	;если ещё не создан, то создаём новый
	If(retval = Null) Then Return fnRetValCreate(s, i, f)
	retval\nxt = New TRetVal
	retval\nxt\root = retval\root
	retval\nxt\sVal = s
	retval\nxt\iVal = i
	retval\nxt\fVal = f
	Return retval\nxt
End Function

;удаление всех результатов
Function fnRetValDelete(retval.TRetVal)
	Local node.TRetVal = retval\root
	While(node <> Null)
		retval = node
		node = node\nxt
		Delete(retval)
	Wend
End Function

;тип для хранения результатов (строки, целые и дробные)
Type TRetVal
	Field sVal$, iVal%, fVal# ;сами данные
	Field nxt.TRetVal ;указатель на следующего
	Field root.TRetVal ;указатель на головной узел
End Type
Для примера использования этого метода ниже представлена функция выценления параметров командной строки - с учётом того, что часть параметров может быть заключена в кавычки, а часть просто через пробел.

Local cl$ = CommandLine()
If(cl = "") Then End
DebugLog(cl)

Local rv.TRetVal = fnParseCommandLine(cl)
Local node.TRetVal = rv
Local file% = WriteFile("files.txt")
;пробегаем по всем результатам
While(node <> Null)
	WriteLine(file, node\sVal)
	node = node\nxt
Wend
CloseFile(file)
;удаляем список с результатами
fnRetValDelete(rv)

End

;в командной строке параметры, содержащие пробелы, обрамляются кавычками
;остальные - нет
Function fnParseCommandLine.TRetVal(cl$)
	Local size% = Len(cl)
	Local k%, cnt%, s$="", char$, q$ = Chr(34) ;кавычка
	Local retval.TRetVal
	For k% = 1 To size ;проходим по всем буквам
		char = Mid(cl, k, 1)
		If(char = q) ;встретилась кавычка
			cnt = cnt+1
			DebugLog("1")
			If(cnt = 2) ;закрылась кавычка
				retval = fnRetValAdd(retval, s)
				s = ""
				k = k+1 ;пропускаем пробел
				cnt = 0
			EndIf
		Else If(char = " " And cnt = 0) ;если пробел не внутри кавычек, то он отделяет параметры
			retval = fnRetValAdd(retval, s)
			s = ""
			DebugLog("2")
		Else
			s = s + char
			If(k = size) ;если достигли конца строки, то последний параметр забираем тоже
				DebugLog("3")
				retval = fnRetValAdd(retval, s)
			EndIf
		EndIf
	Next
	Return retval\root ;возвращаем указатель на корень списка
End Function
ПС. Если кто-то знает как в блитц максе выцепить из командной строки русские символы, то подскажите - нужно такое: кидаем файл, содержащий в пути или названии кириллицу, на ехе-шник, и нужно достать/преобразовать путь так, чтоб можно было сделать с ним LoadImage() и прочее.
(Offline)
 
Ответить с цитированием
Старый 10.11.2012, 05:36   #8
Черный крыс
 
Сообщений: n/a
Ответ: Возвращение нескольких результатов из функции + Разбиение строки по символу

Эээээ так это ты так с БМаксом изголяешься??? 0_о

На БМаксе так делать это всеравно что с куклой на свидание сходить =)

В БМаксе функции могут возвращать что угодно, хоть массивы, хоть контейнеры.

Ну а если надо указать прямо, то для таких целей там есть специальный оператор - "Var", который передает прямой адрес переменной.
 
Ответить с цитированием
Старый 10.11.2012, 12:11   #9
H@NON
Дэвелопер
 
Регистрация: 17.01.2007
Сообщений: 1,552
Написано 351 полезных сообщений
(для 774 пользователей)
Ответ: Возвращение нескольких результатов из функции + Разбиение строки по символу

написано же, раздел для Blitz3D...
(Offline)
 
Ответить с цитированием
Сообщение было полезно следующим пользователям:
Colossus (10.11.2012)
Старый 30.11.2012, 11:47   #10
Жека
Дэвелопер
 
Регистрация: 04.09.2005
Адрес: Красноярск
Сообщений: 1,376
Написано 491 полезных сообщений
(для 886 пользователей)
Ответ: Возвращение нескольких результатов из функции + Разбиение строки по символу

Diablo1909, мои примеры выше для Blitz3D.
Научи меня вот этому:
Если кто-то знает как в блитц максе выцепить из командной строки русские символы, то подскажите - нужно такое: кидаем файл, содержащий в пути или названии кириллицу, на ехе-шник, и нужно достать/преобразовать путь так, чтоб можно было сделать с ним LoadImage() и прочее.
(Offline)
 
Ответить с цитированием
Старый 30.11.2012, 17:13   #11
Черный крыс
 
Сообщений: n/a
Ответ: Возвращение нескольких результатов из функции + Разбиение строки по символу

Кирилицу в названиях файла всегда надо убирать. Ибо не везде работает.
 
Ответить с цитированием
Сообщение было полезно следующим пользователям:
moka (30.11.2012)
Старый 03.12.2012, 06:50   #12
Жека
Дэвелопер
 
Регистрация: 04.09.2005
Адрес: Красноярск
Сообщений: 1,376
Написано 491 полезных сообщений
(для 886 пользователей)
Ответ: Возвращение нескольких результатов из функции + Разбиение строки по символу

Приходится убирать Я для себя утилитки пишу, поэтому универсальность не нужна.
(Offline)
 
Ответить с цитированием
Старый 28.12.2012, 16:29   #13
kostya261
AnyKey`щик
 
Регистрация: 27.08.2007
Сообщений: 17
Написано одно полезное сообщение
Ответ: Возвращение нескольких результатов из функции + Разбиение строки по символу

Сообщение от Жека Посмотреть сообщение
Метод №1: использование глобальных массивов.
На оптимальность работы функции я не претендую, мне нужно от неё парсить параметры в строчках типа
130,30,30
Я конечно в этом мало понимаю, но что если юзать либо списки (type), либо банки?
(Offline)
 
Ответить с цитированием
Старый 28.12.2012, 16:33   #14
kostya261
AnyKey`щик
 
Регистрация: 27.08.2007
Сообщений: 17
Написано одно полезное сообщение
Ответ: Возвращение нескольких результатов из функции + Разбиение строки по символу

Сообщение от Hartmann1 Посмотреть сообщение
Ну и в крайнем случае можно банки использовать, неудобно конечно что встроеного PokeString нету.
Так его написать, две минуты времени нужно
(Offline)
 
Ответить с цитированием
Ответ


Опции темы

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.


Часовой пояс GMT +4, время: 21:42.


vBulletin® Version 3.6.5.
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Перевод: zCarot
Style crйe par Allan - vBulletin-Ressources.com