Wiki: BASIC

Lang Directive

Standard FreeBASIC is often less concise than other dialects like QBasic and fblite. A large part of this is that FreeBASIC requires explicit variable declaration, whereas the other dialects don't. Print j+1 is a perfectly valid QBasic program; since j hasn't been declared it will default to a value of 0. Both alternate dialects allow the variable suffix system to specify the type instead of using dim, but in turn, disallow the use of var.

E.g. a$ = "abc" is a string variable, which has a default of an empty string.

This can be taken advantage of using BASIC's #lang directive, which can be placed in a program to switch which dialect it uses. #lang "qb" sets the language to QBasic; #lang "fblite" sets it to fblite.

QBasic is often preferable to fblite because it requires less bytes in the lang directive, but QBasic lacks some functions that fblite and FreeBASIC such as iif() (replaced by __iif()) and some string functions need the suffix $ (e.g. chr$() and mid$())

See https://freebasic.net/wiki/CompilerDialects for more info about the differences between dialects.

QBasic also has a CGSE tips page.

Open strings

If a string literal appears at the end of a line, it doesn't need a closing quotation mark. ?"Hello is perfectly valid. This also helps with the #lang directive since it uses a string, ie. #lang"qb.

Printing

? is a shorter alias for Print, ie. ?"Hello" vs Print"Hello". You can just have ? on a line to print a newline on its own. Elements can be separated by semicolons to print without newlines, or with a trailing semicolon to have no newline.

?"abc";i;"def"  ' Print number in string
?               ' Print just a newline
?"no newline";  ' Print string with no newline

When printing a positive signed integer, BASIC will append a space beforehand, so variables will need to be converted to unsigned or stringified.

var i=5u:?i     ' Declare it to be unsigned to begin with
var i=5:?i+0u   ' Convert to unsigned
var i=5:?""&i   ' Stringify it (can't do ?i&", since that looks like a suffix)
i=5:?""&i       ' Use alternate dialects to avoid var (note that qb prints integers with a trailing space)

Remove spaces after numbers

Spaces can be left out after number literals. This can help in for loops (see below), and other infix operators. As a specific example, moduloing by a power of 2 can be replaced with an and call, e.g. x mod 2 => 1and x.

Looping

There are a few ways to loop in BASIC:

var i=0:for i=0to 99:code:next
var i=0:while i<99:code:i+=1:wend
var i=0:a:code:i+=1:if i<99 goto a
var i=0:do:code:*ERROR*i+=1:loop    ' Termination by error (details are left as an exercise to the reader)

These are useful in various contexts. The for loop is the shortest and most straightforward. The while loop is good if you're looping until a loop variable is zero or if you don't want to increment the variable. The goto is good for infinite loops, terminating on errors (e.g. going to the wrong place in memory). The goto can also be used in conjunction with other labels, using on x goto l1,l2,l3, which doesn't jump if x is not in 1,2,3.

Don't use step, it is shorter to just add whatever to the variable in the loop:

for i=0to 99step 9:code:next
for i=0to 99:code:i+=8:next

Negative steps can start with a negated start where you negate it in the loop.

for i=99to 0step-1:?i:next
for i=-99to 0:?-i:next

Consecutive nexts can be combined for a single byte save (or more if you manage to line up three or more)

for i=1To 10
for j=1To 2
    ' ...
next j,i

Misc tips