Home
Site Structure

Programming Home
  Basic Home
    GUI & OS Home
    QB Knowledge Base
    Professor Answers
    Codename Surena
    QB Downloads

Write Us

Special Links
QB DirectoryNEW

Codename Surena
Forums
Sepent Basic GUI & OS Home
Register Log In
The Professor Answers Your Questions...
Have a question on QB programming? Just ask...and be sure that he knows the answer.

A Message from The Professor
Life will be boring if you don't have anything to do. For example what would happen if there weren't so many questions for The Professor to answer? Surely he would go and start writing more code! It's a programmer's way. So go and start the work (of course after reading The Professor's column!). If there are any problems, as there are always, just send your question to the Professor to prof@sepent.com.


   Dear Professor,
   Would you please  write  a program  for me  which enabes the
computer  to  tell  the  user  whether  the  given  word  is  a
palindrome (e.g. dad, mum, hannah) or not, using QBasic. Please
help me. I have been working on this problem for a long time.
               Yours,
               Felix Malawi
								
It is very simple. Take a look at this code:

DIM wrd As STRING
DIM wrd2 As STRING
DIM i As INTEGER

INPUT "Enter a word: ", wrd
wrd = LCASE$(wrd)

FOR i = LEN(wrd) TO 1 STEP -1
   wrd2 = wrd2 + MID$(wrd, i, 1)
NEXT

IF wrd2 = wrd THEN
   Print "The word is a palindrome."
ELSE
   Print "The word is not a palindrome."
END IF

         The Professor
								

   Dear Professor,
   When utilizing a PRINT USING format statement  (for example,
print using "###.##"; 1115.55), when I run the program, I still
get output, but preceded by %.  Since I am  a  new  student  of
QBasic, I wanted to know what this means.
                                   Sincerely,
                                   Lee Floyd
								
   Dear Lee,
   A percent mark being printed at the left of the number shows
you that the number is larger than the field. It is clear  that
1115.55 does not fit in ###.## because  it  has  one digit more
than the field. In this instance  you  should change the format
string to ####.##  to  fix  the  problem.   You  should  always 
remember that the help system of QB is your primary resource of  
syntax of the statements. You could easily and quickly find the
answer to this question using the help  in a few minutes  while
you got the answer from The Professor in a few days!
                                            The Professor
								

   Dear Professor,
   I have downloaded VBDOS to a new folder.  I have QB 4.5  and
some programs I've written in another folder.  How  do  I   get
VBDOS to "recognize" the QB 4.5 programs?  I haven't been  able
to  "copy and paste" the code from one to the  other  with  any
success, either.  I can do it one line at  a  time  (with  many
mouse clicks per line)  but  there  must  be  a better way.
 
   I am completely unfamiliar with libraries.  This sounds like
what I really need- a place to store subroutines, accessible to
all programs.  Is this assumption correct?  How do I create and
use libraries?
 
   Can you recommend a site where information such as  this  is
available?  Or should I pester you every couple days?  :-)
 
   Truly ignorant and quite thankful (not  for  the  ignorance,
but for your help).
         Dale Ludwig

								
   Dear Dale,
   To enable VBDOS to open your old programs,  you should  save
the files in text format. To do this, open the files in  QB 4.5 
and choose "Save As..." from "File" menu. Under "Format" frame,
select "Text" option and save the  file.  Now you can open  the
file in VBDOS.

   Your  guess about how the libraries work is quite right. The
libraries are a way  of  reusing  code  in  your  programs,  or 
sharing them with others without distributing your source code.
You can put the needed subroutines in a  module  or  a  project
with  multiple  modules  and  open  them  in  QB,  then  choose
"Make Library..."  from "Run" menu.  Two files will be created.
A  file with  ".LIB"  extension  which is the library file that
will be linked to your program when making  the  EXE,  and  the
other one a file with ".QLB" extension which is called a  quick
library.   Quick  libraries  can  be  loaded  in  QB  or  VBDOS
environment using the /L command-line option. When you want  to
debug and run your programs that use a library you should  load
the quick library first. Remember  that  quick  libraries  have 
different format for various versions of QB and VBDOS.

   The Professor cannot recommend you a  single  site  to  find
information about QB.  There are a lot of QB sites,  especially
those that have a Learning or Tutorials section. Search the  QB
sites that you know. Almost all QB related sites have links  to
other sites that can guide you  to  find  the  information  you 
need. Sepent also has a QB Knowledge Base that may help you  in
some  areas  of  programming.  The  Knowledge Base  is  located 
at   http://www.sepent.com/prog/basic/knbase/.  Of  course  the
knowledge base is now small and does not cover many aspects  of
programming in QB,  but Sepent is going to extend the knowledge
base in near future.
	              The Professor
								

   Dear Professor,
   I've suddenly developed  a  problem in my QB4.5 program. All
was well. I made  some  minor  changes to the display --changed
some PRINT statements. I added some more data. Everything still
worked until I exited and attempted to restart the  program. It
wouldn't run. It says, "Binding" in the very bottom left corner
and freezes. If I compile the program, it still works.   

   How can  I avoid "binding" so I can run the program and edit
it at the same time? 
            Thank you, 
            Dale Ludwig 
								
   Dear Dale,
   The problem is probably the size of your program.   If  your
program size has exceeded the largest possible size,  then such
problems  may  occur.   You  can  do  several things to fix the
problem. You can move to QB 7.1 or VBDOS that can manage larger
files. This is a quick way, although sometimes some changes  to
the code are required.   The better way, of course, is reducing 
the size of your program. For example,  if you  have  a  lot of
DATA statements that make the code very large, you can put  the
data in an external file and load them dynamically in run-time.
Also, you can split your code into several modules and work  on
them, then compile each module to a separate .OBJ file and link
them together.
            The Professor

								

   Dear Professor,
   I'm using the QBASIC.EXE interpreter.  When CHAINing between
programs, can I make COMMON variables also CONSTant?
                                        Richard Emery
					
   Dear Richard,
   There are three ways The Professor can suggest you, although
none of them is a perfect solution for  you.  One way is to use
common  variables  instead  of  constants.  This is not in fact
recommended.  The better way  which needs more work  is putting
CONST statements in all used modules. The last way is upgrading
to a higher version of QB.  Using higher versions,  you can put
all general constants  in  an  include  module (a .bi file) and
including it in all the modules with $INCLUDE meta command.

   Also you can use a multiple-module program in these versions
which  is  usually  better  than  using CHAIN command (For more
information on modular programming in QB you can visit Sepent's
QB Knowledge Base located at http://www.sepent.com/prog/basic/knbase/).
                                 The Professor
					

   Dear Professor,
   Is there a way to give a  student only 3 seconds to type  an
answer? 
Thanks, Alison.
					
   Dear Alison,
   The Professor can suggest you two ways, one easy to be  done
and the other not that easy.

   You can simply use an INPUT statement and then calculate the 
time it took the user  to answer the question and if it is less 
than 3 seconds,  the program can give  the user the appropriate
score. This can be done like this:

DIM StartTime AS SINGLE
DIM EndTime AS SINGLE
DIM ans AS STRING

CLS

PRINT "You have three seconds to answer the following question."
PRINT
StartTime = TIMER
INPUT "What's your name?! ", ans
EndTime = TIMER

IF EndTime - StartTime > 3 THEN
   PRINT "Oops! It took you too long."
   PRINT "You don't get any score."
ELSE
   'Of course, you should check the answer, but here
   'it is not necessary! (How can you check the name?)
   PRINT "Excellent! You did it!"
END IF

END

The second way, needs more work. You should implement an  INPUT
statement using INKEY$ function. It does not  seem  very  good,
but it's the best choice if your program is a high quality one.
The Professor can guide you to do it. Here is a simple sample:

DECLARE SUB CustomInput (var AS STRING)

CONST True = -1

DIM SHARED TimedOut AS INTEGER

ON TIMER(3) GOSUB TimeHandler
TIMER ON

DIM ans AS STRING

CLS
PRINT "You have three seconds to answer the following question."
PRINT

PRINT "What's your name?! ";
CustomInput ans

TIMER OFF

PRINT

IF TimedOut THEN
   PRINT "Oops! It took you too long."
   PRINT "You don't get any score."
ELSE
   'Of course, you should check the answer, but here
   'it is not necessary! (How can you check the name?)
   PRINT "Excellent! You did it!"
END IF

END

TimeHandler:
   BEEP
   TimedOut = True
   RETURN

SUB CustomInput (var AS STRING)
   CONST ScreenWidth = 80

   DIM startrow AS INTEGER
   DIM startcol AS INTEGER
   DIM curpos AS INTEGER
   DIM ch AS STRING

   startrow = CSRLIN
   startcol = POS(0)
   curpos = startcol

   LOCATE startrow, startcol, 1

   IF startcol = ScreenWidth THEN
      'Not enoguh space.
      ERROR 200
   ELSE
      DO
         IF TimedOut THEN EXIT SUB

         ch = INKEY$

         IF LEN(ch) = 1 THEN
            SELECT CASE ASC(ch)
               CASE 97 TO 122, 65 TO 90, 48 TO 57, 32
                  'You can add other allowed characters to
                  'this CASE statement.
                 
                  IF curpos < 80 THEN
                     LOCATE startrow, curpos, 1
                     PRINT ch;
                     var = var + ch
                     curpos = curpos + 1
                  END IF

               CASE 8
                  IF curpos > startcol THEN
                     curpos = curpos - 1
                     var = LEFT$(var, LEN(var) - 1)
                     LOCATE startrow, curpos
                     PRINT SPACE$(1);
                     LOCATE startrow, curpos, 1
                  END IF

               CASE 13
                  PRINT
                  EXIT SUB

            END SELECT
         END IF
      LOOP
   END IF
END SUB

   This code, obviously, does not have many features.  But you can
add other features to it easily!

   Uh, what a long  (and pleasant) answer it was! Have fun!
                                                  The Professor
					

Dear Professor,
My program (attached to this email) gives  me  an "OUT OF DATA"
error message. Could you please try it to see what I have done?
I would appreciate it. Thanks.
                         Jesse Hobby

Attached Code(Finalpro.BAS)
---------------------------
100 REM    FINAL PROJECT           Jesse Hobby     12-8-02
110 REM this program will ask the user to enter an instrument name and then
120 REM it will display the instrument name, classification, key of
125 REM instrument, year of invention, and inventor of the instrument.
130 variables:
140 REM       uname$          instrument name chosen by user
150 REM       iname$          instrument name
160 REM       class$          instrument classification
170 REM       counter         counts number of times there was no match
180 REM       invn$           inventor of instrument
190 REM       year$           year instrument was invented
200 REM       key$            key of instrument
205
210 PRINT "Hello, what is the instrument name you would like";
215 PRINT "to receive information; about; "; ""
220 INPUT uname$
225 PRINT "Name__________Classification____Inventor______Year____Key"
230 counter = 0
240 DO
250 READ iname$, class$, invn$, year$, key$
260    IF iname$ = "end" THEN EXIT DO
270    IF uname$ = iname$ THEN
280       PRINT iname$, class$, invn$, year$, key$
290       counter = counter + 1
300 END IF
310 LOOP
320 IF counter = 0 THEN
330    PRINT "I'm sorry but there is no information available";
335    PRINT " on that instrument.; "; ""
340 END IF
350 PRINT "Thank you for using this program."
360 PRINT "This program was designed by Jesse Hobby."
370 PRINT "All musical information received from my brilliant";
375 PRINT " sweet heart Cambria; Quinn.; "; ""
(some PRINT statements removed!)
550 PRINT "Copywright December 8, 2002 - a J & C Creation"
560
570 DATA tuba, brass, Jean Aste', 1817, F
580 DATA clarinet, woodwind, 1700, B flat
590 DATA flute, woodwind, Theobald Boehm, 1794, C
600 DATA piano, percussion, Bartolomeo Cristofori, 1709, C
610 DATA saxophone, woodwind, Adolphe Sax, 1840, F
620 DATA violin, string, Andrea Amati, 1510, C
630 DATA guitar, string, Spanish Peasants, 1100, C
640 DATA end, end, end, 0, O
650 END
---------------------------

					
Dear Jesse,
The problem with your program is only a comma! Take a  look  at
line 580. You should put a comma  between  "B"  and  "Flat"  (I
think the data  is incorrect,  but this comma will correct  the
syntax of  the program.  You can then correct the  data).  Your
program will work, if you add the comma.  Remmember  that  data
elements should always be separated by commas.
                                         The Professor

P.S.: The Professor should explain somthing here. This error is
      in fact caused by a logical mistake,  that is not placing
      the inventor's name in its place  at  line  580.  So   it
      can be said  that  this is a matter of  missing   a  data
      element, not missing a comma! (You see he is a professor,
      not a musician!!)
					

Dear Professor,
   Is it  possible  to  use  OPEN COM  statement without ON COM
statement in QB?

   Also, my old program uses ON COM statement in  each  module.
When I converted this program  to QB, an error message occurres
telling  me that  ON  COM  statement  cannot  be  used  in  SUB
procedures. What's the problem? Thanks.
                         Lukman NulHakim
					
Dear Lukman,
   Of course  it  is possible to use OPEN COM statement without
using ON COM. But about your second question I should tell  you
that all QBASIC event-trapping  statements  (ON ... statements)
-except ON LOCAL ERROR- are module level and cannot  be  set up
in a SUB or FUNCTION.
                The Professor
					

Dear Professor,
I’m new in QBASIC programming,  but my Boss wants me to convert 
an NS88Basic program  to  QBASIC.  Some code of the program I'm
making interface with port (PLC system), and I don’t know about
port programming  in  QBASIC.  So can you give a little example
about it, please? Thanks.
                 Lukman NulHakim
					
Dear Lukman,
The Professor  is  glad  to  hear  from  you.  But  you haven't
included much information on what exactly you want to do.  So I
will give you  some  general instructions.  First  of  all, you
should know  that  all versions  of  QB only support  accessing
serial communications ports(COM1 & COM2) directly. You may open
a communications channel using OPEN COM statement. The port can
be opened in three file-access modes: INPUT, OUTPUT and RANDOM.
In each mode, you can use ordinary file-access commands to read
and/or  write  from/in  the  port.  You  can  also  use  ON COM
statement  to  trap  communication events.  Refer  to  the help
system  of  your version  of  QB for detailed information about
these statements as well as examples on their usage.
                                           The Professor
					

Dear Professor,
I have a problem with  a  program I made in QBASIC (The code is
attached to the email).  I use SCREEN 13  to read the DATA in a
FOR...NEXT loop.  It writes  the word "sponge".  The problem is
that when I use a GOTO command  to  run the drawing code again,
It doesn't read the data. What's wrong?
                                 Steve Wagner
Attached code (Sponge.BAS):
--------------------------------
SCREEN 13

FOR y = 1 TO 5
FOR x = 1 TO 28
READ clr
IF clr = 1 THEN LINE (x * 5, y * 5)-(x * 5 + 5, y * 5 + 5), 14, BF
IF clr = 0 THEN LINE (x * 5, y * 5)-(x * 5 + 5, y * 5 + 5), 1, BF
NEXT
NEXT
DATA 1,1,1,0,1,1,1,0,0,1,1,1,1,0,1,0,0,0,1,0,1,1,1,1,0,1,1,1
DATA 1,0,0,0,1,0,0,1,0,1,0,0,1,0,1,1,0,0,1,0,1,0,0,0,0,1,0,0
DATA 1,1,1,0,1,1,1,0,0,1,0,0,1,0,1,0,1,0,1,0,1,0,1,1,0,1,1,1
DATA 0,0,1,0,1,0,0,0,0,1,0,0,1,0,1,0,0,1,1,0,1,0,0,1,0,1,0,0
DATA 1,1,1,0,1,0,0,0,0,1,1,1,1,0,1,0,0,0,1,0,1,1,1,1,0,1,1,1

startscreen:

PRINT ""
PRINT ""
PRINT ""
PRINT ""
PRINT ""
PRINT "This is Spongebob Trivia!"
PRINT ""
PRINT "Please press H for help"
PRINT "or S to start the game"
INPUT sorh$
IF sorh$ = "h" THEN
        GOTO help
ELSEIF sorh$ = "s" THEN
        GOTO difficulty
ELSE
        PRINT "dummy!"
        GOTO startscreen
END IF

help:
PRINT ""
PRINT "Help!"
PRINT "There are 2 different skill levels in"
PRINT "this trivia game:"
PRINT "easy: All multiple choice."
PRINT "hard: All short answer"
PRINT "After answering a question you will"
PRINT "be told either right or wrong,"
PRINT " and at the end of the game, your"
PRINT "score will be given. Have fun!"
PRINT ""
INPUT "Type r to return to the title screen"; helpr$
IF helpr$ = "r" THEN
        CLS
        GOTO startscreen
ELSE
        CLS
        GOTO startscreen
END IF
difficulty:
PRINT ""
INPUT "Easy or Hard?"; diff$
IF diff$ = "easy" THEN
        PRINT ""
        GOTO easystart
ELSEIF diff$ = "hard" THEN
        PRINT ""
        GOTO hardstart
ELSE
        PRINT ""
        PRINT "dummy"
        GOTO difficulty
END IF

easystart:
hardstart:
--------------------------
					

Dear Steve,
The answer to your problem is really easy(If I had realized the
problem correctly!). You  should put the "startscreen" label at
the begining of your program after  SCREEN 13  statement.  Like
this:

SCREEN 13

startscreen:

Then you should put a RESTORE statement after it. This restores
the DATA reading order to the first DATA statement and  you can
read   the  DATA  correctly.  Without  it,  you  would  get  an
"OUT OF DATA" error message. I hope this had helped you.
                                                The Professor
					

Dear Professor,
I have written a program  in  QuickBASIC 7.1 (BASIC PDS) and  I
want user not be able to interrupt execution of the  executable
file by pressing Ctrl-Break. Can you help?
                                           Sincerely Yours,
                                           Sepent
					
Your problem is really very easy  to  solve, young Sepent. Just
uncheck  "Run-Time Error Checking"   option in  "Make EXE File"
dialog  box.  Or  if  you  use  command-line,  don't include /D
command line option. Then Ctrl-Break will not work!