Тип прохода 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
Другие вопросы по тегам