Тип прохода QBasic в качестве аргумента функции
Вернулся к старому доброму qbasic по ностальгическим причинам и никогда раньше не использовал типы и функции в qbasic, так как в то время я был очень молод.
TYPE Vector2
x AS SINGLE
y AS SINGLE
END TYPE
FUNCTION Vector2Mag (a AS Vector2)
Vector2Mag = SQR((a.x * a.x) + (a.y * a.y))
END FUNCTION
FUNCTION Vector2Add (a AS Vector2, b AS Vector2)
DIM r AS Vector2
r.x = a.x + b.x
r.y = a.y + b.y
Vector2Add = r
END FUNCTION
Но я получаю
Illegal SUB/FUNCTION parameter on current line
используя qb64 в обеих первых функциональных строках. Google не помог, похоже, я все делаю правильно. Я проверил передачу нескольких переменных, указав тип для параметра, как использовать типы, но ничего не помогло.
Спасибо, парни.
4 ответа
Это было какое-то время, но я считаю, что проблема в том, что вы на самом деле не можете вернуть UDT (пользовательский тип, он же "любой тип, который не встроен"). Что вам нужно сделать, это передать третий аргумент Vector2Add
и сделать это SUB
, Например:
SUB Vector2Add (r AS Vector2, a AS Vector2, b AS Vector2)
r.x = a.x + b.x
r.y = a.y + b.y
END SUB
SUB
это почти точный перевод с эквивалентным кодом C, кроме синтаксических различий. Я считаю, что вы обычно добавляете суффикс типа к имени FUNCTION
в QB или он будет использовать свой тип по умолчанию, который может быть переопределен DEFxxx M-N
(или же _DEFINE
в QB64; и нет, вы не можете использовать _DEFINE
с УДЦ). Например, возвращая строку:
'Default type for all identifiers beginning with 'S' is STRING.
' Type suffixes, "AS xxxx" clauses and future "DEFxxx" items override the behavior.
DEFSTR S-S
FUNCTION swapFirstLast$ (s)
swapFirstLast$ = RIGHT$(s, 1) + MID$(s, 2, LEN(s) - 2) + LEFT$(s, 1)
END FUNCTION
QB64 ограничен в этом отношении, поскольку он стремится быть максимально совместимым с синтаксисом, используемым QuickBASIC 4.5, насколько это возможно. FreeBASIC, другой язык, основанный на QB, не имеет таких ограничений:
'Notice the "AS Vector2" at the end of this next line and the RETURN statement
' that FB introduced for FUNCTIONs (originally it was used to return from an
' "old-style" subroutine that was invoked via the GOSUB statement).
FUNCTION Vector2Add (a AS Vector2, b AS Vector2) AS Vector2
DIM r AS Vector2
r.x = a.x + b.x
r.y = a.y + b.y
RETURN r
END FUNCTION
Важно помнить, что QB64 в основном все еще QB, за исключением того, что он будет компилировать код для запуска в современных операционных системах (а не в DOS). FreeBASIC, с другой стороны, решил пожертвовать некоторой совместимостью ради создания более "современного" языка, сохраняющего синтаксис QB.
Определение или использование пользовательских переменных внутри функций недопустимо в QB. Не имеет значения, объявлена ли функция DEF FNname ... END DEF или FUNCTION ... END FUNCTION
Что вы можете сделать, это отправить указатель на адрес пользовательской переменной, а затем функция / подпрограмма использует адрес, чтобы прочитать его непосредственно из памяти. Элементы пользовательской переменной хранятся именно в том порядке, в котором они определены. В этом примере a (двухбайтовое целое) будет сохранено сначала в формате с прямым порядком байтов, затем b, всего четыре байта.
TYPE xtyp
DIM a AS INTEGER
DIM b AS INTEGER
END TYPE
DIM var AS xtyp
var.a = 5
var.b = 7
DEF SEG = VARSEG(var)
PRINT "The value of var.a and var.b multiplied is"; mpl(VARPTR(var))
END
'-------------------------- End of main program, function begins here -------
FUNCTION mpl(addr)
factor1 = PEEK(addr) + PEEK(addr + 1) * 256
factor2 = PEEK(addr + 2) + PEEK(addr + 3) * 256
mpl = factor1 * factor2
END FUNCTION
DEF SEG
используется для установки текущего сегмента, и VARSEG()
возвращает сегмент числовой или пользовательской переменной.PEEK()
используется для чтения байта из определенной позиции памяти, и VARPTR()
возвращает адрес числовой или пользовательской переменной в своем сегменте. Обратите внимание, что в приведенном выше коде предполагается, что оба фактора не подписаны. Если они подписаны, преобразование отдельных байтов в целые числа должно немного отличаться.
Иметь функцию записи в разделяемую переменную и вернуть -1, чтобы обозначить успех
TYPE testType
x AS INTEGER
y AS INTEGER
END TYPE
DIM SHARED ret AS testType
DIM a AS testType,b as testType
a.x=5
b.x=7
IF add(a,b) THEN a=ret
FUNCTION add(a AS testType, b AS testType)
ret.x=a.x+b.x
ret.y=a.y+b.y
add=-1
END FUNCTION
это позволяет легче обрабатывать нефатальные ошибки, чем делать SUB
Вместо того, чтобы пытаться вернуть UDT к имени функции, используйте глобальный UDT:
TYPE Vector2
x AS SINGLE
y AS SINGLE
END TYPE
DIM SHARED r AS Vector2
FUNCTION Vector2Mag (a AS Vector2)
Vector2Mag = SQR((a.x * a.x) + (a.y * a.y))
END FUNCTION
FUNCTION Vector2Add (a AS Vector2, b AS Vector2)
r.x = a.x + b.x
r.y = a.y + b.y
'Vector2Add = r
END FUNCTION