home *** CD-ROM | disk | FTP | other *** search
Text File | 2013-11-08 | 872.7 KB | 24,289 lines |
- Microsoft QuickBASIC: Programming in BASIC
-
-
- ════════════════════════════════════════════════════════════════════════════
-
-
- Microsoft(R) QuickBASIC: Programming in BASIC
-
- For IBM(R) Personal Computers and Compatibles
-
-
- ════════════════════════════════════════════════════════════════════════════
-
-
- Information in this document is subject to change without notice and does
- not represent a commitment on the part of Microsoft Corporation. The
- software described in this document is furnished under a license agreement
- or nondisclosure agreement. The software may be used or copied only in
- accordance with the terms of the agreement. It is against the law to copy
- the software on any medium except as specifically allowed in the license
- or nondisclosure agreement. No part of this manual may be reproduced or
- transmitted in any form or by any means, electronic or mechanical,
- including photocopying and recording, for any purpose without the express
- written permission of Microsoft.
-
- (C)Copyright Microsoft Corporation, 1987, 1988. All rights reserved.
-
- Simultaneously published in the U.S. and Canada.
-
- Printed and bound in the United States of America.
-
- Microsoft, MS, MS-DOS, CodeView, GW-BASIC, and XENIX
-
- are registered trademarks of Microsoft Corporation.
-
- Hayes is a registered trademark of Hayes Microcomputer Products, Inc.
-
- IBM and PS/2 are registered trademarks of International Business Machines
- Corporation.
-
- Intel is a registered trademark of Intel Corporation.
-
- ProKey is a trademark of RoseSoft, Inc.
-
- SideKick and SuperKey are registered trademarks of Borland International,
- Inc.
-
- WordStar is a registered trademark of MicroPro International Corporation.
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- Contents
-
- Introduction
- The QuickBASIC Language
- The QuickBASIC Environment
- Using This Manual
- Selected Programming Topics
- The Heart of BASIC
- Appendixes
- Document Conventions
- Programming Style in this Manual
-
- PART 1 SELECTED PROGRAMMING TOPICS
-
- Chapter 1 Control-Flow Structures
- 1.1 Changing Statement Execution Order
- 1.2 Boolean Expressions
- 1.3 Decision Structures
- 1.3.1 Block IF...THEN...ELSE
- 1.3.2 SELECT CASE
- 1.3.2.1 Using the SELECT CASE Statement
- 1.3.2.2 SELECT CASE Versus ON...GOSUB
- 1.4 Looping Structures
- 1.4.1 FOR...NEXT Loops
- 1.4.1.1 Exiting a FOR...NEXT Loop with EXIT FOR
- 1.4.1.2 Pausing Program Execution with FOR...NEXT
- 1.4.2 WHILE...WEND Loops
- 1.4.3 DO...LOOP Loops
- 1.4.3.1 Loop Tests: One Way to Exit DO...LOOP
- 1.4.3.2 EXIT DO: An Alternative Way to Exit
- DO...LOOP
- 1.5 Sample Applications
- 1.5.1 Checkbook-Balancing Program (CHECK.BAS)
- 1.5.2 Carriage-Return and Line-Feed Filter (CRLF.BAS)
-
- Chapter 2 SUB and FUNCTION Procedures
- 2.1 Procedures: Building Blocks for Programming
- 2.2 Comparing Procedures with Subroutines and Functions
- 2.2.1 Comparing SUB with GOSUB
- 2.2.1.1 Local and Global Variables
- 2.2.1.2 Use in Multiple-Module Programs
- 2.2.1.3 Operating on Different Sets of Variables
- 2.2.2 Comparing FUNCTION with DEF FN
- 2.2.2.1 Local and Global Variables
- 2.2.2.2 Changing Variables Passed to the Procedure
- 2.2.2.3 Calling the Procedure within Its
- Definition
- 2.2.2.4 Use in Multiple-Module Programs
- 2.3 Defining Procedures
- 2.4 Calling Procedures
- 2.4.1 Calling a FUNCTION Procedure
- 2.4.2 Calling a SUB Procedure
- 2.5 Passing Arguments to Procedures
- 2.5.1 Parameters and Arguments
- 2.5.2 Passing Constants and Expressions
- 2.5.3 Passing Variables
- 2.5.3.1 Passing Simple Variables
- 2.5.3.2 Passing an Entire Array
- 2.5.3.3 Passing Individual Array Elements
- 2.5.3.4 Using Array-Bound Functions
- 2.5.3.5 Passing an Entire Record
- 2.5.3.6 Passing Individual Elements of a Record
- 2.5.4 Checking Arguments with the DECLARE Statement
- 2.5.4.1 When QuickBASIC Does Not Generate a DECLARE
- Statement
- 2.5.4.2 Developing Programs outside the QuickBASIC
- Environment
- 2.5.4.3 Using Include Files for Declarations
- 2.5.4.4 Declaring Procedures in Quick Libraries
- 2.5.5 Passing Arguments by Reference
- 2.5.6 Passing Arguments by Value
- 2.6 Sharing Variables with SHARED
- 2.6.1 Sharing Variables with Specific Procedures in a
- Module
- 2.6.2 Sharing Variables with All Procedures in a Module
- 2.6.3 Sharing Variables with Other Modules
- 2.6.4 The Problem of Variable Aliasing
- 2.7 Automatic and STATIC Variables
- 2.8 Preserving Values of Local Variables with the STATIC
- Statement
- 2.9 Recursive Procedures
- 2.9.1 The Factorial Function
- 2.9.2 Adjusting the Size of the Stack
- 2.10 Transferring Control to Another Program with CHAIN
- 2.11 Sample Application: Recursive Directory Search
- (WHEREIS.BAS)
-
- Chapter 3 File and Device I/O
- 3.1 Printing Text on the Screen
- 3.1.1 Screen Rows and Columns
- 3.1.2 Displaying Text and Numbers with PRINT
- 3.1.3 Displaying Formatted Output with PRINT USING
- 3.1.4 Skipping Spaces and Advancing to a Specific Column
- 3.1.5 Changing the Number of Columns or Rows
- 3.1.6 Creating a Text Viewport
- 3.2 Getting Input from the Keyboard
- 3.2.1 The INPUT Statement
- 3.2.2 The LINE INPUT Statement
- 3.2.3 The INPUT$ Function
- 3.2.4 The INKEY$ Function
- 3.3 Controlling the Text Cursor
- 3.3.1 Positioning the Cursor
- 3.3.2 Changing the Cursor's Shape
- 3.3.3 Getting Information about the Cursor's Location
- 3.4 Working with Data Files
- 3.4.1 How Data Files Are Organized
- 3.4.2 Sequential and Random-Access Files
- 3.4.3 Opening a Data File
- 3.4.3.1 File Numbers in BASIC
- 3.4.3.2 File Names in BASIC
- 3.4.4 Closing a Data File
- 3.4.5 Using Sequential Files
- 3.4.5.1 Records in Sequential Files
- 3.4.5.2 Putting Data in a New Sequential File
- 3.4.5.3 Reading Data from a Sequential File
- 3.4.5.4 Adding Data to a Sequential File
- 3.4.5.5 Other Ways to Write Data to a Sequential
- File
- 3.4.5.6 Other Ways to Read Data from a Sequential
- File
- 3.4.6 Using Random-Access Files
- 3.4.6.1 Records in Random-Access Files
- 3.4.6.2 Adding Data to a Random-Access File
- 3.4.6.7 Reading Data Sequentially
- 3.4.6.8 Using Record Numbers to Retrieve Records
- 3.4.7 Binary File I/O
- 3.4.7.1 Comparing Binary Access and Random Access
- 3.4.7.2 Positioning the File Pointer with SEEK
- 3.5 Working with Devices
- 3.5.1 Differences between Device I/O and File I/O
- 3.5.2 Communications through the Serial Port
- 3.6 Sample Applications
- 3.6.1 Perpetual Calendar (CAL.BAS)
- 3.6.2 Indexing a Random-Access File (INDEX.BAS)
- 3.6.3 Terminal Emulator (TERMINAL.BAS)
-
- Chapter 4 String Processing
- 4.1 Strings Defined
- 4.2 Variable- and Fixed-Length Strings
- 4.2.1 Variable-Length Strings
- 4.2.2 Fixed-Length Strings
- 4.3 Combining Strings
- 4.4 Comparing Strings
- 4.5 Searching for Strings
- 4.6 Retrieving Parts of Strings
- 4.6.1 Retrieving Characters from the Left Side of a
- String
- 4.6.2 Retrieving Characters from the Right Side of a
- String
- 4.6.3 Retrieving Characters from Anywhere in a String
- 4.7 Generating Strings
- 4.8 Changing the Case of Letters
- 4.9 Strings and Numbers
- 4.10 Changing Strings
- 4.11 Sample Application: Converting a String to a Number
- (STRTONUM.BAS)
-
- Chapter 5 Graphics
- 5.1 What You Need for Graphics Programs
- 5.2 Pixels and Screen Coordinates
- 5.3 Drawing Basic Shapes: Points, Lines, Boxes, and Circles
- 5.3.1 Plotting Points with PSET and PRESET
- 5.3.2 Drawing Lines and Boxes with LINE
- 5.3.2.1 Using the STEP Option
- 5.3.2.2 Drawing Boxes
- 5.3.2.3 Drawing Dotted Lines
- 5.4 Drawing Circles and Ellipses with CIRCLE
- 5.4.1 Drawing Circles
- 5.4.2 Drawing Ellipses
- 5.4.3 Drawing Arcs
- 5.4.4 Drawing Pie Shapes
- 5.4.5 Drawing Shapes to Proportion with the Aspect Ratio
- 5.5 Defining a Graphics Viewport
- 5.6 Redefining Viewport Coordinates with WINDOW
- 5.6.1 The Order of Coordinate Pairs
- 5.6.2 Keeping Track of View and Physical Coordinates
- 5.7 Using Colors
- 5.7.1 Selecting a Color for Graphics Output
- 5.7.2 Changing the Foreground or Background Color
- 5.7.3 Changing Colors with PALETTE and PALETTE USING
- 5.8 Painting Shapes
- 5.8.1 Painting with Colors
- 5.8.2 Painting with Patterns: Tiling
- 5.8.2.1 Pattern-Tile Size in Different Screen
- Modes
- 5.8.2.2 Creating a Single-Color Pattern in Screen
- Mode 2
- 5.8.2.3 Creating a Multicolor Pattern in Screen Mode
- 1
- 5.8.2.4 Creating a Multicolor Pattern in Screen Mode
- 8
- 5.9 DRAW: a Graphics Macro Language
- 5.10 Basic Animation Techniques
- 5.10.1 Saving Images with GET
- 5.10.2 Moving Images with PUT
- 5.10.3 Animation with GET and PUT
- 5.10.4 Animating with Screen Pages
- 5.11 Sample Applications
- 5.11.1 Bar-Graph Generator (BAR.BAS)
- 5.11.2 Color in a Figure Generated Mathematically
- (MANDEL.BAS)
- 5.11.3 Pattern Editor (EDPAT.BAS)
-
- Chapter 6 Error and Event Trapping
- 6.1 Error Trapping
- 6.1.1 Activating Error Trapping
- 6.1.2 Writing an Error-Handling Routine
- 6.1.2.1 Using ERR to Identify Errors
- 6.1.2.2 Returning from an Error-Handling Routine
- 6.2 Event Trapping
- 6.2.1 Detecting Events by Polling
- 6.2.2 Detecting Events by Trapping
- 6.2.3 Specifying the Event to Trap and Activating Event
- Trapping
- 6.2.4 Events That BASIC Can Trap
- 6.2.5 Suspending or Disabling Event Trapping
- 6.2.6 Trapping Keystrokes
- 6.2.6.1 Trapping User-Defined Keys
- 6.2.6.2 Trapping User-Defined Shifted Keys
- 6.2.7 Trapping Music Events
- 6.3 Error and Event Trapping in SUB or FUNCTION Procedures
- 6.4 Trapping across Multiple Modules
- 6.4.1 Event Trapping across Modules
- 6.4.2 Error Trapping across Modules
- 6.5 Trapping Errors and Events in Programs Compiled with BC
- 6.6 Sample Application: Trapping File-Access Errors
- (FILERR.BAS)
-
- Chapter 7 Programming with Modules
- 7.1 Why Use Modules?
- 7.2 Main Modules
- 7.3 Modules Containing Only Procedures
- 7.4 Creating a Procedures-Only Module
- 7.5 Loading Modules
- 7.6 Using the DECLARE Statement with Multiple Modules
- 7.7 Accessing Variables from Two or More Modules
- 7.8 Using Modules During Program Development
- 7.9 Compiling and Linking Modules
- 7.10 Quick Libraries
- 7.10.1 Creating Quick Libraries
- 7.11 Tips for Good Programming with Modules
-
- PART 2 HEART OF BASIC
-
- Chapter 8 Statement and Function Summary
- ABS Function
- ASC Function
- ATN Function
- BEEP Statement
- BLOAD Statement
- BSAVE Statement
- CALL Statement (BASIC Procedures)
- CALL, CALLS Statement (Non-BASIC Procedures)
- CALL INT86OLD Statements
- CALL ABSOLUTE Statement
- CALL INTERRUPT Statements
- CDBL Function
- CHAIN Statement
- CHDIR Statement
- CHR$ Function
- CINT Function
- CIRCLE Statement
- CLEAR Statement
- CLNG Function
- CLOSE Statement
- CLS Statement
- COLOR Statement
- COM Statements
- COMMAND$ Function
- COMMON Statement
- CONST Statement
- COS Function
- CSNG Function
- CSRLIN Function
- CVI, CVS, CVL, CVD Functions
- CVSMBF, CVDMBF Functions
- DATA Statement
- DATE$ Function
- DATE$ Statement
- DECLARE Statement (BASIC Procedures)
- DECLARE Statement (Non-BASIC Procedures)
- DEF FN Statement
- DEF SEG Statement
- DEFtype Statements
- DIM Statement
- DO...LOOP Statements
- DRAW Statement
- END Statement
- ENVIRON$ Function
- ENVIRON Statement
- EOF Function
- ERASE Statement
- ERDEV, ERDEV$ Functions
- ERR, ERL Functions
- ERROR Statement
- EXIT Statement
- EXP Function
- FIELD Statement
- FILEATTR Function
- FILES Statement
- FIX Function
- FOR...NEXT Statement
- FRE Function
- FREEFILE Function
- FUNCTION Statement
- GET Statement──File I/O
- GET Statement──Graphics
- GOSUB...RETURN Statements
- GOTO Statement
- HEX$ Function
- IF...THEN...ELSE Statements
- INKEY$ Function
- INP Function
- INPUT$ Function
- INPUT Statement
- INPUT # Statement
- INSTR Function
- INT Function
- IOCTL$ Function
- IOCTL Statement
- KEY Statements
- KEY(n) Statements
- KILL Statement
- LBOUND Function
- LCASE$ Function
- LEFT$ Function
- LEN Function
- LET Statement
- LINE Statement
- LINE INPUT Statement
- LINE INPUT # Statement
- LOC Function
- LOCATE Statement
- LOCK...UNLOCK Statement
- LOF Function
- LOG Function
- LPOS Function
- LPRINT, LPRINT USING Statements
- LSET Statement
- LTRIM$ Function
- MID$ Function
- MID$ Statement
- MKD$, MKI$, MKL$, MKS$ Functions
- MKDIR Statement
- MKSMBF$, MKDMBF$ Functions
- NAME Statement
- OCT$ Function
- ON ERROR Statement
- ON event Statements
- ON UEVENT GOSUB Statement
- ON...GOSUB, ON...GOTO Statements
- OPEN Statement
- OPEN COM Statement
- OPTION BASE Statement
- OUT Statement
- PAINT Statement
- PALETTE, PALETTE USING Statements
- PCOPY Statement
- PEEK Function
- PEN Function
- PEN ON, OFF, and STOP Statements
- PLAY Function
- PLAY Statement
- PLAY ON, OFF, and STOP Statements
- PMAP Function
- POINT Function
- POKE Statement
- POS Function
- PRESET Statement
- PRINT Statement
- PRINT #, PRINT # USING Statements
- PRINT USING Statement
- PSET Statement
- PUT Statement──File I/O
- PUT Statement──Graphics
- RANDOMIZE Statement
- READ Statement
- REDIM Statement
- REM Statement
- RESET Statement
- RESTORE Statement
- RESUME Statement
- RETURN Statement
- RIGHT$ Function
- RMDIR Statement
- RND Function
- RSET Statement
- RTRIM$ Function
- RUN Statement
- SADD Function
- SCREEN Function
- SCREEN Statement
- SEEK Function
- SEEK Statement
- SELECT CASE Statement
- SETMEM Function
- SGN Function
- SHARED Statement
- SHELL Statement
- SIN Function
- SLEEP Statement
- SOUND Statement
- SPACE$ Function
- SPC Function
- SQR Function
- STATIC Statement
- STICK Function
- STOP Statement
- STR$ Function
- STRIG Function and Statement
- STRIG ON, OFF, and STOP Statements
- STRING$ Function
- SUB Statements
- SWAP Statement
- SYSTEM Statement
- TAB Function
- TAN Function
- TIME$ Function
- TIME$ Statement
- TIMER Function
- TIMER ON, OFF, and STOP Statements
- TRON/TROFF Statements
- TYPE Statement
- UBOUND Function
- UCASE$ Function
- UEVENT Statement
- UNLOCK Statement
- VAL Function
- VARPTR, VARSEG Functions
- VARPTR$ Function
- VIEW Statement
- VIEW PRINT Statement
- WAIT Statement
- WHILE...WEND Statement
- WIDTH Statement
- WINDOW Statement
- WRITE Statement
- WRITE # Statement
-
- Chapter 9 Quick-Reference Tables
- 9.1 Summary of Control-Flow Statements
- 9.2 Summary of Statements Used in BASIC Procedures
- 9.3 Summary of Standard I/O Statements
- 9.4 Summary of File I/O Statements
- 9.5 Summary of String-Processing Statements and Functions
- 9.6 Summary of Graphics Statements and Functions
- 9.7 Summary of Trapping Statements and Functions
-
- Appendix A Converting BASICA Programs to QuickBASIC
-
- Appendix B Differences from Previous Versions of QuickBASIC
-
- Appendix C Limits in QuickBASIC
-
- Appendix D Keyboard Scan Codes and ASCII Character Codes
-
- Appendix E BASIC Reserved Words
-
- Appendix F Metacommands
-
- Appendix G Compiling and Linking from DOS
-
- Appendix H Creating and Using Quick Libraries
-
- Appendix I Error Messages
-
- Figures
- Figure 1.1 Logic of FOR...NEXT Loop with Positive STEP
- Figure 1.2 Logic of FOR...NEXT Loop with Negative STEP
- Figure 1.3 Logic of WHILE...WEND Loop
- Figure 1.4 Logic of DO WHILE...LOOP
- Figure 1.5 Logic of DO UNTIL...LOOP
- Figure 1.6 Logic of DO...LOOP WHILE
- Figure 1.7 Logic of DO...LOOP UNTIL
- Figure 2.1 Parameters and Arguments
- Figure 3.1 Text Output on Screen
- Figure 3.2 Records in Sequential Files
- Figure 3.3 Records in a Random-Access File
- Figure 5.1 Coordinates of Selected Pixels in Screen Mode 2
- Figure 5.2 How Angles Are Measured for CIRCLE
- Figure 5.3 The Aspect Ratio In Screen Mode 1
- Figure 5.4 WINDOW Contrasted with WINDOW SCREEN
- Figure 5.5 Patterned Circle
- Figure 6.1 Program Flow of Control with RESUME
- Figure 6.2 Program Flow of Control with RESUME NEXT
- Figure 7.1 Main Module Showing Module-Level Code and Procedures
- Figure H.1 Make Library Dialog Box
-
- Tables
- Table 1.1 Relational Operators Used in Basic
- Table 1.2 Block IF...THEN...ELSE Syntax and Example
- Table 1.3 SELECT CASE Syntax and Example
- Table 1.4 FOR...NEXT Syntax and Example
- Table 1.5 WHILE...WEND Syntax and Example
- Table 1.6 DO...LOOP Syntax and Example: Test at the Beginning
- Table 1.7 DO...LOOP Syntax and Example: Test at the End
- Table 3.1 Devices Supported by BASIC for I/O
- Table 5.1 Color Palettes in Screen Mode 1
- Table 5.2 Background Colors in Screen Mode 1
- Table 5.3 Binary to Hexadecimal Conversion
- Table 5.4 The Effect of Different Action Options in Screen Mode 2
- Table 5.5 The Effect of Different Action Options on Color in Screen Mode 1
- (Palette 1)
- Table 6.1 BC Command-Line Options for Error and Event Trapping
- Table 9.1 Statements Used in Looping and Decision-Making
- Table 9.2 Statements Used in Procedures
- Table 9.3 Statements and Functions Used for Standard I/O
- Table 9.4 Statements and Functions Used for Data-File I/O
- Table 9.5 Statements and Functions Used for Processing Strings
- Table 9.6 Statements and Functions Used for Graphics Output
- Table 9.7 Statements andn Functions Used in Error and Event Trapping
- Table A.1 Statements Requiring Modification
- Table B.1 Features of Microsoft QuickBASIC Version 4.5
- Table B.2 Menus with New Commands in QuickBASIC Version 4.5
- Table B.3 Editing-Key Changes
- Table B.4 QB and BC Options Not Used in QuickBASIC Versions 4.0 or 4.5
- Table B.5 Options Introduced in Version 4.0 for the QB and BC Commands
- Table B.6 Debugging-Key Changes
- Table B.7 Changes to the BASIC Language
- Table C.1 QuickBASIC Limits
- Table G.1 Input to the BC Command
- Table G.2 Input to the LINK Command
- Table G.3 Input to the LIB Command
- Table I.1 Run-Time Error Codes
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- Introduction
-
- Microsoft(R) QuickBASIC 4.5 is a major advance in making BASIC both more
- powerful and easier to use. It provides the most advanced BASIC yet
- offered for microcomputers, supported by an operating environment that
- allows you to focus on program creation──not the mechanics of writing or
- debugging.
-
-
- The QuickBASIC Language
-
- If you already know how to program in BASICA (or a similar interpreted
- BASIC), you'll appreciate the enhanced language features QuickBASIC
- provides to make it easier to write and maintain your software. For
- example:
-
- ■ The SELECT CASE statement cleanly transfers control to any block of code
- without the use of nested IF...THEN...ELSE statements. SELECT CASE
- permits an exceptionally wide range of test expressions, so you can
- create exactly the comparison you need.
-
- ■ QuickBASIC's SUB and FUNCTION procedures allow you to place groups of
- program statements into subprograms that your main program can call
- repeatedly. QuickBASIC's modularity makes it easy to save these
- procedures and reuse them in other programs.
-
- ■ QuickBASIC procedures are fully recursive──a procedure can call itself
- repeatedly. This simplifies the programming of many numerical and
- sorting algorithms that are best expressed recursively.
-
- ■ You can define your own data types, made up of any combination of
- integer, real, and string variables. Related variables can be
- conveniently grouped under a single name, which simplifies passing them
- to a procedure or writing them to a file.
-
- ■ QuickBASIC supports binary file access. Your programs can read and
- manipulate files in any format because binary I/O can directly access
- any byte in the file.
-
- QuickBASIC is a powerful development tool for professional use. Yet it is
- also the ideal language for beginning and intermediate programmers──people
- who aren't professional programmers but need a language that helps them
- reach their programming goals efficiently.
-
-
- The QuickBASIC Environment
-
- QuickBASIC isn't just an outstanding language. It is also an integrated
- programming environment that significantly simplifies writing and
- debugging software:
-
- ■ As you type in your program, a smart editor checks each line for syntax
- errors. When you are ready to run, press a single key to execute the
- program instantly. If something is wrong, use the full-screen editor to
- correct the problem, then run the program again.
-
- ■ You can debug your programs without exiting QuickBASIC. The integrated
- debugger lets you examine and alter variables, execute any part of the
- program, or halt execution when a particular condition is met. All these
- things happen within the QuickBASIC environment; you don't have to alter
- the program or add PRINT statements.
-
- ■ QuickBASIC 4.5 has two new commands to make the debugger even more
- powerful: the Instant Watch command and the Break on Errors command.
-
- ■ Also new to QuickBASIC 4.5 is the Microsoft QB Advisor, our on-line
- help. The QB Advisor is always at hand, whether you are writing,
- running, or debugging. Just place the cursor on the keyword or
- user-defined name you want to know more about, then press F1. The QB
- Advisor describes the syntax of BASIC statements and functions, explains
- how to use them, and even provides usable programming examples.
-
-
- Using This Manual
-
- This manual is in three parts. Part 1, "Selected Programming Topics,"
- provides information on specific programming techniques and strategies.
- Part 2, "Heart of BASIC," and the appendixes contain important reference
- material.
-
- Selected Programming Topics
-
- Each chapter in this first section focuses on a single programming area.
- Studying this material will help you to quickly master
-
- ■ Control-flow structures
-
- ■ SUB and FUNCTION procedures
-
- ■ File and device input and output
-
- ■ String processing
-
- ■ Graphics
-
- ■ Error and event trapping
-
- ■ Programming with modules
-
- The presentation of each topic is straightforward and easy to understand,
- with many short programming examples that demonstrate how each part of
- BASIC works. The progression is from simple to more complex topics, so you
- can work through this material at your own pace without worrying about the
- order in which to study it. The focus throughout is on utility, not
- theory──how you can solve common programming problems with QuickBASIC.
-
- In addition to the short examples, the chapters contain complete working
- programs that demonstrate the programming principles presented in that
- chapter. For your convenience, these programs are also included on your
- QuickBASIC release disks.
-
- If you're an experienced BASIC programmer, you'll probably want to browse
- through the table of contents for a topic that catches your interest. If
- you're a novice programmer, though, you should probably work through each
- chapter from beginning to end. If you have never programmed in any
- language, you should start with Chapter 4 of Learning to Use Microsoft
- QuickBASIC, "Interlude: BASIC for Beginners."
-
- Regardless of your interests or background, these seven chapters will help
- you learn almost everything you need to know to write sophisticated BASIC
- applications.
-
- The Heart of BASIC
-
- The second part of this manual, the "Heart of BASIC," is a handy,
- two-part quick reference to BASIC statements and functions.
-
- Chapter 8, "Statement and Function Summary," is an alphabetically
- arranged summary of every BASIC keyword, describing its action or use and
- displaying its syntax. If your memory needs jogging on statement or
- function use, turn to this section.
-
- In Chapter 9, "Quick-Reference Tables," the most commonly used BASIC
- statements and functions are displayed in six sections in table form, with
- each statement given a brief description. The contents of these sections
- match the material presented in Chapters 1 through 6 of "Selected
- Programming Topics." If you are trying to figure out how to accomplish a
- particular programming task, turn to this section.
-
- Appendixes
-
- The third section of this manual is a group of appendixes containing
- reference information on
-
- ■ Converting BASICA programs
-
- ■ Differences from previous versions
-
- ■ Limits in QuickBASIC
-
- ■ Keyboard scan codes and ASCII codes
-
- ■ BASIC reserved words
-
- ■ Metacommands
-
- ■ Compiling and linking from DOS
-
- ■ Creating and using Quick libraries
-
- ■ Error messages
-
-
- Document Conventions
-
- This manual uses the following typographic conventions:
-
- ╓┌─┌────────────────────────┌────────────────────────────────────────────────╖
- Example of Convention Description
- ──────────────────────────────────────────────────────────────────────────
- QB.LIB, ADD.EXE, COPY, Uppercase (capital) letters indicate file names
- LINK, /X and DOS-level commands. Uppercase is also used
- for command-line options (unless the application
- accepts only lowercase).
-
- SUB, IF, LOOP, PRINT, Bold capital letters indicate language-specific
- WHILE, TIME$ keywords with special meaning to Microsoft BASIC.
- Example of Convention Description
- ──────────────────────────────────────────────────────────────────────────
- WHILE, TIME$ keywords with special meaning to Microsoft BASIC.
- Keywords are a required part of statement syntax,
- unless they are enclosed in double brackets as
- explained below. In programs you write, you must
- enter keywords exactly as shown. However, you can
- use uppercase letters or lowercase letters.
-
- CALL NewProc(arg1!, This kind of type is used for program examples,
- var2%) program output, and error messages within the
- text.
-
- '$INCLUDE:'BC.BI' A column of three dots indicates that part of the
- . example program has been intentionally omitted.
- .
- .
- CHAIN "PROG1"
- END
-
- ' Make one pass The apostrophe (single right quotation mark)
- Example of Convention Description
- ──────────────────────────────────────────────────────────────────────────
- ' Make one pass The apostrophe (single right quotation mark)
- marks the beginning of a comment in sample
- programs.
-
- filespec Italic letters indicate placeholders for
- information you must supply, such as a file name.
- Italics are also occasionally used in the text
- for emphasis.
-
- [[optional-item]] Items inside double square brackets are optional.
-
- {choice1 | choice2} Braces and a vertical bar indicate a choice among
- two or more items. You must choose one of the
- items unless all of the items are also enclosed
- in double square brackets.
-
- repeating elements... Three dots following an item indicate that more
- items having the same form may appear.
-
- Example of Convention Description
- ──────────────────────────────────────────────────────────────────────────
- ALT+F1 Capital letters are used for the names of keys
- and key sequences, such as ENTER and CTRL+R.
-
- A plus (+) indicates a combination of keys. For
- example, CTRL+E means to hold down the CTRL key
- while pressing the E key.
-
- The carriage-return key, sometimes marked with a
- bent arrow, is referred to as ENTER.
-
- The cursor movement ("arrow") keys on the numeric
- keypad are called DIRECTION keys. Individual
- DIRECTION keys are referred to by the direction
- of the arrow on the key top (LEFT, RIGHT, UP,
- DOWN) or the name on the key top (PGUP, PGDN).
-
- The key names used in this manual correspond to
- the names on the IBM(R) Personal Computer keys.
- Example of Convention Description
- ──────────────────────────────────────────────────────────────────────────
- the names on the IBM(R) Personal Computer keys.
- Other machines may use different names.
-
- "defined term" Quotation marks usually indicate a new term
- defined in the text.
-
- Video Graphics Array Acronyms are usually spelled out the first time
- (VGA) they are used.
- ──────────────────────────────────────────────────────────────────────────
-
-
- The syntax below (for the "LOCK...UNLOCK" statements) illustrates many of
- the typographic conventions in this manual:
-
- LOCK[[#]]filenumber[[,{record|[[start]] TO end}]] . . .
- UNLOCK[[#]]filenumber[[,{record |[[start]] TO end}]]
-
- ──────────────────────────────────────────────────────────────────────────
- NOTE
- Throughout this manual, the term "DOS" refers to both the MS-DOS(R) and
- IBM Personal Computer DOS operating systems. The name of a specific
- operating system is used when it is necessary to note features that are
- unique to that system. The term "BASICA" refers to interpreted versions
- of BASIC in general.
- ──────────────────────────────────────────────────────────────────────────
-
-
- Programming Style in this Manual
-
- The following guidelines were used in writing programs in this manual and
- on the distribution disks. These guidelines are only recommendations for
- program readability; you are not obliged to follow them when writing your
- own programs.
-
- ■ Keywords and symbolic constants appear in uppercase letters:
-
- ' PRINT, DO, LOOP, UNTIL are keywords:
- PRINT "Title Page"
- DO LOOP UNTIL Response$ = "N"
-
- ' FALSE and TRUE are symbolic constants
- ' equal to 0 and -1, respectively:
- CONST FALSE = 0, TRUE = NOT FALSE
-
- ■ Variable names are in lowercase with an initial capital letter; variable
- names with more than one syllable may contain other capital letters to
- clarify the division:
-
- NumRecords% = 45
- DateOfBirth$ = "11/24/54"
-
- ■ Line labels are used instead of line numbers. The use of line labels is
- restricted to event-trapping and error-handling routines, as well as
- DATA statements when referenced with RESTORE:
-
- ' TimerHandler and ScreenTwoData are line labels:
- ON TIMER GOSUB TimerHandler
- RESTORE ScreenTwoData
-
- ■ As noted in the preceding section, a single apostrophe (') introduces
- comments:
-
- ' This is a comment; these two lines
- ' are ignored when the program is running.
-
- ■ Control-flow blocks and statements in procedures or subroutines are
- indented from the enclosing code:
-
- SUB GetInput STATIC
- FOR I% = 1 TO 10
- INPUT X
- IF X > 0 THEN
- .
- .
- .
- ELSE
- .
- .
- .
- END IF
- NEXT I%
- END SUB
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- PART 1 SELECTED PROGRAMMING TOPICS
- ────────────────────────────────────────────────────────────────────────────
-
- Part 1 introduces the fundamentals of programming in BASIC. Simpler topics
- are covered first.
-
- Chapter 1 discusses the control-flow structures that direct your
- program's execution. Chapter 2 is about QuickBASIC SUB and FUNCTION
- procedures, two very powerful programming tools. Chapter 3 describes the
- ways you can use QuickBASIC to work with the data your program accepts and
- produces. Chapter 4 covers the use of text strings, and Chapter 5
- presents QuickBASIC's graphics capabilities.
-
- More advanced topics are covered in the last two chapters. Chapter 6
- looks at error and event trapping, and Chapter 7 tells you how to use
- programming with modules to your advantage.
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- Chapter 1 Control-Flow Structures
-
- This chapter shows you how to use control-flow structures──specifically,
- loops and decision statements──to control the flow of your program's
- execution. Loops make a program execute a sequence of statements however
- many times you want. Decision statements let the program decide which of
- several alternative paths to take.
-
- When you are finished with this chapter, you will know how to do the
- following tasks related to using loops and decision statements in your
- BASIC programs:
-
- ■ Compare expressions using relational operators
-
- ■ Combine string or numeric expressions with logical operators and
- determine if the resulting expression is true or false
-
- ■ Create branches in the flow of the program with the statements
- IF...THEN...ELSE and SELECT CASE
-
- ■ Write loops that repeat statements a specific number of times
-
- ■ Write loops that repeat statements while or until a certain condition is
- true
-
-
- 1.1 Changing Statement Execution Order
-
- Left unchecked by control-flow statements, a program's logic flows through
- statements from left to right, top to bottom. While some very simple
- programs can be written with only this unidirectional flow, most of the
- power and utility of any programming language comes from its ability to
- change statement execution order with decision structures and loops.
-
- With a decision structure, a program can evaluate an expression, then
- branch to one of several different groups of related statements (statement
- blocks) depending on the result of the evaluation. With a loop, a program
- can repeatedly execute statement blocks.
-
- If you are coming to this version of BASIC after programming in BASICA,
- you will appreciate the added versatility of these additional control-flow
- structures:
-
- ■ The block IF...THEN...ELSE statement
-
- ■ The SELECT CASE statement
-
- ■ The DO...LOOP and EXIT DO statements
-
- ■ The EXIT FOR statement, which provides an alternative way to exit
- FOR...NEXT loops
-
-
- 1.2 Boolean Expressions
-
- A Boolean expression is any expression that returns the value "true" or
- "false." BASIC uses Boolean expressions in certain kinds of decision
- structures and loops. The following IF...THEN...ELSE statement contains a
- Boolean expression, X < Y:
-
- IF X < Y THEN CALL Procedure1 ELSE CALL Procedure2
-
- In the previous example, if the Boolean expression is true (if the value
- of the variable X is in fact less than the value of the variable Y), then
- Procedure1 is executed; otherwise (if X is greater than or equal to Y),
- Procedure2 is executed.
-
- The preceding example also demonstrates a common use of Boolean
- expressions: comparing two other expressions (in this case, X and Y) to
- determine the relationship between them. These comparisons are made with
- the relational operators shown in Table 1.1.
-
- Table 1.1 Relational Operators Used in BASIC
- Operator Meaning
- ──────────────────────────────────────────────────────────────────────────
- = Equal
-
- < > Not equal
-
- < Less than
-
- <= Less than or equal to
-
- > Greater than
-
- >= Greater than or equal to
- ──────────────────────────────────────────────────────────────────────────
-
- You can use these relational operators to compare string expressions. In
- this case "greater than," "less than," and so on refer to alphabetical
- order. For example, the following expression is true, since the word
- "deduce" comes alphabetically before the word "deduct":
-
- "deduce" < "deduct"
-
- Logical operators
-
- Boolean expressions also frequently use the "logical operators" AND, OR,
- NOT, XOR, IMP, and EQV. These operators allow you to construct compound
- tests from one or more Boolean expressions. For example,
-
- expression1 AND expression2
-
- is true only if expression1 and expression2 are both true. Thus, in the
- following example, the message All sorted is printed only if both the
- Boolean expressions X <= Y and Y <= Z are true:
-
- IF (X <= Y) AND (Y <= Z) THEN PRINT "All sorted"
-
- The parentheses around the Boolean expressions in the last example are not
- really necessary, since relational operators such as <= are evaluated
- before logical operators such as AND. However, parentheses make a complex
- Boolean expression more readable and ensure that its components are
- evaluated in the order that you intend.
-
- BASIC uses the numeric values -1 and 0 to represent true and false,
- respectively. You can see this by asking BASIC to print a true expression
- and a false expression, as in the next example:
-
- x = 5
- y = 10
- PRINT x < y ' Evaluate, print a "true" Boolean expression.
- PRINT x > y ' Evaluate, print a "false" Boolean expression.
-
- Output
-
- -1
- 0
-
- The value -1 for true makes more sense when you consider how BASIC's NOT
- operator works: NOT inverts each bit in the binary representation of its
- operand, changing 1 bits to 0 bits, and 0 bits to 1 bits. Therefore, since
- the integer value 0 (false) is stored internally as a sequence of sixteen
- 0 bits, NOT 0 (true) is stored internally as sixteen 1 bits, as shown
- below:
-
- 0000000000000000
-
- TRUE = NOT FALSE = 1111111111111111
-
- In the two's-complement method that BASIC uses to store integers, sixteen
- 1 bits represent the value -1.
-
- Note that BASIC outputs -1 when it evaluates a Boolean expression as true;
- however, BASIC considers any nonzero value to be true, as shown by the
- output from the following example:
-
- INPUT "Enter a value: ", x
-
- IF x THEN PRINT x "is true."
-
- Output
-
- Enter a value: 2
- 2 is true.
-
- The NOT operator in BASIC is a "bitwise" operator. Some programming
- languages, such as C and Pascal, have both a bitwise NOT operator and a
- "logical" NOT operator. The distinction is as follows:
-
- ■ A bitwise NOT returns false (0) only for the value -1.
-
- ■ A logical NOT returns false (0) for any true (nonzero) value.
-
- In BASIC, for any true expression not equal to -1, NOT expression returns
- another true value, as shown by the following list:
-
- Value of expression Value of NOT expression
- ──────────────────────────────────────────────────────────────────────────
- 1 -2
-
- 2 -3
-
- -2 1
-
- -1 0
- ──────────────────────────────────────────────────────────────────────────
-
- So beware: NOT expression is false only if expression evaluates to a value
- of -1. If you define Boolean constants or variables for use in your
- programs, use -1 for true.
-
- You can use the values 0 and -1 to define helpful mnemonic Boolean
- constants for use in loops or decisions. This technique is used in many of
- the examples in this manual, as shown in the following program fragment,
- which sorts the elements of an array named Amount in ascending order:
-
- ' Define symbolic constants to use in program:
- CONST FALSE = 0, TRUE = NOT FALSE
- .
- .
- .
-
- DO
- Swaps = FALSE
- FOR I = 1 TO TransacNum - 1
- IF Amount(I) < Amount(I+1) THEN
- SWAP Amount(I), Amount(I+1)
- Swaps = TRUE
- END IF
- NEXT I
- LOOP WHILE Swaps ' Keep looping while Swaps is TRUE.
- .
- .
- .
-
-
- 1.3 Decision Structures
-
- Based on the value of an expression, decision structures cause a program
- to take one of the following two actions:
-
- 1. Execute one of several alternative statements within the decision
- structure itself
-
- 2. Branch to another part of the program outside the decision structure
-
- In BASICA, decision-making is handled solely by the single-line
- IF...THEN[[...ELSE]] statement. In its simplest form (IF...THEN) the
- expression following the IF keyword is evaluated. If the expression is
- true, the program executes the statements following the THEN keyword; if
- the expression is false, the program continues with the next line after
- the IF...THEN statement. Lines 50 and 70 from the following BASICA program
- fragment show examples of IF...THEN:
-
- 30 INPUT A
- 40 ' If A is greater than 100, print a message and branch
- 45 ' back to line 30; otherwise, go on to line 60:
- 50 IF A > 100 THEN PRINT "Too big": GOTO 30
- 60 ' If A is equal to 100, branch to line 300;
- 65 ' otherwise, go on to line 80:
- 70 IF A = 100 THEN GOTO 300
- 80 PRINT A/100: GOTO 30
- .
- .
- .
-
- By adding the ELSE clause to an IF...THEN statement, you can have your
- program take one set of actions (those following the THEN keyword) if an
- expression is true, and another set of actions (those following the ELSE
- keyword) if it is false. The next program fragment shows how ELSE works in
- an IF...THEN...ELSE statement:
-
- 10 INPUT "What is your password"; Pass$
- 15 ' If user enters "sword", branch to line 50;
- 20 ' otherwise, print a message and branch back to line 10:
- 30 IF Pass$="sword" THEN 50 ELSE PRINT "Try again": GOTO 10
- .
- .
- .
-
- While BASICA's single-line IF...THEN...ELSE is adequate for simple
- decisions, it can lead to virtually unreadable code in cases of more
- complicated ones. This is especially true if you write your programs so
- all alternative actions take place within the IF...THEN...ELSE statement
- itself or if you nest IF...THEN... ELSE statements (that is, if you put
- one IF...THEN...ELSE inside another, a perfectly legal construction). As
- an example of how difficult it is to follow even a simple test, consider
- the next fragment from a BASICA program:
-
- 10 ' The following nested IF...THEN...ELSE statements print
- 15 ' different output for each of the following four cases:
- 20 ' 1) A <= 50, B <= 50 3) A > 50, B <= 50
- 25 ' 2) A <= 50, B > 50 4) A > 50, B > 50
- 30
- 35 INPUT A, B
- 40
- 45 ' Note: even though line 70 extends over several physical
- 50 ' lines on the screen, it is just one "logical line"
- 55 ' (everything typed before the <ENTER> key was pressed).
- 60 ' BASICA wraps long lines on the screen.
- 65
- 70 IF A <= 50 THEN IF B <= 50 THEN PRINT "A <= 50, B <= 50"
- ELSE PRINT "A <= 50, B > 50" ELSE IF B <= 50 THEN PRINT "A >
- 50, B <= 50" ELSE PRINT "A > 50, B > 50"
-
- To avoid the kind of complicated statement shown above, BASIC now includes
- the block form of the IF...THEN...ELSE statement, so that a decision is no
- longer restricted to one logical line. The following shows the same BASICA
- program rewritten to use block IF...THEN...ELSE:
-
- INPUT A, B
- IF A <= 50 THEN
- IF B <= 50 THEN
- PRINT "A <= 50, B <= 50"
- ELSE
- PRINT "A <= 50, B > 50"
- END IF
- ELSE
- IF B <= 50 THEN
- PRINT "A > 50, B <= 50"
- ELSE
- PRINT "A > 50, B > 50"
- END IF
- END IF
-
- QuickBASIC also provides the SELECT CASE...END SELECT (referred to as
- SELECT CASE) statement for structured decisions.
-
- Both the block IF...THEN...ELSE statement and the SELECT CASE statement
- allow the appearance of your code to be based on program logic, rather
- than requiring many statements to be crowded onto one line. This gives you
- increased flexibility while you are programming, as well as improved
- program readability and ease of maintenance when you are done.
-
- 1.3.1 Block IF...THEN...ELSE
-
- Table 1.2 shows the syntax of the block IF...THEN...ELSE statement and
- gives an example of its use.
-
- Table 1.2 Block IF...THEN...ELSE Syntax and Example
- Syntax Example
- ──────────────────────────────────────────────────────────────────────────
- IF condition1 THEN IF X > 0 THEN
- [[statementblock-1]] PRINT "X is positive"
- [[ELSEIF condition2 THEN PosNum = PosNum + 1
- [[statementblock-2]]]] ELSEIF X < 0 THEN
- . PRINT "X is negative"
- . NegNum = NegNum + 1
- . ELSE
- [[ELSE PRINT "X is zero"
- [[statementblock-n]]]] END IF
- END IF
- ──────────────────────────────────────────────────────────────────────────
-
- The arguments condition1, condition2, and so on are expressions. They can
- be any numeric expression──in which case true becomes any nonzero value,
- and false is zero──or they can be Boolean expressions, in which case true
- is -1 and false is zero. As explained in Section 1.2, Boolean expressions
- typically compare two numeric or string expressions using one of the
- relational operators such as < or >=.
-
- Each IF, ELSEIF, and ELSE clause is followed by a block of statements.
- None of the statements in the block can be on the same line as the IF,
- ELSEIF, or ELSE clause; otherwise, BASIC considers it a single-line
- IF...THEN statement.
-
- BASIC evaluates each of the expressions in the IF and ELSEIF clauses from
- top to bottom, skipping over statement blocks until it finds the first
- true expression. When it finds a true expression, it executes the
- statements corresponding to the expression, then branches out of the block
- to the statement following the END IF clause.
-
- If none of the expressions in the IF or ELSEIF clauses is true, BASIC
- skips to the ELSE clause, if there is one, and executes its statements.
- Otherwise, if there is no ELSE clause, the program continues with the next
- statement after the END IF clause.
-
- The ELSE and ELSEIF clauses are both optional, as shown in the following
- example:
-
- ' If the value of X is less than 100, do the two statements
- ' before END IF; otherwise, go to the INPUT statement
- ' following END IF:
-
- IF X < 100 THEN
- PRINT X
- Number = Number + 1
- END IF
- INPUT "New value"; Response$
- .
- .
- .
-
- A single block IF...THEN...ELSE can contain multiple ELSEIF statements, as
- shown below:
-
- IF C$ >= "A" AND C$ <= "Z" THEN
- PRINT "Capital letter"
- ELSEIF C$ >= "a" AND C$ <= "z" THEN
- PRINT "Lowercase letter"
- ELSEIF C$ >= "0" AND C$ <= "9" THEN
- PRINT "Number"
- ELSE
- PRINT "Not alphanumeric"
- END IF
-
- At most, only one block of statements is executed, even if more than one
- condition is true. For example, if you enter the word ace as input to the
- next example, it prints the message Input too short but does not print the
- message Can't start with an a:
-
- INPUT Check$
- IF LEN(Check$) > 6 THEN
- PRINT "Input too long"
- ELSEIF LEN(Check$) < 6 THEN
- PRINT "Input too short"
- ELSEIF LEFT$(Check$, 1) = "a" THEN
- PRINT "Can't start with an a"
- END IF
-
- IF...THEN...ELSE statements can be nested; in other words, you can put an
- IF...THEN...ELSE statement inside another IF...THEN...ELSE statement, as
- shown here:
-
- IF X > 0 THEN
- IF Y > 0 THEN
- IF Z > 0 THEN
- PRINT "All are greater than zero."
- ELSE
- PRINT "Only X and Y greater than zero."
- END IF
- END IF
- ELSEIF X = 0 THEN
- IF Y = 0 THEN
- IF Z = 0 THEN
- PRINT "All equal zero."
- ELSE
- PRINT "Only X and Y equal zero."
- END IF
- END IF
- ELSE
- PRINT "X is less than zero."
- END IF
-
- 1.3.2 SELECT CASE
-
- The SELECT CASE statement is a multiple-choice decision structure similar
- to the block IF...THEN...ELSE statement. Block IF...THEN...ELSE can be
- used anywhere SELECT CASE can be used.
-
- The major difference between the two is that SELECT CASE evaluates a
- single expression, then executes different statements or branches to
- different parts of the program based on the result. In contrast, a block
- IF...THEN...ELSE can evaluate completely different expressions.
-
- Examples
-
- The following examples illustrate the similarities and differences between
- the SELECT CASE and IF...THEN...ELSE statements. Here is an example of
- using block IF...THEN...ELSE for a multiple-choice decision:
-
- INPUT X
- IF X = 1 THEN
- PRINT "One"
- ELSEIF X = 2 THEN
- PRINT "Two"
- ELSEIF X = 3 THEN
- PRINT "Three"
- ELSE
- PRINT "Must be integer from 1-3."
- END IF
-
- The above decision is rewritten using SELECT CASE below:
-
- INPUT X
- SELECT CASE X
- CASE 1
- PRINT "One"
- CASE 2
- PRINT "Two"
- CASE 3
- PRINT "Three"
- CASE ELSE
- PRINT "Must be integer from 1-3."
- END SELECT
-
- The following decision can be made either with the SELECT CASE or the
- block IF...THEN...ELSE statement. The comparison is more efficient with
- the IF...THEN...ELSE statement because different expressions are being
- evaluated in the IF and ELSEIF clauses.
-
- INPUT X, Y
- IF X = 0 AND Y = 0 THEN
- PRINT "Both are zero."
- ELSEIF X = 0 THEN
- PRINT "Only X is zero."
- ELSEIF Y = 0 THEN
- PRINT "Only Y is zero."
- ELSE
- PRINT "Neither is zero."
- END IF
-
- 1.3.2.1 Using the SELECT CASE Statement
-
- Table 1.3 shows the syntax of a SELECT CASE statement and an example.
-
- Table 1.3 SELECT CASE Syntax and Example
- Syntax Example
- ──────────────────────────────────────────────────────────────────────────
- SELECT CASE expression INPUT TestValue
- CASE expressionlist1 SELECT CASE TestValue
- [[statementblock-1]] CASE 1, 3, 5, 7, 9
- [[CASE expressionlist2 PRINT "Odd"
- [[statementblock-2]]]] CASE 2, 4, 6, 8
- . PRINT "Even"
- . CASE IS < 1
- . PRINT "Too low"
- [[CASE ELSE CASE IS > 9
- [[statementblock-n]]]] PRINT "Too high"
- END SELECT CASE ELSE
- PRINT "Not an integer"
- END SELECT
-
- ──────────────────────────────────────────────────────────────────────────
-
- The expressionlist arguments following a CASE clause can be one or more of
- the following, separated by commas:
-
- ■ A numeric expression or a range of numeric expressions
-
- ■ A string expression or a range of string expressions
-
- To specify a range of expressions, use the following syntax for the CASE
- statement:
-
- CASE expression TO expression CASE IS relational-operator expression
-
- The relational-operator is any of the operators shown in Table 1.1. For
- example, if you use CASE 1 TO 4, the statements associated with this case
- are executed when the expression in the SELECT CASE statement is greater
- than or equal to 1 and less than or equal to 4. If you use CASE IS < 5,
- the associated statements are executed only if expression is less than 5.
-
- If you are expressing a range with the TO keyword, be sure to put the
- lesser value first. For example, if you want to test for a value between
- -5 and -1, write the CASE statement as follows:
-
- CASE -5 TO -1
-
- However, the following statement is not a valid way to specify the range
- from -5 to -1, so the statements associated with this case are never
- executed:
-
- CASE -1 TO -5
-
- Similarly, a range of string constants should list the string that comes
- first alphabetically:
-
- CASE "aardvark" TO "bear"
-
- Multiple expressions or ranges of expressions can be listed for each CASE
- clause, as in the following lines:
-
- CASE 1 TO 4, 7 TO 9, WildCard1%, WildCard2%
- CASE IS = Test$, IS = "end of data"
- CASE IS < LowerBound, 5, 6, 12, IS > UpperBound
- CASE IS < "HAN", "MAO" TO "TAO"
-
- If the value of the SELECT CASE expression appears in the list following a
- CASE clause, only the statements associated with that CASE clause are
- executed. Control then jumps to the first executable statement following
- END SELECT, not the next block of statements inside the SELECT CASE
- structure, as shown by the output from the next example (where the user
- enters 1):
-
- INPUT x
- SELECT CASE x
- CASE 1
- PRINT "One, ";
- CASE 2
- PRINT "Two, ";
- CASE 3
- PRINT "Three, ";
- END SELECT
- PRINT "that's all"
-
- Output
-
- ? 1
- One, that's all
-
- If the same value or range of values appears in more than one CASE clause,
- only the statements associated with the first occurrence are executed, as
- shown by the next example's output (where the user has entered ABORIGINE):
-
- INPUT Test$
- SELECT CASE Test$
- CASE "A" TO "AZZZZZZZZZZZZZZZZZ"
- PRINT "An uppercase word beginning with capital A"
- CASE IS < "A"
- PRINT "Some sequence of nonalphabetic characters"
- CASE "ABORIGINE"
- ' This case is never executed since ABORIGINE
- ' falls within the range in the first CASE clause:
- PRINT "A special case"
- END SELECT
-
- Output
-
- ? ABORIGINE
- An uppercase word beginning with capital A
-
- If you use a CASE ELSE clause, it must be the last CASE clause listed in
- the SELECT CASE statement. The statements between a CASE ELSE clause and
- an END SELECT clause are executed only if the expression does not match
- any of the other CASE selections in the SELECT CASE statement. In fact, it
- is a good idea to have a CASE ELSE statement in your SELECT CASE block to
- handle unforeseen values for expression. However, if there is no CASE ELSE
- statement and no match is found in any CASE statement for expression, the
- program continues execution.
-
- Example
-
- The following program fragment demonstrates a common use of the SELECT
- CASE statement: it prints a menu on the screen, then branches to different
- subprograms based on the number typed by the user.
-
- DO ' Start menu loop.
-
- CLS ' Clear screen.
-
- ' Print five menu choices on the screen:
- PRINT "MAIN MENU" : PRINT
- PRINT "1) Add New Names"
- PRINT "2) Delete Names"
- PRINT "3) Change Information"
- PRINT "4) List Names"
- PRINT
- PRINT "5) EXIT"
-
- ' Print input prompt:
- PRINT : PRINT "Type your selection (1 to 5):"
-
- ' Wait for the user to press a key. INPUT$(1)
- ' reads one character input from the keyboard:
- Ch$ = INPUT$(1)
-
- ' Use SELECT CASE to process response:
- SELECT CASE Ch$
-
- CASE "1"
- CALL AddData
- CASE "2"
- CALL DeleteData
- CASE "3"
- CALL ChangeData
- CASE "4"
- CALL ListData
- CASE "5"
- EXIT DO ' The only way to exit the menu loop
- CASE ELSE
- BEEP
- END SELECT
-
- LOOP ' End menu loop.
-
- END
-
- ' Subprograms AddData, DeleteData, ChangeData, and ListData:
- .
- .
- .
-
- 1.3.2.2 SELECT CASE Versus ON...GOSUB
-
- You can use the more versatile SELECT CASE statement as a replacement for
- the old ON expression {GOSUB| GOTO} statement. The SELECT CASE statement
- has many advantages over the ON...GOSUB statement, as summarized below:
-
- ■ The expression in SELECT CASE expression can evaluate to either a string
- or numeric value. The expression given in the statement ON
- expression{GOSUB| GOTO} must evaluate to a number within the range 0 to
- 255.
-
- ■ The SELECT CASE statement branches to a statement block immediately
- following the matching CASE clause. In contrast, ON expression GOSUB
- branches to a subroutine in another part of the program.
-
- ■ CASE clauses can be used to test an expression against a range of
- values. When the range is quite large, this is not easily done with ON
- expression{GOSUB| GOTO}, especially as shown in the following fragments.
-
- In the fragment below, the ON...GOSUB statement branches to one of the
- subroutines 50, 100, or 150, depending on the value input by the user:
-
- X% = -1
- WHILE X%
- INPUT "Enter choice (0 to quit): ", X%
- IF X% = 0 THEN END
- WHILE X% < 1 OR X% > 12
- PRINT "Must be value from 1 to 12"
- INPUT "Enter choice (0 to quit): ", X%
- WEND
- ON x% GOSUB 50,50,50,50,50,50,50,50,100,100,100,150
- WEND
- .
- .
- .
-
- Contrast the preceding example with the next one, which uses a SELECT CASE
- statement with ranges of values in each CASE clause:
-
- DO
- INPUT "Enter choice (0 to quit): ", X%
- SELECT CASE X%
- CASE 0
- END
- CASE 1 TO 8 ' Replaces "subroutine 50"
- ' in preceding example
- CASE 9 TO 11 ' Replaces "subroutine 100"
- ' in preceding example
- CASE 12 ' Replaces "subroutine 150"
- ' in preceding example
- CASE ELSE ' Input was out of range.
- PRINT "Must be value from 1 to 12"
- END SELECT
- LOOP
-
-
- 1.4 Looping Structures
-
- Looping structures repeat a block of statements (the loop), either for a
- specified number of times or until a certain expression (the loop
- condition) is true or false.
-
- Users of BASICA are familiar with two looping structures, FOR...NEXT and
- WHILE...WEND, which are discussed in Sections 1.4.1 and 1.4.2,
- respectively. QuickBASIC has extended the available loop structures with
- the DO...LOOP statement, discussed in Section 1.4.3.
-
- 1.4.1 FOR...NEXT Loops
-
- A FOR...NEXT loop repeats the statements enclosed in the loop a definite
- number of times, counting from a starting value to an ending value by
- increasing or decreasing a loop counter. As long as the loop counter has
- not reached the ending value, the loop continues to execute. Table 1.4
- shows the syntax of the FOR...NEXT statement and gives an example of its
- use.
-
- Table 1.4 FOR...NEXT Syntax and Example
- Syntax Example
- ──────────────────────────────────────────────────────────────────────────
- FOR counter = start TO end [[STEP FOR I% = 1 to 10
- stepsize]] Array%(I%) = I%
- [[statementblock-1]] NEXT
- [[EXIT FOR
- [[statementblock-2]]]]
- NEXT[[counter]]
- ──────────────────────────────────────────────────────────────────────────
-
- In a FOR...NEXT loop, the counter variable initially has the value of the
- expression start. After each repetition of the loop, the value of counter
- is adjusted. If you leave off the optional STEP keyword, the default value
- for this adjustment is one; that is, one is added to counter each time the
- loop executes. If you use STEP, then counter is adjusted by the amount
- stepsize. The stepsize argument can be any numeric value; if it is
- negative, the loop counts down from start to end. After the counter
- variable is increased or decreased, its value is compared with end. At
- this point, if either of the following is true, the loop is completed:
-
- ■ The loop is counting up (stepsize is positive) and counter is greater
- than end.
-
- ■ The loop is counting down (stepsize is negative) and counter is less
- than end.
-
- Figure 1.1 shows the logic of a FOR...NEXT loop when the value of
- stepsize is positive.
-
-
- ┌────────────────────────────────────┐
- │ │
- │ Figure 1.1 can be found on │
- │ page 20 of the printed manual. │
- │ │
- └────────────────────────────────────┘
-
- Figure 1.1 Logic of FOR...NEXT Loop with Positive STEP
-
- Figure 1.2 shows the logic of a FOR...NEXT loop when the value of
- stepsize is negative.
-
-
- ┌────────────────────────────────────┐
- │ │
- │ Figure 1.2 can be found on │
- │ page 21 of the printed manual. │
- │ │
- └────────────────────────────────────┘
-
- Figure 1.2 Logic of FOR...NEXT Loop with Negative STEP
-
- A FOR...NEXT statement always "tests at the top," so if one of the
- following conditions is true, the loop is never executed:
-
- ■ Step size is positive, and the initial value of start is greater than
- the value of end:
-
- ' Loop never executes, because I% starts out greater
- ' than 9:
- FOR I% = 10 TO 9
- .
- .
- .
- NEXT I%
-
- ■ Step size is negative, and the initial value of start is less than the
- value of end:
-
- ' Loop never executes, because I% starts out less than 9:
- FOR I% = -10 TO -9 STEP -1
- .
- .
- .
- NEXT I%
-
- You don't have to use the counter argument in the NEXT clause; however, if
- you have several nested FOR...NEXT loops (one loop inside another),
- listing the counter arguments can be a helpful way to keep track of what
- loop you are in.
-
- Here are some general guidelines for nesting FOR...NEXT loops:
-
- ■ If you use a loop counter variable in a NEXT clause, the counter for a
- nested loop must appear before the counter for any enclosing loop. In
- other words, the following is a legal nesting:
-
- FOR I = 1 TO 10
- FOR J = -5 TO 0
- .
- .
- .
- NEXT J
- NEXT I
-
- However, the following is not a legal nesting:
-
- FOR I = 1 TO 10
- FOR J = -5 TO 0
- .
- .
- .
- NEXT I
- NEXT J
-
- ■ If you use a separate NEXT clause to end each loop, then the number of
- NEXT clauses must always be the same as the number of FOR clauses.
-
- ■ If you use a single NEXT clause to terminate several levels of
- FOR...NEXT loops, then the loop-counter variables must appear after the
- NEXT clause in "inside-out" order:
-
- NEXT innermost-loopcounter,... , outermost-loopcounter
-
- In this case, the number of loop-counter variables in the NEXT clause
- must be the same as the number of FOR clauses.
-
- Examples
-
- The three program fragments below illustrate different ways of nesting
- FOR... NEXT loops to produce the identical output that follows. The first
- example shows nested FOR...NEXT loops with loop counters and separate NEXT
- clauses for each loop:
-
- FOR I = 1 TO 2
- FOR J = 4 TO 5
- FOR K = 7 TO 8
- PRINT I, J, K
- NEXT K
- NEXT J
- NEXT I
-
- The following example also uses loop counters but only one NEXT clause for
- all three loops:
-
- FOR I = 1 TO 2
- FOR J = 4 TO 5
- FOR K = 7 TO 8
- PRINT I, J, K
- NEXT K, J, I
-
- The final example shows nested FOR...NEXT loops without loop counters:
-
- FOR I = 1 TO 2
- FOR J = 4 TO 5
- FOR K = 7 TO 8
- PRINT I, J, K
- NEXT
- NEXT
- NEXT
-
- Output
-
- 1 4 7
- 1 4 8
- 1 5 7
- 1 5 8
- 2 4 7
- 2 4 8
- 2 5 7
- 2 5 8
-
- 1.4.1.1 Exiting a FOR...NEXT Loop with EXIT FOR
-
- Sometimes you may want to exit a FOR...NEXT loop before the counter
- variable reaches the ending value of the loop. You can do this with the
- EXIT FOR statement. A single FOR...NEXT loop can have any number of EXIT
- FOR statements, and the EXIT FOR statements can appear anywhere within the
- loop. The following fragment shows one use for an EXIT FOR statement:
-
- ' Print the square roots of the numbers from 1 to 30,000.
- ' If the user presses any key while this loop is executing,
- ' control exits from the loop:
- FOR I% = 1 TO 30000
- PRINT SQR(I%)
- IF INKEY$ <> "" THEN EXIT FOR
- NEXT
- .
- .
- .
-
- EXIT FOR exits only the smallest enclosing FOR...NEXT loop in which it
- appears. For example, if the user pressed a key while the following nested
- loops were executing, the program would simply exit the innermost loop. If
- the outermost loop were still active (that is if the value of I% <= 100),
- control would pass right back to the innermost loop:
-
- FOR I% = 1 TO 100
- FOR J% = 1 TO 100
- PRINT I% / J%
- IF INKEY$ <> "" THEN EXIT FOR
- NEXT J%
- NEXT I%
-
- 1.4.1.2 Pausing Program Execution with FOR...NEXT
-
- Many BASICA programs use an empty FOR...NEXT loop such as the following to
- insert a pause in a program:
-
- .
- .
- .
- ' There are no statements in the body of this loop;
- ' all it does is count from 1 to 10,000
- ' using integers (whole numbers).
- FOR I% = 1 TO 10000: NEXT
- .
- .
- .
-
- For very short pauses or pauses that do not have to be some exact
- interval, using FOR...NEXT is fine. The problem with using an empty
- FOR...NEXT loop in this way is that different computers, different
- versions of BASIC, or different compile-time options can all affect how
- quickly the arithmetic in a FOR... NEXT loop is performed. So the length
- of a pause can vary widely. QuickBASIC's SLEEP statement now provides a
- better alternative. (See Chapter 8, "Statement and Function Summary," for
- the syntax of SLEEP.)
-
- 1.4.2 WHILE...WEND Loops
-
- The FOR...NEXT statement is useful when you know ahead of time exactly how
- many times a loop should be executed. When you cannot predict the precise
- number of times a loop should be executed, but do know the condition that
- will end the loop, the WHILE...WEND statement is useful. Instead of
- counting to determine if it should keep executing a loop, WHILE...WEND
- repeats the loop as long as the loop condition is true.
-
- Table 1.5 shows the syntax of the WHILE...WEND statement and an example.
-
- Table 1.5 WHILE...WEND Syntax and Example
- Syntax Example
- ──────────────────────────────────────────────────────────────────────────
- WHILE condition INPUT R$
- [[statementblock]] WHILE R$ <> "Y" AND R$ <> "N"
- WEND PRINT "Answer must be Y or N."
- INPUT R$
- WEND
- ──────────────────────────────────────────────────────────────────────────
-
- Example
-
- The following example assigns an initial value of ten to the variable X,
- then successively halves that value and keeps halving it until the value
- of X is less than .00001:
-
- X = 10
-
- WHILE X > .00001
- PRINT X
- X = X/2
- WEND
-
- Figure 1.3 illustrates the logic of a WHILE...WEND loop.
-
-
- ┌────────────────────────────────────┐
- │ │
- │ Figure 1.3 can be found on │
- │ page 26 of the printed manual. │
- │ │
- └────────────────────────────────────┘
-
- Figure 1.3 Logic of WHILE...WEND Loop
-
- 1.4.3 DO...LOOP Loops
-
- Like the WHILE...WEND statement, the DO...LOOP statement executes a block
- of statements an indeterminate number of times; that is, exiting from the
- loop depends on the truth or falsehood of the loop condition. Unlike
- WHILE...WEND, DO...LOOP allows you to test for either a true or false
- condition. You can also put the test at either the beginning or the end of
- the loop.
-
- Table 1.6 shows the syntax of a loop that tests at the loop's beginning.
-
- Table 1.6 DO...LOOP Syntax and Example: Test at the Beginning
- Syntax Example
- ──────────────────────────────────────────────────────────────────────────
- DO[[{WHILE| UNTIL} condition]] DO UNTIL INKEY$ <> ""
- [[statementblock-1]] ' An empty loop that
- [[EXIT DO ' pauses until a key
- [[statementblock-2]]]] ' is pressed
- LOOP LOOP
- ──────────────────────────────────────────────────────────────────────────
-
- Figures 1.4 and 1.5 illustrate the two kinds of DO...LOOP statements
- that test at the beginning of the loop.
-
-
- ┌────────────────────────────────────┐
- │ │
- │ Figure 1.4 can be found on │
- │ page 27 of the printed manual. │
- │ │
- └────────────────────────────────────┘
-
- Figure 1.4 Logic of DO WHILE...LOOP
-
-
- ┌────────────────────────────────────┐
- │ │
- │ Figure 1.5 can be found on │
- │ page 28 of the printed manual. │
- │ │
- └────────────────────────────────────┘
-
- Figure 1.5 Logic of DO UNTIL...LOOP
-
- Table 1.7 shows the syntax of a loop that tests for true or false at the
- end of the loop.
-
- Table 1.7 DO...LOOP Syntax and Example: Test at the End
- Syntax Example
- ──────────────────────────────────────────────────────────────────────────
- DO DO
- [[statementblock-1]] INPUT "Change: ", Ch
- [[EXIT DO Total = Total + Ch
- [[statementblock-2]]]] LOOP WHILE Ch <> 0
- LOOP[[{WHILE| UNTIL} condition]]
- ──────────────────────────────────────────────────────────────────────────
-
- Figures 1.6 and 1.7 illustrate the two kinds of DO...LOOP statements
- that test at the end of the loop.
-
-
- ┌────────────────────────────────────┐
- │ │
- │ Figure 1.6 can be found on │
- │ page 29 of the printed manual. │
- │ │
- └────────────────────────────────────┘
-
- Figure 1.6 Logic of DO...LOOP WHILE
-
-
- ┌────────────────────────────────────┐
- │ │
- │ Figure 1.7 can be found on │
- │ page 30 of the printed manual. │
- │ │
- └────────────────────────────────────┘
-
- Figure 1.7 Logic of DO...LOOP UNTIL
-
- 1.4.3.1 Loop Tests: One Way to Exit DO...LOOP
-
- You can use a loop test at the end of a DO...LOOP statement to create a
- loop in which the statements always execute at least once. With the
- WHILE...WEND statement, you sometimes have to resort to the trick of
- presetting the loop variable to some value in order to force the first
- pass through the loop. With DO...LOOP, such tricks are no longer
- necessary. The examples below illustrate both approaches:
-
- ' WHILE...WEND loop tests at the top, so assigning "Y"
- ' to Response$ is necessary to force execution of the
- ' loop at least once:
- Response$ = "Y"
- WHILE UCASE$(Response$) = "Y"
- .
- .
- .
- INPUT "Do again"; Response$
- WEND
-
- ' The same loop using DO...LOOP to test after the
- ' body of the loop:
- DO
- .
- .
- .
- INPUT "Do again"; Response$
- LOOP WHILE UCASE$(Response$) = "Y"
-
- You can also rewrite a condition expressed with WHILE using UNTIL instead,
- as in the following:
-
- ' =======================================================
- ' Using DO WHILE NOT...LOOP
- ' =======================================================
-
- ' While the end of file 1 has not been reached, read
- ' a line from the file and print it on the screen:
- DO WHILE NOT EOF(1)
- LINE INPUT #1, LineBuffer$
- PRINT LineBuffer$
- LOOP
-
- ' =======================================================
- ' Using DO UNTIL...LOOP
- ' =======================================================
-
- ' Until the end of file 1 has been reached, read
- ' a line from the file and print it on the screen:
- DO UNTIL EOF(1)
- LINE INPUT #1, LineBuffer$
- PRINT LineBuffer$
- LOOP
-
- 1.4.3.2 EXIT DO: An Alternative Way to Exit DO...LOOP
-
- Inside a DO...LOOP statement, other statements are executed that
- eventually change the loop-test condition from true to false or false to
- true, ending the loop. In the DO...LOOP examples presented so far, the
- test has occurred either at the beginning or the end of the loop. However,
- by using the EXIT DO statement to exit from the loop, you can move the
- test elsewhere inside the loop. A single DO...LOOP can contain any number
- of EXIT DO statements, and the EXIT DO statements can appear anywhere
- within the loop.
-
- Example
-
- The following example opens a file and reads it, one line at a time, until
- the end of the file is reached or until it finds the pattern input by the
- user. If it finds the pattern before getting to the end of the file, an
- EXIT DO statement exits the loop.
-
- INPUT "File to search: ", File$
- IF File$ = "" THEN END
-
- INPUT "Pattern to search for: ", Pattern$
- OPEN File$ FOR INPUT AS #1
-
- DO UNTIL EOF(1) ' EOF(1) returns a true value if the
- ' end of the file has been reached.
- LINE INPUT #1, TempLine$
- IF INSTR(TempLine$, Pattern$) > 0 THEN
-
- ' Print the first line containing the pattern and
- ' exit the loop:
- PRINT TempLine$
- EXIT DO
- END IF
- LOOP
-
-
- 1.5 Sample Applications
-
- The sample applications for this chapter are a checkbook-balancing program
- and a program that ensures that every line in a text file ends with a
- carriage-return and line-feed sequence.
-
- 1.5.1 Checkbook-Balancing Program (CHECK.BAS)
-
- This program prompts the user for the starting checking-account balance
- and all transactions──withdrawals or deposits──that have occurred. It then
- prints a sorted list of the transactions and the final balance in the
- account.
-
- Statements and Functions Used
-
- The program demonstrates the following statements discussed in this
- chapter:
-
- ■ DO...LOOP WHILE
-
- ■ FOR...NEXT
-
- ■ EXIT FOR
-
- ■ Block IF...THEN...ELSE
-
- Program Listing
-
- DIM Amount(1 TO 100)
- CONST FALSE = 0, TRUE = NOT FALSE
-
- CLS
- ' Get account's starting balance:
- INPUT "Type starting balance, then press <ENTER>: ", Balance
-
- ' Get transactions. Continue accepting input
- ' until the input is zero for a transaction,
- ' or until 100 transactions have been entered:
- FOR TransacNum% = 1 TO 100
- PRINT TransacNum%;
- PRINT ") Enter transaction amount (0 to end): ";
- INPUT "", Amount(TransacNum%)
- IF Amount(TransacNum%) = 0 THEN
- TransacNum% = TransacNum% - 1
- EXIT FOR
- END IF
- NEXT
-
- ' Sort transactions in ascending order,
- ' using a "bubble sort":
- Limit% = TransacNum%
- DO
- Swaps% = FALSE
- FOR I% = 1 TO (Limit% - 1)
-
- ' If two adjacent elements are out of order,
- ' switch those elements:
- IF Amount(I%) < Amount(I% + 1) THEN
- SWAP Amount(I%), Amount(I% + 1)
- Swaps% = I%
- END IF
- NEXT I%
-
- ' Sort on next pass only to where last switch was made:
- Limit% = Swaps%
-
- ' Sort until no elements are exchanged:
- LOOP WHILE Swaps%
-
- ' Print the sorted transaction array. If a transaction
- ' is greater than zero, print it as a "CREDIT"; if a
- ' transaction is less than zero, print it as a "DEBIT":
- FOR I% = 1 TO TransacNum%
- IF Amount(I%) > 0 THEN
- PRINT USING "CREDIT: $$#####.##"; Amount(I%)
- ELSEIF Amount(I%) < 0 THEN
- PRINT USING "DEBIT: $$#####.##"; Amount(I%)
- END IF
-
- ' Update balance:
- Balance = Balance + Amount(I%)
- NEXT I%
-
- ' Print the final balance:
- PRINT
- PRINT "--------------------------"
- PRINT USING "Final Balance: $$######.##"; Balance
- END
-
- 1.5.2 Carriage-Return and Line-Feed Filter (CRLF.BAS)
-
- Some text files are saved in a format that uses only a carriage return
- (return to the beginning of the line) or a line feed (advance to the next
- line) to signify the end of a line. Many text editors expand this single
- carriage return (CR) or line feed (LF) to a carriage-return and line-feed
- (CR-LF) sequence whenever you load the file for editing. However, if you
- use a text editor that does not expand a single CR or LF to CR-LF, you may
- have to modify the file so it has the correct sequence at the end of each
- line.
-
- The following program is a filter that opens a file, expands a single CR
- or LF to a CR-LF combination, then writes the adjusted lines to a new
- file. The original contents of the file are saved in a file with a .BAK
- extension.
-
- Statements and Functions Used
-
- This program demonstrates the following statements discussed in this
- chapter:
-
- ■ DO...LOOP WHILE
-
- ■ DO UNTIL...LOOP
-
- ■ Block IF...THEN...ELSE
-
- ■ SELECT CASE...END SELECT
-
- To make this program more useful, it contains the following constructions
- not discussed in this chapter:
-
- ■ A FUNCTION procedure named Backup$ that creates the file with the .BAK
- extension.
-
- See Chapter 2, "SUB and FUNCTION Procedures," for more information on
- defining and using procedures.
-
- ■ An error-handling routine named ErrorHandler to deal with errors that
- could occur when the user enters a file name. For instance, if the user
- enters the name of a nonexistent file, this routine prompts for a new
- name. Without this routine, such an error would end the program.
-
- See Chapter 6, "Error and Event Trapping," for more information on
- trapping errors.
-
- Program Listing
-
- DEFINT A-Z ' Default variable type is integer.
-
- ' The Backup$ FUNCTION makes a backup file with
- ' the same base as FileName$ plus a .BAK extension:
- DECLARE FUNCTION Backup$ (FileName$)
-
- ' Initialize symbolic constants and variables:
- CONST FALSE = 0, TRUE = NOT FALSE
-
- CarReturn$ = CHR$(13)
- LineFeed$ = CHR$(10)
-
- DO
- CLS
-
- ' Input the name of the file to change:
- INPUT "Which file do you want to convert"; OutFile$
-
- InFile$ = Backup$(OutFile$) ' Get backup file's name.
-
- ON ERROR GOTO ErrorHandler ' Turn on error trapping.
-
- NAME OutFile$ AS InFile$ ' Rename input file as
- ' backup file.
-
- ON ERROR GOTO 0 ' Turn off error trapping.
-
- ' Open backup file for input and old file for output:
- OPEN InFile$ FOR INPUT AS #1
- OPEN OutFile$ FOR OUTPUT AS #2
-
- ' The PrevCarReturn variable is a flag set to TRUE
- ' whenever the program reads a carriage-return character:
- PrevCarReturn = FALSE
-
- ' Read from input file until reaching end of file:
- DO UNTIL EOF(1)
-
- ' This is not end of file, so read a character:
- FileChar$ = INPUT$(1, #1)
-
- SELECT CASE FileChar$
-
- CASE CarReturn$ ' The character is a CR.
-
- ' If the previous character was also a
- ' CR, put a LF before the character:
- IF PrevCarReturn THEN
- FileChar$ = LineFeed$ + FileChar$
- END IF
-
- ' In any case, set the PrevCarReturn
- ' variable to TRUE:
- PrevCarReturn = TRUE
-
- CASE LineFeed$ ' The character is a LF.
-
- ' If the previous character was not a
- ' CR, put a CR before the character:
- IF NOT PrevCarReturn THEN
- FileChar$ = CarReturn$ + FileChar$
- END IF
-
- ' Set the PrevCarReturn variable to FALSE:
- PrevCarReturn = FALSE
-
- CASE ELSE ' Neither a CR nor a LF.
-
- ' If the previous character was a CR,
- ' set the PrevCarReturn variable to FALSE
- ' and put a LF before the current character:
- IF PrevCarReturn THEN
- PrevCarReturn = FALSE
- FileChar$ = LineFeed$ + FileChar$
- END IF
-
- END SELECT
-
- ' Write the character(s) to the new file:
- PRINT #2, FileChar$;
- LOOP
-
- ' Write a LF if the last character in the file was a CR:
- IF PrevCarReturn THEN PRINT #2, LineFeed$;
-
- CLOSE ' Close both files.
- PRINT "Another file (Y/N)?" ' Prompt to continue.
-
- ' Change the input to uppercase (capital letter):
- More$ = UCASE$(INPUT$(1))
-
- ' Continue the program if the user entered a "y" or a "Y":
- LOOP WHILE More$ = "Y"
- END
-
- ErrorHandler: ' Error-handling routine
- CONST NOFILE = 53, FILEEXISTS = 58
-
- ' The ERR function returns the error code for last error:
- SELECT CASE ERR
- CASE NOFILE ' Program couldn't find file
- ' with input name.
-
- PRINT "No such file in current directory."
- INPUT "Enter new name: ", OutFile$
- InFile$ = Backup$(OutFile$)
- RESUME
- CASE FILEEXISTS ' There is already a file named
- ' <filename>.BAK in this directory:
- ' remove it, then continue.
- KILL InFile$
- RESUME
- CASE ELSE ' An unanticipated error occurred:
- ' stop the program.
- ON ERROR GOTO 0
- END SELECT
-
- ' ======================== BACKUP$ =========================
- ' This procedure returns a file name that consists of the
- ' base name of the input file (everything before the ".")
- ' plus the extension ".BAK"
- ' ==========================================================
-
- FUNCTION Backup$ (FileName$) STATIC
-
- ' Look for a period:
- Extension = INSTR(FileName$, ".")
-
- ' If there is a period, add .BAK to the base:
- IF Extension > 0 THEN
- Backup$ = LEFT$(FileName$, Extension - 1) + ".BAK"
-
- ' Otherwise, add .BAK to the whole name:
- ELSE
- Backup$ = FileName$ + ".BAK"
- END IF
- END FUNCTION
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- Chapter 2 SUB and FUNCTION Procedures
-
- This chapter explains how to simplify your programming by breaking
- programs into smaller logical components. These components──known as
- "procedures"──can then become building blocks that let you enhance and
- extend the BASIC language itself.
-
- When you are finished with this chapter, you will know how to perform the
- following tasks with procedures:
-
- ■ Define and call BASIC procedures
-
- ■ Use local and global variables in procedures
-
- ■ Use procedures instead of GOSUB subroutines and DEF FN functions
-
- ■ Pass arguments to procedures and return values from procedures
-
- ■ Write recursive procedures (procedures that can call themselves)
-
- Although you can create a BASIC program with any text editor, the
- QuickBASIC editor makes it especially easy to write programs that contain
- procedures. Also, in most cases QuickBASIC automatically generates a
- DECLARE statement when you save your program. (Using a DECLARE statement
- ensures that only the correct number and type of arguments are passed to a
- procedure and allows your program to call procedures defined in separate
- modules.)
-
-
- 2.1 Procedures: Building Blocks for Programming
-
- As used in this chapter, the term "procedure" covers both SUB...END SUB
- and FUNCTION...END FUNCTION constructions. Procedures are useful for
- condensing repeated tasks. For example, suppose you are writing a program
- that you eventually intend to compile as a stand-alone application and you
- want the user of this application to be able to pass several arguments to
- the application from the command line. It then makes sense to turn this
- task──breaking the string returned by the COMMAND$ function into two or
- more arguments──into a separate procedure. Once you have this procedure up
- and running, you can use it in other programs. In essence, you are
- extending BASIC to fit your individual needs when you use procedures.
-
- These are the two major benefits of programming with procedures:
-
- 1. Procedures allow you to break your programs into discrete logical
- units, each of which can be more easily debugged than can an entire
- program without procedures.
-
- 2. Procedures used in one program can be used as building blocks in other
- programs, usually with little or no modification.
-
- You can also put procedures in your own Quick library, which is a special
- file that you can load into memory when you start QuickBASIC. Once the
- contents of a Quick library are in memory with QuickBASIC, any program
- that you write has access to the procedures in the library. This makes it
- easier for all of your programs both to share and save code. (See Appendix
- H, "Creating and Using Quick Libraries," for more information on how to
- build Quick libraries.)
-
-
- 2.2 Comparing Procedures with Subroutines and Functions
-
- If you are familiar with earlier versions of BASIC, you might think of a
- SUB...END SUB procedure as being roughly similar to a GOSUB...RETURN
- subroutine. You will also notice some similarities between a FUNCTION...
- END FUNCTION procedure and a DEF FN...END DEF function. However,
- procedures have many advantages over these older constructions, as shown
- in Sections 2.2.1 and 2.2.2 below.
-
- ──────────────────────────────────────────────────────────────────────────
- NOTE
- To avoid confusion between a SUB procedure and the target of a GOSUB
- statement, SUBprocedures are referred to in this manual as
- "subprograms," while statement blocks accessed by
- GOSUB...RETURN statements are referred to as "subroutines."
- ──────────────────────────────────────────────────────────────────────────
-
- 2.2.1 Comparing SUB with GOSUB
-
- Although use of the GOSUB subroutine does help break programs into
- manageable units, SUB procedures have a number of advantages over
- subroutines, as discussed below.
-
- 2.2.1.1 Local and Global Variables
-
- In SUB procedures, all variables are local by default; that is, they exist
- only within the scope of the SUB procedure's definition. To illustrate,
- the variable named I in the Test subprogram below is local to Test, and
- has no connection with the variable named I in the module-level code:
-
- I = 1
- CALL Test
- PRINT I ' I still equals 1.
- END
-
- SUB Test STATIC
- I = 50
- END SUB
-
- A GOSUB has a major drawback as a building block in programs: it contains
- only "global variables." With global variables, if you have a variable
- named I inside your subroutine, and another variable named I outside the
- subroutine but in the same module, they are one and the same. Any changes
- to the value of I in the subroutine affect I everywhere it appears in the
- module. As a result, if you try to patch a subroutine from one module into
- another module, you may have to rename subroutine variables to avoid
- conflict with variable names in the new module.
-
- 2.2.1.2 Use in Multiple-Module Programs
-
- A SUB can be defined in one module and called from another. This
- significantly reduces the amount of code required for a program and
- increases the ease with which code can be shared among a number of
- programs.
-
- A GOSUB subroutine, however, must be defined and used in the same module.
-
- 2.2.1.3 Operating on Different Sets of Variables
-
- A SUB procedure can be called any number of times within a program, with a
- different set of variables being passed to it each time. This is done by
- calling the SUB with an argument list. (See Section 2.5, "Passing
- Arguments to Procedures," for more information on how to do this.) In the
- next example, the subprogram Compare is called twice, with different pairs
- of variables passed to it each time:
-
- X = 4: Y = 5
-
- CALL Compare (X, Y)
-
- Z = 7: W = 2
- CALL Compare (Z, W)
- END
-
- SUB Compare (A, B)
- IF A < B THEN SWAP A, B
- END SUB
-
- Calling a GOSUB subroutine more than once in the same program and having
- it operate on a different set of variables each time is difficult. The
- process involves copying values to and from global variables, as shown in
- the next example:
-
- X = 4: Y = 5
- A = X: B = Y
- GOSUB Compare
- X = A: Y = B
-
- Z = 7 : W = 2
- A = Z : B = W
- GOSUB Compare
- Z = A : W = B
- END
-
- Compare:
- IF A < B THEN SWAP A, B
- RETURN
-
- 2.2.2 Comparing FUNCTION with DEF FN
-
- While the multiline DEF FN function definition answers the need for
- functions more complex than can be squeezed on a single line, FUNCTION
- procedures give you this capability plus the additional advantages
- discussed below.
-
- 2.2.2.1 Local and Global Variables
-
- By default, all variables within a FUNCTION procedure are local to it,
- although you do have the option of using global variables. (See Section
- 2.6, "Sharing Variables with SHARED," for more information on procedures
- and global variables.)
-
- In a DEF FN function, variables used within the function's body are global
- to the current module by default (this is also true for GOSUB
- subroutines). However, you can make a variable in a DEF FN function local
- by putting it in a STATIC statement.
-
- 2.2.2.2 Changing Variables Passed to the Procedure
-
- Variables are passed to FUNCTION procedures by reference or by value. When
- you pass a variable by reference, you can change the variable by changing
- its corresponding parameter in the FUNCTION. For example, after the call
- to GetRemainder in the next program, the value of X is 2, since the value
- of Mis 2 at the end of the FUNCTION:
-
- X = 89
- Y = 40
- PRINT GetRemainder(X, Y)
- PRINT X, Y ' X is now 2.
- END
-
- FUNCTION GetRemainder (M, N)
- GetRemainder = M MOD N
- M = M \ N
- END FUNCTION
-
- Variables are passed to a DEF FN function only by value, so in the next
- example, FNRemainder changes M without affecting X :
-
- DEF FNRemainder (M, N)
- FNRemainder = M MOD N
- M = M \ N
- END DEF
-
- X = 89
- Y = 40
- PRINT FNRemainder(X, Y)
-
- PRINT X,Y ' X is still
- ' 89.
-
- See Sections 2.5.5 and 2.5.6 for more information on the distinction
- between passing by reference and by value.
-
- 2.2.2.3 Calling the Procedure within Its Definition
-
- A FUNCTION procedure can be "recursive"; in other words, it can call
- itself within its own definition. (See Section 2.9 for more information
- on how procedures can be recursive.) A DEF FN function cannot be
- recursive.
-
- 2.2.2.4 Use in Multiple-Module Programs
-
- You can define a FUNCTION procedure in one module and use it in another
- module. You need to put a DECLARE statement in the module in which the
- FUNCTION is used; otherwise, your program thinks the FUNCTION name refers
- to a variable. (See Section 2.5.4, "Checking Arguments with the DECLARE
- Statement," for more information on using DECLARE this way.)
-
- A DEF FN function can only be used in the module in which it is defined.
- Unlike SUB or FUNCTION procedures, which can be called before they appear
- in the program, a DEF FN function must always be defined before it is used
- in a module.
-
- ──────────────────────────────────────────────────────────────────────────
- NOTE
- The name of a FUNCTION procedure can be any valid BASIC variable name,
- except one beginning with the letters FN. The name of a DEF FN function
- must always be preceded by FN.
- ──────────────────────────────────────────────────────────────────────────
-
-
- 2.3 Defining Procedures
-
- BASIC procedure definitions have the following general syntax:
-
- {SUB| FUNCTION} procedurename[[(parameterlist)]] [[STATIC]]
- [[statementblock-1]]
- [[EXIT{SUB| FUNCTION}
- [[statementblock-2]]]]
- END{SUB| FUNCTION}
-
- The following list describes the parts of a procedure definition:
-
- ╓┌─┌────────────────────────┌────────────────────────────────────────────────╖
- Part Description
- ──────────────────────────────────────────────────────────────────────────
- {SUB | FUNCTION} Marks the beginning of a SUB or FUNCTION
- procedure, respectively.
-
- procedurename Any valid variable name up to 40 characters long.
- The same name cannot be used for both a SUB and a
- FUNCTION.
- Part Description
- ──────────────────────────────────────────────────────────────────────────
- FUNCTION.
-
- parameterlist A list of variables, separated by commas, that
- shows the number and type of arguments to be
- passed to the procedure. (Section 2.5.1 explains
- the difference between parameters and arguments.)
-
- STATIC If you use the STATIC attribute, local variables
- are STATIC; that is, they retain their values
- between calls to the procedure.
- If you omit the STATIC attribute, local variables
- are "automatic" by default; that is, they are
- initialized to zeros or null strings at the start
- of each procedure call.
- See Section 2.7, "Automatic and STATIC
- Variables," for more information.
-
- END{SUB| FUNCTION} Ends a SUB or FUNCTION definition. To run
- correctly, every procedure must have exactly one
- Part Description
- ──────────────────────────────────────────────────────────────────────────
- correctly, every procedure must have exactly one
- END{SUB| FUNCTION} statement.
- When your program encounters an END SUB or END
- FUNCTION, it exits the procedure and returns to
- the statement immediately following the one that
- called the procedure. You can also use one or
- more optional EXIT{SUB| FUNCTION} statements
- within the body of a procedure definition to exit
- from the procedure.
- ──────────────────────────────────────────────────────────────────────────
-
-
- All valid BASIC expressions and statements are allowed within a procedure
- definition except the following:
-
- ■ DEF FN...END DEF, FUNCTION...END FUNCTION, or SUB...END SUB
-
- It is not possible to nest procedure definitions or to define a DEF FN
- function inside a procedure. However, a procedure can call another
- procedure or a DEF FN function.
-
- ■ COMMON
-
- ■ DECLARE
-
- ■ DIM SHARED
-
- ■ OPTION BASE
-
- ■ TYPE...END TYPE
-
- Example
-
- The following example is a FUNCTION procedure named IntegerPower :
-
- FUNCTION IntegerPower& (X&, Y&) STATIC
- PowerVal& = 1
- FOR I& = 1 TO Y&
- PowerVal& = PowerVal& * X&
- NEXT I&
- IntegerPower& = PowerVal&
- END FUNCTION
-
-
- 2.4 Calling Procedures
-
- Calling a FUNCTION procedure is different from calling a SUB procedure, as
- shown in the next two sections.
-
- 2.4.1 Calling a FUNCTION Procedure
-
- You call a FUNCTION procedure the same way you use an intrinsic BASIC
- function such as ABS, that is, by using its name in an expression, as
- shown here:
-
- ' Any of the following statements
- ' would call a FUNCTION named "ToDec" :
- PRINT 10 * ToDec
- X = ToDec
- IF ToDec = 10 THEN PRINT "Out of range."
-
- A FUNCTION can return values by changing variables passed to it as
- arguments. (See Section 2.5.5, "Passing Arguments by Reference," for an
- explanation of how this is done.) Additionally, a FUNCTION returns a
- single value in its name, so the name of a FUNCTION must agree with the
- type it returns. For example, if a FUNCTION returns a string value, either
- its name must have the dollar sign ($) type-declaration character appended
- to it or it must be declared as having the string type in a preceding
- DEFSTR statement.
-
- Example
-
- The following program shows a FUNCTION that returns a string value. Note
- that the type-declaration suffix for strings ($) is part of the procedure
- name.
-
- Banner$ = GetInput$ ' Call the FUNCTION and assign the
- ' return value to a string variable.
- PRINT Banner$ ' Print the string.
- END
-
- ' ======================= GETINPUT$ ========================
- ' The $ type-declaration character at the end of this
- ' FUNCTION name means that it returns a string value.
- ' ==========================================================
-
- FUNCTION GetInput$ STATIC
-
- ' Return a string of 10 characters read from the
- ' keyboard, echoing each character as it is typed:
- FOR I% = 1 TO 10
- Char$ = INPUT$(1) ' Get the character.
- PRINT Char$; ' Echo the character on the
- ' screen.
- Temp$ = Temp$ + Char$ ' Add the character to the
- ' string.
- NEXT
- PRINT
- GetInput$ = Temp$ ' Assign the string to the FUNCTION.
- END FUNCTION
-
- ──────────────────────────────────────────────────────────────────────────
- NOTE
- The program example above is written for use in the QB environment only.
- It cannot be compiled using the BC command from DOS.
- ──────────────────────────────────────────────────────────────────────────
-
- 2.4.2 Calling a SUB Procedure
-
- A SUB procedure differs from a FUNCTION procedure in that a SUB cannot be
- called by using its name within an expression. A call to a SUB is a
- stand-alone statement, like BASIC's CIRCLE statement. Also, a SUB does not
- return a value in its name as does a FUNCTION. However, like a FUNCTION, a
- SUB can modify the values of any variables passed to it. (Section 2.5.5,
- "Passing Arguments by Reference," explains how this is done.)
-
- There are two ways to call a SUB procedure:
-
- 1. Put its name in a CALL statement:
-
- CALL PrintMessage
-
- 2. Use its name as a statement by itself:
-
- PrintMessage
-
- If you omit the CALL keyword, don't put parentheses around arguments
- passed to the SUB:
-
- ' Call the ProcessInput subprogram with CALL and pass the
- ' three arguments First$, Second$, and NumArgs% to it:
- CALL ProcessInput (First$, Second$, NumArgs%)
-
-
-
- ' Call the ProcessInput subprogram without CALL and pass
- ' it the same arguments (note no parentheses around the
- ' argument list):
- ProcessInput First$, Second$, NumArgs%
-
-
- See Section 2.5 for more information on passing arguments to procedures.
-
- If your program calls SUB procedures without using CALL, and if you are
- not using QuickBASIC to write the program, you must put the name of the
- SUB in a DECLARE statement before it is called:
-
- DECLARE SUB CheckForKey
- .
- .
- .
- CheckForKey
-
- You need to be concerned about this only if you are developing programs
- outside QuickBASIC, since QuickBASIC automatically inserts DECLARE
- statements wherever they are needed when it saves a program.
-
-
- 2.5 Passing Arguments to Procedures
-
- Sections 2.5.1-2.5.4 explain how to tell the difference between
- parameters and arguments, how to pass arguments to procedures, and how to
- check arguments to make sure they are of the correct type and quantity.
-
- 2.5.1 Parameters and Arguments
-
- The first step in learning about passing arguments to procedures is
- understanding the difference between the terms "parameter" and "argument":
-
- Parameter Argument
- ──────────────────────────────────────────────────────────────────────────
- A variable name that A constant, variable, or expression passed to a
- appears in a SUB, SUB or FUNCTION when the SUB or FUNCTION is
- FUNCTION, or DECLARE called
- statement
- ──────────────────────────────────────────────────────────────────────────
-
- In a procedure definition, parameters are placeholders for arguments. As
- shown in Figure 2.1, when a procedure is called, arguments are plugged
- into the variables in the parameter list, with the first parameter
- receiving the first argument, the second parameter receiving the second
- argument, and so on.
-
-
- ┌───────────────────────────────────────────────────────────────────┐
- │ │
- │ Arguments │
- │ ┌────────┴─────────┐ │
- │ Procedure call───────── CALL TestSub (A%, B!, "text") │
- │ ∙ │ │ │ │
- │ ∙ │ │ │ │
- │ ∙ │
- │ Procedure definition ── SUB TestSub (P1%, P2!, P3$) STATIC │
- │ └────────┬─────────┘ │
- │ Parameters │
- │ │
- └───────────────────────────────────────────────────────────────────┘
-
- Figure 2.1 Parameters and Arguments
-
- Figure 2.1 also demonstrates another important rule: although the names
- of variables in an argument list and a parameter list do not have to be
- the same, the number of parameters and the number of arguments do.
- Furthermore, the type (string, integer numeric, single-precision numeric,
- and so on) should be the same for corresponding arguments and parameters.
- (See Section 2.5.4, "Checking Arguments with the DECLARE Statement," for
- more information on how to ensure that arguments and parameters agree in
- number and type.)
-
- A parameter list consists of any of the following, all separated by
- commas:
-
- ■ Valid variable names, except for fixed-length strings
-
- For example, x$ and x AS STRING are both legal in a parameter list,
- since they refer to variable-length strings. However, x AS STRING * 10
- refers to a fixed-length string 10 characters long and cannot appear in
- a parameter list. (Fixed-length strings are perfectly all right as
- arguments passed to procedures. See Chapter 4, "String Processing," for
- more information on fixed-length and variable-length strings.)
-
- ■ Array names followed by left and right parentheses
-
- An argument list consists of any of the following, all separated by
- commas:
-
- ■ Constants
-
- ■ Expressions
-
- ■ Valid variable names
-
- ■ Array names followed by left and right parentheses
-
- Examples
-
- The following example shows the first line of a subprogram definition with
- a parameter list:
-
- SUB TestSub (A%, Array(), RecVar AS RecType, Cs$)
-
- The first parameter, A%, is an integer; the second parameter, Array(), is
- a single-precision array, since untyped numeric variables are single
- precision by default; the third parameter, RecVar, is a record of type
- RecType; and the fourth parameter, Cs$, is a string.
-
- The CALL TestSub line in the next example calls the TestSub subprogram and
- passes it four arguments of the appropriate type:
-
- TYPE RecType
- Rank AS STRING * 12
- SerialNum AS LONG
- END TYPE
-
- DIM RecVar AS RecType
-
- CALL TestSub (X%, A(), RecVar, "Daphne")
-
- 2.5.2 Passing Constants and Expressions
-
- Constants──whether string or numeric──can appear in the list of arguments
- passed to a procedure. Naturally, a string constant must be passed to a
- string parameter and a numeric constant to a numeric parameter, as shown
- in the next example:
-
- CONST SCREENWIDTH = 80
- CALL PrintBanner (SCREENWIDTH, "Monthly Status Report")
- .
- .
- .
- SUB PrintBanner (SW%, Title$)
- .
- .
- .
- END SUB
-
- If a numeric constant in an argument list does not have the same type as
- the corresponding parameter in the SUB or FUNCTION statement, then the
- constant is coerced to the type of the parameter, as you can see by the
- output from the next example:
-
- CALL test(4.6, 4.1)
- END
-
- SUB test (x%, y%)
- PRINT x%, y%
- END SUB
-
- Output
-
- 5 4
-
- Expressions resulting from operations on variables and constants can also
- be passed to a procedure. As is the case with constants, numeric
- expressions that disagree in type with their parameters are coerced into
- agreement, as shown here:
-
- Checker A! + 25!, NOT BooleanVal%
-
- ' In the next call, putting parentheses around the
- ' long-integer variable Bval& makes it an expression.
- ' The (Bval&) expression is coerced to a short integer
- ' in the Checker SUB:
- Checker A! / 3.1, (Bval&)
- .
- .
- .
- END
-
- SUB Checker (Param1!, Param2%)
- .
- .
- .
- END SUB
-
- 2.5.3 Passing Variables
-
- This section discusses how to pass simple variables, complete arrays,
- elements of arrays, records, and elements of records to procedures.
-
- 2.5.3.1 Passing Simple Variables
-
- In both argument and parameter lists, you can declare the type for a
- simple variable in one of the following three ways:
-
- 1. Append one of the following type-declaration suffixes to the variable
- name: %, &, !, #, or $.
-
- 2. Declare the variable in a declare variablename AS type clause, where
- the placeholder declare can be either DIM, COMMON, REDIM, SHARED, or
- STATIC, and type can be either INTEGER, LONG, SINGLE, DOUBLE, STRING,
- or STRING * n. For example:
-
- DIM A AS LONG
-
- 3. Use a DEFtype statement to set the default type.
-
- No matter which method you choose, corresponding variables must have the
- same type in both the argument and parameter lists, as shown in the
- following example.
-
- Example
-
- In this example, two arguments are passed to the FUNCTION procedure. The
- first is an integer giving the length of the string returned by the
- FUNCTION, while the second is a character that is repeated to make the
- string.
-
- FUNCTION CharString$(A AS INTEGER, B$) STATIC
- CharString$ = STRING$(A%, B$)
- END FUNCTION
-
- DIM X AS INTEGER
- INPUT "Enter a number (1 to 80): ", X
- INPUT "Enter a character: ", Y$
-
- ' Print a string consisting of the Y$ character, repeated
- ' X number of times:
- PRINT CharString$(X, Y$)
- END
-
- Output
-
- Enter a number (1 to 80): 21
- Enter a character: #
- #####################
-
- 2.5.3.2 Passing an Entire Array
-
- To pass all the elements of an array to a procedure, put the array's name,
- followed by left and right parentheses, in both the argument and parameter
- lists.
-
- Example
-
- This example shows how to pass all the elements of an array to a
- procedure:
-
- DIM Values(1 TO 5) AS INTEGER
-
- ' Note empty parentheses after array name when calling
- ' procedure and passing array:
- CALL ChangeArray (1, 5, Values())
- CALL PrintArray (1, 5, Values())
- END
-
- ' Note empty parentheses after P parameter:
-
- SUB ChangeArray (Min%, Max%, P() AS INTEGER) STATIC
- FOR I% = Min% TO Max%
- P(I%) = I% ^ 3
- NEXT I%
- END SUB
-
- SUB PrintArray (Min%, Max%, P() AS INTEGER) STATIC
- FOR I% = Min% TO Max%
- PRINT P(I%)
- NEXT I%
- PRINT
- END SUB
-
- 2.5.3.3 Passing Individual Array Elements
-
- If a procedure does not require an entire array, you can pass individual
- elements of the array instead. To pass an element of an array, use the
- array name followed by the appropriate subscripts inside parentheses.
-
- Example
-
- The SqrVal Array(4,2) statement in the following example passes the
- element in row 4, column 2 of the array to the SqrVal subprogram (note how
- the subprogram actually changes the value of this array element):
-
- DIM Array(1 TO 5,1 TO 3)
-
- Array(4,2) = -36
- PRINT Array(4,2)
- SqrVal Array(4,2)
- PRINT Array(4,2) ' The call to SqrVal has changed
- ' the value of Array(4,2).
- END
- SUB SqrVal(A) STATIC
- A = SQR(ABS(A))
- END SUB
-
- Output
-
- -36
- 6
-
- 2.5.3.4 Using Array-Bound Functions
-
- The LBOUND and UBOUND functions are a useful way to determine the size of
- an array passed to a procedure. The LBOUND function finds the smallest
- index value of an array subscript, while the UBOUND function finds the
- largest one. These functions save you the trouble of having to pass the
- upper and lower bounds of each array dimension to a procedure.
-
- Example
-
- The subprogram in the following example uses the LBOUND function to
- initialize the variables Row and Col to the lowest subscript values in
- each dimension of A. It also uses the UBOUND function to limit the number
- of times the FOR loop executes to the number of elements in the array.
-
- SUB PrintOut(A(2)) STATIC
- FOR Row = LBOUND(A,1) TO UBOUND(A,1)
- FOR Col = LBOUND(A,2) TO UBOUND(A,2)
- PRINT A(Row,Col)
- NEXT Col
- NEXT Row
- END SUB
-
- 2.5.3.5 Passing an Entire Record
-
- To pass a complete record (a variable declared as having a user-defined
- type) to a procedure, complete the following steps:
-
- 1. Define the type (StockItem in this example):
-
- TYPE StockItem
- PartNumber AS STRING * 6
- Description AS STRING * 20
- UnitPrice AS SINGLE
- Quantity AS INTEGER
- END TYPE
-
- 2. Declare a variable (StockRecord) with that type:
-
- DIM StockRecord AS StockItem
-
- 3. Call a procedure (FindRecord) and pass it the variable you have
- declared:
-
- CALL FindRecord(StockRecord)
-
- 4. In the procedure definition, give the parameter the same type as the
- variable:
-
- SUB FindRecord (RecordVar AS StockItem) STATIC
- .
- .
- .
- END SUB
-
- 2.5.3.6 Passing Individual Elements of a Record
-
- To pass an individual element in a record to a procedure, put the name of
- the element (recordname.elementname) in the argument list. Be sure, as
- always, that the corresponding parameter in the procedure definition
- agrees with the type of that element.
-
- Example
-
- The following example shows how to pass the two elements in the record
- variable StockItem to the PrintTag SUB procedure. Note how each parameter
- in the SUB procedure agrees with the type of the individual record
- elements.
-
- TYPE StockType
- PartNumber AS STRING * 6
- Descrip AS STRING * 20
- UnitPrice AS SINGLE
- Quantity AS INTEGER
- END TYPE
-
- DIM StockItem AS StockType
-
- CALL PrintTag (StockItem.Descrip, StockItem.UnitPrice)
- .
- .
- .
- END
-
- SUB PrintTag (Desc$, Price AS SINGLE)
- .
- .
- .
- END SUB
-
- 2.5.4 Checking Arguments with the DECLARE Statement
-
- If you are using QuickBASIC to write your program, you will notice that
- QuickBASIC automatically inserts a DECLARE statement for each procedure
- whenever you save the program. Each DECLARE statement consists of the word
- DECLARE, followed by the words SUB or FUNCTION, the name of the procedure,
- and a set of parentheses. If the procedure has no parameters, then the
- parentheses are empty. If the procedure has parameters, then the
- parentheses enclose a parameterlist that specifies the number and type of
- the arguments to be passed to the procedure. This parameterlist has the
- same format as the list in the definition line of the SUB or FUNCTION.
-
- The purpose of the parameterlist in a DECLARE statement is to turn on
- "type checking" of arguments passed to the procedure. That is, every time
- the procedure is called with variable arguments, those variables are
- checked to be sure they agree with the number and type of the parameters
- in the DECLARE statement.
-
- QuickBASIC puts all procedure definitions at the end of a module when it
- saves a program. Therefore, if there were no DECLARE statements, when you
- tried to compile this program with the BC command you would run into a
- problem known as "forward reference" (calling a procedure before it is
- defined). By generating a prototype of the procedure definition, DECLARE
- statements allow your program to call procedures that are defined later in
- a module, or in another module altogether.
-
- Examples
-
- The next example shows an empty parameter list in the DECLARE statement,
- since no arguments are passed to GetInput$:
-
- DECLARE FUNCTION GetInput$ ()
- X$ = GetInput$
-
- FUNCTION GetInput$ STATIC
- GetInput$ = INPUT$(10)
- END FUNCTION
-
- The next example shows a parameter list in the DECLARE statement, since an
- integer argument is passed to this version of GetInput$ :
-
- DECLARE FUNCTION GetInput$ (X%)
- X$ = GetInput$ (5)
-
- FUNCTION GetInput$ (X%) STATIC
- GetInput$ = INPUT$(X%)
- END FUNCTION
-
- 2.5.4.1 When QuickBASIC Does Not Generate a DECLARE Statement
-
- In certain instances, QuickBASIC does not generate DECLARE statements in
- the module that calls a procedure.
-
- QuickBASIC cannot generate a DECLARE statement in one module for a
- FUNCTION procedure defined in another module if the module is not loaded.
- In such a case, you must type the DECLARE statement yourself at the
- beginning of the module where the FUNCTION is called; otherwise,
- QuickBASIC considers the call to the FUNCTION to be a variable name.
-
- QuickBASIC does not generate a DECLARE statement for a SUB procedure in
- another module, whether that module is loaded or not. The DECLARE
- statement is not needed unless you want to call the SUB procedure without
- using the keyword CALL, however.
-
- QuickBASIC also cannot generate a DECLARE statement for any procedure in a
- Quick library. You must add one to the program yourself.
-
- 2.5.4.2 Developing Programs outside the QuickBASIC Environment
-
- If you are writing your programs with your own text editor and then
- compiling them outside the QuickBASIC environment with the BC and LINK
- commands, be sure to put DECLARE statements in the following three
- locations:
-
- 1. At the beginning of any module that calls a FUNCTION procedure before
- it is defined:
-
- DECLARE FUNCTION Hypot (X!, Y!)
-
- INPUT X, Y
- PRINT Hypot(X, Y)
- END
-
- FUNCTION Hypot (A, B) STATIC
- Hypot = SQR(A ^ 2 + B ^ 2)
- END FUNCTION
-
- 2. At the beginning of any module that calls a SUB procedure before it is
- defined and does not use CALL when calling the SUB:
-
- DECLARE SUB PrintString (X, Y)
- INPUT X, Y
-
- PrintString X, Y ' Note: no parentheses around
- ' arguments
- END
-
- SUB PrintString (A,B) STATIC
-
- ' Convert the numbers to strings, remove any leading
- ' blanks from the second number, and print:
- PRINT STR$(A) + LTRIM$(STR$(B))
- END SUB
-
- When you call a SUB procedure with CALL, you don't have to declare the
- SUB first:
-
- A$ = "466"
- B$ = "123"
- CALL PrintString(A$, B$)
- END
-
- SUB PrintString (X$, Y$) STATIC
- PRINT VAL(X$) + VAL(Y$)
- END SUB
-
- 3. At the beginning of any module that calls a SUB or FUNCTION procedure
- defined in another module (an "external procedure")
-
- If your procedure has no parameters, remember to put empty parentheses
- after the name of the procedure in the DECLARE statement, as in the next
- example:
-
- DECLARE FUNCTION GetHour$ ()
- PRINT GetHour$
- END
-
- FUNCTION GetHour$ STATIC
- GetHour$ = LEFT$(TIME$,2)
- END FUNCTION
-
- Remember, a DECLARE statement can appear only at the module level, not the
- procedure level. A DECLARE statement affects the entire module in which it
- appears.
-
- 2.5.4.3 Using Include Files for Declarations
-
- If you have created a separate procedure-definition module that defines
- one or more SUB or FUNCTION procedures, it is a good idea to make an
- include file to go along with this module. This include file should
- contain the following:
-
- ■ DECLARE statements for all the module's procedures.
-
- ■ TYPE...END TYPE record definitions for any record parameters in this
- module's SUB or FUNCTION procedures.
-
- ■ COMMON statements listing variables shared between this module and other
- modules in the program. (See Section 2.6.3, "Sharing Variables with
- Other Modules," for more information on using COMMON for this purpose.)
-
- Every time you use the definition module in one of your programs, insert a
- $INCLUDE metacommand at the beginning of any module that invokes
- procedures in the definition module. When your program is compiled, the
- actual contents of the include file are substituted for the $INCLUDE
- metacommand.
-
- A simple rule of thumb is to make an include file for every module and
- then use the module and the include file together as outlined above. The
- following list itemizes some of the benefits of this technique:
-
- ■ A module containing procedure definitions remains truly modular──that
- is, you don't have to copy all the DECLARE statements for its procedures
- every time you call them from another module; instead, you can just
- substitute one $INCLUDE metacommand.
-
- ■ In QuickBASIC, using an include file for procedure declarations
- suppresses automatic generation of DECLARE statements when you save a
- program.
-
- ■ Using an include file for declarations avoids problems with getting one
- module to recognize a FUNCTION in another module. (See Section 2.5.4.1,
- "When QuickBASIC Does Not Generate a DECLARE Statement," for more
- information.)
-
- You can take advantage of QuickBASIC's facility for generating DECLARE
- statements when creating your include file. The following steps show you
- how to do this:
-
- 1. Create your module.
-
- 2. Within that module, call any SUB or FUNCTION procedures you have
- defined.
-
- 3. Save the module to get automatic DECLARE statements for all the
- procedures.
-
- 4. Reedit the module, removing the procedure calls and moving the DECLARE
- statements to a separate include file.
-
- See Appendix F, "Metacommands," for more information on the syntax and
- usage of the $INCLUDE metacommand.
-
- Example
-
- The following fragments illustrate how to use a definition module and an
- include file together:
-
- ' =========================================================
- ' MODDEF.BAS
- ' This module contains definitions for the PROMPTER and
- ' MAX! procedures.
- ' =========================================================
-
- FUNCTION Max! (X!, Y!) STATIC
- IF X! > Y! THEN Max! = X! ELSE Max! = Y!
- END FUNCTION
-
- SUB Prompter (Row%, Column%, RecVar AS RecType) STATIC
- LOCATE Row%, Column%
- INPUT "Description: ", RecVar.Description
- INPUT "Quantity: ", RecVar.Quantity
- END SUB
-
- ' =========================================================
- ' MODDEF.BI
- ' This is an include file that contains DECLARE statements
- ' for the PROMPTER and MAX! procedures (as well as a TYPE
- ' statement defining the RecType user type). Use this file
- ' whenever you use the MODDEF.BAS module.
- ' =========================================================
-
- TYPE RecType
- Description AS STRING * 15
- Quantity AS INTEGER
- END TYPE
-
- DECLARE FUNCTION Max! (X!, Y!)
- DECLARE SUB Prompter (Row%, Column%, RecVar AS RecType)
-
- ' ============================================================
- ' SAMPLE.BAS
- ' This module is linked with the MODDEF.BAS module, and
- ' calls the PROMPTER and MAX! procedures in MODDEF.BAS.
- ' ============================================================
-
- ' The next line makes the contents of the MODDEF.BI include
- ' file part of this module as well:
- ' $INCLUDE: 'MODDEF.BI'
- .
- .
- .
- INPUT A, B
- PRINT Max!(A, B) ' Call the Max! FUNCTION in MODDEF.BAS
- .
- .
- .
- Prompter 5, 5, RecVar ' Call the Prompter SUB in MODDEF.BAS
- .
- .
- .
-
- ──────────────────────────────────────────────────────────────────────────
- IMPORTANT
- While it is good programming practice to put procedure declarations in
- an include file, do not put the procedures themselves (SUB...END SUB or
- FUNCTION...END FUNCTION blocks) in an include file. Procedure
- definitions are not allowed inside include files in QuickBASIC Version
- 4.5. If you have used include files to define SUB procedures in programs
- written with QuickBASIC Versions 2.0 or 3.0, either put these
- definitions in a separate module or incorporate them into the module
- where they are called.
- ──────────────────────────────────────────────────────────────────────────
-
- 2.5.4.4 Declaring Procedures in Quick Libraries
-
- A convenient programming practice is to put all the declarations for
- procedures in a Quick library into one include file. With the $INCLUDE
- metacommand you can then incorporate this include file into programs using
- the library. This saves you the trouble of copying all the relevant
- DECLARE statements every time you use the library.
-
- 2.5.5 Passing Arguments by Reference
-
- By default, variables──whether simple scalar variables, arrays and array
- elements, or records──are passed "by reference" to FUNCTION and SUB
- procedures. Here is what is meant by passing variables by reference:
-
- ■ Each program variable has an address, or a location in memory where its
- value is stored.
-
- ■ Calling a procedure and passing variables to it by reference calls the
- procedure and passes it the address of each variable. Thus, the address
- of the variable and the address of its corresponding parameter in the
- procedure are one and the same.
-
- ■ Therefore, if the procedure modifies the value of the parameter, it also
- modifies the value of the variable that is passed.
-
- If you do not want a procedure to change the value of a variable, pass the
- procedure the value contained in the variable, not the address. This way,
- changes are made only to a copy of the variable, not the variable itself.
- See the next section for a discussion of this alternative way of passing
- variables.
-
- Example
-
- In the following program, changes made to the parameter A$ in the Replace
- procedure also change the argument Test$:
-
- Test$ = "a string with all lowercase letters."
- PRINT "Before subprogram call: "; Test$
- CALL Replace (Test$, "a")
- PRINT "After subprogram call: "; Test$
- END
-
- SUB Replace (A$, B$) STATIC
- Start = 1
- DO
-
- ' Look for B$ in A$, starting at the character
- ' with position "Start" in A$:
- Found = INSTR(Start, A$, B$)
- ' Make every occurrence of B$ in A$
- ' an uppercase letter:
- IF Found > 0 THEN
- MID$(A$,Found) = UCASE$(B$)
- Start = Start + 1
- END IF
- LOOP WHILE Found > 0
- END SUB
-
- Output
-
- Before subprogram call: a string with all lowercase letters.
- After subprogram call: A string with All lowercAse letters.
-
- 2.5.6 Passing Arguments by Value
-
- Passing an argument "by value" means the value of the argument is passed,
- rather than its address. In BASIC procedures, passing a variable by value
- is simulated by copying the variable into a temporary location, then
- passing the address of this temporary location. Since the procedure does
- not have access to the address of the original variable, it cannot change
- the original variable; it makes all changes to the copy instead.
-
- You can pass expressions as arguments to procedures, as in the following:
-
- ' A + B is an expression; the values of A and B
- ' are not affected by this procedure call:
- CALL Mult(A + B, B)
-
- Expressions are always passed by value (see Section 2.5.2, "Passing
- Constants and Expressions," for more information).
-
- Example
-
- One way to pass a variable by value is to enclose it in parentheses, thus
- making it an expression. As you can see from the output that follows,
- changes to the SUB procedure's local variable Y are passed back to the
- module-level code as changes to the variable B. However, changes to X in
- the procedure do not affect the value of A, since A is passed by value.
-
- A = 1
- B = 1
- PRINT "Before subprogram call, A ="; A; ", B ="; B
-
- ' A is passed by value, and B is passed by reference:
- CALL Mult((A), B)
- PRINT "After subprogram call, A ="; A; ", B ="; B
- END
-
- SUB Mult (X, Y) STATIC
- X = 2 * X
- Y = 3 * Y
- PRINT "In subprogram, X ="; X; ", Y ="; Y
- END SUB
-
- Output
-
- Before subprogram call, A = 1 , B = 1
- In subprogram, X = 2 , Y = 3
- After subprogram call, A = 1 , B = 3
-
-
- 2.6 Sharing Variables with SHARED
-
- In addition to passing variables through argument and parameter lists,
- procedures can also share variables with other procedures and with code at
- the module level (that is, code within a module but outside of any
- procedure) in one of the two ways listed below:
-
- 1. Variables listed in a SHARED statement within a procedure are shared
- only between that procedure and the module-level code. Use this method
- when different procedures in the same module need different
- combinations of module-level variables.
-
- 2. Variables listed in a module-level COMMON SHARED, DIM SHARED, or REDIM
- SHARED statement are shared between the module-level code and all
- procedures within that module. This method is most useful when all
- procedures in a module use a common set of variables.
-
- You can also use the COMMON or COMMON SHARED statement to share variables
- among two or more modules. Sections 2.6.1-2.6.3 discuss these three ways
- to share variables.
-
- 2.6.1 Sharing Variables with Specific Procedures in a Module
-
- If different procedures within a module need to share different variables
- with the module-level code, use the SHARED statement within each
- procedure.
-
- Arrays in SHARED statements consist of the array name followed by a set of
- empty parentheses ( ):
-
- SUB JustAnotherSub STATIC
- SHARED ArrayName ()
- .
- .
- .
-
- If you give a variable its type in an AS type clause, then the variable
- must also be typed with the AS type clause in a SHARED statement:
-
- DIM Buffer AS STRING * 10
- .
- .
- .
- END
-
- SUB ReadRecords STATIC
- SHARED Buffer AS STRING * 10
- .
- .
- .
- END SUB
-
- Example
-
- In the next example, the SHARED statements in the GetRecords and
- InventoryTotal procedures show the format of a shared variable list:
-
- ' =========================================================
- ' MODULE-LEVEL CODE
- ' =========================================================
- TYPE RecType
- Price AS SINGLE
- Desc AS STRING * 35
- END TYPE
-
- DIM RecVar(1 TO 100) AS RecType ' Array of records
-
- INPUT "File name: ", FileSpec$
- CALL GetRecords
- PRINT InventoryTotal
- END
-
- ' =========================================================
- ' PROCEDURE-LEVEL CODE
- ' =========================================================
- SUB GetRecords STATIC
-
- ' Both FileSpec$ and the RecVar array of records
- ' are shared with the module-level code above:
- SHARED FileSpec$, RecVar() AS RecType
- OPEN FileSpec$ FOR RANDOM AS #1
- .
- .
- .
- END SUB
-
- FUNCTION InventoryTotal STATIC
-
- ' Only the RecVar array is shared with the module-level
- ' code:
- SHARED RecVar() AS RecType
- .
- .
- .
- END FUNCTION
-
- 2.6.2 Sharing Variables with All Procedures in a Module
-
- If variables are declared at the module level with the SHARED attribute in
- a COMMON, DIM, or REDIM statement (for example, by using a statement of
- the form COMMON SHARED variablelist), then all procedures within that
- module have access to those variables; in other words, the SHARED
- attribute makes variables global throughout a module.
-
- The SHARED attribute is convenient when you need to share large numbers of
- variables among all procedures in a module.
-
- Examples
-
- These statements declare variables shared among all procedures in one
- module:
-
- COMMON SHARED A, B, C
- DIM SHARED Array(1 TO 10, 1 TO 10) AS UserType
- REDIM SHARED Alpha(N%)
-
- In the following example, the module-level code shares the string
- arrayStrArray and the integer variables Min and Max with the two SUB
- procedures FillArray and PrintArray :
-
- ' =========================================================
- ' MODULE-LEVEL CODE
- ' =========================================================
- DECLARE SUB FillArray ()
- DECLARE SUB PrintArray ()
-
- ' The following DIM statements share the Min and Max
- ' integer variables and the StrArray string array
- ' with any SUB or FUNCTION in this module:
- DIM SHARED StrArray (33 TO 126) AS STRING * 5
- DIM SHARED Min AS INTEGER, Max AS INTEGER
-
- Min = LBOUND(StrArray)
- Max = UBOUND(StrArray)
-
- FillArray ' Note the absence of argument lists.
- PrintArray
- END
- ' =========================================================
- ' PROCEDURE-LEVEL CODE
- ' =========================================================
- SUB FillArray STATIC
-
- ' Load each element of the array from 33 to 126
- ' with a 5-character string, each character of which
- ' has the ASCII code I%:
- FOR I% = Min TO Max
- StrArray(I%) = STRING$(5, I%)
- NEXT
-
- END SUB
-
- SUB PrintArray STATIC
- FOR I% = Min TO Max
- PRINT StrArray(I%)
- NEXT
- END SUB
-
- Partial output
-
- !!!!!
- """""
- #####
- $$$$$
- %%%%%
- &&&&&
- ""'
- {{{{{
- .
- .
- .
-
- If you are using your own text editor to write your programs and directly
- compiling those programs outside the QuickBASIC development environment,
- note that variable declarations with the SHARED attribute must precede the
- procedure definition. Otherwise, the value of any variable declared with
- SHARED is not available to the procedure, as shown by the output from the
- next example. (If you are using QuickBASIC to create your programs, this
- sequence is not required, since QuickBASIC automatically saves programs in
- the correct order.)
-
- DEFINT A-Z
-
- FUNCTION Adder (X, Y) STATIC
- Adder = X + Y + Z
- END FUNCTION
-
- DIM SHARED Z
- Z = 2
- PRINT Adder (1, 3)
- END
-
- Output
-
- 4
-
- The next example shows how you should save the module shown above, with
- the definition of Adder following the DIM SHARED Z statement:
-
- DEFINT A-Z
-
- DECLARE FUNCTION Adder (X, Y)
-
- ' The variable Z is now shared with Adder:
- DIM SHARED Z
- Z = 2
- PRINT Adder (1, 3)
- END
-
- FUNCTION Adder (X, Y) STATIC
- Adder = X + Y + Z
- END FUNCTION
-
- Output
-
- 6
-
- 2.6.3 Sharing Variables with Other Modules
-
- If you want to share variables across modules in your program, list the
- variables in COMMON or COMMON SHARED statements at the module level in
- each module.
-
- Examples
-
- The following example shows how to share variables between modules by
- using a COMMON statement in the module that calls the SUB procedures, as
- well as a COMMON SHARED statement in the module that defines the
- procedures. With COMMON SHARED, all procedures in the second module have
- access to the common variables:
-
- ' =========================================================
- ' MAIN MODULE
- ' =========================================================
-
- COMMON A, B
- A = 2.5
- B = 1.2
- CALL Square
- CALL Cube
- END
- ' =========================================================
- ' Module with Cube and Square Procedures
- ' =========================================================
-
- ' NOTE: The names of the variables (X, Y) do not have to be
- ' the same as in the other module (A, B). Only the types
- ' have to be the same.
-
- COMMON SHARED X, Y ' This statement is at the module level.
- ' Both X and Y are shared with the CUBE
- ' and SQUARE procedures below.
- SUB Cube STATIC
- PRINT "A cubed ="; X ^ 3
- PRINT "B cubed ="; Y ^ 3
- END SUB
-
- SUB Square STATIC
- PRINT "A squared ="; X ^ 2
- PRINT "B squared ="; Y ^ 2
- END SUB
-
- The following example uses named COMMON blocks at the module levels and
- SHARED statements within procedures to share different sets of variables
- with each procedure:
-
- ' =========================================================
- ' MAIN MODULE
- ' Prints the volume and density of a filled cylinder given
- ' the input values
- ' =========================================================
-
- COMMON /VolumeValues/ Height, Radius, Volume
- COMMON /DensityValues/ Weight, Density
-
- INPUT "Height of cylinder in centimeters: ", Height
- INPUT "Radius of cylinder in centimeters: ", Radius
- INPUT "Weight of filled cylinder in grams: ", Weight
-
- CALL VolumeCalc
- CALL DensityCalc
-
- PRINT "Volume is"; Volume; "cubic centimeters."
- PRINT "Density is"; Density; "grams/cubic centimeter."
- END
-
- ' =========================================================
- ' Module with DensityCalc and VolumeCalc Procedures
- ' =========================================================
-
- COMMON /VolumeValues/ H, R, V
- COMMON /DensityValues/ W, D
-
- SUB VolumeCalc STATIC
-
- ' Share the Height, Radius, and Volume variables
- ' with this procedure:
- SHARED H, R, V
- CONST PI = 3.141592653589#
- V = PI * H * (R ^ 2)
- END SUB
-
- SUB DensityCalc STATIC
-
- ' Share the Weight, Volume, and Density variables
- ' with this procedure:
- SHARED W, V, D
- D = W / V
- END SUB
-
- Output
-
- Height of cylinder in centimeters: 100
- Radius of cylinder in centimeters: 10
- Weight of filled cylinder in grams: 10000
- Volume is 31415.93 cubic centimeters.
- Density is .3183099 grams/cubic centimeter.
-
- 2.6.4 The Problem of Variable Aliasing
-
- "Variable aliasing" is sometimes a problem in long programs containing
- many variables and procedures. Variable aliasing is the situation where
- two or more names refer to the same location in memory. It occurs:
-
- ■ When the same variable appears more than once in the list of arguments
- passed to a procedure.
-
- ■ When a variable passed in an argument list is also accessed by the
- procedure by means of the SHARED statement or the SHARED attribute.
-
- To avoid aliasing problems, double-check variables shared with a procedure
- to make sure they don't also appear in a procedure call's argument list.
- Also, don't pass the same variable twice, as in the next statement:
-
- ' X is passed twice; this will lead to aliasing problems
- ' in the Test procedure:
- CALL Test(X, X, Y)
-
- Example
-
- The following example illustrates how variable aliasing can occur. Here
- the variable A is shared between the module-level code and the SUB
- procedure with the DIM SHARED statement. However, A is also passed by
- reference to the SUB as an argument. Therefore, in the subprogram, A and X
- both refer to the same location in memory. Thus, when the subprogram
- modifies X, it is also modifying A, and vice versa.
-
- DIM SHARED A
- A = 4
- CALL PrintHalf(A)
- END
-
- SUB PrintHalf (X) STATIC
- PRINT "Half of"; X; "plus half of"; A; "equals";
- X = X / 2 ' X and A now both equal 2.
- A = A / 2 ' X and A now both equal 1.
- PRINT A + X
- END SUB
-
- Output
-
- Half of 4 plus half of 4 equals 2
-
-
- 2.7 Automatic and STATIC Variables
-
- When the STATIC attribute appears on a procedure-definition line, it means
- that local variables within the procedure are STATIC; that is, their
- values are preserved between calls to the procedure.
-
- Leaving off the STATIC attribute makes local variables within the
- procedure "automatic" by default; that is, you get a fresh set of local
- variables each time the procedure is called.
-
- You can override the effect of leaving off the STATIC attribute by using
- the STATIC statement within the procedure, thus making some variables
- automatic and others STATIC (see Section 2.8 for more information).
-
- ──────────────────────────────────────────────────────────────────────────
- NOTE
- The SHARED statement also overrides the default for variables in a
- procedure (local STATIC or local automatic), since any variable
- appearing in a SHARED statement is known at the module level and thus is
- not local to the procedure.
- ──────────────────────────────────────────────────────────────────────────
-
-
- 2.8 Preserving Values of Local Variables with the STATIC Statement
-
- Sometimes you may want to make some local variables in a procedure STATIC
- while keeping the rest automatic. List those variables in a STATIC
- statement within the procedure.
-
- Also, putting a variable name in a STATIC statement is a way of making
- absolutely sure that the variable is local, since a STATIC statement
- overrides the effect of a module-level SHARED statement.
-
- A STATIC statement can appear only within a procedure. An array name in a
- STATIC statement must be followed by a set of empty parentheses ( ). Also,
- you must dimension any array that appears in a STATIC statement before
- using the array, as shown in the next example:
-
- SUB SubProg2
- STATIC Array() AS INTEGER
- DIM Array(-5 TO 5, 1 TO 25) AS INTEGER
- .
- .
- .
- END SUB
-
- ──────────────────────────────────────────────────────────────────────────
- NOTE
- If you give a variable its type in an AS type clause, then the AS type
- clause must appear along with the variable's name in both the STATIC and
- DIM statements.
- ──────────────────────────────────────────────────────────────────────────
-
- Example
-
- The following example shows how a STATIC statement preserves the value of
- the string variable Y$ throughout successive calls to TestSub:
-
- DECLARE SUB TestSub ()
- FOR I% = 1 TO 5
- TestSub ' Call TestSub five times.
- NEXT I%
- END
-
- SUB TestSub ' Note: no STATIC attribute
-
- ' Both X$ and Y$ are local variables in TestSub (that is,
- ' their values are not shared with the module-level code).
- ' However since X$ is an automatic variable, it is
- ' reinitialized to a null string every time TestSub is
- ' called. In contrast, Y$ is STATIC, so it retains the
- ' value it had from the last call:
- STATIC Y$
- X$ = X$ + "*"
- Y$ = Y$ + "*"
- PRINT X$, Y$
- END SUB
-
- Output
-
- * *
- * **
- * ***
- * ****
- * *****
-
-
- 2.9 Recursive Procedures
-
- Procedures in BASIC can be recursive. A recursive procedure is one that
- can call itself or call other procedures that in turn call the first
- procedure.
-
- 2.9.1 The Factorial Function
-
- A good way to illustrate recursive procedures is to consider the factorial
- function from mathematics. One way to define n! ("n factorial") is with
- the following formula:
-
- n! = n * (n-1) * (n-2) * ... * 2 * 1
-
- For example, 5 factorial is evaluated as follows:
-
- 5! = 5 * 4 * 3 * 2 * 1 = 120
-
- ──────────────────────────────────────────────────────────────────────────
- NOTE
- Do not confuse the mathematical factorial symbol (!) used in this
- discussion with the single-precision type-declaration suffix used by
- BASIC.
- ──────────────────────────────────────────────────────────────────────────
-
- Factorials lend themselves to a recursive definition as well:
-
- n! = n * (n-1)!
-
- This leads to the following progression:
-
- 5! = 5 * 4!
- 4! = 4 * 3!
- 3! = 3 * 2!
- 2! = 2 * 1!
- 1! = 1 * 0!
-
- Recursion must always have a terminating condition. With factorials this
- terminating condition occurs when 0! is evaluated──by definition, 0! is
- equal to 1.
-
- ──────────────────────────────────────────────────────────────────────────
- NOTE
- Although a recursive procedure can have STATIC variables by default (as
- in the next example), it is often preferable to let automatic variables
- be the default instead. In this way, recursive calls will not overwrite
- variable values from a preceding call.
- ──────────────────────────────────────────────────────────────────────────
-
- Example
-
- The following example uses a recursive FUNCTION procedure to calculate
- factorials:
-
- DECLARE FUNCTION Factorial# (N%)
- Format$ = "###_! = ###################"
- DO
- INPUT "Enter number from 0 - 20 (or -1 to end): ", Num%
- IF Num% >= 0 AND Num% <= 20 THEN
- PRINT USING Format$; Num%; Factorial#(Num%)
- END IF
- LOOP WHILE Num% >= 0
- END
-
- FUNCTION Factorial# (N%) STATIC
-
- IF N% > 0 THEN ' Call Factorial# again
- ' if N is greater than zero.
- Factorial# = N% * Factorial#(N% - 1)
-
- ELSE ' Reached the end of recursive calls
- ' (N% = 0), so "climb back up the ladder."
- Factorial# = 1
- END IF
- END FUNCTION
-
- 2.9.2 Adjusting the Size of the Stack
-
- Recursion can eat up a lot of memory, since each set of automatic
- variables in a SUB or FUNCTION procedure is saved on the stack. (Saving
- variables this way allows a procedure to continue with the correct
- variable values after control returns from a recursive call.)
-
- If you have a recursive procedure with many automatic variables, or a
- deeply nested recursive procedure, you may need to adjust the size of the
- stack with a CLEAR , , stacksize statement, where stacksize is the number
- of bytes from the stack you want to reserve. Otherwise, while your program
- is running you may get the error message Out of stack space.
-
- The following steps outline one way to estimate the amount of memory a
- recursive procedure needs:
-
- 1. Insert a single quotation mark to temporarily turn the recursive call
- into a comment line so that the procedure will be invoked only once
- when the program runs.
-
- 2. Call the FRE(-2) function (which returns the total unused stack space)
- just before you call the recursive procedure. Also call the FRE(-2)
- function right at the end of the recursive procedure. Use PRINT
- statements to display the returned values.
-
- 3. Run the program. The difference in values is the amount of stack space
- (in bytes) used by one call to the procedure.
-
- 4. Estimate the maximum number of times the procedure is likely to be
- invoked, then multiply this value by the stack space consumed by one
- call to the procedure. The result is totalbytes.
-
- 5. Reserve the amount of stack space calculated in step 4:
-
- CLEAR , , totalbytes
-
-
- 2.10 Transferring Control to Another Program with CHAIN
-
- Unlike procedure calls, which occur within the same program, the CHAIN
- statement simply starts a new program. When a program chains to another
- program, the following sequence occurs:
-
- 1. The first program stops running.
-
- 2. The second program is loaded into memory.
-
- 3. The second program starts running.
-
- The advantage of using CHAIN is that it enables you to split a program
- with large memory requirements into several smaller programs.
-
- The COMMON statement allows you to pass variables from one program to
- another program in a chain. A common programming practice is to put these
- COMMON statements in an include file, and then use the $INCLUDE
- metacommand at the beginning of each program in the chain.
-
- ──────────────────────────────────────────────────────────────────────────
- NOTE
- Don't use a COMMON /blockname /variablelist statement (a "named COMMON
- block") to pass variables to a chained program, since variables listed
- in named COMMON blocks are not preserved when chaining. Use a blank
- COMMON block (COMMON variablelist) instead.
- ──────────────────────────────────────────────────────────────────────────
-
- Example
-
- This example, which shows a chain connecting three separate programs, uses
- an include file to declare variables passed in common among the programs:
-
- ' ============ CONTENTS OF INCLUDE FILE COMMONS.BI ========
- DIM Values(10)
- COMMON Values(), NumValues
-
- ' ======================= MAIN.BAS ========================
-
- ' Read in the contents of the COMMONS.BI file:
- ' $INCLUDE: 'COMMONS.BI'
-
- ' Input the data:
- INPUT "Enter number of data values (<=10): ", NumValues
- FOR I = 1 TO NumValues
- Prompt$ = "Value ("+LTRIM$(STR$(I))+")? "
- PRINT Prompt$;
- INPUT "", Values(I)
- NEXT I
-
- ' Have the user specify the calculation to do:
- INPUT "Calculation (1=st. dev., 2=mean)? ", Choice
-
- ' Now, chain to the correct program:
- SELECT CASE Choice
-
- CASE 1: ' Standard Deviation
- CHAIN "STDEV"
-
- CASE 2: ' Mean
- CHAIN "MEAN"
- END SELECT
- END
-
- ' ======================= STDEV.BAS =======================
- ' Calculates the standard deviation of a set of data
- ' =========================================================
-
- ' $INCLUDE: 'COMMONS.BI'
-
- Sum = 0 ' Normal sum
- SumSq = 0 ' Sum of values squared
-
- FOR I = 1 TO NumValues
- Sum = Sum + Values(I)
- SumSq = SumSq + Values(I) ^ 2
- NEXT I
-
- Stdev = SQR(SumSq / NumValues - (Sum / NumValues) ^ 2)
- PRINT "The Standard Deviation of the samples is: " Stdev
- END
-
- ' ======================== MEAN.BAS =======================
- ' Calculates the mean (average) of a set of data
- ' =========================================================
-
- ' $INCLUDE: 'COMMONS.BI'
-
- Sum = 0
-
- FOR I = 1 TO NumValues
- Sum = Sum + Values(I)
- NEXT
-
- Mean = Sum / NumValues
- PRINT "The mean of the samples is: " Mean
- END
-
-
- 2.11 Sample Application: Recursive Directory Search (WHEREIS.BAS)
-
- The following program uses a recursive SUB procedure, ScanDir, to scan a
- disk for the file name input by the user. Each time this program finds the
- given file, it prints the complete directory path to the file.
-
- Statements and Functions Used
-
- This program demonstrates the following statements and keywords discussed
- in this chapter:
-
- ■ DECLARE
-
- ■ FUNCTION...END FUNCTION
-
- ■ STATIC
-
- ■ SUB...END SUB
-
- Program Listing
-
- DEFINT A-Z
-
- ' Declare symbolic constants used in program:
- CONST EOFTYPE = 0, FILETYPE = 1, DIRTYPE = 2, ROOT = "TWH"
-
- DECLARE SUB ScanDir (PathSpec$, Level, FileSpec$, Row)
-
- DECLARE FUNCTION MakeFileName$ (Num)
- DECLARE FUNCTION GetEntry$ (FileNum, EntryType)
-
- CLS
- INPUT "File to look for"; FileSpec$
- PRINT
- PRINT "Enter the directory where the search should start"
- PRINT "(optional drive + directories). Press <ENTER> to "
- PRINT "begin search in root directory of current drive."
- PRINT
- INPUT "Starting directory"; PathSpec$
- CLS
-
- RightCh$ = RIGHT$(PathSpec$, 1)
-
- IF PathSpec$ = "" OR RightCh$ = ":" OR RightCh$ <> "\" THEN
- PathSpec$ = PathSpec$ + "\"
- END IF
-
- FileSpec$ = UCASE$(FileSpec$)
- PathSpec$ = UCASE$(PathSpec$)
- Level = 1
- Row = 3
-
- ' Make the top level call (level 1) to begin the search:
- ScanDir PathSpec$, Level, FileSpec$, Row
-
- KILL ROOT + ".*" ' Delete all temporary files created
- ' by the program.
-
- LOCATE Row + 1, 1: PRINT "Search complete."
- END
-
- ' ======================= GETENTRY ========================
- ' This procedure processes entry lines in a DIR listing
- ' saved to a file.
-
- ' This procedure returns the following values:
-
- ' GetEntry$ A valid file or directory name
- ' EntryType If equal to 1, then GetEntry$
- ' is a file.
- ' If equal to 2, then GetEntry$
- ' is a directory.
- ' =========================================================
-
- FUNCTION GetEntry$ (FileNum, EntryType) STATIC
-
- ' Loop until a valid entry or end-of-file (EOF) is read:
- DO UNTIL EOF(FileNum)
- LINE INPUT #FileNum, EntryLine$
- IF EntryLine$ <> "" THEN
-
- ' Get first character from the line for test:
- TestCh$ = LEFT$(EntryLine$, 1)
- IF TestCh$ <> " " AND TestCh$ <> "." THEN EXIT DO
- END IF
- LOOP
-
- ' Entry or EOF found, decide which:
- IF EOF(FileNum) THEN ' EOF, so return EOFTYPE
- EntryType = EOFTYPE ' in EntryType.
- GetEntry$ = ""
-
- ELSE ' Not EOF, so it must be a
- ' file or a directory.
-
- ' Build and return the entry name:
- EntryName$ = RTRIM$(LEFT$(EntryLine$, 8))
-
- ' Test for extension and add to name if there is one:
- EntryExt$ = RTRIM$(MID$(EntryLine$, 10, 3))
- IF EntryExt$ <> "" THEN
- GetEntry$ = EntryName$ + "." + EntryExt$
- ELSE
- GetEntry$ = EntryName$
- END IF
-
- ' Determine the entry type, and return that value
- ' to the point where GetEntry$ was called:
- IF MID$(EntryLine$, 15, 3) = "DIR" THEN
- EntryType = DIRTYPE ' Directory
- ELSE
- EntryType = FILETYPE ' File
- END IF
-
- END IF
-
- END FUNCTION
-
- ' ===================== MAKEFILENAME$ =====================
- ' This procedure makes a file name from a root string
- ' ("TWH," defined as a symbolic constant at the module
- ' level) and a number passed to it as an argument (Num).
- ' =========================================================
-
- FUNCTION MakeFileName$ (Num) STATIC
-
- MakeFileName$ = ROOT + "." + LTRIM$(STR$(Num))
-
- END FUNCTION
-
- ' ======================= SCANDIR =========================
- ' This procedure recursively scans a directory for the
- ' file name entered by the user.
-
- ' NOTE: The SUB header doesn't use the STATIC keyword
- ' since this procedure needs a new set of variables
- ' each time it is invoked.
- ' =========================================================
-
- SUB ScanDir (PathSpec$, Level, FileSpec$, Row)
-
- LOCATE 1, 1: PRINT "Now searching"; SPACE$(50);
- LOCATE 1, 15: PRINT PathSpec$;
-
- ' Make a file specification for the temporary file:
- TempSpec$ = MakeFileName$(Level)
-
- ' Get a directory listing of the current directory,
- ' and save it in the temporary file:
- SHELL "DIR " + PathSpec$ + " > " + TempSpec$
-
- ' Get the next available file number:
- FileNum = FREEFILE
-
- ' Open the DIR listing file and scan it:
- OPEN TempSpec$ FOR INPUT AS #FileNu
-
- ' Process the file, one line at a time:
- DO
-
- ' Input an entry from the DIR listing file:
- DirEntry$ = GetEntry$(FileNum, EntryType)
-
- ' If entry is a file:
- IF EntryType = FILETYPE THEN
-
- ' If the FileSpec$ string matches,
- ' print entry and exit this loop:
- IF DirEntry$ = FileSpec$ THEN
- LOCATE Row, 1: PRINT PathSpec$; DirEntry$;
- Row = Row + 1
- EntryType = EOFTYPE
- END IF
-
- ' If the entry is a directory, then make a recursive
- ' call to ScanDir with the new directory:
- ELSEIF EntryType = DIRTYPE THEN
- NewPath$ = PathSpec$ + DirEntry$ + "\"
- ScanDir NewPath$, Level + 1, FileSpec$, Row
- LOCATE 1, 1: PRINT "Now searching"; SPACE$(50);
- LOCATE 1, 15: PRINT PathSpec$;
- END IF
-
- LOOP UNTIL EntryType = EOFTYPE
-
- ' Scan on this DIR listing file is finished, so close it:
- CLOSE FileNum
- END SUB
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- Chapter 3 File and Device I/O
-
- This chapter shows you how to use BASIC input and output (I/O) functions
- and statements. These statements permit your programs to access data
- stored in files and to communicate with devices attached to your system.
-
- The chapter includes material on a variety of programming tasks related to
- retrieving, storing, and formatting information. The relationship between
- data files and physical devices such as screens and keyboards is also
- covered.
-
- When you are finished with this chapter, you will know how to perform the
- following programming tasks:
-
- ■ Print text on the screen
-
- ■ Get input from the keyboard for use in a program
-
- ■ Create data files on disk
-
- ■ Store records in data files
-
- ■ Read records from data files
-
- ■ Read or modify data in files that are not in American Standard Code for
- Information Interchange (ASCII) format
-
- ■ Communicate with other computers through the serial port
-
-
- 3.1 Printing Text on the Screen
-
- This section explains how to accomplish the following tasks:
-
- ■ Display text on the screen with PRINT
-
- ■ Display formatted text on the screen with PRINT USING
-
- ■ Skip spaces in a row of printed text with SPC
-
- ■ Skip to a given column in a row of printed text with TAB
-
- ■ Change the number of rows or columns appearing on the screen with WIDTH
-
- ■ Open a text viewport with VIEW PRINT
-
- ──────────────────────────────────────────────────────────────────────────
- NOTE
- Output that appears on the screen is sometimes referred to as "standard
- output." You can redirect standard output by using the DOS command-line
- symbols > or >>, thus sending output that would have gone to the screen
- to a different output device (such as a printer) or to a disk file. (See
- your DOS documentation for more information on redirecting output.)
- ──────────────────────────────────────────────────────────────────────────
-
- 3.1.1 Screen Rows and Columns
-
- To understand how text is printed on the screen, it helps to think of the
- screen as a grid of "rows" and "columns." The height of one row slightly
- exceeds the height of a line of printed output, while the width of one
- column is just wider than the width of one character. A standard screen
- configuration in text mode (nongraphics) is 80 columns wide by 25 rows
- high. Figure 3.1 shows how each character printed on the screen occupies a
- unique cell in the grid, a cell that can be identified by pairing a row
- argument with a column argument.
-
- The bottom row of the screen is not usually used for output, unless you
- use a LOCATE statement to display text there. (See Section 3.3,
- "Controlling the Text Cursor," for more information on LOCATE.)
-
- 3.1.2 Displaying Text and Numbers with PRINT
-
-
- ┌───────────────────────────────────────────────────────────────────┐
- │ │
- │ │
- │ ──────────────── Columns ────────────── │
- │ ┌──────────────────────── │
- │ │ 1 2 3 4 5 6 7 8 9 │
- │ │ ┌───┬───┬───┬───┬───┬───┬───┬───┬───┬─ │
- │ │ │ 1 │ │ │ │ │ │ │ │ │ │ │
- │ │ │ ├───┼───┼───┼───┼───┼───┼───┼───┼───┼─ │
- │ │ │ 2 │ │ │ │ H │ E │ L │ L │ O │ │ │
- │Rows │ ├───┼───┼───┼──\┼───┼───┼───┼───┼───┼─ │
- │ │ │ 3 │ │ │ │ │\──┼───┼───┼───┼───┼── This output starts│
- │ │ │ ├───┼───┼───┼───┼───┼───┼───┼───┼───┼─ in row 2, column 4│
- │ │ 4 │ │ │ │ │ │ │ │ │ │ │
- │ │ ├───┼───┼───┼───┼───┼───┼───┼───┼───┼─ │
- │ │ │ │ │ │ │ │ │ │ │ │
- │ │
- └───────────────────────────────────────────────────────────────────┘
-
- Figure 3.1 Text Output on Screen
-
- By far the most commonly used statement for output to the screen is the
- PRINT statement. With PRINT, you can display numeric or string values, or
- a mixture of the two. In addition, PRINT with no arguments prints a blank
- line.
-
- The following are some general comments about PRINT:
-
- ■ PRINT always prints numbers with a trailing blank space. If the number
- is positive, the number is also preceded by a space; if the number is
- negative, the number is preceded by a minus sign.
-
- ■ The PRINT statement can be used to print lists of expressions.
- Expressions in the list can be separated from other expressions by
- commas, semicolons, one or more blank spaces, or one or more tab
- characters. A comma causes PRINT to skip to the beginning of the next
- "print zone," or block of 14 columns, on the screen. A semicolon (or any
- combination of spaces and/or tabs) between two expressions prints the
- expressions on the screen next to each other, with no spaces in between
- (except for the built-in spaces for numbers).
-
- ■ Ordinarily, PRINT ends each line of output with a new-line sequence (a
- carriage-return and line-feed). However, a comma or semicolon at the end
- of the list of expressions suppresses this; the next printed output from
- the program appears on the same line unless it is too long to fit on
- that line.
-
- ■ PRINT wraps an output line that exceeds the width of the screen onto the
- next line. For example, if you try to print a line that is 100
- characters long on an 80-column screen, the first 80 characters of the
- line show up on one row, followed by the next 20 characters on the next
- row. If the 100-character line didn't start at the left edge of the
- screen (for example, if it followed a PRINT statement ending in a comma
- or semicolon), then the line would print until it reached the 80th
- column of one row and continue in the first column of the next row.
-
- Example
-
- The output from the following program shows some of the different ways you
- can use PRINT:
-
- A = 2
- B = -1
- C = 3
- X$ = "over"
- Y$ = "there"
-
- PRINT A, B, C
- PRINT B, A, C
- PRINT A; B; C
- PRINT X$; Y$
- PRINT X$, Y$;
- PRINT A, B
- PRINT
- FOR I = 1 TO 8
- PRINT X$,
- NEXT
-
- Output
-
- 2 -1 3
- -1 2 3
- 2 -1 3
- overthere
- over there 2 -1
-
- over over over over over
- over over over
-
- 3.1.3 Displaying Formatted Output with PRINT USING
-
- The PRINT USING statement gives greater control than PRINT over the
- appearance of printed data, especially numeric data. Through the use of
- special characters embedded in a format string, PRINT USING allows you to
- specify information such as how many digits from a number (or how many
- characters from a string) are displayed, whether or not a plus (+) sign or
- a dollar sign ($) appears in front of a number, and so forth.
-
- Example
-
- The example that follows gives you a sample of what can be done with PRINT
- USING. You can list more than one expression after the PRINT USING format
- string. As is the case with PRINT, the expressions in the list can be
- separated from one another by commas, semicolons, spaces, or tab
- characters.
-
- X = 441.2318
-
- PRINT USING "The number with 3 decimal places ###.###";X
- PRINT USING "The number with a dollar sign $$##.##";X
- PRINT USING "The number in exponential format #.###^^^^";X
- PRINT USING "Numbers with plus signs +### "; X; 99.9
-
- Output
-
- The number with 3 decimal places 441.232
- The number with a dollar sign $441.23
- The number in exponential format 0.441E+03
- Numbers with plus signs +441 Numbers with plus signs +100
-
- Consult the QB Advisor for more on PRINT USING.
-
- 3.1.4 Skipping Spaces and Advancing to a Specific Column
-
- By using the SPC(n) statement in a PRINT statement, you can skip n spaces
- in a row of printed output, as shown by the output from the next example:
-
- PRINT " 1 2 3"
- PRINT "123456789012345678901234567890"
- PRINT "First Name"; SPC(10); "Last Name"
-
- Output
-
- 1 2 3
- 123456789012345678901234567890
- First Name Last Name
-
- By using the TAB(n) statement in a PRINT statement, you can skip to the
- nth column (counting from the left side of the screen) in a row of printed
- output. The following example uses TAB to produce the same output as that
- shown above:
-
- PRINT " 1 2 3"
- PRINT "123456789012345678901234567890"
- PRINT "First Name"; TAB(21); "Last Name"
-
- Neither SPC nor TAB can be used by itself to position printed output on
- the screen; they can only appear in PRINT statements.
-
- 3.1.5 Changing the Number of Columns or Rows
-
- You can control the maximum number of characters that appear in a single
- row of output by using the WIDTH columns statement. The WIDTH columns
- statement actually changes the size of characters that are printed on the
- screen, so that more or fewer characters can fit on a row. For example,
- WIDTH 40 makes characters wider, so the maximum row length is 40
- characters. WIDTH 80 makes characters narrower, so the maximum row length
- is 80 characters. The numbers 40 and 80 are the only valid values for the
- columns argument.
-
- On machines equipped with an Enhanced Graphics Adapter (EGA) or Video
- Graphics Adapter (VGA), the WIDTH statement can also control the number of
- rows that appear on the screen as follows:
-
- WIDTH[[columns]] [[,rows]]
-
- The value for rows may be 25, 30, 43, 50, or 60, depending on the type of
- display adapter you use and the screen mode set in a preceding SCREEN
- statement.
-
- 3.1.6 Creating a Text Viewport
-
- So far, the entire screen has been used for text output. However, with the
- VIEW PRINT statement, you can restrict printed output to a "text
- viewport," a horizontal slice of the screen. The syntax of the VIEW PRINT
- statement is:
-
- VIEW PRINT[[topline TO bottomline]]
-
- The values for topline and bottomline specify the locations where the
- viewport will begin and end.
-
- A text viewport also gives you control over on-screen scrolling. Without a
- viewport, once printed output reaches the bottom of the screen, text or
- graphics output that was at the top of the screen scrolls off and is lost.
- However, after a VIEW PRINT statement, scrolling takes place only between
- the top and bottom lines of the viewport. This means you can label the
- displayed output at the top and/or bottom of the screen without having to
- worry that the labeling will scroll it off if too many lines of data
- appear. You can also use the CLS 2 statement to clear just the text
- viewport, leaving the contents of the rest of the screen intact. See
- Section 5.5, "Defining a Graphics Viewport," to learn how to create a
- viewport for graphics output on the screen.
-
- Example
-
- You can see the effects of a VIEW PRINT statement by examining the output
- from the next example:
-
- CLS
- LOCATE 3, 1
- PRINT "This is above the text viewport; it doesn't scroll."
-
- LOCATE 4, 1
- PRINT STRING$(60, "_") ' Print horizontal lines above
- LOCATE 11, 1
- PRINT STRING$(60, "_") ' and below the text viewport.
-
- PRINT "This is below the text viewport."
-
- VIEW PRINT 5 TO 10 ' Text viewport extends from
- ' lines 5 to 10.
-
- FOR I = 1 TO 20 ' Print numbers and text in
- PRINT I; "a line of text" ' the viewport.
- NEXT
-
- DO: LOOP WHILE INKEY$ = "" ' Wait for a key press.
- CLS 2 ' Clear just the viewport.
- END
-
- Output (Before User Presses Key)
-
- ┌───────────────────────────────────────────────────────────────────┐
- │ │
- │ │
- │ This is above the text viewport: it doesn't scroll. │
- │ ─────────────────────────────────────────────────────────────── │
- │ 16 a line of text │
- │ 17 a line of text │
- │ 18 a line of text │
- │ 19 a line of text │
- │ 20 a line of text │
- │ │
- │ │
- │ ─────────────────────────────────────────────────────────────── │
- │ This is below the text viewport. │
- │ │
- │ │
- │ │
- │ │
- └───────────────────────────────────────────────────────────────────┘
-
- Output (After User Presses Key)
-
- ┌───────────────────────────────────────────────────────────────────┐
- │ │
- │ │
- │ This is above the text viewport: it doesn't scroll. │
- │ ─────────────────────────────────────────────────────────── │
- │ │
- │ │
- │ │
- │ ─────────────────────────────────────────────────────────── │
- │ This is below the text viewport. │
- │ │
- │ │
- │ │
- │ │
- │ │
- │ │
- │ │
- │ │
- │ │
- └───────────────────────────────────────────────────────────────────┘
-
-
- 3.2 Getting Input from the Keyboard
-
- This section shows you how to use the following statements and functions
- to enable your BASIC programs to accept input entered from the keyboard:
-
- ■ INPUT
-
- ■ LINE INPUT
-
- ■ INPUT$
-
- ■ INKEY$
-
- ──────────────────────────────────────────────────────────────────────────
- NOTE
- Input typed at the keyboard is often referred to as "standard input."
- You can use the DOS symbol < to direct standard input to your program
- from a file or other input device instead of from the keyboard. (See
- your DOS documentation for more information on redirecting input.)
- ──────────────────────────────────────────────────────────────────────────
-
- 3.2.1 The INPUT Statement
-
- The INPUT statement takes information typed by the user and stores it in a
- list of variables, as shown in the following example:
-
- INPUT A%, B, C$
- INPUT D$
- PRINT A%, B, C$, D$
-
- Output
-
- ? 6.6,45,a string
- ? "two, three"
- 7 45 a string two, three
-
- Here are some general comments about INPUT:
-
- ■ An INPUT statement by itself prompts the user with a question mark (?)
- followed by a blinking cursor.
-
- ■ The INPUT statement is followed by one or more variable names. If there
- are more than one variable, they are separated by commas.
-
- ■ The number of constants entered by the user after the INPUT prompt must
- be the same as the number of variables in the INPUT statement itself.
-
- ■ The values the user enters must agree in type with the variables in the
- list following INPUT. In other words, enter a number if the variable is
- designated as having the type integer, long integer, single precision,
- or double precision. Enter a string if the variable is designated as
- having the type string.
-
- ■ Since constants in an input list must be separated by commas, an input
- string constant containing one or more commas should be enclosed in
- double quotes. The double quotes ensure that the string is treated as a
- unit and not broken into two or more parts.
-
- If the user breaks any of the last three rules, BASIC prints the error
- message Redo from start. This message reappears until the input agrees in
- number and type with the variable list.
-
- If you want your input prompt to be more informative than a simple
- question mark, you can make a prompt appear, as in the following example:
-
- INPUT "What is the correct time (hour, min)"; Hr$, Min$
-
- This prints the following prompt:
-
- What is the correct time (hour, min)?
-
- Note the semicolon between the prompt and the input variables. This
- semicolon causes a question mark to appear as part of the prompt.
- Sometimes you may want to eliminate the question mark altogether; in this
- case, put a comma between the prompt and the variable list:
-
- INPUT "Enter the time (hour, min): ", Hr$, Min$
-
- This prints the following prompt:
-
- Enter the time (hour, min):
-
- 3.2.2 The LINE INPUT Statement
-
- If you want your program to accept lines of text with embedded commas,
- leading blanks, or trailing blanks, yet you do not want to have to remind
- the user to enclose the input in double quotes, use the LINE INPUT
- statement. The LINE INPUT statement, as its name implies, accepts a line
- of input (terminated by pressing the ENTER key) from the keyboard and
- stores it in a single string variable. Unlike INPUT, the LINE INPUT
- statement does not print a question mark by default to prompt for input;
- it does, however, allow you to display a prompt string.
-
- The following example shows the difference between INPUT and LINE INPUT:
-
- ' Assign the input to three separate variables:
- INPUT "Enter three values separated by commas: ", A$, B$, C$
-
- ' Assign the input to one variable (commas not treated
- ' as delimiters between input):
- LINE INPUT "Enter the same three values: ", D$
-
- PRINT "A$ = "; A$
- PRINT "B$ = "; B$
- PRINT "C$ = "; C$
- PRINT "D$ = "; D$
-
- Output
-
- Enter 3 values separated by commas: by land, air, and sea
- Enter the same three values: by land, air, and sea
- A$ = by land
- B$ = air
- C$ = and sea
- D$ = by land, air, and sea
-
- With both INPUT and LINE INPUT, input is terminated when the user presses
- the ENTER key, which also advances the cursor to the next line. As the
- next example shows, a semicolon between the INPUT keyword and the prompt
- string keeps the cursor on the same line:
-
- INPUT "First value: ", A
- INPUT; "Second value: ", B
- INPUT " Third value: ", C
-
- The following shows some sample input to the preceding program and the
- positions of the prompts:
-
- First value: 5
- Second value: 4 Third value: 3
-
- 3.2.3 The INPUT$ Function
-
- Both INPUT and LINE INPUT wait for the user to press the ENTER key before
- they store what is typed; that is, they read a line of input, then assign
- it to program variables. In contrast, the INPUT$(number) function doesn't
- wait for the enter key to be pressed; it just reads a specified number of
- characters. For example, the following line in a program reads three
- characters typed by the user, then stores the three-character string in
- the variable Test$:
-
- Test$ = INPUT$(3)
-
- Unlike the INPUT statement, the INPUT$ function does not prompt the user
- for data, nor does it echo input characters on the screen. Also, since
- INPUT$ is a function, it cannot stand by itself as a complete statement.
- INPUT$ must appear in an expression, as in the following:
-
- INPUT x ' INPUT is a statement.
-
- PRINT INPUT$(1) ' INPUT$ is a function, so it must
- Y$ = INPUT$(1) ' appear in an expression.
-
- The INPUT$ function reads input from the keyboard as an unformatted stream
- of characters. Unlike INPUT or LINE INPUT, INPUT$ accepts any key pressed,
- including control keys like ESC or BACKSPACE. For example, pressing the
- ENTER key five times assigns five carriage-return characters to the Test$
- variable in the next line:
-
- Test$ = INPUT$(5)
-
- 3.2.4 The INKEY$ Function
-
- The INKEY$ function completes the list of BASIC's keyboard-input functions
- and statements. When BASIC encounters an expression containing the INKEY$
- function, it checks to see if the user has pressed a key since one of the
- following:
-
- ■ The last time it found an expression with INKEY$
-
- ■ The beginning of the program, if this is the first time INKEY$ appears
-
- If no key has been pressed since the last time the program checked, INKEY$
- returns a null string (""). If a key has been pressed, INKEY$ returns the
- character corresponding to that key.
-
- Example
-
- The most important difference between INKEY$ and the other statements and
- functions discussed in this section is that INKEY$ lets your program
- continue doing other things while it checks for input. In contrast, LINE
- INPUT, INPUT$, and INPUT suspend program execution until there is input,
- as show in this example:
-
- PRINT "Press any key to start. Press any key to end."
-
- ' Don't do anything else until the user presses a key:
- Begin$ = INPUT$(1)
-
- I = 1
-
- ' Print the numbers from one to one million.
- ' Check for a key press while the loop is executing:
- DO
- PRINT I
- I = I + 1
-
- ' Continue looping until the value of the variable I is
- ' greater than one million or until a key is pressed:
- LOOP UNTIL I > 1000000 OR INKEY$ <> ""
-
-
- 3.3 Controlling the Text Cursor
-
- When you display printed text on the screen, the text cursor marks the
- place on the screen where output from the program──or input typed by the
- user──will appear next. In the next example, after the INPUT statement
- displays its 12-letter prompt, First name:, the cursor waits for input in
- row 1 at column 13:
-
- ' Clear the screen; start printing in row one, column one:
- CLS
- INPUT "First name: ", FirstName$
-
- In the next example, the semicolon at the end of the second PRINT
- statement leaves the cursor in row 2 at column 27:
-
- CLS
- PRINT
-
- ' Twenty-six characters are in the next line:
- PRINT "Press any key to continue.";
- PRINT INPUT$(1)
-
- Sections 3.3.1-3.3.3 show how to control the location of the text cursor,
- change its shape, and get information about its location.
-
- 3.3.1 Positioning the Cursor
-
- The input and output statements and functions discussed so far do not
- allow much control over where output is displayed or where the cursor is
- located after the output is displayed. Input prompts or output always
- start in the far left column of the screen and descend one row at a time
- from top to bottom unless a semicolon is used in the PRINT or INPUT
- statements to suppress the carriage-return and line-feed sequence.
-
- The SPC and TAB statements, discussed in Section 3.1.4, "Skipping Spaces
- and Advancing to a Specific Column," give some control over the location
- of the cursor by allowing you to move it to any column within a given row.
-
- The LOCATE statement extends this control one step further. The syntax for
- LOCATE is
-
- LOCATE[[row]][[,[[column]][[,[[cursor]][[,[[start]][[,stop]]]]]]]]
-
- Using the LOCATE statement allows you to position the cursor in any row or
- column on the screen, as shown by the output from the next example:
-
- CLS
- FOR Row = 9 TO 1 STEP -2
- Column = 2 * Row
- LOCATE Row, Column
- PRINT "12345678901234567890";
- NEXT
-
- Output
-
- 12345678901234567890
-
- 12345678901234567890
-
- 12345678901234567890
-
- 12345678901234567890
-
- 12345678901234567890
-
- 3.3.2 Changing the Cursor's Shape
-
- The optional cursor, start, and stop arguments shown in the syntax for the
- LOCATE statement also allow you to change the shape of the cursor and make
- it visible or invisible. A value of 1 for cursor makes the cursor visible,
- while a value of 0 makes the cursor invisible. The start and stop
- arguments control the height of the cursor, if it is on, by specifying the
- top and bottom "pixel" lines, respectively, for the cursor. (Any character
- on the screen is composed of lines of pixels, which are dots of light on
- the screen.) If a cursor spans the height of one row of text, then the
- line of pixels at the top of the cursor has the value 0, while the line of
- pixels at the bottom has a value of 7 or 13, depending on the type of
- display adapter you have. (For monochrome the value is 13; for color it is
- 7.)
-
- You can turn the cursor on and change its shape without specifying a new
- location for it. For example, the following statement keeps the cursor
- wherever it is at the completion of the next PRINT or INPUT statement,
- then makes it half a character high:
-
- LOCATE , , 1, 2, 5 ' Row and column arguments both optional
-
- The following examples show different cursor shapes produced using
- different start and stop values on a color display. Each LOCATE statement
- shown in the left column is followed by the statement
-
- INPUT "PROMPT:", X$
-
- Statement Input Prompt and Cursor Shape
- ──────────────────────────────────────────────────────────────────────────
- LOCATE, , 1, 0, 7 PROMPT:█
-
- LOCATE, , 1, 0, 3 PROMPT:▀
-
- LOCATE, , 1, 4, 7 PROMPT:
-
- LOCATE, , 1, 6, 2 PROMPT:(see page 94 of printed
- manual)
- ──────────────────────────────────────────────────────────────────────────
-
- In the preceding examples, note that making the start argument bigger than
- the stop argument results in a two-piece cursor.
-
- 3.3.3 Getting Information about the Cursor's Location
-
- You can think of the functions CSRLIN and POS(n) as the inverses of the
- LOCATE statement: whereas LOCATE tells the cursor where to go, CSRLIN and
- POS(n) tell your program where the cursor is. The CSRLIN function returns
- the current row and the POS(n) function returns the current column of the
- cursor's position.
-
- The argument n for POS(n) is what is known as a "dummy" argument; that is,
- n is a placeholder that can be any numeric expression. For example, POS(0)
- and POS(1) both return the same value.
-
- Example
-
- The following example uses the POS(n) function to print 50 asterisks in
- rows of 13 asterisks:
-
- FOR I% = 1 TO 50
- PRINT "*"; ' Print an asterisk and keep
- ' the cursor on the same line.
- IF POS(1) > 13 THEN PRINT ' If the cursor's position
- ' is past column 13, advance
- ' to the next line.
- NEXT
-
- Output
-
- *************
- *************
- *************
- ***********
-
-
- 3.4 Working with Data Files
-
- Data files are physical locations on your disk where information is
- permanently stored. The following three tasks are greatly simplified by
- using data files in your BASIC programs:
-
- 1. Creating, manipulating, and storing large amounts of data
-
- 2. Accessing several sets of data with one program
-
- 3. Using the same set of data in several different programs
-
- The sections that follow introduce the concepts of records and fields and
- contrast different ways to access data files from BASIC. When you have
- completed Sections 3.4.1-3.4.7, you should know how to do the following:
-
- ■ Create new data files
-
- ■ Open existing files and read their contents
-
- ■ Add new information to an existing data file
-
- ■ Change the contents of an existing data file
-
- 3.4.1 How Data Files Are Organized
-
- A data file is a collection of related blocks of information, or
- "records." Each record in a data file is further subdivided into "fields"
- or regularly recurring items of information within each record. If you
- compare a data file with a more old-fashioned way of storing information──
- for example, a folder containing application forms filled out by job
- applicants at a particular company──then a record is analogous to one
- application form in that folder. To carry the comparison one step further,
- a field is analogous to an item of information included on every
- application form, such as a Social Security number.
-
- ──────────────────────────────────────────────────────────────────────────
- NOTE
- If you do not want to access a file using records but instead want to
- treat it as an unformatted sequence of bytes, then read Section 3.4.7,
- "Binary File I/O."
- ──────────────────────────────────────────────────────────────────────────
-
- 3.4.2 Sequential and Random-Access Files
-
- The terms "sequential file" and "random-access file" refer to two
- different ways to store and access data on disk from your BASIC programs.
- A simplified way to think of these two kinds of files is with the
- following analogy: a sequential file is like a cassette tape, while a
- random-access file is like an LP record. To find a song on a cassette
- tape, you have to start at the beginning and fast-forward through the tape
- sequentially until you find the song you are looking for──there is no way
- to jump right to the song you want. This is similar to the way you have to
- find information in a sequential file: to get to the 500th record, you
- first have to read records 1 through 499.
-
- In contrast, if you want to play a certain song on an LP, all you have to
- do is lift the tone arm of the record player and put the needle down right
- on the song: you can randomly access anything on the LP without having to
- play all the songs before the one you want. Similarly, you can call up any
- record in a random-access file just by specifying its number, greatly
- reducing access time.
-
- ──────────────────────────────────────────────────────────────────────────
- NOTE
- Although there is no way to jump directly to a specific record in a
- sequential file, the SEEK statement lets you jump directly to a specific
- byte in the file (to "fast forward" or "rewind" the tape, to extend the
- preceding analogy). See Section 3.4.7, "Binary File I/O," for more
- information on how to do this.
- ──────────────────────────────────────────────────────────────────────────
-
- 3.4.3 Opening a Data File
-
- Before your program can read, modify, or add to a data file, it must first
- open the file. BASIC does this with the OPEN statement. The OPEN statement
- can be used to create a new file. The following list describes the various
- uses of the OPEN statement:
-
- ■ Create a new data file and open it so records can be added to it
-
- ' No file named PRICE.DAT is in the current directory:
- OPEN "Price.Dat" FOR OUTPUT AS #1
-
- ■ Open an existing data file so new records overwrite any data already in
- the file
-
- ' A file named PRICE.DAT is already in the current
- ' directory; new records can be written to it, but all
- ' old records are lost:
- OPEN "Price.Dat" FOR OUTPUT AS #1
-
- ■ Open an existing data file so new records are added to the end of the
- file, preserving data already in the file
-
- OPEN "Price.Dat" FOR APPEND AS #1
-
- The APPEND mode will also create a new file if a file with the given
- name does not already appear in the current directory.
-
- ■ Open an existing data file so old records can be read from it
-
- OPEN "Price.Dat" FOR INPUT AS #1
-
- See Section 3.4.5, "Using Sequential Files," for more information about
- the INPUT, OUTPUT, and APPEND modes.
-
- ■ Open an existing data file (or create a new one if a file with that name
- doesn't exist), then read or write fixed-length records to and from the
- file
-
- OPEN "Price.Dat" FOR RANDOM AS #1
-
- See Section 3.4.6, "Using Random-Access Files," for more information
- about this mode.
-
- ■ Open an existing data file (or create a new one if a file with that name
- doesn't exist), then read data from the file or add new data to the
- file, starting at any byte position in the file
-
- OPEN "Price.Dat" FOR BINARY AS #1
-
- See Section 3.4.7, "Binary File I/O," for more information about this
- mode.
-
- 3.4.3.1 File Numbers in BASIC
-
- The OPEN statement does more than just specify a mode for data I/O for a
- particular file (OUTPUT, INPUT, APPEND, RANDOM, or BINARY); it also
- associates a unique file number with that file. This file number, which
- can be any integer from 1 to 255, is then used by subsequent file I/O
- statements in the program as a shorthand way to refer to the file. As long
- as the file is open, this number remains associated with the file. When
- the file is closed, the file number is freed for use with another file.
- (See Section 3.4.4 for information on how files are closed.) Your BASIC
- programs can open more than one file at a time.
-
- The FREEFILE function can help you find an unused file number. This
- function returns the next available number that can be associated with a
- file in an OPEN statement. For example, FREEFILE might return the value 3
- after the following OPEN statements:
-
- OPEN "Test1.Dat" FOR RANDOM AS #1
- OPEN "Test2.Dat" FOR RANDOM AS #2
- FileNum = FREEFILE
- OPEN "Test3.Dat" FOR RANDOM AS #FileNum
-
- The FREEFILE function is particularly useful when you create your own
- library procedures that open files. With FREEFILE, you don't have to pass
- information about the number of open files to these procedures.
-
- 3.4.3.2 File Names in BASIC
-
- File names in OPEN statements can be any string expression, composed of
- any combination of the following characters:
-
- ■ The letters a-z and A-Z
-
- ■ The numbers 0-9
-
- ■ The following special characters:
-
- ( ) { } @ # $ % ^ & ! - _ ' ~
-
- The string expression can also contain an optional drive specification, as
- well as a complete or partial path specification. This means your BASIC
- program can work with data files on another drive or in a directory other
- than the one where the program is running. For example, the following OPEN
- statements are all valid:
-
- OPEN "..\Grades.Qtr" FOR INPUT AS #1
-
- OPEN "a:\salaries\1987.man" FOR INPUT AS #2
-
- FileName$ = "TempFile"
- OPEN FileName$ FOR OUTPUT AS #3
-
- BaseName$ = "Invent"
- OPEN BaseName$ + ".DAT" FOR OUTPUT AS #4
-
- DOS also imposes its own restrictions on file names: you can use no more
- than eight characters for the base name (everything to the left of an
- optional period) and no more than three characters for the extension
- (everything to the right of an optional period). Long file names in BASIC
- programs are truncated in the following fashion:
-
- File Name in Program Resulting File Name in DOS
- ──────────────────────────────────────────────────────────────────────────
- Prog@Data@File PROG@DAT.A@F
- The BASIC name is more than 11 characters long,
- so BASIC takes the first 8 letters for the base
- name, inserts a period (.), and uses the next 3
- letters as the extension. Everything else is
- discarded.
-
- Mail#.Version1 MAIL#.VER
- The base name (Mail#) is shorter than eight
- characters, but the extension (Version1) is
- longer than three, so the extension is shortened
- to three characters.
-
- RELEASE_NOTES.BAK Gives the run-time error message Bad file name.
- The base name must be shorter than eight
- characters if you are going to include an
- explicit extension (.BAK in this case).
- ──────────────────────────────────────────────────────────────────────────
-
- DOS is not case sensitive, so lowercase letters in file names are
- converted to all uppercase (capital) letters. Therefore, you should not
- rely on the mixing of lowercase and uppercase to distinguish between
- files. For example, if you already had a file on the disk named
- INVESTOR.DAT, the following OPEN statement would overwrite that file,
- destroying any information already stored in it:
-
- OPEN "Investor.Dat" FOR OUTPUT AS #1
-
- 3.4.4 Closing a Data File
-
- Closing a data file has two important results: first, it writes any data
- currently in the file's buffer (a temporary holding area in memory) to the
- file; second, it frees the file number associated with that file for use
- by another OPEN statement.
-
- Use the CLOSE statement within a program to close a file. For example, if
- the file Price.Dat is opened with the statement
-
- OPEN "Price.Dat" FOR OUTPUT AS #1
-
- then the statement CLOSE #1 ends output to Price.Dat. If Price.Dat is
- opened with
-
- OPEN "Price.Dat" FOR OUTPUT AS #2
-
- then the appropriate statement for ending output is CLOSE #2. A CLOSE
- statement with no file-number arguments closes all open files.
-
- A data file is also closed when either of the following occurs:
-
- ■ The BASIC program performing I/O ends (program termination always closes
- all open data files).
-
- ■ The program performing I/O transfers control to another program with the
- RUN statement.
-
- 3.4.5 Using Sequential Files
-
- This section discusses how records are organized in sequential data files
- and then shows how to read data from, or write data to, an open sequential
- file.
-
- 3.4.5.1 Records in Sequential Files
-
- Sequential files are ASCII (text) files. This means you can use any word
- processor to view or modify a sequential file. Records are stored in
- sequential files as a single line of text, terminated by a carriage-return
- and line-feed (CR-LF) sequence. Each record is divided into fields, or
- repeated chunks of data that occur in the same order in every record.
- Figure 3.2 shows how three records might appear in a sequential file.
-
-
- ┌──────────────────────────────────────────────────────────────────┐
- │ Record 1 │
- │ ┌─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┐ │
- │ │"│M│c│G│u│i│r│e│"│,│"│M│a│n│a│g│e│r│"│,│5│ │
- │ └─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴───┘ │
- │ └────────┬────────┘ └────────┬────────┘ └┬┘ │
- │ Field 1 Field 2 Field 3 │
- │ │
- │ Record 2 │
- │ ┌─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┐ │
- │ │"│R│o│s│s│"│,│"│E│d│i│t│o│r│"│,│7│ │
- │ └─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┘ │
- │ └─────┬─────┘ └───────┬───────┘ └┬┘ │
- │ Field 1 Field 2 Field 3 │
- │ │
- │ Record 3 │
- │ ┌─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┐ │
- │ │"│S│h│o│s│t│a│k│o│v│i│c│h│"│,│"│W│r│i│t│e│r│"│,│1│2│ │
- │ └─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┘ │
- │ └─────────────┬─────────────┘ └───────┬───────┘ └─┬─┘ │
- │ Field 1 Field 2 Field 3 │
- └──────────────────────────────────────────────────────────────────┘
-
- Figure 3.2 Records in Sequential Files
-
- Note that each record in a sequential file can be a different length;
- moreover, fields can be different lengths in different records.
-
- The kind of variable in which a field is stored determines where that
- field begins and ends. (See Sections 3.4.5.2-3.4.5.6 for examples of
- reading and storing fields from records.) For example, if your program
- reads a field into a string variable, then any of the following can signal
- the end of that field:
-
- ■ Double quotes (") if the string begins with double quotes
-
- ■ Comma (,) if the string does not begin with double quotes
-
- ■ CR-LF if the field is at the end of the record
-
- On the other hand, if your program reads a field into a numeric variable,
- then any of the following can signal the end of that field:
-
- ■ Comma
-
- ■ One or more spaces
-
- ■ CR-LF
-
- 3.4.5.2 Putting Data in a New Sequential File
-
- You can add data to a new sequential file after first opening it to
- receive records with an OPEN filename FOR OUTPUT statement. Use the WRITE
- # statement to write records to the file.
-
- You can open sequential files for reading or for writing but not for both
- at the same time. If you are writing to a sequential file and want to read
- back the data you stored, you must first close the file, then reopen it
- for input.
-
- Example
-
- The following short program creates a sequential file named Price.Dat,
- then adds data entered at the keyboard to the file. The OPEN statement in
- this program both creates the file and readies it to receive records. The
- WRITE # then writes each record to the file. Note that the number used in
- the WRITE # statement is the same number given to the file name Price.Dat
- in the OPEN statement.
-
- ' Create a file named Price.Dat
- ' and open it to receive new data:
-
- OPEN "Price.Dat" FOR OUTPUT AS #1
-
- DO
- ' Continue putting new records in Price.Dat until the
- ' user presses ENTER without entering a company name:
- INPUT "Company (press <ENTER> to quit): ", Company$
-
- IF Company$ <> "" THEN
-
- ' Enter the other fields of the record:
- INPUT "Style: ", Style$
- INPUT "Size: ", Size$
- INPUT "Color: ", Clr$
- INPUT "Quantity: ", Qty
-
- ' Put the new record in the file
- ' with the WRITE # statement:
- WRITE #1, Company$, Style$, Size$, Clr$, Qty
- END IF
- LOOP UNTIL Company$ = ""
-
- ' Close Price.Dat (this ends output to the file):
- CLOSE #1
- END
-
- ──────────────────────────────────────────────────────────────────────────
- WARNING
- If, in the preceding example, you already had a file named Price.Dat on
- the disk, the OUTPUT mode given in the OPEN statement would erase the
- existing contents of Price.Dat before writing any new data to it. If you
- want to add new data to the end of an existing file without erasing what
- is already in it, use the APPEND mode of OPEN. See Section 3.4.5.4,
- "Adding Data to a Sequential File," for more information on this mode.
- ──────────────────────────────────────────────────────────────────────────
-
- 3.4.5.3 Reading Data from a Sequential File
-
- You can read data from a sequential file after first opening it with the
- statement OPEN filename FOR INPUT. Use the INPUT # statement to read
- records from the file one field at a time. (See Section 3.4.5.6, "Other
- Ways to Read Data from a Sequential File," for information on other
- file-input statements and functions you can use with a sequential file.)
-
- Example
-
- The following program opens the Price.Dat data file created in the
- previous example and reads the records from the file, displaying the
- complete record on the screen if the quantity for the item is less than
- the input amount.
-
- The INPUT #1 statement reads one record at a time from Price.Dat,
- assigning the fields in the record to the variables Company$, Style$,
- Size$, Clr$, and Qty. Since this is a sequential file, the records are
- read in order from the first one entered to the last one entered.
-
- The EOF (end-of-file) function tests whether the last record has been read
- by INPUT #. If the last record has been read, EOF returns the value -1
- (true), and the loop for getting data ends; if the last record has not
- been read, EOF returns the value 0 (false), and the next record is read
- from the file.
-
- OPEN "Price.Dat" FOR INPUT AS #1
-
- INPUT "Display all items below what level"; Reorder
-
- DO UNTIL EOF(1)
- INPUT #1, Company$, Style$, Size$, Clr$, Qty
- IF Qty < Reorder THEN
- PRINT Company$, Style$, Size$, Clr$, Qty
- END IF
- LOOP
- CLOSE #1
- END
-
- 3.4.5.4 Adding Data to a Sequential File
-
- As mentioned earlier, if you have a sequential file on disk and want to
- add more data to the end of it, you cannot simply open the file in output
- mode and start writing data. As soon as you open a sequential file in
- output mode, you destroy its current contents. You must use the append
- mode instead, as shown in the next example:
-
- OPEN "Price.Dat" FOR APPEND AS #1
-
- In fact, APPEND is always a safe alternative to OUTPUT, since the append
- mode creates a new file if one with the name specified doesn't already
- exist. For example, if a file named Price.Dat did not reside on disk, the
- example statement above would make a new file with that name.
-
- 3.4.5.5 Other Ways to Write Data to a Sequential File
-
- The preceding examples all use the WRITE # statement to write records to a
- sequential file. There is, however, another statement you can use to write
- sequential file records: PRINT #.
-
- The best way to show the difference between these two data-storage
- statements is to examine the contents of a file created with both. The
- following short fragment opens a file named Test.Dat then places the same
- record in it twice, once with WRITE # and once with PRINT #. After running
- this program you can examine the contents of Test.Dat with the DOS TYPE
- commands:
-
- OPEN "Test.Dat" FOR OUTPUT AS #1
- Nm$ = "Penn, Will"
- Dept$ = "User Education"
- Level = 4
- Age = 25
- WRITE #1, Nm$, Dept$, Level, Age
- PRINT #1, Nm$, Dept$, Level, Age
- CLOSE #1
-
- Output
-
- "Penn, Will","User Education",4,25
- Penn, Will User Education 4 25
-
- The record stored with WRITE # has commas that explicitly separate each
- field of the record, as well as quotes enclosing each string expression.
- On the other hand, PRINT # has written an image of the record to the file
- exactly as it would appear on screen with a simple PRINT statement. The
- commas in the PRINT # statement are interpreted as meaning "advance to the
- next print zone" (a new print zone occurs every 14 spaces, starting at the
- beginning of a line), and quotes are not placed around the string
- expressions.
-
- At this point, you may be wondering what difference these output
- statements make, except in the appearance of the data within the file. The
- answer lies in what happens when your program reads the data back from the
- file with an INPUT # statement. In the following example, the program
- reads the record stored with WRITE # and prints the values of its fields
- without any problem:
-
- OPEN "Test.Dat" FOR INPUT AS #1
-
- ' Input the first record,
- ' and display the contents of each field:
- INPUT #1, Nm$, Dept$, Level, Age
- PRINT Nm$, Dept$, Level, Age
-
- ' Input the second record,
- ' and display the contents of each field:
- INPUT #1, Nm$, Dept$, Level, Age
- PRINT Nm$, Dept$, Level, Age
-
- CLOSE #1
-
- Output
-
- Penn, Will User Education 4 25
-
- However, when the program tries to input the next record stored with PRINT
- #, it produces the error message Input past end of file. Without double
- quotes enclosing the first field, the INPUT # statement sees the comma
- between Penn and Will as a field delimiter, so it assigns only the last
- name Penn to the variable Nm$. INPUT # then reads the rest of the line
- into the variable Dept$. Since all of the record has now been read, there
- is nothing left to put in the variables level and age. The result is the
- error message Input past end of file.
-
- If you are storing records that have string expressions and you want to
- read these records later with the INPUT # statement, follow one of these
- two rules of thumb:
-
- 1. Use the WRITE # statement to store the records.
-
- 2. If you want to use the PRINT # statement, remember it does not put
- commas in the record to separate fields, nor does it put quotes around
- strings. You have to put these field separators in the PRINT #
- statement yourself.
-
- For example, you can avoid the problems shown in the preceding example by
- using PRINT # with quotation marks surrounding each field containing a
- string expression, as in the example below.
-
- Example
-
- ' 34 is ASCII value for double-quote character:
-
- Q$ = CHR$(34)
-
- ' The next four statements all write the record to the
- ' file with double quotes around each string field:
-
- PRINT #1, Q$ Nm$ Q$ Q$ Dept$ Q$ Level Age
- PRINT #1, Q$ Nm$ Q$;Q$ Dept$ Q$;Level;Age
- PRINT #1, Q$ Nm$ Q$,Q$ Dept$ Q$,Level,Age
- WRITE #1, Nm$, Dept$, Level, Age
-
- Output to File
-
- "Penn, Will""User Education" 4 25
- "Penn, Will""User Education" 4 25
- "Penn, Will" "User Education" 4 25
- "Penn, Will","User Education",4,25
-
- 3.4.5.6 Other Ways to Read Data from a Sequential File
-
- In the preceding sections, INPUT # is used to read a record (one line of
- data from a file), assigning different fields in the record to the
- variables listed after INPUT #. This section explores alternative ways to
- read data from sequential files, both as records (LINE INPUT #) and as
- unformatted sequences of bytes (INPUT$).
-
- The LINE INPUT # Statement
-
- With the LINE INPUT # statement, your program can read a line of text
- exactly as it appears in a file without interpreting commas or quotes as
- field delimiters. This is particularly useful in programs that work with
- ASCII text files.
-
- The LINE INPUT # statement reads an entire line from a sequential file (up
- to a carriage-return and line-feed sequence) into a single string
- variable.
-
- Examples
-
- The following short program reads each line from the file Chap1.Txt and
- then echoes that line to the screen:
-
- ' Open Chap1.Txt for sequential input:
- OPEN "Chap1.Txt" FOR INPUT AS #1
-
- ' Keep reading lines sequentially from the file until
- ' there are none left in the file:
-
- DO UNTIL EOF(1)
-
- ' Read a line from the file and store it
- ' in the variable LineBuffer$:
- LINE INPUT #1, LineBuffer$
-
- ' Print the line on the screen:
- PRINT LineBuffer$
- LOOP
-
- The preceding program is easily modified to a file-copying utility that
- prints each line read from the specified input file to another file,
- instead of to the screen:
-
- ' Input names of input and output files:
-
- INPUT "File to copy: ", FileName1$
- IF FileName1$ = "" THEN END
- INPUT "Name of new file: ", FileName2$
- IF FileName2$ = "" THEN END
-
- ' Open first file for sequential input:
- OPEN FileName1$ FOR INPUT AS #1
-
- ' Open second file for sequential output:
- OPEN FileName2$ FOR OUTPUT AS #2
-
- ' Keep reading lines sequentially from first file
- ' until there are none left in the file:
- DO UNTIL EOF(1)
-
- ' Read a line from first file and store it in the
- ' variable LineBuffer$:
- LINE INPUT #1, LineBuffer$
-
- ' Write LineBuffer$ to the second file:
- PRINT #2, LineBuffer$
-
- LOOP
-
- The INPUT$ Function
-
- Yet another way to read data from sequential files (and, in fact, from any
- file) is to use the INPUT$ function. Whereas INPUT # and LINE INPUT # read
- a line at a time from a sequential file, INPUT$ reads a specified number
- of characters from a file, as shown in the following examples:
-
- Statement Action
- ──────────────────────────────────────────────────────────────────────────
- X$ = INPUT$(100, #1) Reads 100 characters from file number 1 and
- assigns all of them to the string variable X$
-
- Test$ = INPUT$(1, #2) Reads one character from file number 2 and
- assigns it to the string variable Test$
-
- ──────────────────────────────────────────────────────────────────────────
-
- The INPUT$ function without a file number always reads input from standard
- input (usually the keyboard).
-
- The INPUT$ function does what is known as "binary input"; that is, it
- reads a file as an unformatted stream of characters. For example, it does
- not see a carriage-return and line-feed sequence as signaling the end of
- an input operation. Therefore, INPUT$ is the best choice when you want
- your program to read every single character from a file or when you want
- it to read a binary, or non-ASCII, file.
-
- Example
-
- The following program copies the named binary file to the screen, printing
- only alphanumeric and punctuation characters in the ASCII range 32 to 126,
- as well as tabs, carriage returns, and line feeds:
-
- ' 9 is ASCII value for horizontal tab, 10 is ASCII
- value
- ' for line feed, and 13 is ASCII value for carriage return:
- CONST LINEFEED = 10, CARRETURN = 13, TABCHAR = 9
-
- INPUT "Print which file: ", FileName$
- IF FileName$ = "" THEN END
-
- OPEN FileName$ FOR INPUT AS #1
-
- DO UNTIL EOF(1)
- Character$ = INPUT$(1, #1)
- CharVal = ASC(Character$)
- SELECT CASE CharVal
- CASE 32 TO 126
- PRINT Character$;
- CASE TABCHAR, CARRETURN
- PRINT Character$;
- CASE LINEFEED
- IF OldCharVal <> CARRETURN THEN PRINT Character$;
- CASE ELSE
- ' This is not one of the characters this program
- ' is interested in, so don't print anything.
- END SELECT
- OldCharVal = CharVal
- LOOP
-
- 3.4.6 Using Random-Access Files
-
- This section discusses how records are organized in random-access data
- files, then shows you how to read data from and write data to a file
- opened for random access.
-
- 3.4.6.1 Records in Random-Access Files
-
- Random-access records are stored quite differently from sequential
- records. Each random-access record is defined with a fixed length, as is
- each field within the record. These fixed lengths determine where a record
- or field begins and ends, as there are no commas separating fields, and no
- carriage-return and line-feed sequences between records. Figure 3.3 shows
- how three records might appear in a random-access file.
-
-
- Record 1 Record 2
- ┌──────────────────┴──────────────────┐┌─────────────────┴─────────────────
- ┌─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬
- │M│c│G│u│i│r│e│ │ │ │M│a│n│a│g│e│r│5│ │R│o│s│s│ │ │ │ │ │ │E│d│i│t│o│r│ │3│
- └─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴
- └─────────┬─────────┘└─────┬──────┘└─┬┘└────────┬─────────┘└─────┬──────┘└─
- Field 1 Field 2 Field 3 Field 1 Field 2 Fie
-
- Figure 3.3 Records in a Random-Access File
-
- If you are storing records containing numbers, using random-access files
- saves disk space when compared with using sequential files. This is
- because sequential files save numbers as a sequence of ASCII characters
- representing each digit, whereas random-access files save numbers in a
- compressed binary format.
-
- For example, the number 17,000 is represented in a sequential file using
- five bytes, one for each digit. However, if 17,000 is stored in an integer
- field of a random-access record, it takes only two bytes of disk space.
-
- In general, integers in random-access files take two bytes, long integers
- and single-precision numbers take four bytes, and double-precision numbers
- take eight bytes.
-
- 3.4.6.2 Adding Data to a Random-Access File
-
- To write a program that adds data to a random-access file, follow these
- steps:
-
- 1. Define the fields of each record.
-
- 2. Open the file in random-access mode and specify the length of each
- record.
-
- 3. Get input for a new record and store the record in the file.
-
- Each of these steps is now considerably easier than it was in BASICA, as
- you can see from the examples that follow.
-
- Defining Fields
-
- You can define your own record with a TYPE...END TYPE statement, which
- allows you to create a composite data type that mixes string and numeric
- elements. This is a big advantage over the earlier method of setting up
- records with a FIELD statement, which required that each field be defined
- as a string. By defining a record with TYPE...END TYPE, you eliminate the
- need to use the functions that convert numeric data to strings (MKtype$,
- MKSMBF$, and MKDMBF$) and strings to numeric data (CVtype, CVSMBF, and
- CVDMBF).
-
- The following fragments contrast these two methods of defining records:
-
- ■ Record defined with TYPE...END TYPE
-
- ' Define the RecordType structure:
- TYPE RecordType
- Name AS STRING * 30
- Age AS INTEGER
- Salary AS SINGLE
- END TYPE
-
- ' Declare the variable RecordVar
- ' as having the type RecordType:
- DIM RecordVar AS RecordType
-
- .
- .
- .
-
- ■ Record defined with FIELD
-
- ' Define the lengths of the fields
- ' in the temporary storage buffer:
- FIELD #1,30 AS Name$,2 AS Age$,4 AS Salary$
- .
- .
- .
-
- Opening the File and Specifying Record Length
-
- Since the length of a random-access record is fixed, you should let your
- program know how long you want each record to be; otherwise, record length
- defaults to 128 bytes.
-
- To specify record length, use the LEN = clause in the OPEN statement. The
- next two fragments, which continue the contrasting examples started above,
- show how to use LEN =.
-
- ■ Specifying the record length for a record that is defined with the
- statement TYPE...END TYPE
-
- .
- .
- .
- ' Open the random-access file and specify the length
- ' of one record as being equal to the length of the
- ' RecordVar variable:
- OPEN "EMPLOYEE.DAT" FOR RANDOM AS #1 LEN = LEN(RecordVar)
- .
- .
- .
-
- ■ Specifying record length for a record defined with FIELD
-
- .
- .
- .
- ' Open the random-access file and specify the length
- ' of a record:
- OPEN "EMPLOYEE.DAT" FOR RANDOM AS #1 LEN = 31
- .
- .
- .
-
- As you can see, when you use FIELD, you have to add the lengths of each
- field yourself (FirstName$ is 10 bytes, LastName$ is 15 bytes, Age$ is 2
- bytes, Salary$ is 4 bytes, so the record is 10+15+2+4 or 31 bytes long).
- With TYPE...END TYPE, you no longer have to do these calculations.
- Instead, just use the LEN function to calculate the length of the variable
- you have created to hold your records (RecordVar, in this case).
-
- Inputting Data and Storing the Record
-
- You can input data directly into the elements of a user-defined record
- without having to worry about left- or right-justification of input within
- a field with LSET or RSET. Compare the following two fragments, which
- continue the examples started above, to see the amount of code this
- approach saves you.
-
- ■ Entering data for a random-access record and storing the record using
- TYPE...END TYPE.
-
- .
- .
- .
-
- ' Enter the data:
- INPUT "First name"; RecordVar.FirstName
- INPUT "Last name"; RecordVar.LastName
- INPUT "Age"; RecordVar.Age
- INPUT "Salary"; RecordVar.Salary
- ' Store the record:
- PUT #1, , RecordVar
-
- .
- .
- .
-
- ■ Entering data for a random-access record and storing the record using
- FIELD
-
- .
- .
- .
-
- ' Enter the data:
- INPUT "First name"; FirstNm$
- INPUT "Last name"; LastNm$
- INPUT "Age"; AgeVal%
- INPUT "Salary"; SalaryVal!
-
- ' Left justify the data in the storage-buffer fields,
- ' using the MKI$ and MKS$ functions to convert numbers
- ' to file strings:
- LSET FirstName$ = FirstNm$
- LSET LastName$ = LastNm$
- LSET Age$ = MKI$(AgeVal%)
- LSET Salary$ = MKS$(SalaryVal!)
-
- ' Store the record:
- PUT #1
-
- .
- .
- .
-
- Putting It All Together
-
- The following program puts together all the steps outlined above──defining
- fields, specifying record length, inputting data, and storing the input
- data──to open a random-access data file named STOCK.DAT and add records to
- it:
-
- DEFINT A-Z
-
- ' Define structure of a single record in the random-access
- ' file. Each record will consist of four fixed-length fields
- ' ("PartNumber", "Description", "UnitPrice", "Quantity"):
- TYPE StockItem
- PartNumber AS STRING * 6
- Description AS STRING * 20
- UnitPrice AS SINGLE
- Quantity AS INTEGER
- END TYPE
-
- ' Declare a variable (StockRecord) using the above type:
- DIM StockRecord AS StockItem
-
- ' Open the random-access file, specifying the length of one
- ' record as the length of the StockRecord variable:
- OPEN "STOCK.DAT" FOR RANDOM AS #1 LEN=LEN(StockRecord)
-
- ' Use LOF() to calculate the number of records already in
- ' the file, so new records will be added after them:
- RecordNumber = LOF(1) \ LEN(StockRecord)
-
- ' Now, add new records:
- DO
-
- ' Input data for a stock record from keyboard and store
- ' in the different elements of the StockRecord variable:
- INPUT "Part Number? ", StockRecord.PartNumber
- INPUT "Description? ", StockRecord.Description
- INPUT "Unit Price ? ", StockRecord.UnitPrice
- INPUT "Quantity ? ", StockRecord.Quantity
-
- RecordNumber = RecordNumber + 1
-
- ' Write data in StockRecord to a new record in the file:
- PUT #1, RecordNumber, StockRecord
-
-
-
- ' Check to see if more data are to be read:
- INPUT "More (Y/N)? ", Resp$
- LOOP UNTIL UCASE$(Resp$) = "N"
-
- ' All done; close the file and end:
- CLOSE #1
- END
-
- If the STOCK.DAT file already existed, this program would add more records
- to the file without overwriting any that were already in the file. The
- following key statement makes this work:
-
- RecordNumber = LOF(1) \ LEN(StockRecord)
-
- Here is what happens:
-
- 1. The LOF(1) function calculates the total number of bytes in the file
- STOCK.DAT. If STOCK.DAT is new or has no records in it, LOF(1) returns
- the value 0.
-
- 2. The LEN(StockRecord) function calculates the number of bytes in one
- record. (StockRecord is defined as having the same structure as the
- user-defined type StockItem.)
-
- 3. Therefore, the number of records is equal to the total bytes in the
- file divided by the bytes in one record.
-
- This is another advantage of having a fixed-length record. Since each
- record is the same size, you can always use the above formula to calculate
- the number of records in the file. Obviously, this would not work with a
- sequential file, since sequential records can have different lengths.
-
- 3.4.6.7 Reading Data Sequentially
-
- Using the technique outlined in the preceding section for calculating the
- number of records in a random-access file, you can write a program that
- reads all the records in that file.
-
- Example
-
- The following program reads records sequentially (from the first record
- stored to the last) from the STOCK.DAT file created in the previous
- section:
-
- ' Define a record structure (type) for random-access
- ' file records:
- TYPE StockItem
- PartNumber AS STRING * 6
- Description AS STRING * 20
- UnitPrice AS SINGLE
- Quantity AS INTEGER
- END TYPE
-
- ' Declare a variable (StockRecord) using the above type:
- DIM StockRecord AS StockItem
-
- ' Open the random-access file:
- OPEN "STOCK.DAT" FOR RANDOM AS #1 LEN = LEN(StockRecord)
-
- ' Calculate number of records in the file:
- NumberOfRecords = LOF(1) \ LEN(StockRecord)
-
- ' Read the records and write the data to the screen:
- FOR RecordNumber = 1 TO NumberOfRecords
-
- ' Read the data from a new record in the file:
- GET #1, RecordNumber, StockRecord
-
-
-
- ' Print the data to the screen:
- PRINT "Part Number: ", StockRecord.PartNumber
- PRINT "Description: ", StockRecord.Description
- PRINT "Unit Price : ", StockRecord.UnitPrice
- PRINT "Quantity : ", StockRecord.Quantity
-
- NEXT
-
- ' All done; close the file and end:
- CLOSE #1
- END
-
- It is not necessary to close STOCK.DAT before reading from it. Opening a
- file for random access lets you write to or read from the file with a
- single OPEN statement.
-
- 3.4.6.8 Using Record Numbers to Retrieve Records
-
- You can read any record from a random-access file by specifying the
- record's number in a GET statement. You can write to any record in a
- random-access file by specifying the record's number in a PUT statement.
- This is one of the major advantages that random-access files have over
- sequential files, since sequential files do not permit direct access to a
- specific record.
-
- The sample-application program INDEX.BAS, listed in Section 3.6.2, shows
- a technique that quickly finds a particular record by searching an index
- of record numbers.
-
- Example
-
- The following fragment shows how to use GET with a record number:
-
- DEFINT A-Z ' Default variable type is integer.
- CONST FALSE = 0, TRUE = NOT FALSE
-
- TYPE StockItem
- PartNumber AS STRING * 6
- Description AS STRING * 20
- UnitPrice AS SINGLE
- Quantity AS INTEGER
- END TYPE
-
- DIM StockRecord AS StockItem
-
- OPEN "STOCK.DAT" FOR RANDOM AS #1 LEN=LEN(StockRecord)
-
- NumberOfRecords = LOF(1) \ LEN(StockRecord)
- GetMoreRecords = TRUE
-
- DO
- PRINT "Enter record number for part you want to see ";
- PRINT "(0 to end): ";
- INPUT "", RecordNumber
-
- IF RecordNumber > 0 AND RecordNumber < NumberOfRecords THEN
-
- ' Get the record whose number was entered and store
- ' it in StockRecord:
- GET #1, RecordNumber, StockRecord
-
- ' Display the record:
- .
- .
- .
- ELSEIF RecordNumber = 0 THEN
- GetMoreRecords = FALSE
- ELSE
- PRINT "Input value out of range."
- END IF
- LOOP WHILE GetMoreRecords
- END
-
- 3.4.7 Binary File I/O
-
- Binary access is a third way──in addition to random access and sequential
- access──to read or write a file's data. Use the following statement to
- open a file for binary I/O:
-
- OPEN file FOR BINARY AS #filenum
-
- Binary access is a way to get at the raw bytes of any file, not just an
- ASCII file. This makes it very useful for reading or modifying files saved
- in a non-ASCII format, such as Microsoft Word files or executable (.EXE)
- files.
-
- Files opened for binary access are treated as an unformatted sequence of
- bytes. Although you can read or write a record (a variable declared as
- having a user-defined type) to a file opened in the binary mode, the file
- itself does not have to be organized into fixed-length records. In fact,
- binary I/O does not have to deal with records at all, unless you consider
- each byte in a file as a separate record.
-
- 3.4.7.1 Comparing Binary Access and Random Access
-
- The binary-access mode is similar to the random-access mode in that you
- can both read from and write to a file after a single OPEN statement.
- (Binary thus differs from sequential access, where you must first close a
- file and then reopen it if you want to switch between reading and
- writing.) Also, like random access, binary access lets you move backwards
- and forwards within an open file. Binary access even supports the same
- statements used for reading and writing random-access files:
-
- {GET| PUT} [[#]]filenumber, [[position]], variable
-
- Here, variable can have any type, including a variable-length string or a
- user-defined type, and position points to the place in the file where the
- next GET or PUT operation will take place. (The position is relative to
- the beginning of the file; that is, the first byte in the file has
- position one, the second byte has position two, and so on.) If you leave
- off the position argument, successive GET and PUT operations move the file
- pointer sequentially through the file from the first byte to the last.
-
- The GET statement reads a number of bytes from the file equal to the
- length of variable. Similarly, the PUT statement writes a number of bytes
- to the file equal to the length of variable. For example, if variable has
- integer type, then GET reads two bytes into variable; if variable has
- single-precision type, GET reads four bytes. Therefore, if you don't
- specify a position argument in a GET or PUT statement, the file pointer is
- moved a distance equal to the length of variable.
-
- The GET statement and INPUT$ function are the only ways to read data from
- a file opened in binary mode. The PUT statement is the only way to write
- data to a file opened in binary mode.
-
- Binary access, unlike random access, enables you to move to any byte
- position in a file and then read or write any number of bytes you want. In
- contrast, random access can only move to a record boundary and read a
- fixed number of bytes (the length of a record) each time.
-
- 3.4.7.2 Positioning the File Pointer with SEEK
-
- If you want to move the file pointer to a certain place in a file without
- actually performing any I/O, use the SEEK statement. Its syntax is
-
- SEEK filenumber, position
-
- After a SEEK statement, the next read or write operation in the file
- opened with filenumber begins at the byte noted in position.
-
- The counterpart to the SEEK statement is the SEEK function, with this
- syntax:
-
- SEEK(filenumber)
-
- The SEEK function tells you the byte position where the very next read or
- write operation begins. (If you are using binary I/O to access a file, the
- LOC and SEEK functions give similar results, but LOC returns the position
- of the last byte read or written, while SEEK returns the position of the
- next byte to be read or written.)
-
- The SEEK statement and function also work on files opened for sequential
- or random access. With sequential access, both the statement and the
- function behave the same as they do with binary access; that is, the SEEK
- statement moves the file pointer to specific byte positions, and the SEEK
- function returns information about the next byte to read or write.
-
- However, if a file is opened for random access, the SEEK statement can
- move the file pointer only to the beginning of a record, not to a byte
- within a record. Also, when used with random-access files, the SEEK
- function returns the number of the next record rather than the position of
- the next byte.
-
- Example
-
- The following program opens a QuickBASIC Quick library, then reads and
- prints the names of BASIC procedures and other external symbols contained
- in the library. This program is in the file named QLBDUMP.BAS on the
- QuickBASIC distribution disks.
-
- ' This program prints the names of Quick library procedures.
- DECLARE SUB DumpSym (SymStart AS INTEGER, QHdrPos AS LONG)
-
- TYPE ExeHdr ' Part of DOS .EXE header
- other1 AS STRING * 8 ' Other header information
- CParHdr AS INTEGER ' Size of header in paragraphs
- other2 AS STRING * 10 ' Other header information
- IP AS INTEGER ' Initial IP value
- CS AS INTEGER ' Initial (relative) CS value
- END TYPE
-
- TYPE QBHdr ' QLB header
- QBHead AS STRING * 6 ' QB specific heading
- Magic AS INTEGER ' Magic word: identifies file as a Quick li
- SymStart AS INTEGER ' Offset from header to first code symbol
- DatStart AS INTEGER ' Offset from header to first data symbol
- END TYPE
-
- TYPE QbSym ' QuickLib symbol entry
- Flags AS INTEGER ' Symbol flags
- NameStart AS INTEGER ' Offset into name table
- other AS STRING * 4 ' Other header information
- END TYPE
-
- DIM EHdr AS ExeHdr, Qhdr AS QBHdr, QHdrPos AS LONG
-
- INPUT "Enter Quick library file name: ", FileName$
- FileName$ = UCASE$(FileName$)
- IF INSTR(FileName$,".QLB") = 0 THEN FileName$ = FileName$ + ".QLB"
- INPUT "Enter output file name or press ENTER for screen: ", OutFile$
- OutFile$ = UCASE$(OutFile$)
- IF OutFile$ = "" THEN OutFile$ = "CON"
- OPEN FileName$ FOR BINARY AS #1
- OPEN OutFile$ FOR OUTPUT AS #2
-
- GET #1, , EHdr ' Read the EXE format header.
- QHdrPos = (EHdr.CParHdr + EHdr.CS) * 16 + EHdr.IP + 1
-
- GET #1, QHdrPos, Qhdr ' Read the QuickLib format header.
- IF Qhdr.Magic <> &H6C75 THEN PRINT "Not a QB UserLibrary": END
-
- PRINT #2, "Code Symbols:": PRINT #2,
- DumpSym Qhdr.SymStart, QHdrPos ' dump code symbols
- PRINT #2,
- PRINT #2, "Data Symbols:": PRINT #2, ""
- DumpSym Qhdr.DatStart, QHdrPos ' dump data symbols
- PRINT #2,
-
- END
-
- SUB DumpSym (SymStart AS INTEGER, QHdrPos AS LONG)
- DIM QlbSym AS QbSym
- DIM NextSym AS LONG, CurrentSym AS LONG
-
- ' Calculate the location of the first symbol entry,
- ' then read that entry:
- NextSym = QHdrPos + Qhdr.SymStart
- GET #1, NextSym, QlbSym
-
- DO
- NextSym = SEEK(1) ' Save the location of the next symbol.
- CurrentSym = QHdrPos + QlbSym.NameStart
- SEEK #1, CurrentSym ' Use SEEK to move to the name
- ' for the current symbol entry.
- Prospect$ = INPUT$(40, 1) ' Read the longest legal string,
- ' plus one additional byte for
- ' the final null character (CHR$(0)).
-
- ' Extract the null-terminated name:
- SName$ = LEFT$(Prospect$, INSTR(Prospect$, CHR$(0)))
-
- ' Print only those names that do not begin with "__", "$", or "b$"
- ' as these names are usually considered reserved:
- T$ = LEFT$(SName$, 2)
- IF T$ <> "__" AND LEFT$(SName$, 1) <> "$" AND UCASE$(T$) <> "B$" THEN
- PRINT #2, " " + SName$
- END IF
-
- GET #1, NextSym, QlbSym ' Read a symbol entry.
- LOOP WHILE QlbSym.Flags ' Flags=0 (false) means end of table.
-
- END SUB
-
-
- 3.5 Working with Devices
-
- Microsoft BASIC supports device I/O. This means certain computer
- peripherals can be opened for I/O just like data files on disk. Input from
- or output to these devices can be done with the statements and functions
- listed in Table 9.4, "Statements and Functions Used for Data-File I/O,"
- with the exceptions noted in Section 3.5.1, "Differences between Device
- I/O and File I/O." Table 3.1 lists the devices supported by BASIC.
-
- Table 3.1 Devices Supported by BASIC for I/O
- Name Device I/O Mode Supported
- ──────────────────────────────────────────────────────────────────────────
- COM1: First serial port Input and output
-
- COM2: Second serial port Input and output
-
- CONS: Screen Output only
-
- KYBD: Keyboard Input only
-
- LPT1: First printer Output only
-
- LPT2: Second printer Output only
-
- LPT3: Third printer Output only
-
- SCRN: Screen Output only
-
- ──────────────────────────────────────────────────────────────────────────
-
- 3.5.1 Differences between Device I/O and File I/O
-
- Certain functions and statements used for file I/O are not allowed for
- device I/O, while other statements and functions behave differently. These
- are some of the differences:
-
- ■ The CONS:, SCRN:, and LPTn: devices cannot be opened in the input or
- append modes.
-
- ■ The KYBD: device cannot be opened in the output or append modes.
-
- ■ The EOF, LOC, and LOF functions cannot be used with the CONS:, KYBD:,
- LPTn:, or SCRN: devices.
-
- ■ The EOF, LOC, and LOF functions can be used with the COMn: serial
- device; however, the values these functions return have a different
- meaning than the values they return when used with data files. (See
- Section 3.5.2 for an explanation of what these functions do when used
- with COMn:.)
-
- Example
-
- The following program shows how the devices LPT1: or SCRN: can be opened
- for output using the same syntax as that for data files. This program
- reads all the lines from the file chosen by the user and then prints the
- lines on the screen or the printer according to the user's choice.
-
- CLS
- ' Input the name of the file to look at:
- INPUT "Name of file to display: ", FileNam$
-
- ' If no name is entered, end the program;
- ' otherwise, open the given file for reading (INPUT):
- IF FileNam$ = "" THEN END ELSE OPEN FileNam$ FOR INPUT AS #1
-
- ' Input choice for displaying file (Screen or Printer);
- ' continue prompting for input until either the "S" or "P"
- ' keys are pressed:
- DO
- ' Go to row 2, column 1 on the screen and print prompt:
- LOCATE 2, 1, 1
- PRINT "Send output to screen (S), or to printer (P): ";
-
- ' Print over anything after the prompt:
- PRINT SPACE$(2);
-
- ' Relocate cursor after the prompt, and make it visible:
- LOCATE 2, 47, 1
- Choice$ = UCASE$(INPUT$(1)) ' Get input.
- PRINT Choice$
- LOOP WHILE Choice$ <> "S" AND Choice$ <> "P"
-
- ' Depending on the key pressed, open either the printer
- ' or the screen for output:
- SELECT CASE Choice$
- CASE "P"
- OPEN "LPT1:" FOR OUTPUT AS #2
- PRINT "Printing file on printer."
- CASE "S"
- CLS
- OPEN "SCRN:" FOR OUTPUT AS #2
- END SELECT
-
- ' Set the width of the chosen output device to 80 columns:
- WIDTH #2, 80
-
- ' As long as there are lines in the file, read a line
- ' from the file and print it on the chosen device:
- DO UNTIL EOF(1)
- LINE INPUT #1, LineBuffer$
- PRINT #2, LineBuffer$
- LOOP
-
- CLOSE ' End input from the file and output to the device.
- END
-
- 3.5.2 Communications through the Serial Port
-
- The OPEN "COMn:" statement (where n can be 1 or, if you have two serial
- ports, 2) allows you to open your computer's serial port(s) for serial
- (bit-by-bit) communication with other computers or with peripheral devices
- such as modems or serial printers. The following are some of the
- parameters you can specify:
-
- ■ Rate of data transmission, measured in "baud" (bits per second)
-
- ■ Whether or not to detect transmission errors and how those errors will
- be detected
-
- ■ How many stop bits (1, 1.5, or 2) are to be used to signal the end of a
- transmitted byte
-
- ■ How many bits in each byte of data transmitted or received constitute
- actual data
-
- When the serial port is opened for communication, an input buffer is set
- aside to hold the bytes being read from other device. This is because, at
- high baud rates, characters arrive faster than they can be processed. The
- default size for this buffer is 512 bytes, and it can be modified with the
- LEN = numbytes option of the OPEN "COMn:" statement. The values returned
- by the EOF, LOC, and LOF functions when used with a communications device
- return information about the size of this buffer, as shown in the
- following list:
-
- Function Information Returned
- ──────────────────────────────────────────────────────────────────────────
- EOF Whether or not any characters are waiting to be
- read from the input buffer
-
- LOC The number of characters waiting in the input
- buffer
-
- LOF The amount of space remaining (in bytes) in the
- output buffer
-
- ──────────────────────────────────────────────────────────────────────────
-
- Since every character is potentially significant data, both INPUT # and
- LINE INPUT # have serious drawbacks for getting input from another device.
- This is because INPUT # stops reading data into a variable when it
- encounters a comma or new line (and, sometimes, a space or double quote),
- and LINE INPUT # stops reading data when it encounters a new line. This
- makes INPUT$ the best function to use for input from a communications
- device, since it reads all characters.
-
- The following line uses the LOC function to check the input buffer for the
- number of characters waiting there from the communications device opened
- as file #1; it then uses the INPUT$ function to read those characters,
- assigning them to a string variable named ModemInput$:
-
- ModemInput$ = INPUT$(LOC(1), #1)
-
-
- 3.6 Sample Applications
-
- The sample applications listed in this section include a screen-handling
- program that prints a calendar for any month in any year from 1899 to
- 2099, a file I/O program that builds and searches an index of record
- numbers from a random-access file, and a communications program that makes
- your PC behave like a terminal when connected to a modem.
-
- 3.6.1 Perpetual Calendar (CAL.BAS)
-
- After prompting the user to input a month from 1 to 12 and a year from
- 1899 to 2099, the following program prints the calendar for the given
- month and year. The IsLeapYear procedure makes appropriate adjustments to
- the calendar for months in a leap year.
-
- Statements and Functions Used
-
- This program demonstrates the following screen-handling functions and
- statements discussed in Sections 3.1-3.3:
-
- ■ INPUT
-
- ■ INPUT$
-
- ■ LOCATE
-
- ■ POS(0)
-
- ■ PRINT
-
- ■ PRINT USING
-
- ■ TAB
-
- Program Listing
-
- The perpetual calendar program CAL.BAS is listed below.
-
- DEFINT A-Z ' Default variable type is integer.
-
- ' Define a data type for the names of the months and the
- ' number of days in each:
- TYPE MonthType
- Number AS INTEGER ' Number of days in the month
- MName AS STRING * 9 ' Name of the month
- END TYPE
-
- ' Declare procedures used:
- DECLARE FUNCTION IsLeapYear% (N%)
- DECLARE FUNCTION GetInput% (Prompt$, Row%, LowVal%, HighVal%)
-
- DECLARE SUB PrintCalendar (Year%, Month%)
- DECLARE SUB ComputeMonth (Year%, Month%, StartDay%, TotalDays%)
-
- DIM MonthData(1 TO 12) AS MonthType
-
- ' Initialize month definitions from DATA statements below:
- FOR I = 1 TO 12
- READ MonthData(I).MName, MonthData(I).Number
- NEXT
-
- ' Main loop, repeat for as many months as desired:
- DO
- CLS
-
- ' Get year and month as input:
- Year = GetInput("Year (1899 to 2099): ", 1, 1899, 2099)
- Month = GetInput("Month (1 to 12): ", 2, 1, 12)
-
- ' Print the calendar:
- PrintCalendar Year, Month
- ' Another Date?
- LOCATE 13, 1 ' Locate in 13th row, 1st column.
- PRINT "New Date? "; ' Keep cursor on same line.
- LOCATE , , 1, 0, 13 ' Turn cursor on and make it one
- ' character high.
- Resp$ = INPUT$(1) ' Wait for a key press.
- PRINT Resp$ ' Print the key pressed.
-
- LOOP WHILE UCASE$(Resp$) = "Y"
- END
-
- ' Data for the months of a year:
- DATA January, 31, February, 28, March, 31
- DATA April, 30, May, 31, June, 30, July, 31, August, 31
- DATA September, 30, October, 31, November, 30, December, 31
-
- ' ====================== COMPUTEMONTH =====================
- ' Computes the first day and the total days in a month
- ' =========================================================
-
- SUB ComputeMonth (Year, Month, StartDay, TotalDays) STATIC
- SHARED MonthData() AS MonthType
-
- CONST LEAP = 366 MOD 7
- CONST NORMAL = 365 MOD 7
-
- ' Calculate total number of days (NumDays) since 1/1/1899:
-
- ' Start with whole years:
- NumDays = 0
- FOR I = 1899 TO Year - 1
- IF IsLeapYear(I) THEN ' If leap year,
- NumDays = NumDays + LEAP ' add 366 MOD 7.
- ELSE ' If normal year,
- NumDays = NumDays + NORMAL ' add 365 MOD 7.
- END IF
- NEXT
-
- ' Next, add in days from whole months:
- FOR I = 1 TO Month - 1
- NumDays = NumDays + MonthData(I).Number
- NEXT
-
- ' Set the number of days in the requested month:
- TotalDays = MonthData(Month).Number
-
- ' Compensate if requested year is a leap year:
- IF IsLeapYear(Year) THEN
-
- ' If after February, add one to total days:
- IF Month > 2 THEN
- NumDays = NumDays + 1
-
- ' If February, add one to the month's days:
- ELSEIF Month = 2 THEN
- TotalDays = TotalDays + 1
- END IF
- END IF
-
- ' 1/1/1899 was a Sunday, so calculating "NumDays MOD 7"
- ' gives the day of week (Sunday = 0, Monday = 1, Tuesday
- ' = 2, and so on) for the first day of the input month:
- StartDay = NumDays MOD 7
- END SUB
-
- ' ======================== GETINPUT =======================
- ' Prompts for input, then tests for a valid range
- ' =========================================================
-
- FUNCTION GetInput (Prompt$, Row, LowVal, HighVal) STATIC
-
- ' Locate prompt at specified row, turn cursor on and
- ' make it one character high:
- LOCATE Row, 1, 1, 0, 13
- PRINT Prompt$;
-
- ' Save column position:
- Column = POS(0)
-
- ' Input value until it's within range:
- DO
- LOCATE Row, Column ' Locate cursor at end of prompt.
- PRINT SPACE$(10) ' Erase anything already there.
- LOCATE Row, Column ' Relocate cursor at end of prompt.
- INPUT "", Value ' Input value with no prompt.
- LOOP WHILE (Value < LowVal OR Value > HighVal
-
- ' Return valid input as value of function:
- GetInput = Value
-
- END FUNCTION
-
- ' ====================== ISLEAPYEAR =======================
- ' Determines if a year is a leap year or not
- ' =========================================================
-
- FUNCTION IsLeapYear (N) STATIC
-
- ' If the year is evenly divisible by 4 and not divisible
- ' by 100, or if the year is evenly divisible by 400,
- ' then it's a leap year:
- IsLeapYear = (N MOD 4=0 AND N MOD 100<>0) OR (N MOD 400=0)
- END FUNCTION
-
- ' ===================== PRINTCALENDAR =====================
- ' Prints a formatted calendar given the year and month
- ' =========================================================
-
- SUB PrintCalendar (Year, Month) STATIC
- SHARED MonthData() AS MonthType
-
- ' Compute starting day (Su M Tu ...)
- ' and total days for the month:
- ComputeMonth Year, Month, StartDay, TotalDays
- CLS
- Header$ = RTRIM$(MonthData(Month).MName) + "," + STR$(Year)
-
- ' Calculate location for centering month and year:
- LeftMargin = (35 - LEN(Header$)) \ 2
-
- ' Print header:
- PRINT TAB(LeftMargin); Header$
- PRINT
- PRINT "Su M Tu W Th F Sa"
- PRINT
-
- ' Recalculate and print tab
- ' to the first day of the month (Su M Tu ...):
- LeftMargin = 5 * StartDay + 1
- PRINT TAB(LeftMargin);
-
- ' Print out the days of the month:
- FOR I = 1 TO TotalDays
- PRINT USING "##"; I;
-
- ' Advance to the next line
- ' when the cursor is past column 32:
- IF POS(0) > 32 THEN PRINT
- NEXT
-
- END SUB
-
- Output
-
- ┌───────────────────────────────────────────────────────────────────┐
- │ │
- │ June, 1988 │
- │ │
- │ Su M Tu W Th F Sa │
- │ │
- │ 1 2 3 4 │
- │ 5 6 7 8 9 10 11 │
- │ 12 13 14 15 16 17 18 │
- │ 19 20 21 22 23 24 25 │
- │ 26 27 28 29 30 │
- │ │
- │ │
- │ New Date? │
- │ │
- └───────────────────────────────────────────────────────────────────┘
-
- 3.6.2 Indexing a Random-Access File (INDEX.BAS)
-
- The following program uses an indexing technique to store and retrieve
- records in a random-access file. Each element of the Index array has two
- parts: a string field (PartNumber) and an integer field (RecordNumber).
- This array is sorted alphabetically on the PartNumber field, which allows
- the array to be rapidly searched for a specific part number using a binary
- search.
-
- The Index array functions much like the index to a book. When you want to
- find the pages in a book that deal with a particular topic, you look up an
- entry for that topic in the index. The entry then points to a page number
- in the book. Similarly, this program looks up a part number in the
- alphabetically sorted Index array. Once it finds the part number, the
- associated record number in the RecordNumber field points to the record
- containing all the information for that part.
-
- Statements and Functions Used
-
- This program demonstrates the following functions and statements used in
- accessing random-access files:
-
- ■ TYPE...END TYPE
-
- ■ OPEN...FOR RANDOM
-
- ■ GET #
-
- ■ PUT #
-
- ■ LOF
-
- Program Listing
-
- The random-access file indexing program INDEX.BAS is listed below.
-
- DEFINT A-Z
-
- ' Define the symbolic constants used globally in the program:
- CONST FALSE = 0, TRUE = NOT FALSE
-
- ' Define a record structure for random-file records:
- TYPE StockItem
- PartNumber AS STRING * 6
- Description AS STRING * 20
- UnitPrice AS SINGLE
- Quantity AS INTEGER
- END TYPE
-
- ' Define a record structure for each element of the index:
- TYPE IndexType
- RecordNumber AS INTEGER
- PartNumber AS STRING * 6
- END TYPE
-
- ' Declare procedures that will be called:
- DECLARE FUNCTION Filter$ (Prompt$)
- DECLARE FUNCTION FindRecord% (PartNumber$, RecordVar AS StockItem)
-
- DECLARE SUB AddRecord (RecordVar AS StockItem)
- DECLARE SUB InputRecord (RecordVar AS StockItem)
- DECLARE SUB PrintRecord (RecordVar AS StockItem)
- DECLARE SUB SortIndex ()
- DECLARE SUB ShowPartNumbers ()
- ' Define a buffer (using the StockItem type)
- ' and define and dimension the index array:
- DIM StockRecord AS StockItem, Index(1 TO 100) AS IndexType
-
- ' Open the random-access file:
- OPEN "STOCK.DAT" FOR RANDOM AS #1 LEN = LEN(StockRecord)
-
- ' Calculate number of records in the file:
- NumberOfRecords = LOF(1) \ LEN(StockRecord)
-
- ' If there are records, read them and build the index:
- IF NumberOfRecords <> 0 THEN
- FOR RecordNumber = 1 TO NumberOfRecords
-
- ' Read the data from a new record in the file:
- GET #1, RecordNumber, StockRecord
-
- ' Place part number and record number in index:
- Index(RecordNumber).RecordNumber = RecordNumber
- Index(RecordNumber).PartNumber = StockRecord.PartNumber
- NEXT
-
- SortIndex ' Sort index in part-number order.
- END IF
-
- DO ' Main-menu loop.
- CLS
- PRINT "(A)dd records."
- PRINT "(L)ook up records."
- PRINT "(Q)uit program."
- PRINT
- LOCATE , , 1
- PRINT "Type your choice (A, L, or Q) here: ";
-
- ' Loop until user presses, A, L, or Q:
- DO
- Choice$ = UCASE$(INPUT$(1))
- LOOP WHILE INSTR("ALQ", Choice$) = 0
-
- ' Branch according to choice:
- SELECT CASE Choice$
- CASE "A"
- AddRecord StockRecord
- CASE "L"
- IF NumberOfRecords = 0 THEN
- PRINT : PRINT "No records in file yet. ";
- PRINT "Press any key to continue.";
- Pause$ = INPUT$(1)
- ELSE
- InputRecord StockRecord
- END IF
- CASE "Q" ' End program.
- END SELECT
- LOOP UNTIL Choice$ = "Q"
-
- CLOSE #1 ' All done, close file and end.
- END
-
- ' ======================== ADDRECORD ======================
- ' Adds records to the file from input typed at the keyboard
- ' =========================================================
-
- SUB AddRecord (RecordVar AS StockItem) STATIC
- SHARED Index() AS IndexType, NumberOfRecords
- DO
- CLS
- INPUT "Part Number: ", RecordVar.PartNumber
- INPUT "Description: ", RecordVar.Description
-
- ' Call the Filter$ FUNCTION to input price & quantity:
- RecordVar.UnitPrice = VAL(Filter$("Unit Price : "))
- RecordVar.Quantity = VAL(Filter$("Quantity : "))
-
- NumberOfRecords = NumberOfRecords + 1
-
- PUT #1, NumberOfRecords, RecordVar
-
- Index(NumberOfRecords).RecordNumber = NumberOfRecords
- Index(NumberOfRecords).PartNumber = RecordVar.PartNumber
- PRINT : PRINT "Add another? ";
- OK$ = UCASE$(INPUT$(1))
- LOOP WHILE OK$ = "Y"
-
- SortIndex ' Sort index file again.
- END SUB
-
- ' ========================= FILTER ========================
- ' Filters all non-numeric characters from a string
- ' and returns the filtered string
- ' =========================================================
-
- FUNCTION Filter$ (Prompt$) STATIC
- ValTemp2$ = ""
- PRINT Prompt$; ' Print the prompt passed.
- INPUT "", ValTemp1$ ' Input a number as
- ' a string.
- StringLength = LEN(ValTemp1$) ' Get the string's length.
- FOR I% = 1 TO StringLength ' Go through the string,
- Char$ = MID$(ValTemp1$, I%, 1) ' one character at a time.
-
- ' Is the character a valid part of a number (i.e.,
- ' a digit or a decimal point)? If yes, add it to
- ' the end of a new string:
- IF INSTR(".0123456789", Char$) > 0 THEN
- ValTemp2$ = ValTemp2$ + Char$
-
- ' Otherwise, check to see if it's a lowercase "l",
- ' since typewriter users may enter a one that way:
- ELSEIF Char$ = "l" THEN
- ValTemp2$ = ValTemp2$ + "1" ' Change the "l" to a "1".
- END IF
- NEXT I%
-
- Filter$ = ValTemp2$ ' Return filtered string.
-
- END FUNCTION
-
- ' ======================= FINDRECORD ===================
- ' Uses a binary search to locate a record in the index
- ' ======================================================
-
- FUNCTION FindRecord% (Part$, RecordVar AS StockItem) STATIC
- SHARED Index() AS IndexType, NumberOfRecords
-
- ' Set top and bottom bounds of search:
- TopRecord = NumberOfRecords
- BottomRecord = 1
-
- ' Search until top of range is less than bottom:
- DO UNTIL (TopRecord < BottomRecord)
-
- ' Choose midpoint:
- Midpoint = (TopRecord + BottomRecord) \ 2
-
- ' Test to see if it's the one wanted (RTRIM$()
- ' trims trailing blanks from a fixed string):
- Test$ = RTRIM$(Index(Midpoint).PartNumber)
-
- ' If it is, exit loop:
- IF Test$ = Part$ THEN
- EXIT DO
-
- ' Otherwise, if what we're looking for is greater,
- ' move bottom up:
- ELSEIF Part$ > Test$ THEN
- BottomRecord = Midpoint + 1
-
- ' Otherwise, move the top down:
- ELSE
- TopRecord = Midpoint - 1
- END IF
- LOOP
-
- ' If part was found, input record from file using
- ' pointer in index and set FindRecord% to TRUE:
- IF Test$ = Part$ THEN
- GET #1, Index(Midpoint).RecordNumber, RecordVar
- FindRecord% = TRUE
-
- ' Otherwise, if part was not found, set FindRecord%
- ' to FALSE:
- ELSE
- FindRecord% = FALSE
- END IF
- END FUNCTION
-
- ' ======================= INPUTRECORD =====================
- ' First, INPUTRECORD calls SHOWPARTNUMBERS, which prints
- ' a menu of part numbers on the top of the screen. Next,
- ' INPUTRECORD prompts the user to enter a part number.
- ' Finally, it calls the FINDRECORD and PRINTRECORD
- ' procedures to find and print the given record.
- ' =========================================================
-
- SUB InputRecord (RecordVar AS StockItem) STATIC
- CLS
- ShowPartNumbers ' Call the ShowPartNumbers SUB.
-
- ' Print data from specified records
- ' on the bottom part of the screen:
- DO
- PRINT "Type a part number listed above ";
- INPUT "(or Q to quit) and press <ENTER>: ", Part$
- IF UCASE$(Part$) <> "Q" THEN
- IF FindRecord(Part$, RecordVar) THEN
- PrintRecord RecordVar
- ELSE
- PRINT "Part not found."
- END IF
- END IF
- PRINT STRING$(40, "_")
- LOOP WHILE UCASE$(Part$) <> "Q"
-
- VIEW PRINT ' Restore the text viewport to entire screen.
- END SUB
-
- ' ======================= PRINTRECORD =====================
- ' Prints a record on the screen
- ' =========================================================
-
- SUB PrintRecord (RecordVar AS StockItem) STATIC
- PRINT "Part Number: "; RecordVar.PartNumber
- PRINT "Description: "; RecordVar.Description
- PRINT USING "Unit Price :$$###.##"; RecordVar.UnitPrice
- PRINT "Quantity :"; RecordVar.Quantity
- END SUB
-
- ' ===================== SHOWPARTNUMBERS ===================
- ' Prints an index of all the part numbers in the upper part
- ' of the screen
- ' =========================================================
-
- SUB ShowPartNumbers STATIC
- SHARED Index() AS IndexType, NumberOfRecords
-
- CONST NUMCOLS = 8, COLWIDTH = 80 \ NUMCOLS
-
- ' At the top of the screen, print a menu indexing all
- ' the part numbers for records in the file. This menu is
- ' printed in columns of equal length (except possibly the
- ' last column, which may be shorter than the others):
- ColumnLength = NumberOfRecords
- DO WHILE ColumnLength MOD NUMCOLS
- ColumnLength = ColumnLength + 1
- LOOP
- ColumnLength = ColumnLength \ NUMCOLS
- Column = 1
- RecordNumber = 1
-
- DO UNTIL RecordNumber > NumberOfRecords
- FOR Row = 1 TO ColumnLength
- LOCATE Row, Column
- PRINT Index(RecordNumber).PartNumber
- RecordNumber = RecordNumber + 1
- IF RecordNumber > NumberOfRecords THEN EXIT FOR
- NEXT Row
- Column = Column + COLWIDTH
- LOOP
-
- LOCATE ColumnLength + 1, 1
- PRINT STRING$(80, "_") ' Print separator line.
-
- ' Scroll information about records below the part-number
- ' menu (this way, the part numbers are not erased):
- VIEW PRINT ColumnLength + 2 TO 24
- END SUB
-
- ' ========================= SORTINDEX =====================
- ' Sorts the index by part number
- ' =========================================================
-
- SUB SortIndex STATIC
-
-
- SHARED Index() AS IndexType, NumberOfRecords
-
- ' Set comparison offset to half the number of records
- ' in index:
- Offset = NumberOfRecords \ 2
-
- ' Loop until offset gets to zero:
- DO WHILE Offset > 0
- Limit = NumberOfRecords - Offset
- DO
-
- ' Assume no switches at this offset:
- Switch = FALSE
-
- ' Compare elements and switch ones out of order:
- FOR I = 1 TO Limit
- IF Index(I).PartNumber > Index(I + Offset).PartNumber THEN
- SWAP Index(I), Index(I + Offset)
- Switch = I
- END IF
- NEXT I
-
- ' Sort on next pass only to where
- ' last switch was made:
- Limit = Switch
- LOOP WHILE Switch
-
- ' No switches at last offset, try one half as big:
- Offset = Offset \ 2
- LOOP
- END SUB
-
- Output
-
- ┌────────────────────────────────────────────────────────────────────────┐
- │ │
- │ 0235 0417 0583 8721 │
- │ │
- │ ────────────────────────────────────────────────────────────────────── │
- │ Type a part number listed above <or Q to quit> and press <ENTER>: 0417 │
- │ Part Number: 0417 │
- │ Description: oil filter │
- │ Unit Price : $5.99 │
- │ Quantity : 12 │
- │ │
- │ ──────────────────────────────────────── │
- │ Type a part number listed above <or Q to quit> and press <ENTER>: 8721 │
- │ Part Number: 8721 │
- │ Description: chamois cloth │
- │ Unit Price : $8.99 │
- │ Quantity : 23 │
- │ │
- │ ──────────────────────────────────────── │
- │ Type a part number listed above <or Q to quit> and press <ENTER>: │
- │ │
- └────────────────────────────────────────────────────────────────────────┘
-
- 3.6.3 Terminal Emulator (TERMINAL.BAS)
-
- The following simple program turns your computer into a "dumb" terminal;
- that is, it makes your computer function solely as an I/O device in tandem
- with a modem. This program uses the OPEN "COM1:" statement and associated
- device I/O functions to do the following two things:
-
- 1. Send the characters you type to the modem
-
- 2. Print characters returned by the modem on the screen
-
- Note that typed characters displayed on the screen are first sent to the
- modem and then returned to your computer through the open communications
- channel. You can verify this if you have a modem with Receive Detect (RD)
- and Send Detect (SD) lights──they will flash in sequence as you type.
-
- To dial a number, you would have to enter the Attention Dial Touch-Tone
- (ATDT) or Attention Dial Pulse (ATDP) commands at the keyboard (assuming
- you have a Hayes(R)-compatible modem).
-
- Any other commands sent to the modem would also have to be entered at the
- keyboard.
-
- Statements and Functions Used
-
- This program demonstrates the following functions and statements used in
- communicating with a modem through your computer's serial port:
-
- ■ OPEN "COM1:"
-
- ■ EOF
-
- ■ INPUT$
-
- ■ LOC
-
- Program Listing
-
- DEFINT A-Z
-
- DECLARE SUB Filter (InString$)
-
- COLOR 7, 1 ' Set screen color.
- CLS
-
- Quit$ = CHR$(0) + CHR$(16) ' Value returned by INKEY$
- ' when ALT+q is pressed.
-
- ' Set up prompt on bottom line of screen and turn cursor on:
- LOCATE 24, 1, 1
- PRINT STRING$(80, "_");
- LOCATE 25, 1
- PRINT TAB(30); "Press ALT+q to quit";
-
- VIEW PRINT 1 TO 23 ' Print between lines 1 & 23.
-
- ' Open communications (1200 baud, no parity, 8-bit data,
- ' 1 stop bit, 256-byte input buffer):
- OPEN "COM1:1200,N,8,1" FOR RANDOM AS #1 LEN = 256
-
- DO ' Main communications loop.
-
- KeyInput$ = INKEY$ ' Check the keyboard.
-
- IF KeyInput$ = Quit$ THEN ' Exit the loop if the user
- EXIT DO ' pressed ALT+q.
-
- ELSEIF KeyInput$ <> "" THEN ' Otherwise, if the user has
- PRINT #1, KeyInput$; ' pressed a key, send the
- END IF ' character typed to modem.
-
- ' Check the modem. If characters are waiting (EOF(1) is
- ' true), get them and print them to the screen:
- IF NOT EOF(1) THEN
-
- ' LOC(1) gives the number of characters waiting:
- ModemInput$ = INPUT$(LOC(1), #1)
-
- Filter ModemInput$ ' Filter out line feeds and
- PRINT ModemInput$; ' backspaces, then print.
- END IF
- LOOP
-
- CLOSE ' End communications.
- CLS
- END
-
- '
- ' ========================= FILTER ========================
- ' Filters characters in an input string
- ' =========================================================
- '
- SUB Filter (InString$) STATIC
-
- ' Look for backspace characters and recode
- ' them to CHR$(29) (the LEFT cursor key):
- DO
- BackSpace = INSTR(InString$, CHR$(8))
- IF BackSpace THEN
- MID$(InString$, BackSpace) = CHR$(29)
- END IF
- LOOP WHILE BackSpace
-
- ' Look for line-feed characters and
- ' remove any found:
- DO
- LnFd = INSTR(InString$, CHR$(10))
- IF LnFd THEN
- InString$=LEFT$(InString$,LnFd-1)+MID$(InString$,LnFd+1)
- END IF
- LOOP WHILE LnFd
-
- END SUB
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- Chapter 4 String Processing
-
- This chapter shows you how to manipulate sequences of ASCII characters,
- known as strings. String manipulation is indispensable when you are
- processing text files, sorting data, or modifying string-data input.
-
- When you are finished with this chapter, you will know how to perform the
- following string-processing tasks:
-
- ■ Declare fixed-length strings
-
- ■ Compare strings and sort them alphabetically
-
- ■ Search for one string inside another
-
- ■ Get part of a string
-
- ■ Trim spaces from the beginning or end of a string
-
- ■ Generate a string by repeating a single character
-
- ■ Change uppercase letters in a string to lowercase and vice versa
-
- ■ Convert numeric expressions to string representations and vice versa
-
-
- 4.1 Strings Defined
-
- A string is a sequence of contiguous characters. Examples of characters
- are the letters of the alphabet (a-z and A-Z), punctuation symbols such as
- commas (,) or question marks (?), and other symbols from the fields of
- math and finance such as plus (+) or percent (%) signs.
-
- In this chapter, the term "string" can refer to any of the following:
-
- ■ A string constant
-
- ■ A string variable
-
- ■ A string expression
-
- String constants are declared in one of two ways:
-
- 1. By enclosing a sequence of characters between double quotes, as in the
- following PRINT statement:
-
- PRINT "Processing the file. Please wait."
-
- This is known as a "literal string constant."
-
- 2. By setting a name equal to a literal string in a CONST statement, as in
- the following:
-
- ' Define the string constant MESSAGE:
- CONST MESSAGE = "Drive door open."
-
- This is known as a "symbolic string constant."
-
- String variables can be declared in one of three ways:
-
- 1. By appending the string-type suffix ($) to the variable name:
-
- LINE INPUT "Enter your name: "; Buffer$
-
- 2. By using the DEFSTR statement:
-
- ' All variables beginning with the letter "B"
- ' are strings, unless they end with one of the
- ' numeric-type suffixes (%, &, !, or #):
- DEFSTR B
- .
- .
- .
- Buffer = "Your name here" ' Buffer is a string variable
-
- 3. By declaring the string name in an AS STRING statement:
-
- DIM Buffer1 AS STRING ' Buffer1 is a variable-
- ' length string.
- DIM Buffer2 AS STRING*10 ' Buffer2 is a fixed-length
- ' string 10 bytes long.
-
- A string expression is a combination of string variables, constants,
- and/or string functions.
-
- Of course, the character components of strings are not stored in your
- computer's memory in a form generally recognizable to humans. Instead,
- each character is translated to a number known as the ASCII code for that
- character. For example, capital "A" is stored as decimal 65 (or
- hexadecimal 41H), while lowercase "a" is stored as decimal 97 (or
- hexadecimal 61H). See Appendix D, "Keyboard Scan Codes and ASCII
- Character Codes," for a complete list of the ASCII codes for each
- character.
-
- You can also use the BASIC ASC function to determine the ASCII code for a
- character; for example, ASC("A") returns the value 65. The inverse of the
- ASC function is the CHR$ function. CHR$ takes an ASCII code as its
- argument and returns the character with that code; for example, the
- statement PRINT CHR$(64) displays the character @.
-
-
- 4.2 Variable- and Fixed-Length Strings
-
- In previous versions of BASIC, strings were always variable length. BASIC
- now supports both variable-length strings and fixed-length strings.
-
- 4.2.1 Variable-Length Strings
-
- Variable-length strings are "elastic"; that is, they expand and contract
- to store different numbers of characters (from none to a maximum of
- 32,767). For example, the length of the variable Temp$ in the following
- example varies according to the size of what is stored in Temp$:
-
- Temp$ = "1234567"
-
- ' LEN function returns length of string
- ' (number of characters it contains):
-
-
-
- PRINT LEN(Temp$)
-
- Temp$ = "1234"
- PRINT LEN(Temp$)
-
- Output
-
- 7
- 4
-
- 4.2.2 Fixed-Length Strings
-
- Fixed-length strings are commonly used as record elements in a TYPE...END
- TYPE user-defined data type. However, they can also be declared by
- themselves in COMMON, DIM, REDIM, SHARED, or STATIC statements, as in the
- following statement:
-
- DIM Buffer AS STRING * 10
-
- As their name implies, fixed-length strings have a constant length,
- regardless of the length of the string stored in them. This is shown by
- the output from the following example:
-
- DIM LastName AS STRING * 12
- DIM FirstName AS STRING * 10
-
- LastName = "Huntington-Ashley"
- FirstName = "Claire"
-
- PRINT "123456789012345678901234567890"
- PRINT FirstName; LastName
- PRINT LEN(FirstName)
- PRINT LEN(LastName)
-
- Output
-
- 123456789012345678901234567890
- Claire Huntington-A
- 10
- 12
-
- Note that the lengths of the string variables FirstName and LastName did
- not change, as demonstrated by the values returned by the LEN function (as
- well as the four spaces following the six-letter name, Claire).
-
- The output from the above example also illustrates how values assigned to
- fixed-length variables are left-justified and, if necessary, truncated on
- the right. It is not necessary to use the LSET function to left-justify
- values in fixed-length strings; this is done automatically. If you want to
- right-justify a string inside a fixed-length string, use RSET, as shown
- here:
-
- DIM NameBuffer AS STRING * 10
- RSET NameBuffer = "Claire"
- PRINT "1234567890"
- PRINT NameBuffer
-
- Output
-
- 1234567890
- Claire
-
-
- 4.3 Combining Strings
-
- Two strings can be combined with the plus (+) operator. The string
- following the plus operator is appended to the string preceding the plus
- operator, as shown in the next example:
-
- A$ = "first string"
- B$ = "second string"
- C$ = A$ + B$
- PRINT C$
-
- Output
-
- first stringsecond string
-
- The process of combining strings in this way is called "concatenation,"
- which means linking together.
-
- Note that in the previous example, the two strings are combined without
- any intervening spaces. If you want a space in the combined string, you
- could pad one of the strings A$ or B$, like this:
-
- B$ = " second string" ' Leading blank in B$
-
- Because values are left-justified in fixed-length strings, you may find
- extra spaces when you concatenate them, as in this example:
-
- TYPE NameType
- First AS STRING * 10
- Last AS STRING * 12
- END TYPE
-
- DIM NameRecord AS NameType
-
- ' The constant "Ed" is left-justified in the variable
- ' NameRecord.First, so there are eight trailing blanks:
- NameRecord.First = "Ed"
- NameRecord.Last = "Feldstein"
-
- ' Print a line of numbers for reference:
- PRINT "123456789012345678901234567890"
-
- WholeName$ = NameRecord.First + NameRecord.Last
- PRINT WholeName$
-
- Output
-
- 123456789012345678901234567890
- Ed Feldstein
-
- The LTRIM$ function returns a string with its leading spaces stripped
- away, while the RTRIM$ function returns a string with its trailing spaces
- stripped away. The original string is unaltered. (See Section 4.6,
- "Retrieving Parts of Strings," for more information on these functions.)
-
-
- 4.4 Comparing Strings
-
- Strings are compared with the following relational operators:
-
- Operator Meaning
- ──────────────────────────────────────────────────────────────────────────
- < > Not equal
-
- = Equal
-
- < Less than
-
- > Greater than
-
- <= Less than or equal to
-
- >= Greater than or equal to
- ──────────────────────────────────────────────────────────────────────────
-
- A single character is greater than another character if its ASCII value is
- greater. For example, the ASCII value of the letter "B" is greater than
- the ASCII value of the letter "A," so the expression "B" > "A"is true.
-
- When comparing two strings, BASIC looks at the ASCII values of
- corresponding characters. The first character where the two strings differ
- determines the alphabetical order of the strings. For instance, the
- strings "doorman" and "doormats" are the same up to the seventh character
- in each ("n" and "t"). Since the ASCII value of "n" is less than the ASCII
- value of "t", the expression "doorman" < "doormats"is true. Note that the
- ASCII values for letters follow alphabetical order from A to Z and from a
- to z, so you can use the relational operators listed above to alphabetize
- strings. Moreover, uppercase letters have smaller ASCII values than
- lowercase letters, so in a sorted list of strings, "ASCII" would come
- before "ascii".
-
- If there is no difference between corresponding characters of two strings
- and they are the same length, then the two strings are equal. If there is
- no difference between corresponding characters of two strings, but one of
- the strings is longer, then the longer string is greater than the shorter
- string. For example "abc" = "abc" and "aaaaaaa" > "aaa" are both true
- expressions.
-
- Leading and trailing blank spaces are significant in string comparisons.
- For example, the string " test" is less than the string "test", since a
- blank space (" ") is less than a"t"; on the other hand, the string "test "
- is greater than the string "test". Keep this in mind when comparing
- fixed-length and variable-length strings, since fixed-length strings may
- contain trailing spaces.
-
-
- 4.5 Searching for Strings
-
- One of the most common string-processing tasks is searching for a string
- inside another string. The INSTR(string1, string2) function tells you
- whether or not string2 is contained in string1 by returning the position
- of the first character in string1 (if any) where the match begins, as
- shown in this next example:
-
- String1$ = "A line of text with 37 letters in it."
- String2$ = "letters"
-
- PRINT " 1 2 3 4"
- PRINT "1234567890123456789012345678901234567890"
- PRINT String1$
- PRINT String2$
- PRINT INSTR(String1$, String2$)
-
- Output
-
- 1 2 3 4
- 1234567890123456789012345678901234567890
- A line of text with 37 letters in it.
- letters
- 24
-
- If no match is found (that is, string2 is not a substring of string1),
- INSTR returns the value 0.
-
- A variation of the syntax shown above, INSTR(position, string1, string2),
- allows you to specify where you want the search to start in string1. To
- illustrate, making the following modification to the preceding example
- changes the output:
-
- ' Start looking for a match at the 30th
- ' character of String1$:
- PRINT INSTR(30, String1$, String2$)
-
- Output
-
- 1 2 3 4
- 1234567890123456789012345678901234567890
- A line of text with 37 letters in it.
- letters
- 0
-
- In other words, the string "letters" does not appear after the 30th
- character of String1$.
-
- The INSTR(position, string1, string2) variation is useful for finding
- every occurrence of string2 in string1 instead of just the first
- occurrence, as shown in the next example:
-
- String1$ = "the dog jumped over the broken saxophone."
- String2$ = "the"
- PRINT String1$
-
- Start = 1
- NumMatches = 0
-
- DO
- Match = INSTR(Start, String1$, String2$)
- IF Match > 0 THEN
- PRINT TAB(Match); String2$
- Start = Match + 1
- NumMatches = NumMatches + 1
- END IF
- LOOP WHILE MATCH
-
- PRINT "Number of matches ="; NumMatches
-
- Output
-
- the dog jumped over the broken saxophone.
- the
- the
- Number of matches = 2
-
-
- 4.6 Retrieving Parts of Strings
-
- Section 4.3, "Combining Strings," shows how to put strings together
- (concatenate them) by using the + operator. Several functions are
- available in BASIC that take strings apart, returning pieces of a string,
- either from the left side, the right side, or the middle of a target
- string.
-
- 4.6.1 Retrieving Characters from the Left Side of a String
-
- The LEFT$ and RTRIM$ functions return characters from the left side of a
- string. The LEFT$(string, number) function returns the specified number of
- characters from the left side of the string. For example:
-
- Test$ = "Overtly"
-
- ' Print the leftmost 4 characters from Test$:
- PRINT LEFT$(Test$, 4)
-
- Output
-
- Over
-
- Note that LEFT$, like the other functions described in this chapter, does
- not change the original string Test$; it merely returns a different
- string, a copy of part of Test$.
-
- The RTRIM$ function returns the left part of a string after removing any
- blank spaces at the end. For example, contrast the output from the two
- PRINT statements in the following example:
-
- PRINT "a left-justified string "; "next"
- PRINT RTRIM$("a left-justified string "); "next"
-
- Output
-
- a left-justified string next
- a left-justified stringnext
-
- The RTRIM$ function is useful for comparing fixed-length and
- variable-length strings, as in the next example:
-
- DIM NameRecord AS STRING * 10
- NameRecord = "Ed"
-
- NameTest$ = "Ed"
-
- ' Use RTRIM$ to trim all the blank spaces from the right
- ' side of the fixed-length string NameRecord, then compare
- ' it with the variable-length string NameTest$:
- IF RTRIM$(NameRecord) = NameTest$ THEN
- PRINT "They're equal"
- ELSE
- PRINT "They're not equal"
- END IF
-
- Output
-
- They're equal
-
- 4.6.2 Retrieving Characters from the Right Side of a String
-
- The RIGHT$ and LTRIM$ functions return characters from the right side of a
- string. The RIGHT$(string, number) function returns the specified number
- of characters from the right side of the string. For example:
-
- Test$ = "1234567890"
-
- ' Print the rightmost 5 characters from Test$:
- PRINT RIGHT$(Test$,5)
-
- Output
-
- 67890
-
- The LTRIM$ function returns the right part of a string after removing any
- blank spaces at the beginning. For example, contrast the output from the
- next two PRINT statements:
-
- PRINT "first"; " a right-justified string"
- PRINT "first"; LTRIM$(" a right-justified string")
-
- Output
-
- first a right-justified string
- firsta right-justified string
-
- 4.6.3 Retrieving Characters from Anywhere in a String
-
- Use the MID$ function to retrieve any number of characters from any point
- in a string. The MID$(string, start, number) function returns the
- specified number of characters from the string, starting at the character
- with position start. For example, the statement
-
- MID$("**over the hill**", 12, 4)
-
- starts at the twelfth character (or h) of the string
-
- **over the hill**
-
- and returns that character plus the next three characters (hill).
-
- The following example shows how to use the MID$ function to step through a
- line of text character by character:
-
- .
- .
- .
- ' Get the number of characters in the string of text:
- Length = LEN(TextString$)
-
- FOR I = 1 TO Length
-
- ' Get the first character, then the second, third,
- ' and so forth, up to the end of the string:
- Char$ = MID$(TextString$, I, 1)
-
- ' Evaluate that character:
- .
- .
- .
- NEXT
-
-
- 4.7 Generating Strings
-
- The easiest way to create a string of one character repeated over and over
- is to use the intrinsic function STRING$. The STRING$(number, string)
- function produces a new string the specified number of characters long,
- each character of which is the first character of the string argument. For
- example, the statement
-
- Filler$ = STRING$(27, "*")
-
- generates a string of 27 asterisks. For characters that cannot be produced
- by typing, such as characters whose ASCII values are greater than 127, use
- the alternative form of this function, STRING$(number, code). This form
- creates a string the specified number of characters long, each character
- of which has the ASCII code specified by the code argument, as in the next
- example:
-
- ' Print a string of 10 "@" characters
- ' (64 is ASCII code for @):
- PRINT STRING$(10, 64)
-
- Output
-
- @@@@@@@@@@@
-
- The SPACE$(number) function generates a string consisting of the specified
- number of blank spaces.
-
-
- 4.8 Changing the Case of Letters
-
- You may want to convert uppercase (capital) letters in a string to
- lowercase or vice versa. This conversion would be useful in a
- case-insensitive search for a particular string pattern in a large file
- (in other words, help, HELP, or Help would all be considered the same).
- These functions would also be handy when you are not sure whether a user
- will input text in capital or lowercase letters.
-
- The UCASE$ and LCASE$ functions make the following conversions to a
- string:
-
- ■ UCASE$ returns a copy of the string passed to it, with all the lowercase
- letters converted to uppercase.
-
- ■ LCASE$ returns a copy of the string passed to it, with all the uppercase
- letters converted to lowercase.
-
- Example
-
- Sample$ = "* The ASCII Appendix: a table
- of useful codes *"
- PRINT Sample$
- PRINT UCASE$(Sample$)
- PRINT LCASE$(Sample$)
-
- Output
-
- * The ASCII Appendix: a table of useful codes *
- * THE ASCII APPENDIX: A TABLE OF USEFUL CODES *
- * the ascii appendix: a table of useful codes *
-
- Letters that are already uppercase, as well as characters that are not
- letters, remain unchanged by UCASE$; similarly, lowercase letters and
- characters that are not letters are unaffected by LCASE$.
-
-
- 4.9 Strings and Numbers
-
- BASIC does not allow a string to be assigned to a numeric variable, nor
- does it allow a numeric expression to be assigned to a string variable.
- For example, both of these statements result in an error message reading
- Type mismatch:
-
- TempBuffer$ = 45
- Counter% = "45"
-
- Instead, use the STR$ function to return the string representation of a
- number or the VAL function to return the numeric representation of a
- string:
-
- ' The following statements are both valid:
- TempBuffer$ = STR$(45)
- Counter% = VAL("45")
-
- Note that STR$ includes the leading blank space that BASIC prints for
- positive numbers, as this short example shows:
-
- FOR I = 0 TO 9
- PRINT STR$(I);
- NEXT
-
- Output
-
- 0 1 2 3 4 5 6 7 8 9
-
- If you want to eliminate this space, you can use the LTRIM$ function, as
- shown in the example below:
-
- FOR I = 0 TO 9
- PRINT LTRIM$(STR$(I));
- NEXT
-
- Output
-
- 0123456789
-
- Another way to format numeric output is with the PRINT USING statement
- (see Section 3.1, "Printing Text on the Screen").
-
-
- 4.10 Changing Strings
-
- The functions mentioned in each of the preceding sections all leave their
- string arguments unchanged. Changes are made to a copy of the argument.
-
- In contrast, the MID$ statement (unlike the MID$ function discussed in
- Section 4.6.3, "Retrieving Characters from Anywhere in a String") changes
- its argument by embedding another string in it. The embedded string
- replaces part or all of the original string, as shown in the following
- example:
-
- Temp$ = "In the sun."
- PRINT Temp$
-
- ' Replace the "I" with an "O":
- MID$(Temp$,1) = "O"
-
- ' Replace "sun." with "road":
- MID$(Temp$,8) = "road"
- PRINT Temp$
-
- Output
-
- In the sun.
- On the road
-
-
- 4.11 Sample Application: Converting a String to a Number (STRTONUM.BAS)
-
- The following program takes a number that is input as a string, filters
- any numeric characters (such as commas) out of the string, then converts
- the string to a number with the VAL function.
-
- Statements and Functions Used
-
- This program demonstrates the following string-handling functions
- discussed in this chapter:
-
- ■ INSTR
-
- ■ LEN
-
- ■ MID$
-
- ■ VAL
-
- Program Listing
-
- DECLARE FUNCTION Filter$ (Txt$, FilterString$)
-
- ' Input a line:
- LINE INPUT "Enter a number with commas: ", A$
-
- ' Look only for valid numeric characters (0123456789.-)
- ' in the input string:
- CleanNum$ = Filter$(A$, "0123456789.-")
-
- ' Convert the string to a number:
- PRINT "The number's value = " VAL(CleanNum$)
- END
-
- ' ========================== FILTER =======================
- ' Takes unwanted characters out of a string by
- ' comparing them with a filter string containing
- ' only acceptable numeric characters
- ' =========================================================
-
- FUNCTION Filter$ (Txt$, FilterString$) STATIC
- Temp$ = ""
- TxtLength = LEN(Txt$)
-
- FOR I = 1 TO TxtLength ' Isolate each character in
- C$ = MID$(Txt$, I, 1) ' the string.
-
- ' If the character is in the filter string, save it:
- IF INSTR(FilterString$, C$) <> 0 THEN
- Temp$ = Temp$ + C$
- END IF
- NEXT I
-
- Filter$ = Temp$
- END FUNCTION
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- Chapter 5 Graphics
-
- This chapter shows you how to use the graphics statements and functions of
- BASIC to create a wide variety of shapes, colors, and patterns on your
- screen. With graphics, you can add a visual dimension to almost any
- program, whether it's a game, an educational tool, a scientific
- application, or a financial package.
-
- When you have finished studying this chapter, you will know how to perform
- the following graphics tasks:
-
- ■ Use the physical-coordinate system of your personal computer's screen to
- locate individual pixels, turn those pixels on or off, and change their
- colors
-
- ■ Draw lines
-
- ■ Draw and fill simple shapes, such as circles, ovals, and boxes
-
- ■ Restrict the area of the screen showing graphics output by using
- viewports
-
- ■ Adjust the coordinates used to locate a pixel by redefining screen
- coordinates
-
- ■ Use color in graphics output
-
- ■ Create patterns and use them to fill enclosed figures
-
- ■ Copy images and reproduce them in another location on the screen
-
- ■ Animate graphics output
-
- Section 5.1 below contains important information on what you'll need to
- run the graphics examples shown in this chapter. Read it first.
-
-
- 5.1 What You Need for Graphics Programs
-
- To run the graphics examples shown in this chapter, your computer must
- have graphics capability, either built in or in the form of a graphics
- card such as the Color Graphics Adapter (CGA), Enhanced Graphics Adapter
- (EGA), or Video Graphics Array (VGA). You also need a video display
- (either monochrome or color) that supports pixel-based graphics.
-
- Also, please keep in mind that these programs all require that your screen
- be in one of the "screen modes" supporting graphics output. (The screen
- mode controls the clarity of graphics images, the number of colors
- available, and the part of the video memory to display.) To select a
- graphics output mode, use the following statement in your program before
- using any of the graphics statements or functions described in this
- chapter:
-
- SCREEN mode
-
- Here, mode can be either 1, 2, 3, 4, 7, 8, 9, 10, 11, 12, or 13, depending
- on the monitor/adapter combination installed on your computer.
-
- If you are not sure whether or not the users of your programs have
- hardware that supports graphics, you can use the following simple test:
-
- CONST FALSE = 0, TRUE = NOT FALSE
-
- ' Test to make sure user has hardware
- ' with color/graphics capability:
- ON ERROR GOTO Message ' Turn on error trapping.
- SCREEN 1 ' Try graphics mode one.
- ON ERROR GOTO 0 ' Turn off error trapping.
- IF NoGraphics THEN END ' End if no graphics hardware.
- .
- .
- .
- END
-
- ' Error-handling routine:
- Message:
- PRINT "This program requires graphics capability."
- NoGraphics = TRUE
- RESUME NEXT
-
- If the user has only a monochrome display with no graphics adapter, the
- SCREEN statement produces an error that in turn triggers a branch to the
- error-handling routine Message. (See Chapter 6, "Error and Event
- Trapping," for more information on error trapping.)
-
-
- 5.2 Pixels and Screen Coordinates
-
- Shapes and figures on a video display are composed of individual dots of
- light known as picture elements or "pixels" (or sometimes as "pels") for
- short. BASIC draws and paints on the screen by turning these pixels on or
- off and by changing their colors.
-
- A typical screen is composed of a grid of pixels. The exact number of
- pixels in this grid depends on the hardware you have installed and the
- screen mode you have selected in the SCREEN statement. The larger the
- number of pixels, the higher the clarity of graphics output. For example,
- a SCREEN 1 statement gives a resolution of 320 pixels horizontally by 200
- pixels vertically (320 x 200 pixels), while a SCREEN 2 statement gives a
- resolution of 640 x 200 pixels. The higher horizontal density in screen
- mode 2──640 pixels per row versus 320 pixels per row──gives images a
- sharper, less ragged appearance than they have in screen mode 1.
-
- Depending on the graphics capability of your system, you can use other
- screen modes that support even higher resolutions (as well as adjust other
- screen characteristics). Consult the QB Advisor for more information.
-
- When your screen is in one of the graphics modes, you can locate each
- pixel by means of pairs of coordinates. The first number in each
- coordinate pair tells the number of pixels from the left side of the
- screen, while the second number in each pair tells the number of pixels
- from the top of the screen. For example, in screen mode 2 the point in the
- extreme upper-left corner of the screen has coordinates (0, 0), the point
- in the center of the screen has coordinates (320, 100), and the point in
- the extreme lower-right corner of the screen has coordinates (639, 199),
- as shown in Figure 5.1.
-
- BASIC uses these screen coordinates to determine where to display graphics
- (for example, to locate the end points of a line or the center of a
- circle), as shown in Section 5.3, "Drawing Basic Shapes."
-
- Graphics coordinates differ from text-mode coordinates specified in a
- LOCATE statement. First, LOCATE is not as precise: graphics coordinates
- pinpoint individual pixels on the screen, whereas coordinates used by
- LOCATE are character positions. Second, text-mode coordinates are given in
- the form "row, column," as in the following:
-
- ' Move to the 13th row, 15th column,
- ' then print the message shown:
- LOCATE 13, 15
- PRINT "This should appear in the middle of the screen."
-
- This is the reverse of graphics coordinates, which are given in the form
- "column, row." A LOCATE statement has no effect on the positioning of
- graphics output on the screen.
-
-
- ┌──────────────────────────────────────────────────────────────────┐
- │ x positive │
- │ ──────────────────────────────────────────── │
- │ ┌──────────────────────────────────────────────────┐ │
- │ │ │°(0,0) °(320,0) (639,0)°│ │
- │ │ │ │ │
- │ │ │ │ │
- │ │ │ │ │
- │ │ │ │ │
- │ y │ │ °(320,100) │ │
- │ positive │ │ │ │
- │ │ │ │ │
- │ │ │ │ │
- │ │ │ │ │
- │ │ │ │ │
- │ │°(0,199) °(320,199) (639,199)°│ │
- │ └──────────────────────────────────────────────────┘ │
- └──────────────────────────────────────────────────────────────────┘
-
- Figure 5.1 Coordinates of Selected Pixels in Screen Mode 2
-
-
- 5.3 Drawing Basic Shapes: Points, Lines, Boxes, and Circles
-
- You can pass coordinate values to BASIC graphics statements to produce a
- variety of simple figures, as shown in Sections 5.3.1-5.3.2.
-
- 5.3.1 Plotting Points with PSET and PRESET
-
- The most fundamental level of control over graphics output is simply
- turning individual pixels on and off. You do this in BASIC with the PSET
- (for pixel set) and PRESET (for pixel reset) statements. The statement
- PSET (x, y) gives the pixel at location (x, y) the current foreground
- color. The PRESET (x, y) statement gives the pixel at location (x, y) the
- current background color.
-
- On monochrome monitors, the foreground color is the color that is used for
- printed text and is typically white, amber, or light green; the background
- color on monochrome monitors is typically black or dark green. You can
- choose another color for PSET and PRESET to use by adding an optional
- color argument. The syntax is then:
-
- PSET (x, y), color
-
- or
-
- PRESET (x, y), color
-
- See Section 5.7 for more information on choosing colors.
-
- Because PSET uses the current foreground color by default and PRESET uses
- the current background color by default, PRESET without a color argument
- erases a point drawn with PSET, as shown in the next example:
-
- SCREEN 2 ' 640 x 200 resolution
- PRINT "Press any key to end."
-
- DO
-
- ' Draw a horizontal line from the left to the right:
- FOR X = 0 TO 640
- PSET (X, 100)
- NEXT
-
- ' Erase the line from the right to the left:
- FOR X = 640 TO 0 STEP -1
- PRESET (X, 100)
- NEXT
-
- LOOP UNTIL INKEY$ <> ""
- END
-
- While it is possible to draw any figure using only PSET statements to
- manipulate individual pixels, the output tends to be rather slow, since
- most pictures consist of many pixels. BASIC has several statements that
- dramatically increase the speed with which simple figures──such as lines,
- boxes, and ellipses──are drawn, as shown in Sections 5.3.2 and
- 5.4.1-5.4.4.
-
- 5.3.2 Drawing Lines and Boxes with LINE
-
- When using PSET or PRESET, you specify only one coordinate pair since you
- are dealing with only one point on the screen. With LINE, you specify two
- pairs, one for each end of a line segment. The simplest form of the LINE
- statement is as follows:
-
- LINE (x1, y1) - (x2, y2)
-
- where (x1, y1) are the coordinates of one end of a line segment and (x2,
- y2) are the coordinates of the other. For example, the following statement
- draws a straight line from the pixel with coordinates (10, 10) to the
- pixel with coordinates (150, 200):
-
- SCREEN 1
- LINE (10, 10)-(150, 200)
-
- Note that BASIC does not care about the order of the coordinate pairs: a
- line from (x1, y1) to (x2, y2) is the same as a line from (x2, y2) to (x1,
- y1). This means you could also write the preceding statement as:
-
- SCREEN 1
- LINE (150, 200)-(10, 10)
-
- However, reversing the order of the coordinates could have an effect on
- graphics statements that follow, as shown in the next section.
-
- 5.3.2.1 Using the STEP Option
-
- Up to this point, screen coordinates have been presented as absolute
- values measuring the horizontal and vertical distances from the extreme
- upper-left corner of the screen, which has coordinates (0, 0). However, by
- using the STEP option in any of the following graphics statements, you can
- make the coordinates that follow STEP relative to the last point
- referenced on the screen:
-
- CIRCLE
- GET
- LINE
- PAINT
- PRESET
- PSET
- PUT
-
- If you picture images as being drawn on the screen by a tiny paintbrush
- exactly the size of one pixel, then the last point referenced is the
- location of this paintbrush, or "graphics cursor," when it finishes
- drawing an image. For example, the following statements leave the graphics
- cursor at the pixel with coordinates (100, 150):
-
- SCREEN 2
- LINE (10, 10)-(100, 150)
-
- If the next graphics statement in the program is
-
- PSET STEP(20, 20)
-
- then the point plotted by PSET is not in the upper-left quadrant of the
- screen. Instead, the STEP option has made the coordinates (20, 20)
- relative to the last point referenced, which has coordinates (100, 150).
- This makes the absolute coordinates of the point (100 + 20, 150 + 20) or
- (120, 170).
-
- In the last example, the last point referenced is determined by a
- preceding graphics statement. You can also establish a reference point
- within the same statement, as shown in the next example:
-
- ' Set 640 x 200 pixel resolution, and make the last
- ' point referenced the center of the screen:
- SCREEN 2
-
- ' Draw a line from the lower-left corner of the screen
- ' to the upper-left corner:
- LINE STEP(-310, 100) -STEP(0, -200)
-
- ' Draw the "stair steps" down from the upper-left corner
- ' to the right side of the screen:
- FOR I% = 1 TO 20
- LINE -STEP(30, 0) ' Draw the horizontal line.
- LINE -STEP(0, 5) ' Draw the vertical line.
- NEXT
-
- ' Draw the unconnected vertical line segments from the
- ' right side to the lower-left corner:
- FOR I% = 1 TO 20
- LINE STEP(-30, 0) -STEP(0, 5)
- NEXT
-
- DO: LOOP WHILE INKEY$ = "" ' Wait for a keystroke.
-
- Output
-
- ┌──────────────────────────────────────────────────────────────────┐
- │ ┌─┐ │
- │ │ └──────┐ │
- │ │ └──────┐ │
- │ │ └──────┐ │
- │ │ └──────┐ │
- │ │ └──────┐ │
- │ │ └──────┐ │
- │ │ └──────┐ │
- │ │ └──────┐ │
- │ │ │
- │ │ │ │
- │ │ │ │
- │ │ │ │
- │ │ │ │
- │ │ │ │
- │ │ │ │
- │ │ │ │
- │ │ │ │
- └──────────────────────────────────────────────────────────────────┘
-
- ──────────────────────────────────────────────────────────────────────────
- NOTE
- Note the empty DO loop at the end of the last program. If you are
- running a compiled, stand-alone BASIC program that produces graphics
- output, your program needs some mechanism like this at the end to hold
- the output on the screen. Otherwise, it vanishes from the screen before
- the user has time to notice it.
- ──────────────────────────────────────────────────────────────────────────
-
- 5.3.2.2 Drawing Boxes
-
- Using the forms of the LINE statement already presented, it is quite easy
- to write a short program that connects four straight lines to form a box,
- as shown here:
-
- SCREEN 1 ' 320 x 200 pixel resolution
-
- ' Draw a box measuring 120 pixels on a side:
- LINE (50, 50)-(170, 50)
- LINE -STEP(0, 120)
- LINE -STEP(-120, 0)
- LINE -STEP(0, -120)
-
- However, BASIC provides an even simpler way to draw a box, using a single
- LINE statement with the B (for box) option. The B option is shown in the
- next example, which produces the same output as the four LINE statements
- in the preceding program:
-
- SCREEN 1 ' 320 x 200 pixel resolution
-
- ' Draw a box with coordinates (50, 50) for the upper-left
- ' corner, and (170, 170) for the lower-right corner:
- LINE (50, 50)-(170, 170), , B
-
- When you add the B option, the LINE statement no longer connects the two
- points you specify with a straight line; instead, it draws a rectangle
- whose opposite corners (upper left and lower right) are at the locations
- specified.
-
- Two commas precede the B in the last example. The first comma functions
- here as a placeholder for an unused option (the color argument), which
- allows you to pick the color for a line or the sides of a box. (See
- Section 5.7 for more information on the use of color.)
-
- As before, it does not matter what order the coordinate pairs are given
- in, so the rectangle from the last example could also be drawn with this
- statement:
-
- LINE (170, 170)-(50, 50), , B
-
- Adding the F (for fill) option after B fills the interior of the box with
- the same color used to draw the sides. With a monochrome display, this is
- the same as the foreground color used for printed text. If your hardware
- has color capabilities, you can change this color with the optional color
- argument (see Section 5.7.1, "Selecting a Color for Graphics Output").
-
- The syntax introduced here for drawing a box is the general syntax used in
- BASIC to define a rectangular graphics region, and it also appears in the
- GET and VIEW statements:
-
- {GET| LINE| VIEW} (x1, y1) - (x2, y2),...
-
- Here, (x1, y1) and (x2, y2) are the coordinates of diagonally opposite
- corners of the rectangle (upper left and lower right). (See Section 5.5,
- "Defining a Graphics Viewport," for a discussion of VIEW, and Section
- 5.10, "Basic Animation Techniques," for information on GET and PUT.)
-
- 5.3.2.3 Drawing Dotted Lines
-
- The previous sections explain how to use LINE to draw solid lines and use
- them in rectangles; that is, no pixels are skipped. Using yet another
- option with LINE, you can draw dashed or dotted lines instead. This
- process is known as "line styling." The following is the syntax for
- drawing a single dashed line from point (x1, y1) to point (x2, y2) using
- the current foreground color:
-
- LINE (x1,y1) - (x2,y2), ,[[B]], style
-
- Here style is a 16-bit decimal or hexadecimal integer. The LINE statement
- uses the binary representation of the line-style argument to create dashes
- and blank spaces, with a 1 bit meaning "turn on the pixel," and a 0 bit
- meaning "leave the pixel off." For example, the hexadecimal integer &HCCCC
- is equal to the binary integer 1100110011001100, and when used as a style
- argument it draws a line alternating two pixels on, two pixels off.
-
- Example
-
- The following example shows different dashed lines produced using
- different values for style:
-
- SCREEN 2 ' 640 x 200 pixel resolution
-
- ' Style data:
- DATA &HCCCC, &HFF00, &HF0F0
- DATA &HF000, &H7777, &H8888
-
- Row% = 4
- Column% = 4
- XLeft% = 60
- XRight% = 600
- Y% = 28
-
- FOR I% = 1 TO 6
- READ Style%
- LOCATE Row%, Column%
- PRINT HEX$(Style%)
- LINE (XLeft%, Y%)-(XRight%,Y%), , , Style%
- Row% = Row% + 3
- Y% = Y% + 24
- NEXT
-
- Output
-
- ┌───────────────────────────────────────────────────────────────────┐
- │ │
- │ │
- │ CCCC····························································· │
- │ │
- │ FF00------------------------------------------------------------- │
- │ │
- │ F0F0 │
- │ │
- │ F000- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - │
- │ │
- │ 7777───────────────────────────────────────────────────────────── │
- │ │
- │ 8888............................................................. │
- │ │
- │ │
- │ │
- └───────────────────────────────────────────────────────────────────┘
-
-
- 5.4 Drawing Circles and Ellipses with CIRCLE
-
- The CIRCLE statement draws a variety of circular and elliptical, or oval,
- shapes. In addition, CIRCLE draws arcs (segments of circles), and
- pie-shaped wedges. In graphics mode you can produce just about any kind of
- curved line with some variation of CIRCLE.
-
- 5.4.1 Drawing Circles
-
- To draw a circle, you need to know only two things: the location of its
- center and the length of its radius (the distance from the center to any
- point on the circle). With this information and a reasonably steady hand
- (or better yet, a compass), you can produce an attractive circle.
-
- Similarly, BASIC needs only the location of a circle's center and the
- length of its radius to draw a circle. The simplest form of the CIRCLE
- syntax is
-
- CIRCLE[[STEP]](x, y), radius
-
- where x, y are the coordinates of the center, and radius is the radius of
- the circle. The next example draws a circle with center (200, 100) and
- radius 75:
-
- SCREEN 2
- CIRCLE (200, 100), 75
-
- You could rewrite the preceding example as follows, making the same circle
- but using the STEP option to make the coordinates relative to the center
- rather than to the upper-left corner:
-
- SCREEN 2 ' Uses center of screen (320,100) as the
- ' reference point for the CIRCLE statement:
- CIRCLE STEP(-120, 0), 75
-
- 5.4.2 Drawing Ellipses
-
- The CIRCLE statement automatically adjusts the "aspect ratio" to make sure
- that circles appear round and not flattened on your screen. However, you
- may need to adjust the aspect ratio to make circles come out right on your
- monitor, or you may want to change the aspect ratio to draw the oval
- figure known as an ellipse. In either case, use the syntax
-
- CIRCLE[[STEP]] (x,y), radius, , , , aspect
-
- where aspect is a positive real number. (See Section 5.4.5 for more
- information on the aspect ratio and how to calculate it for different
- screen modes.)
-
- The extra commas between radius and aspect are placeholders for other
- options that tell CIRCLE which color to use (if you have a color
- monitor/adapter and are using one of the screen modes that support color),
- or whether to draw an arc or wedge. (See Sections 5.4.3, "Drawing Arcs,"
- and 5.7.1, "Selecting a Color for Graphics Output," for more information
- on these options.)
-
- Since the aspect argument specifies the ratio of the vertical to
- horizontal dimensions, large values for aspect produce ellipses stretched
- out along the vertical axis, while small values for aspect produce
- ellipses stretched out along the horizontal axis. Since an ellipse has two
- radii──one horizontal x-radius and one vertical y-radius──BASIC uses the
- single radius argument in a CIRCLE statement as follows: if aspect is less
- than one, then radius is the x-radius; if aspect is greater than or equal
- to one, then radius is the y-radius.
-
- Example
-
- The following example and its output show how different aspect values
- affect whether the CIRCLE statement uses the radius argument as the
- x-radius or the y-radius of an ellipse:
-
- SCREEN 1
-
- ' This draws the ellipse on the left:
- CIRCLE (60, 100), 80, , , , 3
-
- ' This draws the ellipse on the right:
- CIRCLE (180, 100), 80, , , , 3/10
-
- Output
-
- ┌────────────────────────────────────┐
- │ │
- │ The output for this example │
- │ can be found on page 160 of │
- │ the printed manual. │
- │ │
- └────────────────────────────────────┘
-
- 5.4.3 Drawing Arcs
-
- An arc is a segment of a ellipse, in other words a short, curved line. To
- understand how the CIRCLE statement draws arcs, you need to know how BASIC
- measures angles.
-
- BASIC uses the radian as its unit of angle measure, not only in the CIRCLE
- statement, but also in the intrinsic trigonometric functions such as COS,
- SIN, or TAN. (The one exception to this use of radians is the DRAW
- statement, which expects angle measurements in degrees. See Section 5.9
- for more information about DRAW.)
-
- The radian is closely related to the radius of a circle. In fact, the word
- "radian" is derived from the word "radius." The circumference of a circle
- equals 2 * π * radius, where π is equal to approximately 3.14159265.
- Similarly, the number of radians in one complete angle of revolution (or
- 360) equals 2 * π, or a little more than 6.28. If you are more used to
- thinking of angles in terms of degrees, here are some common equivalences:
-
- Angle in Degrees Angle in Radians
- ──────────────────────────────────────────────────────────────────────────
- 360 2π (approximately 6.283)
-
- 180 π (approximately 3.142)
-
- 90 π/2 (approximately 1.571)
-
- 60 π/3 (approximately 1.047)
- ──────────────────────────────────────────────────────────────────────────
-
- If you picture a clock face on the screen, CIRCLE measures angles by
- starting at the "3:00" position and rotating counterclockwise, as shown in
- Figure 5.2:
-
-
- ┌────────────────────────────────────┐
- │ │
- │ Figure 5.2 can be found on │
- │ page 161 of the printed manual. │
- │ │
- └────────────────────────────────────┘
-
- Figure 5.2 How Angles Are Measured for CIRCLE
-
- The general formula for converting from degrees to radians is to multiply
- degrees by π/180.
-
- To draw an arc, give angle arguments defining the arc's limits:
-
- CIRCLE[[STEP]] (x, y), radius,[[color]], start, end [[, aspect]]
-
- Example
-
- The CIRCLE statements in the next example draw seven arcs, with the
- innermost arc starting at the "3:00" position (0 radians) and the
- outermost arc starting at the "6:00" position (3π/2 radians), as you can
- see from the output:
-
- SCREEN 2
- CLS
-
- CONST PI = 3.141592653589# ' Double-precision constant
-
- StartAngle = 0
- FOR Radius% = 100 TO 220 STEP 20
- EndAngle = StartAngle + (PI / 2.01)
- CIRCLE (320, 100), Radius%, , StartAngle, EndAngle
- StartAngle = StartAngle + (PI / 4)
- NEXT Radius%
-
- Output
-
- ┌────────────────────────────────────┐
- │ │
- │ The output for this example │
- │ can be found on page 162 of │
- │ the printed manual. │
- │ │
- └────────────────────────────────────┘
-
- 5.4.4 Drawing Pie Shapes
-
- By making either of CIRCLE's start or end arguments negative, you can
- connect the arc at its beginning or ending point with the center of the
- circle. By making both arguments negative, you can draw shapes ranging
- from a wedge that resembles a slice of pie to the pie itself with the
- piece missing.
-
- Example
-
- This example draws a pie shape with a piece missing:
-
- SCREEN 2
-
- CONST RADIUS = 150, PI = 3.141592653589#
-
- StartAngle = 2.5
- EndAngle = PI
-
- ' Draw the wedge:
- CIRCLE (320, 100), RADIUS, , -StartAngle, -EndAngle
-
- ' Swap the values for the start and end angles:
- SWAP StartAngle, EndAngle
-
- ' Move the center 10 pixels down and 70 pixels to the
- ' right, then draw the "pie" with the wedge missing:
- CIRCLE STEP(70, 10), RADIUS, , -StartAngle, -EndAngle
-
- Output
-
- ┌────────────────────────────────────┐
- │ │
- │ The output for this example │
- │ can be found on page 163 of │
- │ the printed manual. │
- │ │
- └────────────────────────────────────┘
-
- 5.4.5 Drawing Shapes to Proportion with the Aspect Ratio
-
- As discussed in Section 5.4.2, "Drawing Ellipses," BASIC's CIRCLE
- statement automatically corrects the aspect ratio, which determines how
- figures are scaled on the screen. However, with other graphics statements
- you need to scale horizontal and vertical dimensions yourself to make
- shapes appear with correct proportions. For example, although the
- following statement draws a rectangle that measures 100 pixels on all
- sides, it does not look like a square:
-
- SCREEN 1
- LINE (0, 0)-(100, 100), , B
-
- In fact, this is not an optical illusion; the rectangle really is taller
- than it is wide. This is because in screen mode 1 there is more space
- between pixels vertically than horizontally. To draw a perfect square, you
- have to change the aspect ratio.
-
- The aspect ratio is defined as follows: in a given screen mode consider
- two lines, one vertical and one horizontal, that appear to have the same
- length. The aspect ratio is the number of pixels in the vertical line
- divided by the number of pixels in the horizontal line. This ratio depends
- on two factors:
-
- 1. Because of the way pixels are spaced on most screens, a horizontal row
- has more pixels than a vertical column of the exact same physical
- length in all screen modes except modes 11 and 12.
-
- 2. The standard personal computer's video-display screen is wider than it
- is high. Typically, the ratio of screen width to screen height is 4:3.
-
- To see how these two factors interact to produce the aspect ratio,
- consider a screen after a SCREEN 1 statement, which gives a resolution of
- 320 x 200 pixels. If you draw a rectangle from the top of the screen to
- the bottom, and from the left side of the screen three-fourths of the way
- across, you have a square, as shown in Figure 5.3.
-
-
- ┌────────────────────────────────────────────────────────────────┐
- │ ┌──────────────────────────────────────────────────────┐ │
- │ │ ┌───────────────────────────────────┬─ - - - - - - │ │
- │ │ │ │ │ │
- │ │ │ │ │ │ │
- │ │ │ │ │ │ │
- │ │ │ │ │ │ │
- │ │ │ ────────── 240 pixels───────────│ 200 pixels │ │
- │ │ │ │ │ │ │
- │ │ │ │ │ │ │
- │ │ │ │ │ │ │
- │ │ │ │ │ │ │
- │ │ │ │ │ │ │
- │ │ │ │ │ │
- │ │ └───────────────────────────────────┴─ - - - - - - - │ │
- │ │ ──────────────────320 pixels───────────────────────│ │
- │ └──────────────────────────────────────────────────────┘ │
- │ │
- └────────────────────────────────────────────────────────────────┘
- Figure 5.3 The Aspect Ratio In Screen Mode 1
-
- As you can see from the diagram, this square has a height of 200 pixels
- and a width of 240 pixels. The ratio of the square's height to its width
- (200 / 240, or when simplified, 5 / 6) is the aspect ratio for this screen
- resolution. In other words, to draw a square in 320 x 200 resolution, make
- its height in pixels equal to 5 / 6 times its width in pixels, as shown in
- the next example:
-
- SCREEN 1 ' 320 x 200 pixel resolution
-
- ' The height of this box is 100 pixels, and the width is
- ' 120 pixels, which makes the ratio of the height to the
- ' width equal to 100/120, or 5/6. The result is a square:
- LINE (50, 50) -STEP(120, 100), , B
-
- The formula for calculating the aspect ratio for a given screen mode is
-
- (4 / 3) * (ypixels / xpixels)
-
- where xpixelsby ypixels is the current screen resolution. In screen mode
- 1, this formula shows the aspect ratio to be (4 / 3) * (200 / 320), or 5 /
- 6; in screen mode 2, the aspect ratio is (4 / 3) * (200 / 640), or 5 / 12.
-
- If you have a video display with a ratio of width to height that is not
- equal to 4:3, use the more general form of the formula for computing the
- aspect ratio:
-
- (screenwidth / screenheight) * (ypixels / xpixels)
-
- The CIRCLE statement can be made to draw an ellipse by varying the value
- of the aspect argument, as shown above in Section 5.4.2.
-
-
- 5.5 Defining a Graphics Viewport
-
- The graphics examples presented so far have all used the entire
- video-display screen as their drawing board, with absolute coordinate
- distances measured from the extreme upper-left corner of the screen.
-
- However, using the VIEW statement you can also define a kind of miniature
- screen (known as a "graphics viewport") inside the boundaries of the
- physical screen. Once it is defined, all graphics operations take place
- within this viewport. Any graphics output outside the viewport boundaries
- is "clipped"; that is, any attempt to plot a point outside the viewport is
- ignored. There are two main advantages to using a viewport:
-
- 1. A viewport makes it easy to change the size and position of the screen
- area where graphics appear.
-
- 2. Using CLS 1, you can clear the screen inside a viewport without
- disturbing the screen outside the viewport.
-
- ──────────────────────────────────────────────────────────────────────────
- NOTE
- Refer to Section 3.1.6 to learn how to create a "text viewport" for
- output printed on the screen.
- ──────────────────────────────────────────────────────────────────────────
-
- The general syntax for VIEW (note that the STEP option is not allowed with
- VIEW) is
-
- VIEW[[[[SCREEN]] (x1, y1) - (x2, y2)[[,[[color]], [[border]]]]]]
-
- where (x1, y1) and (x2, y2) define the corners of the viewport, using the
- standard BASIC syntax for rectangles (see Section 5.3.2.2, "Drawing
- Boxes"). The optional color and border arguments allow you to choose a
- color for the interior and edges, respectively, of the viewport rectangle.
- See Section 5.7 below for more information on setting and changing
- colors.
-
- The VIEW statement without arguments makes the entire screen the viewport.
- Without the SCREEN option, the VIEW statement makes all pixel coordinates
- relative to the viewport, rather than the full screen. In other words,
- after the statement
-
- VIEW (50, 60)-(150, 175)
-
- the pixel plotted with
-
- PSET (10, 10)
-
- is visible, since it is 10 pixels below and 10 pixels to the right of the
- upper-left corner of the viewport. Note that this makes the pixel's
- absolute screen coordinates (50 + 10, 60 + 10) or (60, 70).
-
- In contrast, the VIEW statement with the SCREEN option keeps all
- coordinates absolute; that is, coordinates measure distances from the side
- of the screen, not from the sides of the viewport. Therefore, after the
- statement
-
- VIEW SCREEN (50, 60)-(150, 175)
-
- the pixel plotted with
-
- PSET (10, 10)
-
- is not visible, since it is 10 pixels below and 10 pixels to the right of
- the upper-left corner of the screen──outside the viewport.
-
- Examples
-
- The output from the next two examples should further clarify the
- distinction between VIEW and VIEW SCREEN:
-
- SCREEN 2
-
- VIEW (100, 50)-(450, 150), , 1
-
- ' This circle's center point has absolute coordinates
- ' (100 + 100, 50 + 50), or (200, 100):
- CIRCLE (100, 50), 50
-
- Output using VIEW
-
- ┌────────────────────────────────────┐
- │ │
- │ The output for this example │
- │ can be found on page 167 of │
- │ the printed manual. │
- │ │
- └────────────────────────────────────┘
-
- SCREEN 2
-
- ' This circle's center point has absolute coordinates
- ' (100, 50), so only part of the circle appears
- ' within the view port:
- VIEW SCREEN (100, 50)-(450, 150), , 1
- CIRCLE (100, 50), 50
-
- Output using VIEW SCREEN
-
- ┌────────────────────────────────────┐
- │ │
- │ The output for this example │
- │ can be found on page 167 of │
- │ the printed manual. │
- │ │
- └────────────────────────────────────┘
-
- Note that graphics output located outside the current viewport is clipped
- by the viewport's edges and does not appear on the screen.
-
-
- 5.6 Redefining Viewport Coordinates with WINDOW
-
- This section shows you how to use the WINDOW statement and your own
- coordinate system to redefine pixel coordinates.
-
- In Sections 5.2-5.5, the coordinates used to locate pixels on the screen
- represent actual physical distances from the upper-left corner of the
- screen (or the upper-left corner of the current viewport, if it has been
- defined with a VIEW statement). These are known as "physical coordinates."
- The "origin," or reference point, for physical coordinates is always the
- upper-left corner of the screen or viewport, which has coordinates (0, 0).
-
- As you move down the screen and to the right, x values (horizontal
- coordinates) and y values (vertical coordinates) get bigger, as shown in
- the upper diagram of Figure 5.4. While this scheme is standard for video
- displays, it may seem counterintuitive if you have used other coordinate
- systems to draw graphs. For example, on the Cartesian grid used in
- mathematics, y values get bigger toward the top of a graph and smaller
- toward the bottom.
-
- With BASIC's WINDOW statement, you can change the way pixels are addressed
- to use any coordinate system you choose, thus freeing you from the
- limitations of using physical coordinates.
-
- The general syntax for WINDOW is
-
- WINDOW [[[[SCREEN]] (x1, y1) - (x2, y2)]]
-
- where y1, y2, x1, and x2 are real numbers specifying the top, bottom,
- left, and right sides of the window, respectively. These numbers are known
- as "view coordinates." For example, the following statement remaps your
- screen so that it is bounded on the top and bottom by the lines y = 10 and
- y = -15 and on the left and right by the lines x = -25 and x = 5 :
-
- WINDOW (-25, -15)-(5, 10)
-
- After a WINDOW statement, y values get bigger toward the top of the
- screen. In contrast, after a WINDOW SCREEN statement, y values get bigger
- toward the bottom of the screen. The bottom half of Figure 5.4 shows the
- effects of both a WINDOW statement and a WINDOW SCREEN statement on a line
- drawn in screen mode 2. Note also how both of these statements change the
- coordinates of the screen corners. A WINDOW statement with no arguments
- restores the regular physical-coordinate system.
-
- Example
-
-
- ┌──────────────────────────────────────────────────────────────────────────
- │ Increasing X
- │ ─────────────────────────────
- │ ┌────────────────────────────┐
- │ │ │°(0,0) (639,0)°│
- │ │ │ │
- │ Increasing │ │ │
- │ Y │ │ │
- │ │ │ │
- │ │ │ │
- │ │ │°(0,199) (639,199)°│
- │ └────────────────────────────┘
- │ ^
- │ / \
- │ / \
- │ WINDOW (-25, -15) - (5, 10) WINDOW SCREEN (-25, -15) - (5, 10)
- │ LINE (-15, -10 - (-5, -5) LINE (-15, -10) - (-5, -5)
- │ / \
- │ / \
- │ / \
- │ Increasing X
- │ ─────────────────────────
- │ ┌─────────────────────┐ ┌────────────────────────┐
- │ │°(-25,10) (5,10)°│ ││°(-25,-15) (5,-15)° │
- │ ││ │ ││ °(-15,-10) │
- │ ││ (0,0)° │ ││ \ │
- │ Increasing││ │ Increasing││ °(-5,-5) │
- │ Y ││ (-5,-5)° │ Y ││ │
- │ ││(-15,-10) / │ ││ ° │
- │ ││ ° │ ││ (0,0) │
- │ ││°(-25,-15) (5,-15)°│ ││°(-25,10) (5,10)°│
- │ └─────────────────────┘ └────────────────────────┘
- │ ──────────────────────
- │ Increasing X
- └──────────────────────────────────────────────────────────────────────────
-
- Figure 5.4 WINDOW Contrasted with WINDOW SCREEN
-
- The following example uses both VIEW and WINDOW to simplify writing a
- program to graph the sine-wave function for angle values from 0 radians to
- p radians (or 0° to 180°). This program is in the file named SINEWAVE.BAS
- on the QuickBASIC distribution disks.
-
- SCREEN 2
-
- ' Viewport sized to proper scale for graph:
- VIEW (20, 2)-(620, 172), , 1
- CONST PI = 3.141592653589#
-
- ' Make window large enough to graph sine wave from
- ' 0 radians to pi radians:
- WINDOW (0, -1.1)-(PI, 1.1)
- Style% = &HFF00 ' Use to make dashed line.
- VIEW PRINT 23 TO 24 ' Scroll printed output in rows 23, 24.
- DO
- PRINT TAB(20);
- INPUT "Number of cycles (0 to end): ", Cycles
- CLS
- LINE (PI, 0)-(0, 0), , , Style% ' Draw the x axis.
- IF Cycles > 0 THEN
-
- ' Start at (0,0) and plot the graph:
- FOR X = 0 TO PI STEP .01
- Y = SIN(Cycles * X) ' Calculate the y coordinate.
- LINE -(X, Y) ' Draw a line to new point.
- NEXT X
- END IF
- LOOP WHILE Cycles > 0
-
- Output
-
- ┌────────────────────────────────────┐
- │ │
- │ The output for this example │
- │ can be found on page 170 of │
- │ the printed manual. │
- │ │
- └────────────────────────────────────┘
-
- 5.6.1 The Order of Coordinate Pairs
-
- As with the other BASIC graphics statements that define rectangular areas
- (GET, LINE, and VIEW), the order of coordinate pairs in a WINDOW statement
- is unimportant. The first pair of statements below has the same effect as
- the second pair of statements:
-
- VIEW (100, 20)-(300, 120)
- WINDOW (-4, -3)-(0, 0)
-
- VIEW (300, 120)-(100, 20)
- WINDOW (0, 0)-(-4, -3)
-
- 5.6.2 Keeping Track of View and Physical Coordinates
-
- The PMAP and POINT functions are useful for keeping track of physical and
- view coordinates. POINT(number) tells you the current location of the
- graphics cursor by returning either the physical or view coordinates
- (depending on the value for number) of the last point referenced in a
- graphics statement. PMAP allows you to translate physical coordinates to
- view coordinates and vice versa. The physical-coordinate values returned
- by PMAP are always relative to the current viewport.
-
- Examples
-
- The following example shows the different values that are returned by
- POINT (number) for number values of 0, 1, 2, or 3:
-
- SCREEN 2
- ' Define the view-coordinate window:
- WINDOW (-10, -30)-(-5, -10)
- ' Draw a line from the point with view coordinates (-9,-28)
- ' to the point with view coordinates (-6,-24):
- LINE (-9, -28)-(-6, -24)
-
- PRINT "Physical x-coordinate of the last point = " POINT(0)
- PRINT "Physical y-coordinate of the last point = " POINT(1)
- PRINT
- PRINT "View x-coordinate of the last point = " POINT(2)
- PRINT "View y-coordinate of the last point = " POINT(3)
-
- END
-
- Output
-
- Physical x-coordinate of the last point = 511
- Physical y-coordinate of the last point = 139
-
- View x-coordinate of the last point = -6
- View y-coordinate of the last point = -24
-
- Given the WINDOW statement in the preceding example, the next four PMAP
- statements would print the output that follows:
-
- ' Map the view x-coordinate -6 to physical x and print:
- PhysX% = PMAP(-6, 0)
- PRINT PhysX%
-
- ' Map the view y-coordinate -24 to physical y and print:
- PhysY% = PMAP(-24, 1)
- PRINT PhysY%
-
- ' Map physical x back to view x and print:
- ViewX% = PMAP(PhysX%, 2)
- PRINT ViewX%
-
- ' Map physical y back to view y and print:
- ViewY% = PMAP(PhysY%, 3)
- PRINT ViewY%
-
- Output
-
- 511
- 139
- -6
- -24
-
-
- 5.7 Using Colors
-
- If you have a Color Graphics Adapter (CGA), you can choose between the
- following two graphics modes only:
-
- 1. Screen mode 2 has 640 x 200 high resolution, with only one foreground
- and one background color. This is known as "monochrome," since all
- graphics output has the same color.
-
- 2. Screen mode 1 has 320 x 200 medium resolution with 4 foreground colors
- and 16 background colors.
-
- There is thus a tradeoff between color and clarity in the two screen modes
- supported by most color-graphics display adapter hardware. Depending on
- the graphics capability of your system, you may not have to sacrifice
- clarity to get a full range of color. However, this section focuses on
- screen modes 1 and 2.
-
- 5.7.1 Selecting a Color for Graphics Output
-
- The following list shows where to put the color argument in the graphics
- statements discussed in previous sections of this chapter. This list also
- shows other options (such as BF with the LINE statement or border with the
- VIEW statement) that can have a different colors. (Please note that these
- do not give the complete syntax for some of these statements. This summary
- is intended to show how to use the color option in those statements that
- accept it.)
-
- PSET (x, y), color
- PRESET (x, y), color
- LINE (x1, y1) - (x2, y2), color [[, B[[F]]]]
- CIRCLE (x, y), radius, color
- VIEW (x1, y1) - (x2, y2), color, border
-
- In screen mode 1, the color argument is a numeric expression with the
- value 0, 1, 2, or 3. Each of these values, known as an "attribute,"
- represents a different color, as demonstrated by the following program:
-
- ' Draw an "invisible" line (same color as background):
- LINE (10, 10)-(310, 10), 0
-
- ' Draw a light blue (cyan) line:
- LINE (10, 30)-(310, 30), 1
-
- ' Draw a purple (magenta) line:
- LINE (10, 50)-(310, 50), 2
-
- ' Draw a white line:
- LINE (10, 70)-(310, 70), 3
- END
-
- As noted in the comments for the preceding example, a color value of 0
- produces no visible output, since it is always equal to the current
- background color. At first glance, this may not seem like such a useful
- color value, but in fact it is useful for erasing a figure without having
- to clear the entire screen or viewport, as shown in the next example:
-
- SCREEN 1
-
- CIRCLE (100, 100), 80, 2, , , 3 ' Draw an ellipse.
- Pause$ = INPUT$(1) ' Wait for a key press.
- CIRCLE (100, 100), 80, 0, , , 3 ' Erase the ellipse.
-
- 5.7.2 Changing the Foreground or Background Color
-
- Section 5.7.1 above describes how to use 4 different foreground colors
- for graphics output. You have a wider variety of colors in screen mode 1
- for the screen's background: 16 in all.
-
- In addition, you can change the foreground color by using a different
- "palette." In screen mode 1, there are two palettes, or groups of four
- colors. Each palette assigns a different color to the same attribute; so,
- for instance, in palette 1 (the default) the color associated with
- attribute 2 is magenta, while in palette 0 the color associated with
- attribute 2 is red. If you have a CGA, these colors are predetermined for
- each palette; that is, the color assigned to number 2 in palette 1 is
- always magenta, while the color assigned to number 2 in palette 0 is
- always red.
-
- If you have an Enhanced Graphics Adapter (EGA) or Video Graphics Adapter
- (VGA), you can use the PALETTE statement to choose the color displayed by
- any attribute. For example, by changing arguments in a PALETTE statement,
- you could make the color displayed by attribute 1 green one time and brown
- the next. (See Section 5.7.3, "Changing Colors with PALETTE and PALETTE
- USING," in this manual for more information on reassigning colors.)
-
- In screen mode 1, the COLOR statement allows you to control both the
- background color and the palette for the foreground colors. Here is the
- syntax for COLOR in screen mode 1:
-
- COLOR[[background]] [[, palette]]
-
- The background argument is a numeric expression from 0 to 15, and palette
- is a numeric expression equal to either 0 or 1.
-
- Table 5.1 shows the colors produced with the 4 different foreground
- numbers in each of the two palettes, while Table 5.2 shows the colors
- produced with the 16 different background numbers.
-
- Table 5.1 Color Palettes in Screen Mode 1
- Foreground Color Number Color in Palette 0 Color in Palette 1
- ──────────────────────────────────────────────────────────────────────────
- 0 Current background Current background color
- color
-
- 1 Green Cyan (bluish green)
-
- 2 Red Magenta (light purple)
-
- 3 Brown White (light grey on some
- monitors)
- ──────────────────────────────────────────────────────────────────────────
-
- Table 5.2 Background Colors in Screen Mode 1
- ╓┌─┌────────────────────────┌────────────────────────────────────────────────╖
- Background Color Number Color
- ──────────────────────────────────────────────────────────────────────────
- 0 Black
-
- 1 Blue
-
- Background Color Number Color
- ──────────────────────────────────────────────────────────────────────────
- 2 Green
-
- 3 Cyan
-
- 4 Red
-
- 5 Magenta
-
- 6 Brown (dark yellow on some monitors)
-
- 7 White (light grey on some monitors)
-
- 8 Dark grey (black on some monitors)
-
- 9 Light blue
-
- 10 Light green
-
- Background Color Number Color
- ──────────────────────────────────────────────────────────────────────────
- 11 Light cyan
-
- 12 Light red
-
- 13 Light magenta
-
- 14 Light yellow (may have greenish tinge on some
- monitors)
-
- 15 Bright white or very light grey
- ──────────────────────────────────────────────────────────────────────────
-
-
- Example
-
- The following program shows all combinations of the two color palettes
- with the 16 different background screen colors. This program is in the
- file named COLORS.BAS on the QuickBASIC distribution disks.
-
- SCREEN 1
-
- Esc$ = CHR$(27)
- ' Draw three boxes and paint the interior
- ' of each box with a different color:
- FOR ColorVal = 1 TO 3
- LINE (X, Y) -STEP(60, 50), ColorVal, BF
- X = X + 61
- Y = Y + 51
- NEXT ColorVal
-
- LOCATE 21, 1
- PRINT "Press ESC to end."
- PRINT "Press any other key to continue."
-
- ' Restrict additional printed output to the 23rd line:
- VIEW PRINT 23 TO 23
- DO
- PaletteVal = 1
- DO
-
- ' PaletteVal is either 1 or 0:
- PaletteVal = 1 - PaletteVal
-
- ' Set the background color and choose the palette:
- COLOR BackGroundVal, PaletteVal
- PRINT "Background ="; BackGroundVal;
- PRINT "Palette ="; PaletteVal;
-
- Pause$ = INPUT$(1) ' Wait for a keystroke.
- PRINT
-
- ' Exit the loop if both palettes have been shown,
- ' or if the user pressed the ESC key:
- LOOP UNTIL PaletteVal = 1 OR Pause$ = Esc$
-
- BackGroundVal = BackGroundVal + 1
-
- ' Exit this loop if all 16 background colors have
- ' been shown, or if the user pressed the ESC key:
- LOOP UNTIL BackGroundVal > 15 OR Pause$ = Esc$
-
- SCREEN 0 ' Restore text mode and
- WIDTH 80 ' 80-column screen width.
-
- 5.7.3 Changing Colors with PALETTE and PALETTE USING
-
- The preceding section showed how you can change the color displayed by an
- attribute simply by specifying a different palette in the COLOR statement.
- However, this restricts you to two fixed color palettes, with just 4
- colors in each. Furthermore, each attribute can stand for only one of two
- possible colors; for example, attribute 1 can signify only green or cyan.
-
- With an EGA or VGA, your choices are potentially much broader. (If you
- don't have an EGA or VGA, you may want to skip this section.) For
- instance, depending on the amount of video memory available to your
- computer, with a VGA you can choose from a palette with as many as 256K
- (that's right, over 256,000) colors and assign those colors to 256
- different attributes. Even an EGA allows you to display up to 16 different
- colors from a palette of 64 colors.
-
- In contrast to the COLOR statement, the PALETTE and PALETTE USING
- statements give you a lot more flexibility in manipulating the available
- color palette. Using these statements, you can assign any color from the
- palette to any attribute. For example, after the following statement, the
- output of all graphics statements using attribute 4 appears in light
- magenta (color 13):
-
- PALETTE 4, 13
-
- This color change is instantaneous and affects not only subsequent
- graphics statements but any output already on the screen. In other words,
- you can draw and paint your screen, then switch the palette to achieve an
- immediate change of color, as shown by the following example:
-
- SCREEN 8
- LINE (50, 50)-(150, 150), 4 ' Draws a line in red.
- SLEEP 1 ' Pauses program.
- PALETTE 4, 13 ' Attribute 4 now means color
- ' 13, so the line drawn in the
- ' last statement is now light
- ' magenta.
-
- With the PALETTE statement's USING option, you can change the colors
- assigned to every attribute all at once.
-
- Example
-
- The following example uses the PALETTE USING statement to give the
- illusion of movement on the screen by constantly rotating the colors
- displayed by attributes 1 through 15. This program is in the file named
- PALETTE.BAS on the QuickBASIC distribution disks.
-
- DECLARE SUB InitPalette ()
- DECLARE SUB ChangePalette ()
- DECLARE SUB DrawEllipses ()
-
- DEFINT A-Z
- DIM SHARED PaletteArray(15)
-
- SCREEN 8 ' 640 x 200 resolution; 16 colors
-
- InitPalette ' Initialize PaletteArray.
- DrawEllipses ' Draw and paint concentric ellipses.
-
- DO ' Shift the palette until a key
- ChangePalette ' is pressed.
- LOOP WHILE INKEY$ = ""
-
- END
-
-
- ' ====================== InitPalette ======================
- ' This procedure initializes the integer array used to
- ' change the palette.
- ' =========================================================
-
- SUB InitPalette STATIC
- FOR I = 0 TO 15
- PaletteArray(I) = I
- NEXT I
- END SUB
- ' ===================== DrawEllipses ======================
- ' This procedure draws 15 concentric ellipses and
- ' paints the interior of each with a different color.
- ' =========================================================
-
- SUB DrawEllipses STATIC
- CONST ASPECT = 1 / 3
- FOR ColorVal = 15 TO 1 STEP -1
- Radius = 20 * ColorVal
- CIRCLE (320, 100), Radius, ColorVal, , , ASPECT
- PAINT (320, 100), ColorVal
- NEXT
- END SUB
-
-
- ' ===================== ChangePalette =====================
- ' This procedure rotates the palette by one each time it
- ' is called. For example, after the first call to
- ' ChangePalette, PaletteArray(1) = 2, PaletteArray(2) = 3,
- ' . . . , PaletteArray(14) = 15, and PaletteArray(15) = 1
- ' =========================================================
-
- SUB ChangePalette STATIC
- FOR I = 1 TO 15
- PaletteArray(I) = (PaletteArray(I) MOD 15) + 1
- NEXT I
- PALETTE USING PaletteArray(0) ' Shift the color displayed
- ' by each of the attributes.
- END SUB
-
-
- 5.8 Painting Shapes
-
- Section 5.3.2.2 above shows how to draw a box with the LINE statement's B
- option, then paint the box by appending the F (for fill) option:
-
- SCREEN 1
-
- ' Draw a square, then paint the interior with color 1
- ' (cyan in the default palette):
- LINE (50, 50)-(110, 100), 1, BF
-
- With BASIC's PAINT statement, you can fill any enclosed figure with any
- color you choose. PAINT also allows you to fill enclosed figures with your
- own custom patterns, such as stripes or checks, as shown in Section
- 5.8.2, "Painting with Patterns."
-
- 5.8.1 Painting with Colors
-
- To paint an enclosed shape with a solid color, use this form of the PAINT
- statement:
-
- PAINT[[STEP]](x, y) [[,[[interior]],[[border]]]]
-
- Here, x, y are the coordinates of a point in the interior of the figure
- you want to paint, interior is the number for the color you want to paint
- with, and border is the color number for the outline of the figure.
-
- For example, the following program lines draw a circle in cyan, then paint
- the inside of the circle magenta:
-
- SCREEN 1
- CIRCLE (160, 100), 50, 1
- PAINT (160, 100), 2, 1
-
- The following three rules apply when painting figures:
-
- 1. The coordinates given in the PAINT statement must refer to a point
- inside the figure.
-
- For example, any one of the following statements would have the same
- effect as the PAINT statements shown in the two preceding examples,
- since all of the coordinates identify points in the interior of the
- circle:
-
- PAINT (150, 90), 2, 1
- PAINT (170, 110), 2, 1
- PAINT (180, 80), 2, 1
-
- In contrast, since (5, 5) identifies a point outside the circle, the
- next statement would paint all of the screen except the inside of the
- circle, leaving it colored with the current background color:
-
- PAINT (5, 5), 2, 1
-
- If the coordinates in a PAINT statement specify a point right on the
- border of the figure, then no painting occurs:
-
- LINE (50, 50)-(150, 150), , B ' Draw a box.
- PAINT (50, 100) ' The point with coordinates
- ' (50, 100) is on the top edge of the
- ' box, so no painting occurs.
-
- 2. The figure must be completely enclosed; otherwise, the paint color will
- "leak out," filling the entire screen or viewport (or any larger figure
- completely enclosing the first one).
-
- For example, in the following program, the CIRCLE statement draws an
- ellipse that is not quite complete (there is a small gap on the right
- side); the LINE statement then encloses the partial ellipse inside a
- box. Even though painting starts in the interior of the ellipse, the
- paint color flows through the gap and fills the entire box.
-
- SCREEN 2
- CONST PI = 3.141592653589#
- CIRCLE (300, 100), 80, , 0, 1.9 * PI, 3
- LINE (200, 10)-(400, 190), , B
- PAINT (300, 100)
-
- 3. If you are painting an object a different color from the one used to
- outline the object, you must use the border option to tell PAINT where
- to stop painting.
-
- For example, the following program draws a triangle outlined in green
- (attribute 1 in palette 0) and then tries to paint the interior of the
- triangle red (attribute 2). However, since the PAINT statement doesn't
- indicate where to stop painting, it paints the entire screen red.
-
- SCREEN 1
- COLOR , 0
-
- LINE (10, 25)-(310, 25), 1
- LINE -(160, 175), 1
- LINE -(10, 25), 1
-
- PAINT (160, 100), 2
-
- Making the following change to the PAINT statement (choose red for the
- interior and stop when a border colored green is reached) produces the
- desired effect:
-
- PAINT (160, 100), 2, 1
-
- Note that you don't have to specify a border color in the PAINT
- statement if the paint color is the same as the border color.
-
- LINE (10, 25)-(310, 25), 1
- LINE -(160, 175), 1
- LINE -(10, 25), 1
-
- PAINT (160, 100), 1
-
- 5.8.2 Painting with Patterns: Tiling
-
- You can use the PAINT statement to fill any enclosed figure with a
- pattern; this process is known as "tiling." A "tile" is the pattern's
- basic building block. The process is identical to laying down tiles on a
- floor. When you use tiling, the argument interior in the syntax for PAINT
- is a string expression, rather than a number. While interior can be any
- string expression, a convenient way to define tile patterns uses the
- following form for interior:
-
- CHR$(arg1) + CHR$(arg2) + CHR$(arg3) + ... + CHR$(argn)
-
- Here, arg1, arg2, and so forth are eight-bit integers. See Sections
- 5.8.2.2-5.8.2.4 below for an explanation of how these eight-bit integers
- are derived.
-
- 5.8.2.1 Pattern-Tile Size in Different Screen Modes
-
- Each tile for a pattern is composed of a rectangular grid of pixels. This
- tile grid can have up to 64 rows in all screen modes. However, the number
- of pixels in each row depends on the screen mode.
-
- Here is why the length of each tile row varies according to the screen
- mode: although the number of bits in each row is fixed at eight (the
- length of an integer), the number of pixels these eight bits can represent
- decreases as the number of color attributes in a given screen mode
- increases. For example, in screen mode 2, which has only 1 color
- attribute, the number of bits per pixel is 1; in screen mode 1, which has
- 4 different attributes, the number of bits per pixel is 2; and in the EGA
- screen mode 7, which has 16 attributes, the number of bits per pixel is 4.
- The following formula allows you to compute the bits per pixel in any
- given screen mode:
-
- bits-per-pixel = log2(numattributes)
-
- Here, numattributes is the number of color attributes in that screen mode.
- (The on-line QB Advisor has this information.)
-
- Thus, the length of a tile row is eight pixels in screen mode 2 (eight
- bits divided by one bit per pixel), but only four pixels in screen mode 1
- (eight bits divided by two bits per pixel).
-
- The next three sections show the step-by-step process involved in creating
- a pattern tile. Section 5.8.2.2 shows how to make a monochrome pattern in
- screen mode 2. Next, Section 5.8.2.3 shows how to make a multicolored
- pattern in screen mode 1. Finally, if you have an EGA, read Section
- 5.8.2.4 to see how to make a multicolored pattern in screen mode 8.
-
- 5.8.2.2 Creating a Single-Color Pattern in Screen Mode 2
-
- The following steps show how to define and use a pattern tile that
- resembles the letter "M":
-
- 1. Draw the pattern for a tile in a grid with 8 columns and however many
- rows you need (up to 64). In this example, the tile has 6 rows; an
- asterisk (*) in a box means the pixel is on:
-
- ┌──────────────────────────────────────────────────────────────────┐
- │ 1 pixel │
- │ ┌──┴───┐ │
- │ ┌ ┌─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┐ │
- │ 1 pixel ─┤ │ * │ │ │ │ │ * │ │ │ │
- │ └ ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤ │
- │ │ * │ * │ │ │ * │ * │ │ │ │
- │ ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤ │
- │ │ * │ │ * │ * │ │ * │ │ │ │
- │ ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤ │
- │ │ * │ │ │ │ │ * │ │ │ │
- │ ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤ │
- │ │ * │ │ │ │ │ * │ │ │ │
- │ ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤ │
- │ │ * │ │ │ │ │ * │ │ │ │
- │ ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤ │
- │ │ │ │ │ │ │ │ │ │ │
- │ └─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┘ │
- │ │
- └──────────────────────────────────────────────────────────────────┘
-
- 2. Next, translate each row of pixels to an eight-bit number, with a 1
- meaning the pixel is on, and a 0 meaning the pixel is off:
-
- ┌─────────────────────────────────────────────────────────────────┐
- │ │
- │ ┌─────┬─────┬─────┬─────┬─────┬─────┬─────┬─────┐ │
- │ │ 1 │ 0 │ 0 │ 0 │ 0 │ 1 │ 0 │ 0 │ │
- │ ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤ │
- │ │ 1 │ 1 │ 0 │ 0 │ 0 │ 1 │ 0 │ 0 │ │
- │ ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤ │
- │ │ 1 │ 0 │ 1 │ 1 │ 0 │ 1 │ 0 │ 0 │ │
- │ ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤ │
- │ │ 1 │ 0 │ 0 │ 0 │ 0 │ 1 │ 0 │ 0 │ │
- │ ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤ │
- │ │ 1 │ 0 │ 0 │ 0 │ 0 │ 1 │ 0 │ 0 │ │
- │ ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤ │
- │ │ 1 │ 0 │ 0 │ 0 │ 0 │ 1 │ 0 │ 0 │ │
- │ ├─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┤ │
- │ │ 0 │ 0 │ 0 │ 0 │ 0 │ 0 │ 0 │ 0 │ │
- │ └─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┘ │
- │ │
- │ │
- └─────────────────────────────────────────────────────────────────┘
-
- 3. Convert the binary numbers given in step 2 to hexadecimal integers:
-
- 10000100 = &H84
- 11001100 = &HCC
- 10110100 = &HB4
- 10000100 = &H84
- 10000100 = &H84
- 00000000 = &H00
-
- These integers do not have to be hexadecimal; they could be decimal or
- octal. However, binary to hexadecimal conversion easier. To convert
- from binary to hexadecimal, read the binary number from right to left.
- Each group of four digits is then converted to its hexadecimal
- equivalent, as shown here:
-
- ┌───────────────────────────────────────────────────────────┐
- │ │
- │ Binary 1010 1001 1111 │
- │ └─┬──┘ └─┬──┘ └─┬──┘ │
- │ │ │ │ │
- │ Hexadecimal A 9 F │
- │ │
- └───────────────────────────────────────────────────────────┘
-
- Table 5.3 lists four-bit binary sequences and their hexadecimal
- equivalents.
-
- 4. Create a string by concatenating the characters with the ASCII values
- from step 3 (use the CHR$ function to get these characters):
-
- Tile$ = CHR$(&H84) + CHR$(&HCC) + CHR$(&HB4)
- Tile$ = Tile$ + CHR$(&H84) + CHR$(&H84) + CHR$(&H00)
-
- 5. Draw a figure and paint its interior, using PAINT and the string
- argument from step 4:
-
- PAINT (X, Y), Tile$
-
- Table 5.3 Binary to Hexadecimal Conversion
- ╓┌─┌────────────────────────┌────────────────────────────────────────────────╖
- Binary Number Hexadecimal Number
- ──────────────────────────────────────────────────────────────────────────
- 0000 0
-
- 0001 1
-
- 0010 2
-
- 0011 3
-
- 0100 4
-
- 0101 5
- Binary Number Hexadecimal Number
- ──────────────────────────────────────────────────────────────────────────
- 0101 5
-
- 0110 6
-
- 0111 7
-
- 1000 8
-
- 1001 9
-
- 1010 A
-
- 1011 B
-
- 1100 C
-
- 1101 D
-
- 1110 E
- Binary Number Hexadecimal Number
- ──────────────────────────────────────────────────────────────────────────
- 1110 E
-
- 1111 F
- ──────────────────────────────────────────────────────────────────────────
-
-
- Example
-
- The following example draws a circle and then paints the circle's interior
- with the pattern created in the preceding steps:
-
- SCREEN 2
- CLS
- Tile$ = CHR$(&H84) + CHR$(&HCC) + CHR$(&HB4)
- Tile$ = Tile$ + CHR$(&H84) + CHR$(&H84) + CHR$(&H00)
- CIRCLE STEP(0, 0), 150
- PAINT STEP(0, 0), Tile$
-
- Output
-
-
- ┌────────────────────────────────────┐
- │ │
- │ Figure 5.5 can be found on │
- │ page 184 of the printed manual. │
- │ │
- └────────────────────────────────────┘
-
- Figure 5.5 Patterned Circle
-
- 5.8.2.3 Creating a Multicolor Pattern in Screen Mode 1
-
- The following steps show how to create a multicolor pattern consisting of
- alternating diagonal stripes of cyan and magenta (or green and red in
- palette 0):
-
- 1. Draw the pattern for a tile in a grid with four columns (four columns
- because each row of pixels is stored in an eight-bit integer and each
- pixel in screen mode 1 requires two bits) and however many rows you
- need (up to 64). In this example, the tile has four rows, as shown in
- the next diagram:
-
- ┌──────────────────────────────────────────────────────────────────┐
- │ │
- │ 1 pixel │
- │ ┌────┴───┐ │
- │ ┌─┌────────┬────────┬────────┬────────┐ │
- │ 1 pixel ┤ │ cyan │magenta │magenta │magenta │ │
- │ │ │ │ │ │ │ │
- │ └─├────────┼────────┼────────┼────────┤ │
- │ │ magenta│ cyan │magenta │magenta │ │
- │ │ │ │ │ │ │
- │ ├────────┼────────┼────────┼────────┤ │
- │ │ magenta│ magenta│ cyan │magenta │ │
- │ │ │ │ │ │ │
- │ ├────────┼────────┼────────┼────────┤ │
- │ │ magenta│ magenta│ magenta│ cyan │ │
- │ │ │ │ │ │ │
- │ └────────┴────────┴────────┴────────┘ │
- │ │
- └──────────────────────────────────────────────────────────────────┘
-
- 2. Convert the colors to their respective color numbers in binary
- notation, as shown below (be sure to use two-bit values, so 1 that =
- binary 01 and 2 = binary 10):
-
- ┌──────────────────────────────────────────────────────────────────┐
- │ │
- │ 2 bits │
- │ ┌───┴────┐ │
- │ ┌────────┬────────┬────────┬────────┐ │
- │ │ 01 │ 10 │ 10 │ 10 │ │
- │ │ │ │ │ │ │
- │ ├────────┼────────┼────────┼────────┤ │
- │ │ 10 │ 01 │ 10 │ 10 │ │
- │ │ │ │ │ │ │
- │ ├────────┼────────┼────────┼────────┤ │
- │ │ 10 │ 10 │ 01 │ 10 │ │
- │ │ │ │ │ │ │
- │ ├────────┼────────┼────────┼────────┤ │
- │ │ 10 │ 10 │ 10 │ 01 │ │
- │ │ │ │ │ │ │
- │ └────────┴────────┴────────┴────────┘ │
- │ │
- └──────────────────────────────────────────────────────────────────┘
-
- 3. Convert the binary numbers from step 2 to hexadecimal integers:
-
- 01101010 = &H6A
- 10011010 = &H9A
- 10100110 = &HA6
- 10101001 = &HA9
-
- 4. Create a string by concatenating the characters with the ASCII values
- from step 3 (use the CHR$ function to get these characters):
-
- Tile$ = CHR$(&H6A) + CHR$(&H9A) + CHR$(&HA6) + CHR$(&HA9)
-
- 5. Draw a figure and paint its interior using PAINT and the string
- argument from step 4:
-
- PAINT (X, Y), Tile$
-
- The following program draws a triangle and then paints its interior with
- the pattern created in the preceding steps:
-
- SCREEN 1
-
- ' Define a pattern:
- Tile$ = CHR$(&H6A) + CHR$(&H9A) + CHR$(&HA6) + CHR$(&HA9)
-
- ' Draw a triangle in white (color 3):
- LINE (10, 25)-(310, 25)
- LINE -(160, 175)
- LINE -(10, 25)
-
- ' Paint the interior of the triangle with the pattern:
- PAINT (160, 100), Tile$
-
- Note that if the figure you want to paint is outlined in a color that is
- also contained in the pattern, then you must give the border argument with
- PAINT as shown below; otherwise, the pattern spills over the edges of the
- figure:
-
- SCREEN 1
-
- ' Define a pattern:
- Tile$ = CHR$(&H6A) + CHR$(&H9A) + CHR$(&HA6) + CHR$(&HA9)
-
- ' Draw a triangle in magenta (color 2):
- LINE (10, 25)-(310, 25), 2
- LINE -(160, 175), 2
- LINE -(10, 25), 2
-
- ' Paint the interior of the triangle with the pattern,
- ' adding the border argument (, 2) to tell PAINT
- ' where to stop:
- PAINT (160, 100), Tile$, 2
-
- Sometimes, after painting a figure with a solid color or pattern, you may
- want to repaint that figure, or some part of it, with a new pattern. If
- the new pattern contains two or more adjacent rows that are the same as
- the figure's current background, you will find that tiling does not work.
- Instead, the pattern starts to spread, finds itself surrounded by pixels
- that are the same as two or more of its rows, then stops.
-
- You can alleviate this problem by using the background argument with PAINT
- if there are at most two adjacent rows in your new pattern that are the
- same as the old background. PAINT with background has the following
- syntax:
-
- PAINT[[ STEP]] (x, y) [[,[[ interior]][[,[[ border]][[,background]] ]]]]
-
- The background argument is a string character of the form CHR$(n) that
- specifies the rows in the pattern tile that are the same as the figure's
- current background. In essence, background tells PAINT to skip over these
- rows when repainting the figure. The next example clarifies how this
- works:
-
- SCREEN 1
-
- ' Define a pattern (two rows each of cyan, magenta, white):
- Tile$ = CHR$(&H55) + CHR$(&H55) + CHR$(&HAA)
- Tile$ = Tile$ + CHR$(&HAA) + CHR$(&HFF) + CHR$(&HFF)
-
- ' Draw a triangle in white (color number 3):
- LINE (10, 25)-(310, 25)
- LINE -(160, 175)
- LINE -(10, 25)
-
- ' Paint the interior magenta:
- PAINT (160, 100), 2, 3
-
- ' Wait for a keystroke:
- Pause$ = INPUT$(1)
-
- ' Since the background is already magenta, CHR$(&HAA) tells
- ' PAINT to skip over the magenta rows in the pattern tile:
- PAINT (160, 100), Tile$, , CHR$(&HAA)
-
- 5.8.2.4 Creating a Multicolor Pattern in Screen Mode 8
-
- In the EGA and VGA screen modes, it takes more than one eight-bit integer
- to define one row in a pattern tile. In these screen modes, a row is
- composed of several layers of eight-bit integers. This is because a pixel
- is represented three dimensionally in a stack of "bit planes" rather than
- sequentially in a single plane, as is the case with screen modes 1 and 2.
- For example, screen mode 8 has four of these bit planes. Each of the four
- bits per pixel in this screen mode is on a different plane.
-
- The following steps diagram the process for creating a multicolor pattern
- consisting of rows of alternating yellow and magenta. Note how each row in
- the pattern tile is represented by four parallel bytes:
-
- 1. Define one row of pixels in the pattern tile. Each pixel in the row
- takes four bits, and each bit is in a different plane, as shown below:
-
- ┌───────────────────────────────────────────────────────────────────────
- │
- │ Read bits for each
- │ plane in this order.
- │ ────────────────────────────────
- │ ─────────────────────────────────
- │ / / 1 / 1 / 0 / 0 / 0 / 0 / 1 / 1 /──── CHR$ (&HC3) + /
- │Read bits for/ / 0 / 0 / 1 / 1 / 1 / 1 / 0 / 0 /──── CHR$ (&H3C) + /
- │each pixel / / 1 / 1 / 1 / 1 / 1 / 1 / 1 / 1 /──── CHR$ (&HFF) + /AD
- │in this / / 0 / 0 / 1 / 1 / 1 / 1 / 0 / 0 /──── CHR$ (&H3C) /CHR$
- │order. / /────────────────────────────────/ valu
- │ Magenta ─┘ │ │ │ │ │ │ │ in t
- │ Magenta ─┘ │ │ │ │ │ │ orde
- │ Yellow ─┘ │ │ │ │ │
- │ Yellow ─┘ │ │ │ │ ┌───────────────────────
- │ Yellow ─┘ │ │ │ │Color Decimal Bina
- │ Yellow ─┘ │ │ │Yellow 14 1110
- │ Magenta ─┘ │ │Magenta 5 0101
- │ Magenta ─┘ └───────────────────────
- │
- └───────────────────────────────────────────────────────────────────────
-
- Add the CHR$ values for all four bit planes to get one tile byte. This
- row is repeated in the pattern tile, so
-
- Row$(1) = Row$(2) =
- CHR$(&HC3) + CHR$(&H3C) + CHR$(&HFF) + CHR$(&H3C)
-
- 2. Define another row of pixels in the pattern tile, as follows:
-
- ┌───────────────────────────────────────────────────────────────────────
- │
- │ Read bits for each
- │ plane in this order.
- │ ────────────────────────────────
- │ ─────────────────────────────────
- │ / / 0 / 0 / 1 / 1 / 1 / 1 / 0 / 0 /──── CHR$ (&HC3) + /
- │Read bits for/ / 1 / 1 / 0 / 0 / 0 / 0 / 1 / 1 /──── CHR$ (&H3C) + /
- │each pixel / / 1 / 1 / 1 / 1 / 1 / 1 / 1 / 1 /──── CHR$ (&HFF) + /AD
- │in this / / 1 / 1 / 0 / 0 / 0 / 0 / 1 / 1 /──── CHR$ (&H3C) /CHR$
- │order. / /────────────────────────────────/ valu
- │ Yellow ─┘ │ │ │ │ │ │ │ in t
- │ Yellow ─┘ │ │ │ │ │ │ orde
- │ Magenta ─┘ │ │ │ │ │
- │ Magenta ─┘ │ │ │ │ ┌───────────────────────
- │ Magenta ─┘ │ │ │ │Color Decimal Bina
- │ Magenta ─┘ │ │ │Yellow 14 1110
- │ Yellow ─┘ │ │Magenta 5 0101
- │ Yellow ─┘ └───────────────────────
- │
- └───────────────────────────────────────────────────────────────────────
-
- This row is also repeated in the pattern tile, so
-
- Row$(3) = Row$(4) =
- CHR$(&H3C) + CHR$(&HC3) + CHR$(&HFF) + CHR$(&HC3)
-
- Example
-
- The following example draws a box, then paints its interior with the
- pattern created in the preceding steps:
-
- SCREEN 8
- DIM Row$(1 TO 4)
-
- ' Two rows of alternating magenta and yellow:
- Row$(1) = CHR$(&HC3) + CHR$(&H3C) + CHR$(&HFF) + CHR$(&H3C)
- Row$(2) = Row$(1)
-
- ' Invert the pattern (two rows of alternating yellow
- ' and magenta):
- Row$(3) = CHR$(&H3C) + CHR$(&HC3) + CHR$(&HFF) + CHR$(&HC3)
- Row$(4) = Row$(3)
-
- ' Create a pattern tile from the rows defined above:
- FOR I% = 1 TO 4
- Tile$ = Tile$ + Row$(I%)
- NEXT I%
-
- ' Draw box and fill it with the pattern:
- LINE (50, 50)-(570, 150), , B
- PAINT (320, 100), Tile$
-
-
- 5.9 DRAW: a Graphics Macro Language
-
- The DRAW statement is a miniature language by itself. It draws and paints
- images on the screen using a set of one- or two-letter commands, known as
- "macros," embedded in a string expression.
-
- DRAW offers the following advantages over the other graphics statements
- discussed so far:
-
- ■ The macro string argument to DRAW is compact: a single, short string can
- produce the same output as several LINE statements.
-
- ■ Images created with DRAW can easily be scaled──that is, enlarged or
- reduced in size──by using the S macro in the macro string.
-
- ■ Images created with DRAW can be rotated any number of degrees by using
- the TA macro in the macro string.
-
- Consult the QB Advisor for more information.
-
- Example
-
- The following program gives a brief introduction to the movement macros U,
- D, L, R, E, F, G, and H; the "plot/don't plot" macro B; and the color
- macro C. This program draws horizontal, vertical, and diagonal lines in
- different colors, depending on which DIRECTION key on the numeric keypad
- (UP, DOWN, LEFT, PGUP, PGDN, and so on) is pressed.
-
- This program is in the file named PLOTTER.BAS on the QuickBASIC
- distribution disks.
-
- ' Values for keys on the numeric keypad and the spacebar:
- CONST UP = 72, DOWN = 80, LFT = 75, RGHT = 77
- CONST UPLFT = 71, UPRGHT = 73, DOWNLFT = 79, DOWNRGHT = 81
- CONST SPACEBAR = " "
-
- ' Null$ is the first character of the two-character INKEY$
- ' value returned for direction keys such as UP and DOWN:
- Null$ = CHR$(0)
-
- ' Plot$ = "" means draw lines; Plot$ = "B" means
- ' move graphics cursor, but don't draw lines:
- Plot$ = ""
-
- PRINT "Use the cursor movement keys to draw lines."
- PRINT "Press spacebar to toggle line drawing on and off."
- PRINT "Press <ENTER> to begin. Press q to end the program."
- DO : LOOP WHILE INKEY$ = ""
-
- SCREEN 1
-
- DO
- SELECT CASE KeyVal$
- CASE Null$ + CHR$(UP)
- DRAW Plot$ + "C1 U2"
- CASE Null$ + CHR$(DOWN)
- DRAW Plot$ + "C1 D2"
- CASE Null$ + CHR$(LFT)
- DRAW Plot$ + "C2 L2"
- CASE Null$ + CHR$(RGHT)
- DRAW Plot$ + "C2 R2"
- CASE Null$ + CHR$(UPLFT)
- DRAW Plot$ + "C3 H2"
- CASE Null$ + CHR$(UPRGHT)
- DRAW Plot$ + "C3 E2"
- CASE Null$ + CHR$(DOWNLFT)
- DRAW Plot$ + "C3 G2"
- CASE Null$ + CHR$(DOWNRGHT)
- DRAW Plot$ + "C3 F2"
- CASE SPACEBAR
- IF Plot$ = "" THEN Plot$ = "B " ELSE Plot$ = ""
- CASE ELSE
- ' The user pressed some key other than one of the
- ' direction keys, the spacebar, or "q," so
- ' don't do anything.
- END SELECT
-
- KeyVal$ = INKEY$
-
- LOOP UNTIL KeyVal$ = "q"
-
- SCREEN 0, 0 ' Restore the screen to 80-column
- WIDTH 80 ' text mode and end.
- END
-
- Output
-
- Here's a sample sketch created with this program.
-
- ┌──────────────────────────────────────────────────────────────────┐
- │ │
- │ │
- │ / ────\ │ │ │ ┌────\ │ / │ │
- │ │ │ │ │ │ │ │ / │ │
- │ │ │ │ │ │ │ /\ │ │
- │ │ │ │ │ │ │ │ \ │ │
- │ \────\/ \─────/ │ \─────/ │ \ │
- │ \ │
- │ ───────────────────────────────── │
- │ │
- │ ─────────────────────────────── │
- │ │
- │ ──────────────────────────── │
- │ │
- └──────────────────────────────────────────────────────────────────┘
-
-
- 5.10 Basic Animation Techniques
-
- Using only the graphics statements covered in earlier sections, you can do
- simple animation of objects on the screen. For instance, you can first
- draw a circle with CIRCLE, then redraw it with the background color to
- erase it, and finally recalculate the circle's center point and draw it in
- a new location.
-
- This technique works well enough for simple figures, but its disadvantages
- become apparent when animating more complex images. Even though the
- graphics statements are very fast, you can still notice the lag. Moreover,
- it is not possible to preserve the background with this method: when you
- erase the object, you also erase whatever was already on the screen.
-
- Two statements allow you to do high-speed animation: GET and PUT. You can
- create an image using output from statements such as PSET, LINE, CIRCLE,
- or PAINT, then take a "snapshot" of that image with GET, copying the image
- to memory. With PUT, you can then reproduce the image stored with GET
- anywhere on the screen or viewport.
-
- 5.10.1 Saving Images with GET
-
- After you have created the original image on the screen, you need to
- calculate the x- and y-coordinates of a rectangle large enough to hold the
- entire image. You then use GET to copy the entire rectangle to memory. The
- syntax for the graphics GET statement is
-
- GET[[STEP]](x1, y1) -[[STEP]](x2, y2), array-name
-
- where (x1, y1) and (x2, y2) give the coordinates of a rectangle's
- upper-left and lower-right corners. The argument array-name refers to any
- numeric array. The size specified in a DIM statement for array-name
- depends on the following three factors:
-
- 1. The height and width of the rectangle enclosing the image
-
- 2. The screen mode chosen for graphics output
-
- 3. The type of the array (integer, long integer, single precision, or
- double precision)
-
- ──────────────────────────────────────────────────────────────────────────
- NOTE
- Although the array used to store images can have any numeric type, it is
- strongly recommended that you use only integer arrays. All possible
- graphics patterns on the screen can be represented by integers. This is
- not the case, however, with single-precision or double-precision real
- numbers: some graphics patterns are not valid real numbers, and it could
- lead to unforeseen results if these patterns were stored in a
- real-number array.
- ──────────────────────────────────────────────────────────────────────────
-
- The formula for calculating the size in bytes of arrayname is
-
- size-in-bytes = 4 + height * planes * INT((width * bits-per-pixel/planes +
- 7)/8)
-
- where height and width are the dimensions, in number of pixels, of the
- rectangle to get, and the value for bits-per-pixel depends on the number
- of colors available in the given screen mode. More colors mean more bits
- are required to define each pixel. In screen mode 1, two bits define a
- pixel, while in screen mode 2, one bit is enough. (See Section 5.8.2.1
- above, "Pattern-Tile Size in Different Screen Modes," for the general
- formula for bits-per-pixel.) The following list shows the value for planes
- for each of the screen modes:
-
- Screen Mode Number of Bit
- Planes
- ──────────────────────────────────────────────────────────────────────────
- 1, 2, 11, and 13 1
-
- 9 (64K of video memory) and 10 2
-
- 7, 8, 9 (more than 64K of video memory), and 12 4
- ──────────────────────────────────────────────────────────────────────────
-
- To get the number of elements that should be in the array, divide the
- size-in-bytes by the number of bytes for one element in the array. This is
- where the type of the array comes into play. If it is an integer array,
- each element takes two bytes of memory (the size of an integer), so
- size-in-bytes should be divided by two to get the actual size of the
- array. Similarly, if it is a long integer array, size-in-bytes should be
- divided by four (since one long integer requires four bytes of memory),
- and so on. If it is single precision, divide by four; if it is double
- precision, divide by eight.
-
- The following steps show how to calculate the size of an integer array
- large enough to hold a rectangle in screen mode 1 with coordinates (10,
- 40) for the upper-left corner and (90, 80) for the lower-right corner:
-
- 1. Calculate the height and width of the rectangle:
-
- RectHeight = ABS(y2 - y1) + 1 = 80 - 40 + 1 = 41
- RectWidth = ABS(x2 - x1) + 1 = 90 - 10 + 1 = 81
-
- Remember to add one after subtracting y1 from y2 or x1 from x2. For
- example, if x1 = 10 and x2 = 20, then the width of the rectangle is 20
- - 10 + 1, or 11.
-
- 2. Calculate the size in bytes of the integer array:
-
- ByteSize = 4 + RectHeight * INT((RectWidth * BitsPerPixel + 7) / 8)
- = 4 + 41 * INT((81 * 2 + 7) / 8)
- = 4 + 41 * INT(169 / 8)
- = 4 + 41 * 21
- = 865
-
- 3. Divide the size in bytes by the bytes per element (two for integers)
- and round the result up to the nearest whole number:
-
- 865 / 2 = 433
-
- Therefore, if the name of the array is Image, the following DIM statement
- ensures that Image is big enough to copy the pixel information in the
- rectangle:
-
- DIM Image (1 TO 433) AS INTEGER
-
- ──────────────────────────────────────────────────────────────────────────
- NOTE
- Although the GET statement uses view coordinates after a WINDOW
- statement, you must use physical coordinates to calculate the size of
- the array used in GET. (See Section 5.6 above, "Redefining Viewport
- Coordinates with WINDOW," for more information on WINDOW and how to
- convert view coordinates to physical coordinates.)
- ──────────────────────────────────────────────────────────────────────────
-
- Note that the steps outlined above give the minimum size required for the
- array; however, any larger size will do. For example, the following
- statement also works:
-
- DIM Image (1 TO 500) AS INTEGER
-
- Example
-
- The following program draws an ellipse and paints its interior. A GET
- statement copies the rectangular area containing the ellipse into memory.
- (Section 5.10.2 below, "Moving Images with PUT," shows how to use the PUT
- statement to reproduce the ellipse in a different location.)
-
- SCREEN 1
-
- ' Dimension an integer array large enough
- ' to hold the rectangle:
- DIM Image (1 TO 433) AS INTEGER
-
- ' Draw an ellipse inside the rectangle, using magenta for
- ' the outline and painting the interior white:
- CIRCLE (50, 60), 40, 2, , , .5
- PAINT (50, 60), 3, 2
-
- ' Store the image of the rectangle in the array:
- GET (10, 40)-(90, 80), Image
-
- 5.10.2 Moving Images with PUT
-
- While the GET statement allows you to take a snapshot of an image, PUT
- allows you to paste that image anywhere you want on the screen. A
- statement of the form
-
- PUT (x, y), array-name [[, actionverb]]
-
- copies the rectangular image stored in array-name back to the screen and
- places its upper-left corner at the point with coordinates (x, y). Note
- that only one coordinate pair appears in PUT.
-
- If a WINDOW statement appears in the program before PUT, the coordinates x
- and y refer to the lower-left corner of the rectangle. WINDOW SCREEN,
- however, does not have this effect; that is, after WINDOW SCREEN, x and y
- still refer to the upper-left corner of the rectangle.
-
- For example, adding the next line to the last example in Section 5.10.1
- above causes an exact duplicate of the painted ellipse to appear on the
- right side of the screen much more quickly than redrawing and repainting
- the same figure with CIRCLE and PAINT:
-
- PUT (200, 40), Image
-
- Take care not to specify coordinates that would put any part of the image
- outside the screen or active viewport, as in the following statements:
-
- SCREEN 2
- .
- .
- .
- ' Rectangle measures 141 pixels x 91 pixels:
- GET (10, 10)-(150, 100), Image
- PUT (510, 120), Image
-
- Unlike other graphics statements such as LINE or CIRCLE, PUT does not clip
- images lying outside the viewport. Instead, it produces an error message
- reading Illegal function call.
-
- One of the other advantages of the PUT statement is that you can control
- how the stored image interacts with what is already on the screen by using
- the argument actionverb. The actionverb argument can be one of the
- following options: PSET, PRESET, AND, OR, or XOR.
-
- If you do not care what happens to the existing screen background, use the
- PSET option, since it transfers an exact duplicate of the stored image to
- the screen and overwrites anything that was already there.
-
- Table 5.4 shows how other options affect the way the PUT statement causes
- pixels in a stored image to interact with pixels on the screen. In this
- table, a 1 means a pixel is on and a 0 means a pixel is off.
-
- Table 5.4 The Effect of Different Action Options in Screen Mode 2
- ╓┌─┌──────────────────┌─────────────────┌──────────────────┌─────────────────╖
- Pixel on Screen Pixel on Screen
- Pixel in before PUT after PUT
- Action Option Stored Image Statement Statement
- ──────────────────────────────────────────────────────────────────────────
- PSET 0 0 0
-
- 0 1 0
-
- 1 0 1
-
- 1 1 1
- Pixel on Screen Pixel on Screen
- Pixel in before PUT after PUT
- Action Option Stored Image Statement Statement
- ──────────────────────────────────────────────────────────────────────────
- 1 1 1
-
- PRESET 0 0 1
-
- 0 1 1
-
- 1 0 0
-
- 1 1 0
-
- AND 0 0 0
-
- 0 1 0
-
- 1 0 0
-
- 1 1 1
- Pixel on Screen Pixel on Screen
- Pixel in before PUT after PUT
- Action Option Stored Image Statement Statement
- ──────────────────────────────────────────────────────────────────────────
- 1 1 1
-
- OR 0 0 0
-
- 0 1 1
-
- 1 0 1
-
- 1 1 1
-
- XOR 0 0 0
-
- 0 1 1
-
- 1 0 1
-
- 1 1 0
- Pixel on Screen Pixel on Screen
- Pixel in before PUT after PUT
- Action Option Stored Image Statement Statement
- ──────────────────────────────────────────────────────────────────────────
- 1 1 0
- ──────────────────────────────────────────────────────────────────────────
-
-
- As you can see, these options cause a PUT statement to treat pixels the
- same way logical operators treat numbers. The PRESET option is like the
- logical operator NOT in that it inverts the pixels in the stored image,
- regardless of what was on the screen. The options AND, OR, and XOR are
- identical to the logical operators with the same names; for example, the
- logical operation
-
- 1 XOR 1
-
- gives 0 as its result, just as using the XOR option turns a pixel off when
- both the pixel in the image and the pixel in the background are on.
-
- The output from the following program shows the same image superimposed
- over a filled rectangle using each of the five options discussed above:
-
- SCREEN 2
-
- DIM CircImage (1 TO 485) AS INTEGER
-
- ' Draw and paint an ellipse then store its image with GET:
- CIRCLE (22, 100), 80, , , , 4
- PAINT (22, 100)
- GET (0, 20)-(44, 180), CircImage
- CLS
-
- ' Draw a box and fill it with a pattern:
- LINE (40, 40)-(600, 160), , B
- Pattern$ = CHR$(126) + CHR$(0) + CHR$(126) + CHR$(126)
- PAINT (50, 50), Pattern$
-
- ' Put the images of the ellipse over the box
- ' using the different action options:
- PUT (100, 20), CircImage, PSET
- PUT (200, 20), CircImage, PRESET
- PUT (300, 20), CircImage, AND
- PUT (400, 20), CircImage, OR
- PUT (500, 20), CircImage, XOR
-
- Output
-
- ┌────────────────────────────────────┐
- │ │
- │ The output for this example │
- │ can be found on page 199 of │
- │ the printed manual. │
- │ │
- └────────────────────────────────────┘
-
- In screen modes supporting color, the options PRESET, AND, OR, and XOR
- produce a more complicated interaction, since color involves more than
- simply turning a pixel on or off. However, the analogy made above between
- these options and logical operators still holds in these modes. For
- example, if the current pixel on the screen is color 1 (cyan in palette 1)
- and the pixel in the overlaid image is color 2 (magenta in palette 1),
- then the color of the resulting pixel after a PUT statement depends on the
- option, as shown for just 2 of the 16 different combinations of image
- color and background color in Table 5.5.
-
- Table 5.5 The Effect of Different Action Options on Color in Screen Mode
- 1 (Palette 1)
- Pixel Color on Pixel Color on
- Pixel Color in Screen before Screen after PUT
- Action Option Stored Image PUT Statement Statement
- ──────────────────────────────────────────────────────────────────────────
- PSET 10 (magenta) 01 (cyan) 10 (magenta)
-
- PRESET 10 (magenta) 01 (cyan) 01 (cyan)
-
- AND 10 (magenta) 01 (cyan) 00 (black)
-
- OR 10 (magenta) 01 (cyan) 11 (white)
-
- XOR 10 (magenta) 01 (cyan) 11 (white)
- ──────────────────────────────────────────────────────────────────────────
-
- In palette 1, cyan is assigned to attribute 1 (01 binary), magenta is
- assigned to attribute 2 (10 binary), and white is assigned to attribute 3
- (11 binary). If you have an EGA, you can use the PALETTE statement to
- assign different colors to the attributes 1, 2, and 3.
-
- 5.10.3 Animation with GET and PUT
-
- One of the most useful things that can be done with the GET and PUT
- statements is animation. The two options best suited for animation are XOR
- and PSET. Animation done with PSET is faster; but as shown by the output
- from the last program, PSET erases the screen background. In contrast, XOR
- is slower but restores the screen background after the image is moved.
- Animation with XOR is done with the following four steps:
-
- 1. Put the object on the screen with XOR.
-
- 2. Recalculate the new position of the object.
-
- 3. Put the object on the screen a second time at the old location, using
- XOR again, this time to remove the old image.
-
- 4. Go to step 1, but this time put the object at the new location.
-
- Movement done with these four steps leaves the background unchanged after
- step 3. Flicker can be reduced by minimizing the time between steps 4 and
- 1 and by making sure that there is enough time delay between steps 1 and
- 3. If more than one object is being animated, every object should be
- processed at once, one step at a time.
-
- If it is not important to preserve the background, use the PSET option for
- animation. The idea is to leave a border around the image when you copy it
- with the GET statement. If this border is as large or larger than the
- maximum distance the object will move, then each time the image is put in
- a new location, the border erases all traces of the image in the old
- location. This method can be somewhat faster than the method using XOR
- described above, since only one PUT statement is required to move an
- object (although you must move a larger image).
-
- Examples
-
- The following example shows how to use PUT with the PSET option to produce
- the effect of a ball bouncing off the bottom and sides of a box. Note in
- the output that follows how the rectangle containing the ball, specified
- in the GET statement, erases the filled box and the printed message.
-
- This program is in the file named BALLPSET.BAS on the QuickBASIC
- distribution disks.
-
- DECLARE FUNCTION GetArraySize (WLeft, WRight, WTop,
- WBottom)
-
- SCREEN 2
-
- ' Define a viewport and draw a border around it:
- VIEW (20, 10)-(620, 190),,1
-
- CONST PI = 3.141592653589#
-
- ' Redefine the coordinates of the viewport with view
- ' coordinates:
- WINDOW (-3.15, -.14)-(3.56, 1.01)
-
- ' Arrays in program are now dynamic:
- ' $DYNAMIC
-
- ' Calculate the view coordinates for the top and bottom of a
- ' rectangle large enough to hold the image that will be
- ' drawn with CIRCLE and PAINT:
- WLeft = -.21
- WRight = .21
- WTop = .07
- WBottom = -.07
-
- ' Call the GetArraySize function,
- ' passing it the rectangle's view coordinates:
- ArraySize% = GetArraySize(WLeft, WRight, WTop, WBottom)
-
- DIM Array (1 TO ArraySize%) AS INTEGER
-
- ' Draw and paint the circle:
- CIRCLE (0, 0), .18
- PAINT (0, 0)
-
- ' Store the rectangle in Array:
- GET (WLeft, WTop)-(WRight, WBottom), Array
- CLS
- ' Draw a box and fill it with a pattern:
- LINE (-3, .8)-(3.4, .2), , B
- Pattern$ = CHR$(126) + CHR$(0) + CHR$(126) + CHR$(126)
- PAINT (0, .5), Pattern$
-
- LOCATE 21, 29
- PRINT "Press any key to end."
-
- ' Initialize loop variables:
- StepSize = .02
- StartLoop = -PI
- Decay = 1
-
- DO
- EndLoop = -StartLoop
- FOR X = StartLoop TO EndLoop STEP StepSize
-
- ' Each time the ball "bounces" (hits the bottom of the
- ' viewport), the Decay variable gets smaller, making
- ' the height of the next bounce smaller:
- Y = ABS(COS(X)) * Decay - .14
- IF Y < -.13 THEN Decay = Decay * .9
-
- ' Stop if key pressed or Decay less than .01:
- Esc$ = INKEY$
- IF Esc$ <> "" OR Decay < .01 THEN EXIT FOR
-
- ' Put the image on the screen. The StepSize offset is
- ' smaller than the border around the circle. Thus,
- ' each time the image moves, it erases any traces
- ' left from the previous PUT (and also erases anything
- ' else on the screen):
- PUT (X, Y), Array, PSET
- NEXT X
-
- ' Reverse direction:
- StepSize = -StepSize
- StartLoop = -StartLoop
- LOOP UNTIL Esc$ <> "" OR Decay < .01
-
- END
-
- FUNCTION GetArraySize (WLeft, WRight, WTop, WBottom) STATIC
-
- ' Map the view coordinates passed to this function to
- ' their physical-coordinate equivalents:
- VLeft = PMAP(WLeft, 0)
- VRight = PMAP(WRight, 0)
- VTop = PMAP(WTop, 1)
- VBottom = PMAP(WBottom, 1)
-
- ' Calculate the height and width in pixels
- ' of the enclosing rectangle:
- RectHeight = ABS(VBottom - VTop) + 1
- RectWidth = ABS(VRight - VLeft) + 1
-
- ' Calculate size in bytes of array:
- ByteSize = 4 + RectHeight * INT((RectWidth + 7) \ 8)
-
- ' Array is integer, so divide bytes by two:
- GetArraySize = ByteSize \ 2 + 1
- END FUNCTION
-
- Output
-
- ┌────────────────────────────────────┐
- │ │
- │ The output for this example │
- │ can be found on page 203 of │
- │ the printed manual. │
- │ │
- └────────────────────────────────────┘
-
- Contrast the preceding program with the next program, which uses PUT with
- XOR to preserve the screen's background, according to the four steps
- outlined above. Note how the rectangle containing the ball is smaller than
- in the preceding program, since it is not necessary to leave a border.
- Also note that two PUT statements are required, one to make the image
- visible and another to make it disappear. Finally, observe the empty
- FOR...NEXT delay loop between the PUT statements; this loop reduces the
- flicker that results from the image appearing and disappearing too
- rapidly.
-
- This program is in the file named BALLXOR.BAS on the QuickBASIC
- distribution disks.
-
- .
- .
- .
- ' The rectangle is smaller than the one in the previous
- ' program, which means Array is also smaller:
- WLeft = -.18
- WRight = .18
- WTop = .05
- WBottom = -.05
- .
- .
- .
- DO
- EndLoop = -StartLoop
- FOR X = StartLoop TO EndLoop STEP StepSize
- Y = ABS(COS(X)) * Decay - .14
-
- ' The first PUT statement places the image
- ' on the screen:
- PUT (X,Y), Array, XOR
-
- ' Use an empty FOR...NEXT loop to delay
- ' the program and reduce image flicker:
- FOR I = 1 TO 5: NEXT I
-
- IF Y < -.13 THEN Decay = Decay * .9
- Esc$ = INKEY$
- IF Esc$ <> "" OR Decay < .01 THEN EXIT FOR
-
- ' The second PUT statement erases the image and
- ' restores the background:
- PUT (X, Y), Array, XOR
- NEXT X
-
- StepSize = -StepSize
- StartLoop = -StartLoop
- LOOP UNTIL Esc$ <> "" OR Decay < .01
-
- END
- .
- .
- .
-
- Output
-
- ┌────────────────────────────────────┐
- │ │
- │ The output for this example │
- │ can be found on page 205 of │
- │ the printed manual. │
- │ │
- └────────────────────────────────────┘
-
- 5.10.4 Animating with Screen Pages
-
- This section describes an animation technique that utilizes multiple pages
- of your computer's video memory.
-
- Pages in video memory are analogous to pages in a book. Depending on the
- graphics capability of your computer, what you see displayed on the screen
- may only be part of the video memory available──just as what you see when
- you open a book is only part of the book. However, unlike a book, the
- unseen pages of your computer's video memory can be active; that is, while
- you are looking at one page on the screen, graphics output can be taking
- place on the others. It's as if the author of a book were still writing
- new pages even as you were reading the book.
-
- The area of video memory visible on the screen is called the "visual
- page," while the area of video memory where graphics statements put their
- output is called the "active page." The SCREEN statement allows you to
- select visual and active screen pages with the following syntax:
-
- SCREEN[[mode]],[[,[[apage]][[, vpage]]]]
-
- In this syntax, apage is the number of the active page, and vpage is the
- number of the visual page. The active page and the visual page can be one
- and the same (and are by default when the apage or vpage arguments are not
- used with SCREEN, in which case the value of both arguments is 0).
-
- You can animate objects on the screen by selecting a screen mode with more
- than one video memory page, then alternating the pages, sending output to
- one or more active pages while displaying finished output on the visual
- page. This technique makes an active page visible only when output to that
- page is complete. Since the viewer sees only a finished image, the display
- is instantaneous.
-
- Example
-
- The following program demonstrates the technique discussed above. It
- selects screen mode 7, which has two pages, then draws a cube with the
- DRAW statement. This cube is then rotated through successive 15° angles by
- changing the value of the TA macro in the string used by DRAW. By swapping
- the active and visual pages back and forth, this program always shows a
- completed cube while a new one is being drawn.
-
- This program is in the file named CUBE.BAS on the QuickBASIC distribution
- disks.
-
- ' Define the macro string used to draw the cube
- ' and paint its sides:
- One$ = "BR30 BU25 C1 R54 U45 L54 D45 BE20 P1,1 G20 C2 G20"
- Two$ = "R54 E20 L54 BD5 P2,2 U5 C4 G20 U45 E20 D45 BL5 P4,4"
- Plot$ = One$ + Two$
-
- APage% = 1 ' Initialize values for the active and visual
- VPage% = 0 ' pages as well as the angle of rotation.
- Angle% = 0
-
- DO
- SCREEN 7, , APage%, VPage% ' Draw to the active page
- ' while showing the visual page.
-
- CLS 1 ' Clear the active page.
-
- ' Rotate the cube "Angle%" degrees:
- DRAW "TA" + STR$(Angle%) + Plot$
-
- ' Angle% is some multiple of 15 degrees:
- Angle% = (Angle% + 15) MOD 360
-
- ' Drawing is complete, so make the cube visible in its
- ' new position by switching the active and visual pages:
- SWAP APage%, VPage%
-
- LOOP WHILE INKEY$ = "" ' A keystroke ends the program.
-
- END
-
-
- 5.11 Sample Applications
-
- The sample applications in this chapter are a bar-graph generator, a
- program that plots points in the Mandelbrot Set using different colors,
- and a pattern editor.
-
- 5.11.1 Bar-Graph Generator (BAR.BAS)
-
- This program uses all the forms of the LINE statement presented above in
- Sections 5.3.2.1-5.3.2.3 to draw a filled bar chart. Each bar is filled
- with a pattern specified in a PAINT statement. The input for the program
- consists of titles for the graph, labels for the x- and y-axes, and a set
- of up to five labels (with associated values) for the bars.
-
- Statements and Functions Used
-
- This program demonstrates the use of the following graphics statements:
-
- ■ LINE
-
- ■ PAINT (with a pattern)
-
- ■ SCREEN
-
- Program Listing
-
- The bar-graph generator program BAR.BAS is listed below.
-
- ' Define type for the titles:
- TYPE TitleType
- MainTitle AS STRING * 40
- XTitle AS STRING * 40
- YTitle AS STRING * 18
- END TYPE
-
- DECLARE SUB InputTitles (T AS TitleType)
- DECLARE FUNCTION DrawGraph$ (T AS TitleType, Label$(), Value!(), N%)
- DECLARE FUNCTION InputData% (Label$(), Value!())
-
- ' Variable declarations for titles and bar data:
- DIM Titles AS TitleType, Label$(1 TO 5), Value(1 TO 5)
-
- CONST FALSE = 0, TRUE = NOT FALSE
-
- DO
- InputTitles Titles
- N% = InputData%(Label$(), Value())
- IF N% <> FALSE THEN
- NewGraph$ = DrawGraph$(Titles, Label$(), Value(), N%)
- END IF
- LOOP WHILE NewGraph$ = "Y"
-
- END
-
- ' ======================== DRAWGRAPH ======================
- ' Draws a bar graph from the data entered in the
- ' INPUTTITLES and INPUTDATA procedures.
- ' =========================================================
-
- FUNCTION DrawGraph$ (T AS TitleType, Label$(), Value(), N%) STATIC
-
- ' Set size of graph:
- CONST GRAPHTOP = 24, GRAPHBOTTOM = 171
- CONST GRAPHLEFT = 48, GRAPHRIGHT = 624
- CONST YLENGTH = GRAPHBOTTOM - GRAPHTOP
-
- ' Calculate maximum and minimum values:
- YMax = 0
- YMin = 0
- FOR I% = 1 TO N%
- IF Value(I%) < YMin THEN YMin = Value(I%)
- IF Value(I%) > YMax THEN YMax = Value(I%)
- NEXT I%
-
- ' Calculate width of bars and space between them:
- BarWidth = (GRAPHRIGHT - GRAPHLEFT) / N%
- BarSpace = .2 * BarWidth
- BarWidth = BarWidth - BarSpace
-
- SCREEN 2
- CLS
-
- ' Draw y-axis:
- LINE (GRAPHLEFT, GRAPHTOP)-(GRAPHLEFT, GRAPHBOTTOM), 1
-
- ' Draw main graph title:
- Start% = 44 - (LEN(RTRIM$(T.MainTitle)) / 2)
- LOCATE 2, Start%
- PRINT RTRIM$(T.MainTitle);
-
- ' Annotate y-axis:
- Start% = CINT(13 - LEN(RTRIM$(T.YTitle)) / 2)
- FOR I% = 1 TO LEN(RTRIM$(T.YTitle))
- LOCATE Start% + I% - 1, 1
- PRINT MID$(T.YTitle, I%, 1);
- NEXT I%
-
- ' Calculate scale factor so labels aren't bigger than four digits:
- IF ABS(YMax) > ABS(YMin) THEN
- Power = YMax
- ELSE
- Power = YMin
- END IF
- Power = CINT(LOG(ABS(Power) / 100) / LOG(10))
- IF Power < 0 THEN Power = 0
-
- ' Scale minimum and maximum values down:
- ScaleFactor = 10 ^ Power
- YMax = CINT(YMax / ScaleFactor)
- YMin = CINT(YMin / ScaleFactor)
-
-
- ' If power isn't zero then put scale factor on chart:
- IF Power <> 0 THEN
- LOCATE 3, 2
- PRINT "x 10^"; LTRIM$(STR$(Power))
- END IF
-
- ' Put tic mark and number for Max point on y-axis:
- LINE (GRAPHLEFT - 3, GRAPHTOP) -STEP(3, 0)
- LOCATE 4, 2
- PRINT USING "####"; YMax
-
- ' Put tic mark and number for Min point on y-axis:
- LINE (GRAPHLEFT - 3, GRAPHBOTTOM) -STEP(3, 0)
- LOCATE 22, 2
- PRINT USING "####"; YMin
-
- YMax = YMax * ScaleFactor ' Scale minimum and maximum back
- YMin = YMin * ScaleFactor ' up for charting calculations.
-
- ' Annotate x-axis:
- Start% = 44 - (LEN(RTRIM$(T.XTitle)) / 2)
- LOCATE 25, Start%
- PRINT RTRIM$(T.XTitle);
-
- ' Calculate the pixel range for the y-axis:
- YRange = YMax - YMin
-
- ' Define a diagonally striped pattern:
- Tile$ = CHR$(1)+CHR$(2)+CHR$(4)+CHR$(8)+CHR$(16)+CHR$(32)+CHR$(64)+CHR$
- (128)
-
- ' Draw a zero line if appropriate:
- IF YMin < 0 THEN
- Bottom = GRAPHBOTTOM - ((-YMin) / YRange * YLENGTH)
- LOCATE INT((Bottom - 1) / 8) + 1, 5
- PRINT "0";
- ELSE
- Bottom = GRAPHBOTTOM
- END IF
-
- ' Draw x-axis:
- LINE (GRAPHLEFT - 3, Bottom)-(GRAPHRIGHT, Bottom)
- ' Draw bars and labels:
- Start% = GRAPHLEFT + (BarSpace / 2)
- FOR I% = 1 TO N%
-
- ' Draw a bar label:
- BarMid = Start% + (BarWidth / 2)
- CharMid = INT((BarMid - 1) / 8) + 1
- LOCATE 23, CharMid - INT(LEN(RTRIM$(Label$(I%))) / 2)
- PRINT Label$(I%);
-
- ' Draw the bar and fill it with the striped pattern:
- BarHeight = (Value(I%) / YRange) * YLENGTH
- LINE (Start%, Bottom) -STEP(BarWidth, -BarHeight), , B
- PAINT (BarMid, Bottom - (BarHeight / 2)), Tile$, 1
-
- Start% = Start% + BarWidth + BarSpace
- NEXT I%
- LOCATE 1, 1
- PRINT "New graph? ";
- DrawGraph$ = UCASE$(INPUT$(1))
-
- END FUNCTION
-
- ' ======================== INPUTDATA ======================
- ' Gets input for the bar labels and their values
- ' =========================================================
-
- FUNCTION InputData% (Label$(), Value()) STATIC
-
- ' Initialize the number of data values:
- NumData% = 0
-
- ' Print data-entry instructions:
- CLS
- PRINT "Enter data for up to 5 bars:"
- PRINT " * Enter the label and value for each bar."
- PRINT " * Values can be negative."
- PRINT " * Enter a blank label to stop."
- PRINT
- PRINT "After viewing the graph, press any key ";
- PRINT "to end the program."
-
- ' Accept data until blank label or 5 entries:
- Done% = FALSE
- DO
- NumData% = NumData% + 1
- PRINT
- PRINT "Bar("; LTRIM$(STR$(NumData%)); "):"
- INPUT ; " Label? ", Label$(NumData%)
-
- ' Only input value if label isn't blank:
- IF Label$(NumData%) <> "" THEN
- LOCATE , 35
- INPUT "Value? ", Value(NumData%)
-
- ' If label is blank, decrement data counter
- ' and set Done flag equal to TRUE:
- ELSE
- NumData% = NumData% - 1
- Done% = TRUE
- END IF
- LOOP UNTIL (NumData% = 5) OR Done%
-
- ' Return the number of data values input:
- InputData% = NumData%
-
- END FUNCTION
-
- ' ====================== INPUTTITLES ======================
- ' Accepts input for the three different graph titles
- ' =========================================================
-
- SUB InputTitles (T AS TitleType) STATIC
- SCREEN 0, 0 ' Set text screen.
- DO ' Input titles.
- CLS
- INPUT "Enter main graph title: ", T.MainTitle
- INPUT "Enter x-axis title : ", T.XTitle
- INPUT "Enter y-axis title : ", T.YTitle
-
- ' Check to see if titles are OK:
- LOCATE 7, 1
- PRINT "OK (Y to continue, N to change)? ";
- LOCATE , , 1
- OK$ = UCASE$(INPUT$(1))
- LOOP UNTIL OK$ = "Y"
- END SUB
-
- Output
-
- ┌─────────────────────────────────────────────────────────────────┐
- │ New graph? │
- │ LOW TEMPERATURE BY MONTH │
- │ 15 ┐ ┌───────┐ │
- │ C │ │░░░░░░░│ │
- │ e │ │░░░░░░░│ │
- │ l │ │░░░░░░░│ │
- │ s │ │░░░░░░░│ │
- │ i │ │░░░░░░░│ │
- │ u │ │░░░░░░░│ │
- │ s │ ┌───────┐ │░░░░░░░│ │
- │ │ │░░░░░░░│ │░░░░░░░│ │
- │ D │ │░░░░░░░│ │░░░░░░░│ │
- │ e 0 ┼┬───────┬─┬───────┬─┬───────┬─┴───────┴─┴───────┴─ │
- │ g ││░░░░░░░│ │░░░░░░░│ │░░░░░░░│ │
- │ r ││░░░░░░░│ │░░░░░░░│ └───────┘ │
- │ e ││░░░░░░░│ │░░░░░░░│ │
- │ e ││░░░░░░░│ │░░░░░░░│ │
- │ s │└───────┘ │░░░░░░░│ │
- │ -9┘ └───────┘ │
- │ January February March April May │
- │ Month │
- └─────────────────────────────────────────────────────────────────┘
-
- 5.11.2 Color in a Figure Generated Mathematically (MANDEL.BAS)
-
- This program uses BASIC graphics statements to generate a figure known as
- a "fractal." A fractal is a graphic representation of what happens to
- numbers when they are subjected to a repeated sequence of mathematical
- operations. The fractal generated by this program shows a subset of the
- class of numbers known as complex numbers; this subset is called the
- "Mandelbrot Set," named after Benoit B. Mandelbrot of the IBM Thomas J.
- Watson Research Center.
-
- Briefly, complex numbers have two parts, a real part and a so-called
- imaginary part, some multiple of the √-1. Squaring a complex number, then
- plugging the real and imaginary parts back into a second complex number,
- squaring the new complex number, and repeating the process causes some
- complex numbers to get very large fairly fast. However, others hover
- around some stable value. The stable values are in the Mandelbrot Set and
- are represented in this program by the color black. The unstable values──
- that is, the ones that are moving away from the Mandelbrot Set──are
- represented by the other colors in the palette. The smaller the color
- attribute, the more unstable the point.
-
- See A.K. Dewdney's column, "Computer Recreations," in Scientific American,
- August 1985, for more background on the Mandelbrot Set.
-
- This program also tests for the presence of an EGA card, and if one is
- present, it draws the Mandelbrot Set in screen mode 8. After drawing each
- line, the program rotates the 16 colors in the palette with a PALETTE
- USING statement. If there is no EGA card, the program draws a four-color
- (white, magenta, cyan, and black) Mandelbrot Set in screen mode 1.
-
- Statements and Functions Used
-
- This program demonstrates the use of the following graphics statements:
-
- ■ LINE
-
- ■ PALETTE USING
-
- ■ PMAP
-
- ■ PSET
-
- ■ SCREEN
-
- ■ VIEW
-
- ■ WINDOW
-
- Program Listing
-
- DEFINT A-Z ' Default variable type is integer.
-
- DECLARE SUB ShiftPalette ()
- DECLARE SUB WindowVals (WL%, WR%, WT%, WB%)
- DECLARE SUB ScreenTest (EM%, CR%, VL%, VR%, VT%, VB%)
-
- CONST FALSE = 0, TRUE = NOT FALSE ' Boolean constants
-
- ' Set maximum number of iterations per point:
- CONST MAXLOOP = 30, MAXSIZE = 1000000
-
- DIM PaletteArray(15)
- FOR I = 0 TO 15: PaletteArray(I) = I: NEXT I
-
- ' Call WindowVals to get coordinates of window corners:
- WindowVals WLeft, WRight, WTop, WBottom
-
- ' Call ScreenTest to find out if this is an EGA machine
- ' and get coordinates of viewport corners:
- ScreenTest EgaMode, ColorRange, VLeft, VRight, VTop, VBottom
-
- ' Define viewport and corresponding window:
- VIEW (VLeft, VTop)-(VRight, VBottom), 0, ColorRange
- WINDOW (WLeft, WTop)-(WRight, WBottom)
-
- LOCATE 24, 10 : PRINT "Press any key to quit.";
-
- XLength = VRight - VLeft
- YLength = VBottom - VTop
- ColorWidth = MAXLOOP \ ColorRange
-
- ' Loop through each pixel in viewport and calculate
- ' whether or not it is in the Mandelbrot Set:
- FOR Y = 0 TO YLength ' Loop through every line
- ' in the viewport.
- LogicY = PMAP(Y, 3) ' Get the pixel's view
- ' y-coordinate.
- PSET (WLeft, LogicY) ' Plot leftmost pixel in the line.
- OldColor = 0 ' Start with background color.
-
- FOR X = 0 TO XLength ' Loop through every pixel
- ' in the line.
- LogicX = PMAP(X, 2) ' Get the pixel's view
- ' x-coordinate.
- MandelX& = LogicX
- MandelY& = LogicY
-
-
- ' Do the calculations to see if this point
- ' is in the Mandelbrot Set:
- FOR I = 1 TO MAXLOOP
- RealNum& = MandelX& * MandelX&
- ImagNum& = MandelY& * MandelY&
- IF (RealNum& + ImagNum&) >= MAXSIZE THEN EXIT FOR
- MandelY& = (MandelX& * MandelY&) \ 250 + LogicY
- MandelX& = (RealNum& - ImagNum&) \ 500 + LogicX
- NEXT I
-
- ' Assign a color to the point:
- PColor = I \ ColorWidth
-
- ' If color has changed, draw a line from
- ' the last point referenced to the new point,
- ' using the old color:
- IF PColor <> OldColor THEN
- LINE -(LogicX, LogicY), (ColorRange - OldColor)
- OldColor = PColor
- END IF
-
- IF INKEY$ <> "" THEN END
- NEXT X
-
- ' Draw the last line segment to the right edge
- ' of the viewport:
- LINE -(LogicX, LogicY), (ColorRange - OldColor)
-
- ' If this is an EGA machine, shift the palette after
- ' drawing each line:
- IF EgaMode THEN ShiftPalette
- NEXT Y
-
- DO
- ' Continue shifting the palette
- ' until the user presses a key:
- IF EgaMode THEN ShiftPalette
- LOOP WHILE INKEY$ = ""
-
- SCREEN 0, 0 ' Restore the screen to text mode,
- WIDTH 80 ' 80 columns.
- END
-
- BadScreen: ' Error handler that is invoked if
- EgaMode = FALSE ' there is no EGA graphics card
- RESUME NEXT
-
- ' ====================== ShiftPalette =====================
- ' Rotates the palette by one each time it is called
- ' =========================================================
-
- SUB ShiftPalette STATIC
- SHARED PaletteArray(), ColorRange
-
- FOR I = 1 TO ColorRange
- PaletteArray(I) = (PaletteArray(I) MOD ColorRange) + 1
- NEXT I
- PALETTE USING PaletteArray(0)
-
- END SUB
-
- ' ======================= ScreenTest ======================
- ' Uses a SCREEN 8 statement as a test to see if user has
- ' EGA hardware. If this causes an error, the EM flag is
- ' set to FALSE, and the screen is set with SCREEN 1.
-
- ' Also sets values for corners of viewport (VL = left,
- ' VR = right, VT = top, VB = bottom), scaled with the
- ' correct aspect ratio so viewport is a perfect square.
- ' =========================================================
-
- SUB ScreenTest (EM, CR, VL, VR, VT, VB) STATIC
- EM = TRUE
- ON ERROR GOTO BadScreen
- SCREEN 8, 1
- ON ERROR GOTO 0
-
- IF EM THEN ' No error, SCREEN 8 is OK.
- VL = 110: VR = 529
- VT = 5: VB = 179
- CR = 15 ' 16 colors (0 - 15)
-
- ELSE ' Error, so use SCREEN 1.
- SCREEN 1, 1
- VL = 55: VR = 264
- VT = 5: VB = 179
- CR = 3 ' 4 colors (0 - 3)
- END IF
-
- END SUB
-
- ' ======================= WindowVals ======================
- ' Gets window corners as input from the user, or sets
- ' values for the corners if there is no input
- ' =========================================================
-
- SUB WindowVals (WL, WR, WT, WB) STATIC
- CLS
- PRINT "This program prints the graphic representation of"
- PRINT "the complete Mandelbrot Set. The default window"
- PRINT "is from (-1000,625) to (250,-625). To zoom in on"
- PRINT "part of the figure, input coordinates inside"
- PRINT "this window."
- PRINT "Press <ENTER> to see the default window or"
- PRINT "any other key to input window coordinates: ";
- LOCATE , , 1
- Resp$ = INPUT$(1)
-
- ' User didn't press ENTER, so input window corners:
- IF Resp$ <> CHR$(13) THEN
- PRINT
- INPUT "x-coordinate of upper-left corner: ", WL
- DO
- INPUT "x-coordinate of lower-right corner: ", WR
- IF WR <= WL THEN
- PRINT "Right corner must be greater than left corner."
- END IF
- LOOP WHILE WR <= WL
- INPUT "y-coordinate of upper-left corner: ", WT
- DO
- INPUT "y-coordinate of lower-right corner: ", WB
- IF WB >= WT THEN
- PRINT "Bottom corner must be less than top corner."
- END IF
- LOOP WHILE WB >= WT
-
- ' User pressed ENTER, so set default values:
- ELSE
- WL = -1000
- WR = 250
- WT = 625
- WB = -625
- END IF
- END SUB
-
- Output
-
- The following figure shows the Mandelbrot Set in screen mode 1. This is
- the output you see if you have a CGA and you choose the default window
- coordinates.
-
- ┌────────────────────────────────────┐
- │ │
- │ The output for this example │
- │ can be found on page 217 of │
- │ the printed manual. │
- │ │
- └────────────────────────────────────┘
-
- The next figure shows the Mandelbrot Set with (x, y) coordinates of (-500,
- 250) for the upper-left corner and (-300, 50) for the lower-right corner.
- This figure is drawn in screen mode 8, the default for an EGA or VGA.
-
- ┌────────────────────────────────────┐
- │ │
- │ The output for this example │
- │ can be found on page 217 of │
- │ the printed manual. │
- │ │
- └────────────────────────────────────┘
-
- 5.11.3 Pattern Editor (EDPAT.BAS)
-
- This program allows you to edit a pattern tile for use with PAINT. While
- you are editing the tile on the left side of the screen, you can check the
- appearance of the finished pattern on the right side of the screen. When
- you have finished editing the pattern tile, the program prints the integer
- arguments used by the CHR$ statement to draw each row of the tile.
-
- Statements and Functions Used
-
- This program demonstrates the use of the following graphics statements:
-
- ■ LINE
-
- ■ PAINT (with pattern)
-
- ■ VIEW
-
- Program Listing
-
- DECLARE SUB DrawPattern ()
- DECLARE SUB EditPattern ()
- DECLARE SUB Initialize ()
- DECLARE SUB ShowPattern (OK$)
-
- DIM Bit%(0 TO 7), Pattern$, Esc$, PatternSize%
-
- DO
- Initialize
- EditPattern
- ShowPattern OK$
- LOOP WHILE OK$ = "Y"
-
- END
-
- ' ======================= DRAWPATTERN ====================
- ' Draws a patterned rectangle on the right side of screen
- ' ========================================================
-
- SUB DrawPattern STATIC
- SHARED Pattern$
-
- VIEW (320, 24)-(622, 160), 0, 1 ' Set view to rectangle.
- PAINT (1, 1), Pattern$ ' Use PAINT to fill it.
- VIEW ' Set view to full screen.
-
- END SUB
-
- ' ======================= EDITPATTERN =====================
- ' Edits a tile-byte pattern
- ' =========================================================
-
- SUB EditPattern STATIC
- SHARED Pattern$, Esc$, Bit%(), PatternSize%
-
- ByteNum% = 1 ' Starting position.
- BitNum% = 7
- Null$ = CHR$(0) ' CHR$(0) is the first byte of the
- ' two-byte string returned when a
- ' direction key such as UP or DOWN is
- ' pressed.
- DO
-
- ' Calculate starting location on screen of this bit:
- X% = ((7 - BitNum%) * 16) + 80
- Y% = (ByteNum% + 2) * 8
-
- ' Wait for a key press (flash cursor each 3/10 second):
- State% = 0
- RefTime = 0
- DO
-
- ' Check timer and switch cursor state if 3/10 second:
- IF ABS(TIMER - RefTime) > .3 THEN
- RefTime = TIMER
- State% = 1 - State%
-
- ' Turn the border of bit on and off:
- LINE (X%-1, Y%-1) -STEP(15, 8), State%, B
- END IF
-
- Check$ = INKEY$ ' Check for keystroke.
-
- LOOP WHILE Check$ = "" ' Loop until a key is pressed.
-
- ' Erase cursor:
- LINE (X%-1, Y%-1) -STEP(15, 8), 0, B
-
- SELECT CASE Check$ ' Respond to keystroke.
-
- CASE CHR$(27) ' ESC key pressed:
- EXIT SUB ' exit this subprogram.
-
- CASE CHR$(32) ' SPACEBAR pressed:
- ' reset state of bit.
-
- ' Invert bit in pattern string:
- CurrentByte% = ASC(MID$(Pattern$, ByteNum%, 1))
- CurrentByte% = CurrentByte% XOR Bit%(BitNum%)
- MID$ (Pattern$, ByteNum%) = CHR$(CurrentByte%)
-
- ' Redraw bit on screen:
- IF (CurrentByte% AND Bit%(BitNum%)) <> 0 THEN
- CurrentColor% = 1
- ELSE
- CurrentColor% = 0
- END IF
- LINE (X%+1, Y%+1) -STEP(11, 4), CurrentColor%, BF
-
- CASE CHR$(13) ' ENTER key pressed: draw
- DrawPattern ' pattern in box on right.
-
- CASE Null$ + CHR$(75) ' LEFT key: move cursor left.
-
- BitNum% = BitNum% + 1
- IF BitNum% > 7 THEN BitNum% = 0
-
- CASE Null$ + CHR$(77) ' RIGHT key: move cursor right.
-
- BitNum% = BitNum% - 1
- IF BitNum% < 0 THEN BitNum% = 7
-
- CASE Null$ + CHR$(72) ' UP key: move cursor up.
-
- ByteNum% = ByteNum% - 1
- IF ByteNum% < 1 THEN ByteNum% = PatternSize%
-
- CASE Null$ + CHR$(80) ' DOWN key: move cursor down.
-
- ByteNum% = ByteNum% + 1
- IF ByteNum% > PatternSize% THEN ByteNum% = 1
-
- CASE ELSE
- ' User pressed a key other than ESC, SPACEBAR,
- ' ENTER, UP, DOWN, LEFT, or RIGHT, so don't
- ' do anything.
- END SELECT
- LOOP
- END SUB
-
- ' ======================= INITIALIZE ======================
- ' Sets up starting pattern and screen
- ' =========================================================
-
- SUB Initialize STATIC
- SHARED Pattern$, Esc$, Bit%(), PatternSize%
-
- Esc$ = CHR$(27) ' ESC character is ASCII 27.
-
- ' Set up an array holding bits in positions 0 to 7:
- FOR I% = 0 TO 7
- Bit%(I%) = 2 ^ I%
- NEXT I%
-
- CLS
-
- ' Input the pattern size (in number of bytes):
- LOCATE 5, 5
- PRINT "Enter pattern size (1-16 rows):";
- DO
- LOCATE 5, 38
- PRINT " ";
- LOCATE 5, 38
- INPUT "", PatternSize%
- LOOP WHILE PatternSize% < 1 OR PatternSize% > 16
-
- ' Set initial pattern to all bits set:
- Pattern$ = STRING$(PatternSize%, 255)
-
- SCREEN 2 ' 640 x 200 monochrome graphics mode
-
- ' Draw dividing lines:
- LINE (0, 10)-(635, 10), 1
- LINE (300, 0)-(300, 199)
- LINE (302, 0)-(302, 199)
-
- ' Print titles:
- LOCATE 1, 13: PRINT "Pattern Bytes"
- LOCATE 1, 53: PRINT "Pattern View"
-
- ' Draw editing screen for pattern:
- FOR I% = 1 TO PatternSize%
-
- ' Print label on left of each line:
- LOCATE I% + 3, 8
- PRINT USING "##:"; I%
-
- ' Draw "bit" boxes:
- X% = 80
- Y% = (I% + 2) * 8
- FOR J% = 1 TO 8
- LINE (X%, Y%) -STEP(13, 6), 1, BF
- X% = X% + 16
- NEXT J%
- NEXT I%
-
- DrawPattern ' Draw "Pattern View" box.
-
- LOCATE 21, 1
- PRINT "DIRECTION keys........Move cursor"
- PRINT "SPACEBAR............Changes point"
- PRINT "ENTER............Displays pattern"
- PRINT "ESC.........................Quits";
-
- END SUB
-
- ' ======================== SHOWPATTERN ====================
- ' Prints the CHR$ values used by PAINT to make pattern
- ' =========================================================
-
- SUB ShowPattern (OK$) STATIC
- SHARED Pattern$, PatternSize%
-
- ' Return screen to 80-column text mode:
- SCREEN 0, 0
- WIDTH 80
-
- PRINT "The following characters make up your pattern:"
- PRINT
-
- ' Print out the value for each pattern byte:
- FOR I% = 1 TO PatternSize%
- PatternByte% = ASC(MID$(Pattern$, I%, 1))
- PRINT "CHR$("; LTRIM$(STR$(PatternByte%)); ")"
- NEXT I%
- PRINT
- LOCATE , , 1
- PRINT "New pattern? ";
- OK$ = UCASE$(INPUT$(1))
- END SUB
-
- Output
-
- This is a sample pattern generated by the pattern editor.
-
- ┌────────────────────────────────────┐
- │ │
- │ The output for this example │
- │ can be found on page 223 of │
- │ the printed manual. │
- │ │
- └────────────────────────────────────┘
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- Chapter 6 Error and Event Trapping
-
- This chapter shows how to trap errors and events that occur while a
- program is running. With error trapping, you can protect your program from
- such user errors as entering a string when a numeric value is expected or
- trying to open a file in a nonexistent directory. With event trapping,
- your program can detect and respond to real-time events such as keystrokes
- or data arriving at a COM port.
-
- When you have completed this chapter, you will know how to perform these
- tasks:
-
- ■ Activate error trapping or event trapping
-
- ■ Write a routine to process trapped errors or events
-
- ■ Return control from an error-handling routine or an event-handling
- routine
-
- ■ Write a program that traps any keystroke or combination of keystrokes
-
- ■ Trap errors or events within SUB or FUNCTION procedures
-
- ■ Trap errors or events in programs composed of more than one module
-
-
- 6.1 Error Trapping
-
- Error trapping lets your program intercept run-time errors before they
- force the program to halt. Without error trapping, errors during program
- execution (such as trying to open a nonexistent data file) cause BASIC to
- display the appropriate error message, then stop the program. If someone
- is running the stand-alone version of your program, they will have to
- restart the program, losing data entered or calculations performed before
- the error occurred.
-
- When error trapping is active, the trapped error makes the program branch
- to a user-written "error-handling routine," which corrects the error. If
- you can anticipate errors that might occur when someone else uses your
- program, error trapping will let you handle those errors in a
- "user-friendly" way.
-
- Sections 6.1.1 and 6.1.2 below show how to activate error trapping, how
- to write a routine to handle errors when they are trapped, and how to
- return control from the error-handling routine after it has dealt with the
- error.
-
- 6.1.1 Activating Error Trapping
-
- You activate error trapping with the statement ON ERROR GOTO line, where
- line is a line number or line label identifying the first line of an
- error-handling routine. Once BASIC has encountered an ON ERROR GOTO line
- statement, any run-time error within the module containing that statement
- causes a branch to the specified line. (If the number or label does not
- exist within the module, a run-time error message reading Label not
- defined appears.)
-
- An ON ERROR GOTO statement must be executed before error trapping takes
- effect. Therefore, you must position the ON ERROR GOTO statement so that
- program execution reaches it before it is needed. This statement would
- usually be one of the first executable statements in the main module or a
- procedure.
-
- You cannot use an ON ERROR GOTO 0 statement to branch to an error handler,
- because this statement has a special meaning in error trapping. The ON
- ERROR GOTO 0 statement has two effects, depending on where it appears. If
- it appears outside an error-handling routine, it turns off error trapping.
- If it appears inside an error-handling routine (as it does in the Handler
- routine in the next example), it causes BASIC to print its standard
- message for the given error and stops the program.
-
- Therefore, even if your program has a line with line-number 0, an ON ERROR
- GOTO 0 statement tells BASIC either to turn off error detection or to
- terminate execution.
-
- 6.1.2 Writing an Error-Handling Routine
-
- An error-handling routine consists of the following three parts:
-
- 1. The line label or line number that is specified in the statement ON
- ERROR GOTO line, which is the first statement the program branches to
- after an error
-
- 2. The body of the routine, which determines the error that caused the
- branch and takes appropriate action for each anticipated error
-
- 3. At least one RESUME or RESUME NEXT statement to return control from the
- routine
-
- An error handler must be placed where it cannot be executed during the
- normal flow of program execution. For example, an error-handling routine
- in the program's main module might be placed after an END statement.
- Otherwise, a GOTO statement might be needed to skip over it during normal
- execution.
-
- 6.1.2.1 Using ERR to Identify Errors
-
- Once the program has branched to an error-handling routine, it must
- determine which error caused the branch. To identify the culprit, use the
- ERR function. This function returns a numeric code for the program's most
- recent run-time error. (See Table I.1, "Run-Time Error Codes," for a
- complete list of the error codes associated with run-time errors.)
-
- ──────────────────────────────────────────────────────────────────────────
- NOTE
- Errors cannot be trapped within an error-handling routine. If an error
- occurs while the error-handling routine is processing another error, the
- program displays the message for the new error and then terminates.
- Event handling is also suspended, but resumes when QuickBASIC returns
- from the error handler. The first event that occurred after event
- handling was suspended is saved.
- ──────────────────────────────────────────────────────────────────────────
-
- Example
-
- The following program includes the error-handling routine Handler,
- designed to deal specifically with three different error situations. The
- ERR function, used in a SELECT CASE statement, allows this routine to take
- actions appropriate for each error.
-
- DATA BASIC, Pascal, FORTRAN, C, Modula, Forth
- DATA LISP, Ada, COBOL
-
- CONST FALSE = 0, TRUE = NOT FALSE
-
- EndOfData = FALSE ' Set end of data flag.
-
- ON ERROR GOTO Handler ' Activate error trapping.
-
- OPEN "LPT1:" FOR OUTPUT AS #1 ' Open the printer for output.
-
- DO
- ' Continue reading items from the DATA statements above,
- ' then printing them on the line printer, until there is
- ' an "Out of DATA" error message signifying no more data:
- READ Buffer$
- IF NOT EndOfData THEN
- PRINT #1, Buffer$
- ELSE
- EXIT DO
- END IF
- LOOP
-
- CLOSE #1
- END
-
- Handler: ' Error-handling routine
-
- ' Use ERR to determine which error
- ' caused the branch to "Handler":
- SELECT CASE ERR
- CASE 4
-
- ' 4 is the code for "Out of DATA" in DATA
- ' statements:
- EndOfData = TRUE
- RESUME NEXT
- CASE 25
-
- ' 25 is the code for "Device fault" error,
- ' which can be caused by trying to output
- ' to the printer when it's not on:
- PRINT "Turn printer on, then";
- PRINT "press any key to continue"
- Pause$ = INPUT$(1)
- RESUME
- CASE 27
-
- ' 27 is the code for "Out of paper":
- PRINT "Printer is out of paper. Insert"
- PRINT "paper, then press any key to continue."
- Pause$ = INPUT$(1)
-
- ' Start reading data from the beginning of first
- ' DATA statement after the paper is inserted:
- RESTORE
- RESUME
- CASE ELSE
-
- ' An unanticipated error has occurred; display the
- ' message for that error and stop the program:
- ON ERROR GOTO 0
- END SELECT
-
- 6.1.2.2 Returning from an Error-Handling Routine
-
- The RESUME statement returns control from an error-handling routine. The
- preceding example used the following two variations of RESUME to return
- from Handler:
-
- ╓┌─┌────────────────────────┌────────────────────────────────────────────────╖
- Statement Action
- ──────────────────────────────────────────────────────────────────────────
- RESUME Causes the program to branch back to the exact
- statement that caused the error.
-
- If the program had to go to another module to
- find an active error handler, control returns to
- the last statement executed in that module.
-
- The preceding program used RESUME to return to
- the PRINT statement that attempted to send output
- to the printer, giving it another chance to print
- the value in Buffer$ after the printer has
- (presumably) been turned on.
-
- RESUME NEXT Causes the program to branch back to the
- statement following the one that caused the
- Statement Action
- ──────────────────────────────────────────────────────────────────────────
- statement following the one that caused the
- error.If the program had to go to another module
- to find an active error handler, control returns
- to the statement following the last statement
- executed in that module.
-
- The preceding program used the statement RESUME
- NEXT when recovering from the Out of DATA error.
- In this case, a simple RESUME would have sent the
- program into an endless loop, since each time
- control returned to the READ statement in the
- main program, another Out of DATA error would
- result, invoking the error routine over and over
- again.
-
- ──────────────────────────────────────────────────────────────────────────
-
-
- Figure 6.1 outlines the flow of a program's control during error handling
- with RESUME.
-
-
- ┌──────────────────────────────────────────────────────────────────┐
- │ ┌─────────┐ │
- │ │ Start │ │
- │ └────┬────┘ │
- │ │ │
- │ │ │
- │ ┌─────────────────────┐ ┌──────────────────────┐ │
- │ ┌─│ Statement with error ├───────│ Error handler │ │
- │ │ └──────────┬───────────┘ └───────────┬──────────┘ │
- │ │ │ │ │
- │ │ ┌┼┐ ┌─────────────────────┐ │
- │ └────────────┘│└───────────────────┤ RESUME │ │
- │ │ └──────────────────────┘ │
- │ │ │
- │ ┌────────┐ │
- │ │ End │ │
- │ └─────────┘ │
- └──────────────────────────────────────────────────────────────────┘
-
- Figure 6.1 Program Flow of Control with RESUME
-
- Contrast the preceding figure with Figure 6.2, which shows what happens
- in a program using RESUME NEXT.
-
-
- ┌──────────────────────────────────────────────────────────────────┐
- │ ┌─────────┐ │
- │ │ Start │ │
- │ └────┬────┘ │
- │ │ │
- │ ┌─────────────────────┐ ┌──────────────────────┐ │
- │ │ Statement with error ├───────│ Error handler │ │
- │ └──────────────────────┘ └───────────┬──────────┘ │
- │ │ │
- │ ┌──────────────────────┐ ┌─────────────────────┐ │
- │ │ Statement following │───────┤ RESUME │ │
- │ │the one with the error│ └──────────────────────┘ │
- │ └──────────┬───────────┘ │
- │ │ │
- │ ┌────────┐ │
- │ │ End │ │
- │ └─────────┘ │
- └──────────────────────────────────────────────────────────────────┘
-
- Figure 6.2 Program Flow of Control with RESUME NEXT
-
- Another variant of RESUME is RESUME line, where line is a line number or
- line label outside any SUB...END SUB, FUNCTION...END FUNCTION, or DEF
- FN...END DEF block. Because line must be outside these blocks, a RESUME
- line statement can produce unexpected effects if it appears in an
- error-handling routine inside a SUB or FUNCTION procedure or a DEF FN
- function. It should generally be avoided in favor of RESUME or RESUME
- NEXT.
-
-
- 6.2 Event Trapping
-
- Section 6.2.1 below compares two methods your BASIC programs can use to
- detect events: polling and trapping. Sections 6.2.2-6.2.4 then discuss
- the different events BASIC can trap, how to set and activate a trap, and
- how to suspend or deactivate the trap. Sections 6.2.5-6.2.7 provide more
- detailed information on trapping keystrokes and music events.
-
- 6.2.1 Detecting Events by Polling
-
- One way to detect an event and reroute program control to the appropriate
- routine is to use "event polling." In polling, your program stops whatever
- it is currently doing and explicitly checks for an event. For example, the
- following loop keeps checking the keyboard until the user presses either
- the Q or N keys:
-
- DO
- Test$ = UCASE$(INKEY$)
- LOOP UNTIL Test$ = "N" OR Test$ = "Q"
-
- Polling works well when you know ahead of time exactly where in the flow
- of the program you want to check for an event.
-
- 6.2.2 Detecting Events by Trapping
-
- But suppose you don't want your program to pause, or you would like it to
- check between every statement (that is, check continuously). In these
- cases, polling is unwieldy or impossible, and trapping becomes the better
- alternative.
-
- Example
-
- The following example shows how to use event trapping:
-
- ' Alert the program that it should branch to "KeySub"
- ' whenever the user presses the F1 function key:
- ON KEY(1) GOSUB KeySub
-
- ' Turn on trapping for the F1 key. BASIC now checks in the
- ' background for this event until the end of the program,
- ' or until trapping is disabled with KEY(1) OFF
- ' or suspended with KEY(1) STOP:
- KEY(1) ON
- OPEN "Data" FOR INPUT AS #1
- OPEN "Data.Out" FOR OUTPUT AS #2
-
- DO UNTIL EOF(1)
- LINE INPUT #1, LineBuffer$
- PRINT #2, LineBuffer$
- LOOP
-
- KeySub: ' When the user presses F1, the program
- . ' branches to this procedure.
- .
- .
- RETURN
-
- 6.2.3 Specifying the Event to Trap and Activating Event Trapping
-
- As you can see from the preceding example, three steps are necessary for
- event trapping:
-
- 1. Define a target subroutine that is known as an "event-handling
- subroutine."
-
- 2. Tell the program to branch to the event-handling subroutine when the
- event takes place with an ON event GOSUB statement.
-
- 3. Activate trapping of that event with an ON event GOSUB statement.
-
- Your program cannot trap a given event until it encounters both an event
- ON and an ON event GOSUB statement.
-
- An event-handling routine is an ordinary BASIC GOSUB routine: control
- passes to the first line of the routine whenever the event is detected and
- returns to the main level of the module containing the routine with a
- RETURN statement.
-
- Note the following important differences between the syntax of error
- trapping and the syntax of event trapping:
-
- Error Trapping Event Trapping
- ──────────────────────────────────────────────────────────────────────────
- Activated with the statement ON Activated with an event ON statement;
- ERROR GOTO, which also specifies a separate statement, ON event GOSUB,
- the first line of the error- specifies the first line of the
- handling routine event-handling subroutine
-
- Returns control from the error Returns control from the event
- routine with one or more RESUME, subroutine with one or more RETURN
- RESUME NEXT, or RESUME line statements
- statements
- ──────────────────────────────────────────────────────────────────────────
-
- 6.2.4 Events That BASIC Can Trap
-
- You can trap the following events within a BASIC program:
-
- BASIC Statement Event Trapped
- ──────────────────────────────────────────────────────────────────────────
- COM(portnumber) Data from one of the serial ports (1 or 2)
- appearing in the communications buffer (the
- intermediate storage area for data sent to or
- received from the serial port)
-
- KEY(keynumber) The user pressing the given key
-
- PEN The user activating the light pen
-
- PLAY(queuelimit) The number of notes remaining to be played in the
- background dropping below queuelimit
-
- STRIG(triggernumber) The user squeezing the trigger of the joystick
-
- TIMER(interval) The passage of interval seconds
- ──────────────────────────────────────────────────────────────────────────
-
- 6.2.5 Suspending or Disabling Event Trapping
-
- You can turn off detection and trapping of any event with the event OFF
- statement. Events occurring after an event OFF statement has been executed
- are ignored. If you want to suspend trapping a given event but continue
- detecting it, use the event STOP statement.
-
- After event STOP, if the event occurs, there is no branch to the
- event-handling routine. However, your program remembers that the event
- occurred, and as soon as trapping is turned back on with event ON,
- branching to the event routine occurs immediately.
-
- Event-handling routines execute an implicit event STOP statement for a
- given event whenever program control is in the routine; this is followed
- by an implicit event ON for that event when program control returns from
- the routine. For example, if a key-handling routine is processing a
- keystroke, trapping the same key is suspended until the previous keystroke
- is completely processed by the routine. If the user presses the same key
- during this time, this new keystroke is remembered and trapped after
- control returns from the key-handling routine.
-
- Example
-
- An event trap interrupts whatever is happening in the program at the
- moment the event occurs. Therefore, if you have a block of statements that
- you do not want interrupted, precede them with event STOP and follow them
- with event ON, as in this example:
-
- ' Once every minute (60 seconds),
- ' branch to the ShowTime subroutine:
- ON TIMER(60) GOSUB ShowTime
-
- ' Activate trapping of the 60-second event:
- TIMER ON
- .
- .
- .
- TIMER STOP ' Suspend trapping.
- . ' A sequence of lines you don't want interrupted,
- . ' even if 60 or more seconds elapse
- .
-
- TIMER ON ' Reactivate trapping.
- .
- .
- .
- END
-
- ShowTime:
-
- ' Get the current row and column position of the cursor,
- ' and store them in the variables Row and Column:
- Row = CSRLIN
- Column = POS(0)
-
- ' Go to the 24th row, 20th column, and print the time:
- LOCATE 24, 20
- PRINT TIME$
-
- ' Restore the cursor to its former position
- ' and return to the main program:
- LOCATE Row, Column
- RETURN
-
- 6.2.6 Trapping Keystrokes
-
- To detect a keystroke and route program control to a key-press routine,
- you need both of the following statements in your program:
-
- ON KEY(keynumber) GOSUB line
- KEY(keynumber) ON
-
- Here, the keynumber value corresponds to the following keys:
-
- Value Key
- ──────────────────────────────────────────────────────────────────────────
- 1-10 Function keys F1-F10 (sometimes called "soft
- keys")
-
- 11 The UP direction key
-
- 12 The LEFT direction key
-
- 13 The RIGHT direction key
-
- 14 The DOWN direction key
-
- 15-25 User-defined keys (see Sections 6.2.6.1-6.2.6.2)
-
- 30 The F11 function key (101-key keyboard only)
-
- 31 The F12 function key (101-key keyboard only)
- ──────────────────────────────────────────────────────────────────────────
-
- Examples
-
- The following two lines cause the program to branch to the KeySub routine
- each time the F2 function key is pressed:
-
- ON KEY(2) GOSUB KeySub
- KEY(2) ON
- .
- .
- .
-
- The following four lines cause the program to branch to the DownKey
- routine when the DOWN direction key is pressed and to the UpKey routine
- when the UP direction key is pressed:
-
- ON KEY(11) GOSUB UpKey
- ON KEY(14) GOSUB DownKey
- KEY(11) ON
- KEY(14) ON
- .
- .
- .
-
- 6.2.6.1 Trapping User-Defined Keys
-
- In addition to providing the preassigned key numbers 1-14 (plus 30 and 31
- with the 101-key keyboard), BASIC allows you to assign the numbers 15-25
- to any of the remaining keys on the keyboard. To define your own key to
- trap, use these three statements:
-
- KEY keynumber, CHR$(0) + CHR$(scancode)
- ON KEY(keynumber) GOSUB line
- KEY(keynumber) ON
-
- Here, keynumber is a value from 15 to 25, and scancode is the scan code
- for that key. (See the first column of the "Keyboard Scan Codes" table in
- Appendix D for these codes.) For example, the following lines cause the
- program to branch to the TKey routine each time the user presses T:
-
- ' Define key 15 (the scan code for "t" is decimal 20):
- KEY 15, CHR$(0) + CHR$(20)
-
- ' Define the trap (where to go when "t" is pressed):
- ON KEY(15) GOSUB TKey
-
- KEY(15) ON ' Turn on detection of key 15.
-
- PRINT "Press q to end."
-
- DO ' Idle loop: wait for user to
- LOOP UNTIL INKEY$ = "q" ' press "q".
-
- END
-
- TKey: ' Key-handling subroutine
- PRINT "Pressed t."
- RETURN
-
- 6.2.6.2 Trapping User-Defined Shifted Keys
-
- You can also set a trap for "shifted" keys. A key is said to be shifted
- when you press it simultaneously with one or more of the special keys
- SHIFT, CTRL, or ALTor if you press it after toggling on the keys NUM LOCK
- or CAPS LOCK.
-
- This is how to trap the following key combinations:
-
- KEY keynumber, CHR$(keyboardflag) + CHR$(scancode)
- ON KEY(keynumber) GOSUB line
- KEY(keynumber) ON
-
- Here, keynumber is a value from 15 to 25; scancode is the scan code for
- the primary key; and keyboardflag is the sum of the individual codes for
- the special keys pressed, as shown in the following list:
-
- Key Code for keyboardflag
- ──────────────────────────────────────────────────────────────────────────
- SHIFT 1, 2, or 3
- Key trapping assumes the left and
- right shift keys are the same, so you
- can trap the SHIFT key with 1 (left),
- 2 (right), or 3 (left + right).
-
- CTRL 4
-
- ALT 8
-
- NUM LOCK 32
-
- CAPS LOCK 64
-
- Any extended key on the 101-key 128
- keyboard (in other words, a key
- such as LEFT or DELETE that is not
- on the numeric keypad)
- ──────────────────────────────────────────────────────────────────────────
-
- For example, the following statements turn on trapping of CTRL+S. Note
- these statements are designed to trap both the CTRL+S (lowercase) and
- CTRL+SHIFT+S (uppercase) key combinations. To trap the uppercase S, your
- program must recognize capital letters produced by holding down the SHIFT
- key, as well as those produced when the CAPS LOCK key is active, as shown
- here:
-
- ' 31 = scan code for S key
- ' 4 = code for CTRL key
- KEY 15, CHR$(4) + CHR$(31) ' Trap CTRL+S.
-
- ' 5 = code for CTRL key + code for SHIFT key
- KEY 16, CHR$(5) + CHR$(31) ' Trap CTRL+SHIFT+S.
-
- ' 68 = code for CTRL key + code for CAPSLOCK
- KEY 17, CHR$(68) + CHR$(31) ' Trap CTRL+CAPSLOCK+S.
-
- ON KEY (15) GOSUB CtrlSTrap ' Tell program where to
- ON KEY (16) GOSUB CtrlSTrap ' branch (note: same
- ON KEY (17) GOSUB CtrlSTrap ' subroutine for each key).
-
- KEY (15) ON ' Activate key detection for
- KEY (16) ON ' all three combinations.
- KEY (17) ON
- .
- .
- .
-
- The following statements turn on trapping of CTRL+ALT+DEL:
-
- ' 12 = 4 + 8 = (code for CTRL key) + (code for ALT key)
- ' 83 = scan code for DEL key
- KEY 20, CHR$(12) + CHR$(83)
- ON KEY(20) GOSUB KeyHandler
- KEY(20) ON
- .
- .
- .
-
- Note in the preceding example that the BASIC event trap overrides the
- normal effect of CTRL+ALT+DEL (system reset). Using this trap in your
- program is a handy way to prevent the user from accidentally rebooting
- while a program is running.
-
- If you use a 101-key keyboard, you can trap any of the keys on the
- dedicated keypad by assigning the string
-
- CHR$(128) + CHR$(scancode)
-
- to any of the keynumber values from 15 to 25.
-
- The next example shows how to trap the LEFT direction keys on both the
- dedicated cursor keypad and the numeric keypad.
-
- ' 128 = keyboard flag for keys on the
- ' dedicated cursor keypad
- ' 75 = scan code for LEFT arrow key
-
- KEY 15, CHR$(128) + CHR$(75) ' Trap LEFT key on
- ON KEY(15) GOSUB CursorPad ' the dedicated
- KEY(15) ON ' cursor keypad.
-
- ON KEY(12) GOSUB NumericPad ' Trap LEFT key on
- KEY(12) ON ' the numeric keypad.
-
- DO: LOOP UNTIL INKEY$ = "q" ' Start idle loop.
- END
-
- CursorPad:
- PRINT "Pressed LEFT key on cursor keypad."
- RETURN
-
- NumericPad:
- PRINT "Pressed LEFT key on numeric keypad."
- RETURN
-
- ──────────────────────────────────────────────────────────────────────────
- IMPORTANT
- For compatibility, QuickBASIC adopts many conventions of BASICA. One of
- these has to do with the way FUNCTION keys are trapped.
- If you initiate FUNCTION key trapping with an ON KEY (n) GOSUB
- statement, both BASICA and QuickBASIC trap Fn regardless of whether a
- shift key (CTRL, ALT, SHIFT) is also pressed. This means that
- user-defined traps for shifted versions of that FUNCTION key are
- ignored.
- Therefore, if you wish to trap a FUNCTION key in both its shifted and
- unshifted states, you should create a user definition for each state.
- Keys that are only used unshifted can continue to use the ON KEY (n)
- GOSUB statement.
- ──────────────────────────────────────────────────────────────────────────
-
- 6.2.7 Trapping Music Events
-
- When you use the PLAY statement to play music, you can choose whether the
- music plays in the foreground or in the background. If you choose
- foreground music (which is the default) nothing else can happen until the
- music finishes playing. However, if you use the MB (Music Background)
- option in a PLAY music string, the tune plays in the background while
- subsequent statements in your program continue executing.
-
- The PLAY statement plays music in the background by feeding up to 32 notes
- at a time into a buffer, then playing the notes in the buffer while the
- program does other things. A "music trap" works by checking the number of
- notes currently left to be played in the buffer. As soon as this number
- drops below the limit you set in the trap, the program branches to the
- first line of the specified routine.
-
- To set a music trap in your program, you need the following statements:
-
- ON PLAY(limit) GOSUB line
- PLAY ON
- PLAY "MB"
- .
- .
- .
- PLAY musicstring
- [[PLAY musicstring]]
- .
- .
- .
-
- Here, limit is a number between 1 and 32. For example, this fragment
- causes the program to branch to the MusicTrap subroutine whenever the
- number of notes remaining to be played in the music buffer goes from eight
- to seven:
-
- ON PLAY(8) GOSUB MusicTrap
- PLAY ON
- .
- .
- .
- PLAY "MB" ' Play subsequent notes in the background.
- PLAY "o1 A# B# C-"
- .
- .
- .
- MusicTrap:
- ' Music-trap subroutine
- .
- .
- .
- RETURN
-
- ──────────────────────────────────────────────────────────────────────────
- IMPORTANT
- A music trap is triggered only when the number of notes goes from limit
- to limit-1. For example, if the music buffer in the preceding example
- never contained more than seven notes, the trap would never occur. In
- the example, the trap happens only when the number of notes drops from
- eight to seven.
- ──────────────────────────────────────────────────────────────────────────
-
- You can use a music-trap subroutine to play the same piece of music
- repeatedly while your program executes, as shown in the next example:
-
- ' Turn on trapping of background music events:
- PLAY ON
-
- ' Branch to the Refresh subroutine when there are fewer than
- ' two notes in the background music buffer:
- ON PLAY(2) GOSUB Refresh
-
- PRINT "Press any key to start, q to end."
- Pause$ = INPUT$(1)
-
- ' Select the background music option for PLAY:
- PLAY "MB"
-
- ' Start playing the music, so notes will be put in the
- ' background music buffer:
- GOSUB Refresh
-
- I = 0
-
- DO
-
- ' Print the numbers from 0 to 10,000 over and over until
- ' the user presses the "q" key. While this is happening,
- ' the music will repeat in the background:
- PRINT I
- I = (I + 1) MOD 10001
- LOOP UNTIL INKEY$ = "q"
-
- END
-
- Refresh:
-
- ' Plays the opening motive of
- ' Beethoven's Fifth Symphony:
- Listen$ = "t180 o2 p2 p8 L8 GGG L2 E-"
- Fate$ = "p24 p8 L8 FFF L2 D"
- PLAY Listen$ + Fate$
- RETURN
-
-
- 6.3 Error and Event Trapping in SUB or FUNCTION Procedures
-
- The most important thing to remember when using error or event trapping
- with BASIC procedures is that either of the following statements can
- appear within a SUB...END SUB or FUNCTION...END FUNCTION block:
-
- ON ERROR GOTO line ON event GOSUB line
-
- However, the line referred to in each case must identify a line in the
- module-level code, not another line within the SUB or FUNCTION.
-
- Example
-
- The following example shows where to put an error-handling routine that
- processes errors trapped within a SUB procedure:
-
- CALL ShortSub
- END
-
- CatchError:
- ' Put the CatchError routine at the module level,
- ' outside the subprogram:
- PRINT "Error" ERR "caught by error handler."
- RESUME NEXT
-
- SUB ShortSub STATIC
- ON ERROR GOTO CatchError
- ERROR 62
- END SUB
-
- Output
-
- Error 62 caught by error handler.
-
-
- 6.4 Trapping across Multiple Modules
-
- Prior to QuickBASIC 4.5, only events could be trapped across modules. Once
- an event-handling routine was defined and an event trap was activated in
- one module, an occurrence of that event during program execution in any
- other module triggered a branch to the routine.
-
- Errors could not be trapped across modules. If an error occurred in a
- module lacking an active error handler, program execution would halt, even
- if there were a handler in another module that could have taken care of
- the problem.
-
- QuickBASIC 4.5 expands the scope of error trapping. Errors, as well as
- events, can be trapped across modules. The next two sections explain how
- this works and the slight remaining differences between event and error
- trapping.
-
- 6.4.1 Event Trapping across Modules
-
- The output from the following program shows that a trap set for the F1
- function key in the main module is triggered even when program control is
- in another module:
-
- ' =========================================================
- ' MODULE
- ' =========================================================
- ON KEY (1) GOSUB GotF1Key
- KEY (1) ON
- PRINT "In main module. Press c to continue."
-
- DO: LOOP UNTIL INKEY$ = "c"
-
- CALL SubKey
-
- PRINT "Back in main module. Press q to end."
- DO : LOOP UNTIL INKEY$ = "q"
- END
-
- GotF1Key:
- PRINT "Handled F1 keystroke in main module."
- RETURN
-
- ' =========================================================
- ' SUBKEY MODULE
- ' =========================================================
- SUB SubKey STATIC
- PRINT "In module with SUBKEY. Press r to return."
-
- ' Pressing F1 here still invokes the GotF1Key
- ' subroutine in the MAIN module:
- DO: LOOP UNTIL INKEY$ = "r"
- END SUB
-
- Output
-
- In main module. Press c to continue.
- Handled F1 keystroke in main module.
- In module with SUBKEY. Press r to return.
- Handled F1 keystroke in main module.
- Back in main module. Press q to end.
- Handled F1 keystroke in main module.
-
- 6.4.2 Error Trapping across Modules
-
- Errors can be trapped across multiple modules. If there is no active error
- handler in the module where the error occurred, BASIC looks for one in the
- module from which the active module was invoked, continuing back through
- the sequence of modules called until it finds a module with an active
- error handler. If it cannot find one, an error message is displayed and
- program execution halts.
-
- Note that BASIC does not search through all modules──only the ones that
- were in the path of invocation leading to the code that produced the
- error.
-
- An ON ERROR statement must be executed before an error occurs in order for
- BASIC to look for a handler. Therefore, you must put the ON ERROR GOTO
- statement where the flow of a program's control can reach it; for example,
- place it inside a procedure called from the main module (see the examples
- that follow).
-
- Examples
-
- The following example shows how to trap errors for a procedure in a Quick
- library. The AdapterType procedure in this library tries all possible
- SCREEN statements to see which graphics screen modes your computer's
- hardware supports. (See Appendix H, "Creating and Using Quick Libraries,"
- for more information on Quick libraries.)
-
- ' =========== MODULE-LEVEL CODE IN QUICK LIBRARY ==========
- ' The error-handling routines for procedures in this
- ' library must be defined at this level. This level is
- ' executed only when there is an error in the procedures.
- ' =========================================================
-
- DEFINT A-Z
-
- CONST FALSE = 0, TRUE = NOT FALSE
-
- .
- .
- .
- CALL AdapterType
- .
- .
- .
- END
-
- DitchMe: ' Error-handling routine
- DisplayError = TRUE
- RESUME NEXT
-
- ' ========== PROCEDURE-LEVEL CODE IN QUICK LIBRARY ========
- ' Error trapping is activated at this level.
- ' =========================================================
-
- SUB AdapterType STATIC
-
- SHARED DisplayError ' DisplayError variable is
- ' shared with DitchMe error
- ' handler in code above.
- DIM DisplayType(1 TO 13) ' Dimension DisplayType
- ' array.
-
- J = 1 ' Initialize subscript
- ' counter for DisplayType
- ' array.
-
- ON ERROR GOTO DitchMe ' Set up the error trap.
-
- FOR Test = 13 TO 1 STEP -1
- SCREEN Test ' Try a SCREEN statement to
- ' see if it causes error.
- IF NOT DisplayError THEN ' No error, so this is a
- ' valid screen mode.
- DisplayType(J) = Test ' Store mode in array.
- J = J + 1 ' Increment the subscript
- ' counter.
- ELSE
- DisplayError = FALSE ' Error; reset DisplayError.
- END IF
- NEXT Test
-
- SCREEN 0, 0 ' Set 80-column text mode.
- WIDTH 80
- LOCATE 5, 10
- PRINT "Your computer supports these screen modes:"
- PRINT
-
- FOR I = 1 TO J ' Print modes not causing
- ' errors.
- PRINT TAB(20); "SCREEN"; DisplayType(I)
- NEXT I
-
- LOCATE 20, 10
- PRINT "Press any key to continue..."
-
- DO: LOOP WHILE INKEY$ = ""
-
- END SUB
-
- If you want the error-handling routine in each module to do the exactly
- the same thing, you can have each routine invoke a common error-processing
- SUB procedure, as shown in the next example:
-
- ' =========================================================
- ' MAIN MODULE
- ' =========================================================
-
- DECLARE SUB GlobalHandler (ModuleName$)
- DECLARE SUB ShortSub ()
-
- ON ERROR GOTO LocalHandler
- ERROR 57 ' Simulate occurrence of error 57
- ' ("Device I/O error").
- ShortSub ' Call the ShortSub SUB.
- END
-
- LocalHandler:
- ModuleName$ = "MAIN"
- CALL GlobalHandler(ModuleName$) ' Call the
- ' GlobalHandler SUB.
- RESUME NEXT
-
- ' =========================================================
- ' SHORTSUB MODULE
- ' =========================================================
-
- DECLARE SUB GlobalHandler (ModuleName$)
-
- LocalHandler:
- ModuleName$ = "SHORTSUB"
- GlobalHandler ModuleName$ ' Call GlobalHandler.
- RESUME NEXT
-
- SUB ShortSub STATIC
- ON ERROR GOTO LocalHandler
- ERROR 13 ' Simulate a "Type mismatch" error.
- END SUB
-
-
- ' =========================================================
- ' GLOBALHANDLER MODULE
- ' =========================================================
-
- SUB GlobalHandler (ModuleName$) STATIC
- PRINT "Trapped error";ERR;"in";ModuleName$;"module"
- END SUB
-
- Output
-
- Trapped error 57 in MAIN module.
- Trapped error 13 in SHORTSUB module.
-
-
- 6.5 Trapping Errors and Events in Programs Compiled with BC
-
- If both of the following statements apply to your program, then you must
- use the appropriate BC command-line option listed below when compiling
- your program:
-
- ■ You are developing the program outside the QuickBASIC environment──that
- is, you are using another text editor to enter your BASIC source code,
- then creating a stand-alone executable program from this source code
- with the commands BC and LINK.
-
- ■ Your program contains any of the statements listed in the second column
- below.
-
- Table 6.1 BC Command-Line Options for Error and Event Trapping
- ╓┌─┌──────────────┌────────────────────────────┌─────────────────────────────╖
- Command-Line Statements Explanation
- Option
- ──────────────────────────────────────────────────────────────────────────
- /E ON ERROR GOTO The /E option tells the
- RESUME line compiler your program does its
- own error trapping with ON
- ERROR GOTO and RESUME
- statements.
-
- /V ON event GOSUB The /V option tells the
- event ON program to check between each
- statement to see if the given
- event has taken place
- Command-Line Statements Explanation
- Option
- ──────────────────────────────────────────────────────────────────────────
- event has taken place
- (contrast this with the effect
- of /W).
-
- /W ON event GOSUB The /W option tells the
- event ON program to check between each
- line to see if the given event
- has taken place (contrast this
- with the effect of /V).
- Since BASIC allows multiple
- statements on a single line,
- programs compiled with /W may
- check less frequently than
- those compiled with /V.
-
- /X RESUME The /X option tells the
- RESUME NEXT compiler you have used one of
- RESUME 0 the preceding forms of RESUME
- Command-Line Statements Explanation
- Option
- ──────────────────────────────────────────────────────────────────────────
- RESUME 0 the preceding forms of RESUME
- in your program to return
- control from an error-handling
- routine.
- ──────────────────────────────────────────────────────────────────────────
-
-
- Example
-
- The following DOS command lines compile and link a BASIC module named
- RMTAB.BAS, creating a stand-alone program RMTAB.EXE. (As this program is
- compiled without the /O option, it requires the BRUN45.LIB run-time
- library in order to run. See Appendix G, "Compiling and Linking from
- DOS," for more information on compiling and linking.) Since this module
- contains ON ERROR GOTO and RESUME NEXT statements, the /E and /X options
- are required when compiling.
-
- BC RMTAB , , /E /X;
- LINK RMTAB;
-
-
- 6.6 Sample Application: Trapping File-Access Errors (FILERR.BAS)
-
- The following program gets as input both a file name and a string to
- search for in the file. It then lists all lines in the given file
- containing the specified string. If a file-access error occurs, it is
- trapped and dealt with in the ErrorProc routine.
-
- Statements and Functions Used
-
- This program demonstrates the use of the following error-handling
- statements and functions:
-
- ■ ERR
-
- ■ ON ERROR GOTO
-
- ■ RESUME
-
- ■ RESUME NEXT
-
- Program Listing
-
- ' Declare symbolic constants:
- CONST FALSE = 0, TRUE = NOT FALSE
-
- DECLARE FUNCTION GetFileName$ ()
-
- ' Set up the ERROR trap and specify
- ' the name of the error-handling routine:
- ON ERROR GOTO ErrorProc
-
- DO
- Restart = FALSE
- CLS
-
- FileName$ = GetFileName$ ' Input file name.
-
- IF FileName$ = "" THEN
- END ' End if <ENTER> pressed.
- ELSE
-
- ' Otherwise, open the file, assigning it
- ' the next available file number:
- FileNum = FREEFILE
- OPEN FileName$ FOR INPUT AS FileNum
- END IF
-
- IF NOT Restart THEN
-
- ' Input search string:
- LINE INPUT "Enter string to locate:", LocString$
- LocString$ = UCASE$(LocString$)
-
- ' Loop through the lines in the file,
- ' printing them if they contain the search string:
- LineNum = 1
- DO WHILE NOT EOF(FileNum)
-
- ' Input line from file:
- LINE INPUT #FileNum, LineBuffer$
-
- ' Check for string, printing the line
- ' and its number if found:
- IF INSTR(UCASE$(LineBuffer$), LocString$) <> 0 THEN
- PRINT USING "#### &"; LineNum, LineBuffer$
- END IF
-
- LineNum = LineNum + 1
- LOOP
-
- CLOSE FileNum ' Close the file.
-
- END IF
- LOOP WHILE Restart = TRUE
-
- END
-
- ErrorProc:
-
- SELECT CASE ERR
-
- CASE 64: ' Bad file name
- PRINT "** ERROR - Invalid file name"
-
- ' Get a new file name and try again:
- FileName$ = GetFileName$
-
- ' Resume at the statement that caused the error:
- RESUME
-
- CASE 71: ' Disk not ready.
- PRINT "** ERROR - Disk drive not ready"
- PRINT "Press C to continue, R to restart, Q to quit: "
- DO
- Char$ = UCASE$(INPUT$(1))
- IF Char$ = "C" THEN
- RESUME ' Resume where you left off.
-
- ELSEIF Char$ = "R" THEN
- Restart = TRUE ' Resume at beginning.
- RESUME NEXT
-
- ELSEIF Char$ = "Q" THEN
- END ' Don't resume at all.
- END IF
- LOOP
-
- CASE 53, 76: ' File or path not found.
- PRINT "** ERROR - File or path not found"
- FileName$ = GetFileName$
- RESUME
-
- CASE ELSE: ' Unforeseen error.
-
- ' Disable error trapping and
- ' print standard system message:
- ON ERROR GOTO 0
- END SELECT
-
- ' ===================== GETFILENAME$ =======================
- ' Returns a file name from user input
- ' ==========================================================
-
- FUNCTION GetFileName$ STATIC
- INPUT "Enter file to search (or ENTER to quit):", FTemp$
- GetFileName$ = FTemp$
- END FUNCTION
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- Chapter 7 Programming with Modules
-
- This chapter shows how you can gain more control over your programming
- projects by dividing them into "modules." Modules provide a powerful
- organizing function by letting you divide a program into logically related
- parts (rather than keeping all the code in one file).
-
- This chapter will show you how to use modules to:
-
- ■ Write and test new procedures separately from the rest of the program
-
- ■ Create libraries of your own SUB and FUNCTION procedures that can be
- added to any new program
-
- ■ Combine routines from other languages (such as C or MASM) with your
- BASIC programs
-
-
- 7.1 Why Use Modules?
-
- A module is a file that contains an executable part of your program. A
- complete program can be contained in a single module, or it can be divided
- among two or more modules.
-
- In dividing up a program into modules, logically related sections are
- placed in separate files. This organization can speed and simplify the
- process of writing, testing, and debugging.
-
- Dividing your program into modules has these advantages:
-
- ■ Modules allow procedures to be written separately from the rest of the
- program, then combined with it. This arrangement is especially useful
- for testing the procedures, since they can then be checked outside the
- environment of the program.
-
- ■ Two or more programmers can work on different parts of the same program
- without interference. This is especially helpful in managing complex
- programming projects.
-
- ■ As you create procedures that meet your own specific programming needs,
- you can add these procedures to their own module. They can then be
- reused in new programs simply by loading that module.
-
- ■ Multiple modules simplify software maintenance. A procedure used by many
- programs can be in one library module; if changes are needed, it only
- has to be modified once.
-
-
- 7.2 Main Modules
-
- The module containing the first executable statement of a program is
- called the "main module." This statement is never part of a procedure,
- because execution cannot begin within a procedure.
-
- Everything in a module except SUB and FUNCTION procedures is said to be
- "module-level code." In QuickBASIC, the module-level code is every
- statement that can be accessed without switching to a procedure-editing
- window. Figure 7.1 illustrates the relationship between these elements.
-
-
- 7.3 Modules Containing Only Procedures
-
- A module need not contain module-level code; a module can consist of
- nothing but SUB and FUNCTION procedures. Indeed, this is the most
- important use of modules.
-
- Modules are often used to "split off" the procedures from the body of the
- program. This makes it easy to divide a project among programmers, for
- example. Also, as you create general-purpose procedures that are useful in
- a variety of programs (such as procedures that evaluate matrices, send
- binary data to a COM port, alter strings, or handle errors), these can be
- stored in modules, then used in new programs simply by loading the
- appropriate module into QuickBASIC.
-
- ──────────────────────────────────────────────────────────────────────────
- NOTE
- If a procedure in a procedures-only module needs an error- or
- event-handling routine or a COMMON SHARED statement, these are inserted
- at module level.
- ──────────────────────────────────────────────────────────────────────────
-
-
- ┌───────────────────────────────────────────────────────────────────────┐
- │ Program execution begins here │
- │ ┌─ ┌────────────────────────────────────────────┐ ─┐ │
- │ │ │ declarations and definitions │ │ │
- │ │ │ executable program statement 1 │ │ │
- │ │ │ executable program statement 2 │ │ │
- │ │ │ . │ ├─ Module- │
- │ │ │ . │ │ level code │
- │ │ │ . │ │ │
- │ │ │ END │ │ │
- │ │ │ error-handling routines │ │ │
- │ │ └────────────────────────────────────────────┘ ─┘ │
- │ │ ┌────────────────────────────────────────────┐ ─┐ │
- │ │ │ SUB │ │ │
- │ │ │ statements in first SUB procedure │ │ │
- │ │ │ ENDSUB │ │ │
- │ │ └────────────────────────────────────────────┘ │ │
- │ │ ┌────────────────────────────────────────────┐ │ │
- │ Main ─┤ │ SUB │ │ │
- │module │ │ statements in second SUB procedure │ │ │
- │ │ │ ENDSUB │ │ │
- │ │ └────────────────────────────────────────────┘ │ │
- │ │ . │ │
- │ │ . ├─Procedures │
- │ │ . │ │
- │ │ ┌────────────────────────────────────────────┐ │ │
- │ │ │ FUNCTION │ │ │
- │ │ │ statements in first FUNCTION procedure │ │ │
- │ │ │ ENDFUNCTION │ │ │
- │ │ └────────────────────────────────────────────┘ │ │
- │ │ ┌────────────────────────────────────────────┐ │ │
- │ │ │ FUNCTION │ │ │
- │ │ │ statements in second FUNCTION procedure │ │ │
- │ │ │ ENDFUNCTION │ │ │
- │ │ └────────────────────────────────────────────┘ │ │
- │ │ . │ │
- │ │ . │ │
- │ │ . │ │
- │ └─ ─┘ │
- │ │
- └───────────────────────────────────────────────────────────────────────┘
-
- Figure 7.1 Main Module Showing Module-Level Code and Procedures
-
-
- 7.4 Creating a Procedures-Only Module
-
- It's easy to create a module that contains only procedures. You can enter
- new procedures in a separate file, or you can move procedures from one
- file to another.
-
- To create a new module:
-
- 1. Invoke QuickBASIC without opening or loading any files.
-
- 2. Write all the SUB and FUNCTION procedures you wish, but don't enter any
- module-level code. (Any error- or event-trapping routines and BASIC
- declarations needed are exceptions.)
-
- 3. Use the Save As command to name and save this module.
-
- To move procedures from one module to another:
-
- 1. Load the files containing the procedures you want to move.
-
- 2. If the destination file already exists, use the Load File command from
- the File menu to load it, too. If it doesn't exist, use the Create File
- option from the File menu to make the new file.
-
- 3. Choose the SUBs command from the View menu and use its Move feature to
- transfer the procedures from the old to the new file. This transfer is
- made final when you quit QuickBASIC and respond Yes to the dialog box
- that asks whether you want to save the modified files; otherwise, the
- procedures remain where they were when you started.
-
-
- 7.5 Loading Modules
-
- In QuickBASIC, you can load as many modules as you wish (limited only by
- the available memory) using the Load File command from the File menu. All
- the procedures in all the loaded modules can be called from any other
- procedure or from module-level code. If a module happens to contain a
- procedure that is never called, no harm occurs.
-
- Any or all of the loaded modules can contain module-level code. QuickBASIC
- normally begins execution with the module-level code of the first module
- loaded. If you want execution to begin in a different module, use the Set
- Main Module command from the Run menu. Execution normally halts at the end
- of the designated main module; by design, QuickBASIC does not continue
- execution with the module-level code from other modules.
-
- The ability to choose which module-level code gets executed is useful when
- comparing two versions of the same program. For example, you might want to
- test different user interfaces by putting each in a separate module. You
- can also place test code in a module containing only procedures, then use
- the Set Main Module command to switch between the program and the tests.
-
- You do not have to keep track of which modules your program uses. Whenever
- you use the Save All command, QuickBASIC creates (or updates) a .MAK file,
- which lists all the modules currently loaded. The next time the main
- module is loaded with the Open Program command, QuickBASIC consults this
- .MAK file and automatically loads the modules listed in it.
-
-
- 7.6 Using the DECLARE Statement with Multiple Modules
-
- The DECLARE statement has several important functions in QuickBASIC. Using
- a DECLARE statement will
-
- 1. Specify the sequence and data types of a procedure's parameters
-
- 2. Enable type-checking, which confirms, each time a procedure is called,
- that the arguments agree with the parameters in both number and data
- type
-
- 3. Identify a FUNCTION procedure's name as a procedure name, not a
- variable name
-
- 4. Most important of all, enable the main module to call procedures
- located in other modules (or Quick libraries)
-
- QuickBASIC has its own system for automatically inserting the required
- DECLARE statements into your modules. Section 2.5.4, "Checking Arguments
- with the DECLARE Statement," explains the features and limitations of this
- system.
-
- Despite QuickBASIC's automatic insertion of the DECLARE statement, you may
- wish to create a separate include file that contains all the DECLARE
- statements required for a program. You can update this file manually as
- you add and delete procedures or modify your argument lists.
-
- If you write your programs with a text editor (rather than the QuickBASIC
- programming environment) and compile with BC, you must insert DECLARE
- statements manually.
-
-
- 7.7 Accessing Variables from Two or More Modules
-
- You can use the SHARED attribute to make variables accessible both at
- module level and within that module's procedures. If these procedures are
- moved to another module, however, these variables are no longer shared.
-
- You could pass these variables to each procedure through its argument
- list. This may be inconvenient, though, if you need to pass a large number
- of variables.
-
- One solution is to use COMMON statements, which enable two or more modules
- to access the same group of variables. Section 2.6, "Sharing Variables
- with SHARED," explains how to do this.
-
- Another solution is to use a TYPE...END TYPE statement to combine all the
- variables you wish to pass into a single structure. The argument and
- parameter lists then have to include only one variable name, no matter how
- many variables are passed.
-
- If you are simply splitting up a program and its procedures into separate
- modules, either of these approaches works well. If, on the other hand, you
- are adding a procedure to a module (for use in other programs), you should
- avoid using a COMMON statement. Modules are supposed to make it easy to
- add existing procedures to new programs; COMMON statements complicate the
- process. If a procedure needs a large group of variables, it may not
- belong in a separate module.
-
-
- 7.8 Using Modules During Program Development
-
- When you start a new programming project, you should first look through
- existing modules to see if there are procedures that can be reused in your
- new software. If any of these procedures aren't already in a separate
- module, you should consider moving them to one.
-
- As your program takes shape, newly written procedures automatically become
- part of the program file (that is, the main module). You can move them to
- a separate module for testing or perhaps add them to one of your own
- modules along with other general-purpose procedures that are used in other
- programs.
-
- Your program may need procedures written in other languages. (For example,
- MASM is ideal for direct interface with the hardware, FORTRAN has almost
- any math function you could want, Pascal allows the creation of
- sophisticated data structures, and C provides both structured code and
- direct memory access.) These procedures are compiled and linked into a
- Quick library for use in your program. You can also write a separate
- module to test Quick library procedures the same way you would test other
- procedures.
-
-
- 7.9 Compiling and Linking Modules
-
- The end product of your programming efforts is usually a stand-alone .EXE
- file. You can create one in QuickBASIC by loading all of a program's
- modules, then selecting the Make EXE File command from the Run menu.
-
- You can also compile modules with the BC command-line compiler, then use
- LINK to combine the object code. Object files from code written in other
- languages can be linked at the same time.
-
- ──────────────────────────────────────────────────────────────────────────
- NOTE
- When you use the Make EXE File command, all the module-level code and
- every procedure currently loaded is included in the .EXE file, whether
- or not the program uses this code. If you want your program to be as
- compact as possible, you must unload all unneeded module-level code and
- all unneeded procedures before compiling. The same rule applies when
- using BC to compile from the command line; all unused code should be
- removed from the files.
- ──────────────────────────────────────────────────────────────────────────
-
-
- 7.10 Quick Libraries
-
- Although Microsoft Quick libraries are not modules, it is important that
- you understand their relationship with modules.
-
- A Quick library contains nothing but procedures. These procedures can be
- written not only in QuickBASIC, but also in other Microsoft languages as
- well (C, Pascal, FORTRAN, and MASM).
-
- A Quick library contains only compiled code. (Modules contain QuickBASIC
- source code.) A Quick library is created by linking compiled object code
- (.OBJ files). The code in a Quick library can come from any combination of
- Microsoft languages. Appendix H, "Creating and Using Quick Libraries,"
- explains how to create Quick libraries from object code and how to add new
- object code to existing Quick libraries.
-
- Quick libraries have several uses:
-
- ■ They provide an interface between QuickBASIC and other languages.
-
- ■ They allow designers to hide proprietary software. Updates and utilities
- can be distributed as Quick libraries without revealing the source code.
-
- ■ They load faster and are usually smaller than modules. If a large
- program with many modules loads slowly, converting the nonmain modules
- into a Quick library will improve loading performance.
-
- Note, however, that modules are the easiest way to work on procedures
- during development because modules are immediately ready to run after each
- edit; you don't have to recreate the Quick library. If you want to put
- your QuickBASIC procedures in a Quick library, wait until the procedures
- are complete and thoroughly debugged.
-
- When a Quick library is created, any module-level code in the file it was
- created from is automatically included. However, other modules cannot
- access this code, so it just wastes space. Before converting a module to a
- Quick library, be sure that all module-level statements (except any error
- or event handlers and declarations that are used by the procedures) have
- been removed.
-
- ──────────────────────────────────────────────────────────────────────────
- NOTE
- Quick libraries are not included in .MAK files and must be loaded with
- the / L option when you run QuickBASIC. A Quick library has the file
- extension .QLB. During the process of creating the Quick library,
- another library file with the extension .LIB is created. This file
- contains the same code as the Quick library but in a form that allows it
- to be linked with the rest of the program to create a stand-alone
- application.
-
- If you use Quick libraries to distribute proprietary code
- (data-manipulation procedures, for example), be sure to include the .LIB
- files so that your customers can create stand-alone applications that
- use these procedures. Otherwise, they will be limited to running
- applications within the QuickBASIC environment.
- ──────────────────────────────────────────────────────────────────────────
-
- 7.10.1 Creating Quick Libraries
-
- You can create a Quick library of QuickBASIC procedures with the Make
- Library command from the Run menu. The Quick library created contains
- every procedure currently loaded, whether or not your program calls it.
- (It also contains all the module-level code.) If you want the Quick
- library to be compact, be sure to remove all unused procedures and all
- unnecessary module-level code first.
-
- You can create as many Quick libraries as you like, containing whatever
- combination of procedures you wish. However, only one Quick library can be
- loaded into QuickBASIC at a time. (You would generally create
- application-specific Quick libraries, containing only the procedures a
- particular program needs.) Large Quick libraries can be created by loading
- many modules, then using the Make Library command.
-
- You can also compile one or more modules with the BC command, then link
- the object code files to create a Quick library. Quick libraries of
- procedures written
-
- in other languages are created the same way. In linking, you are not
- limited to one language; the object-code files from any number of
- Microsoft languages can be combined in one Quick library. Appendix H,
- "Creating and Using Quick Libraries," explains how to convert object-code
- (.OBJ) files into Quick libraries.
-
-
- 7.11 Tips for Good Programming with Modules
-
- You can use modules in any way you think will improve your program or help
- organize your work. The following suggestions are offered as a guide.
-
- 1. Think and organize first.
-
- When you start on a new project, make a list of the operations you want
- to be performed by procedures. Then look through your own procedure
- library to see if there are any you can use, either as-is or with
- slight modifications. Don't waste time "reinventing the wheel."
-
- 2. Write generalized procedures with broad application.
-
- Try to write procedures that are useful in a wide variety of programs.
- Don't, however, make the procedure needlessly complex. A good procedure
- is a simple, finely honed tool, not a Swiss army knife.
-
- It is sometimes useful to alter an existing procedure to work in a new
- program. This might require modifying programs you've already written,
- but it's worth the trouble if the revised procedure is more powerful or
- has broader application.
-
- 3. When creating your own procedure modules, keep logically separate
- procedures in separate modules.
-
- It makes sense to put string-manipulation procedures in one module,
- matrix-handling procedures in another, and data-communication
- procedures in a third. This arrangement avoids confusion and makes it
- easy to find the procedure you need.
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- PART 2 HEART OF BASIC
- ────────────────────────────────────────────────────────────────────────────
-
- Part 2 provides a quick-reference guide to all statements and functions
- used in this version of BASIC.
-
- Chapter 8 gives a brief summary of the action of each statement or
- function──organized alphabetically by keyword──and includes syntax lines
- that identify the statement's correct form. Use it when programming to
- remind yourself how each one works.
-
- Chapter 9 is made up of reference tables that organize commonly used
- statements and functions by programming topic. These tables follow the
- same organization as the first six chapters of this book. Use these tables
- to identify alternative ways to approach particular programming
- objectives.
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- Chapter 8 Statement and Function Summary
-
- This chapter summarizes QuickBASIC statements and functions. Each
- statement or function name is followed by an action description and a
- syntax line. The syntax line shows exactly what you must enter to use the
- statement.
-
- Complete details of the typographic conventions used in syntax lines are
- given in the introduction to this manual. In general, items you must type
- exactly as shown are in boldface type; placeholders for items of
- information you must supply are in Italic type. Square brackets indicate
- optional items.
-
- The QB Advisor (QuickBASIC's on-line language help) provides for each
- statement or function:
-
- ■ A summary of the statement's action and syntax (the QuickSCREEN)
-
- ■ Complete details of how to use the statement, including explanations of
- the placeholders
-
- ■ One of more program examples illustrating statement use
-
- You can access this information by putting the cursor on any BASIC keyword
- displayed in the QuickBASIC View window and pressing F1.
-
- The statements and functions in this chapter are grouped by topic in
- Chapter 9, "Quick-Reference Tables." Use Chapter 9 to find out what
- statements are available for a particular programming task.
-
-
- ABS Function
-
- Returns the absolute value of a numeric expression
-
- SYNTAX ABS(numeric-expression)
-
-
- ASC Function
-
- Returns a numeric value that is the ASCII code for the first character in
- a string expression
-
- SYNTAX ASC(stringexpression)
-
-
- ATN Function
-
- Returns the arctangent of a numeric expression (the angle whose tangent is
- equal to the numeric expression)
-
- SYNTAX ATN(numeric-expression)
-
-
- BEEP Statement
-
- Sounds the speaker
-
- SYNTAX BEEP
-
-
- BLOAD Statement
-
- Loads a memory-image file, created by BSAVE, into memory from an input
- file or device
-
- SYNTAX BLOAD filespec [[,offset]]
-
-
- BSAVE Statement
-
- Transfers the contents of an area of memory to an output file or device
-
- SYNTAX BSAVE filespec,offset,length
-
-
- CALL Statement (BASIC Procedures)
-
- Transfers control to a BASIC SUB
-
- SYNTAX 1 CALL name[[(argumentlist )]]
-
- SYNTAX 2 name[[argumentlist]]
-
-
- CALL, CALLS Statement (Non-BASIC Procedures)
-
- Transfers control to a procedure written in another language
-
- SYNTAX 1 CALL name [[(call-argumentlist )]]
-
- SYNTAX 2 name [[call-argumentlist]]
-
- SYNTAX 3 CALLS name [[(calls-argumentlist )]]
-
-
- CALL INT86OLD Statements
-
- Allows programs to perform DOS system calls
-
- SYNTAX CALL INT86OLD (int_no,in_array(),out_array())
- CALL INT86XOLD (int_no,in_array(),out_array())
-
-
- CALL ABSOLUTE Statement
-
- Transfers control to a machine-language procedure
-
- SYNTAX CALL ABSOLUTE ([[argumentlist,]]integervariable)
-
-
- CALL INTERRUPT Statements
-
- Allows BASIC programs to perform DOS system calls
-
- SYNTAX CALL INTERRUPT (interruptnum, inregs, outregs)
- CALL INTERRUPTX (interruptnum, inregs, outregs)
-
-
- CDBL Function
-
- Converts a numeric expression to a double-precision number
-
- SYNTAX CDBL(numeric-expression)
-
-
- CHAIN Statement
-
- Transfers control from the current program to another program
-
- SYNTAX CHAIN filespec
-
-
- CHDIR Statement
-
- Changes the current default directory for the specified drive
-
- SYNTAX CHDIR pathspec
-
-
- CHR$ Function
-
- Returns a one-character string whose ASCII code is the argument
-
- SYNTAX CHR$(code)
-
-
- CINT Function
-
- Converts a numeric expression to an integer by rounding the fractional
- part of the expression
-
- SYNTAX CINT(numeric-expression)
-
-
- CIRCLE Statement
-
- Draws an ellipse or circle with a specified center and radius
-
- SYNTAX CIRCLE[[STEP]]
- (x,y),radius[[,[[color]][[,[[start]][[,[[end]][[,aspect]]]]]]]]
-
-
- CLEAR Statement
-
- Reinitializes all program variables, closes files, and sets the stack size
-
- SYNTAX CLEAR[[,,stack]]
-
-
- CLNG Function
-
- Converts a numeric expression to a long (4-byte) integer by rounding the
- fractional part of the expression
-
- SYNTAX CLNG(numeric-expression)
-
-
- CLOSE Statement
-
- Concludes I/O to a file or device
-
- SYNTAX CLOSE[[[[#]] filenumber [[,[[#]] filenumber]]... ]]
-
-
- CLS Statement
-
- Clears the screen
-
- SYNTAX CLS[[{0| 1| 2}]]
-
-
- COLOR Statement
-
- Selects display colors
-
- SYNTAX COLOR[[foreground]][[,[[background]][[,border]]]] Screen mode 0
- COLOR[[background]][[,palette]] Screen mode 1
- COLOR[[foreground]][[,background]] Screen modes
- 7-10
- COLOR[[foreground]] Screen modes
- 12-13
-
-
- COM Statements
-
- Enables, disables, or inhibits event trapping of communications activity
- on a specified port
-
- SYNTAX COM(n) ON COM(n) OFF COM(n) STOP
-
-
- COMMAND$ Function
-
- Returns the command line used to invoke the program
-
- SYNTAX COMMAND$
-
-
- COMMON Statement
-
- Defines global variables for sharing between modules or for chaining to
- another program
-
- SYNTAX COMMON[[SHARED]][[/blockname/]] variablelist
-
-
- CONST Statement
-
- Declares symbolic constants to use in place of numeric or string values
-
- SYNTAX CONST constantname = expression [[,constantname = expression]]...
-
-
- COS Function
-
- Returns the cosine of an angle given in radians
-
- SYNTAX COS(numeric-expression)
-
-
- CSNG Function
-
- Converts a numeric expression to a single-precision value
-
- SYNTAX CSNG(numeric-expression)
-
-
- CSRLIN Function
-
- Returns the current line (row) position of the cursor
-
- SYNTAX CSRLIN
-
-
- CVI, CVS, CVL, CVD Functions
-
- Convert strings containing numeric values to numbers
-
- SYNTAX CVI(2-byte-string)
- CVS(4-byte-string)
- CVL(4-byte-string)
- CVD(8-byte-string)
-
-
- CVSMBF, CVDMBF Functions
-
- Convert strings containing Microsoft Binary format numbers to IEEE-format
- numbers
-
- SYNTAX CVSMBF (4-byte-string)
- CVDMBF (8-byte-string)
-
-
- DATA Statement
-
- Stores the numeric and string constants used by a program's READ
- statements
-
- SYNTAX DATA constant1 [[,constant2]]...
-
-
- DATE$ Function
-
- Returns a string containing the current date
-
- SYNTAX DATE$
-
-
- DATE$ Statement
-
- Sets the current date
-
- SYNTAX DATE$ = stringexpression
-
-
- DECLARE Statement (BASIC Procedures)
-
- Declares references to BASIC procedures and invokes argument type checking
-
- SYNTAX DECLARE{FUNCTION | SUB } name [[([[parameterlist]])]]
-
-
- DECLARE Statement (Non-BASIC Procedures)
-
- Declares calling sequences for external procedures written in other
- languages
-
- SYNTAX 1 DECLARE FUNCTION name [[CDECL]]
- [[ALIAS "aliasname"]][[([[parameterlist]])]]
-
- SYNTAX 2 DECLARE SUB name [[CDECL]] [[ALIAS
- "aliasname"]][[([[parameterlist]])]]
-
-
- DEF FN Statement
-
- Defines and names a function
-
- SYNTAX 1 DEF FNname[[(parameterlist)]] = expression
-
- SYNTAX 2 DEF FNname[[(parameterlist)]]
- .
- .
- .
- FNname = expression
- .
- .
- .
- END DEF
-
-
- DEF SEG Statement
-
- Sets the current segment address for a subsequent PEEK function or a
- BLOAD, BSAVE, CALL ABSOLUTE, or POKE statement
-
- SYNTAX DEF SEG[[=address]]
-
-
- DEFtype Statements
-
- Set the default data type for variables, DEF FN functions, and FUNCTION
- procedures
-
- SYNTAX DEFINT letterrange [[,letterrange]]...
- DEFSNG letterrange [[,letterrange]]...
- DEFDBL letterrange [[,letterrange]]...
- DEFLNG letterrange [[,letterrange]]...
- DEFSTR letterrange [[,letterrange]]...
-
-
- DIM Statement
-
- Declares a variable and allocates storage space
-
- SYNTAX DIM[[SHARED]] variable[[(subscripts)]] [[AS type]]
- [[,variable[[(subscripts)]] [[AStype]]]]...
-
-
- DO...LOOP Statements
-
- Repeats a block of statements while a condition is true or until a
- condition becomes true
-
- SYNTAX 1 DO [[statementblock]]
- LOOP[[{WHILE| UNTIL} booleanexpression]]
-
- SYNTAX 2 DO[[{WHILE| UNTIL} booleanexpression]]
- [[statementblock]]
- LOOP
-
-
- DRAW Statement
-
- Draws an object defined by stringexpression
-
- SYNTAX DRAW stringexpression
-
-
- END Statement
-
- Ends a BASIC program, procedure, or block
-
- SYNTAX END[[{DEF| FUNCTION | IF| SELECT| SUB | TYPE}]]
-
-
- ENVIRON$ Function
-
- Retrieves an environment string from the DOS environment-string table
-
- SYNTAX ENVIRON$ (environmentstring)
- ENVIRON$ (n)
-
-
- ENVIRON Statement
-
- Modifies a parameter in the DOS environment-string table
-
- SYNTAX ENVIRON stringexpression
-
-
- EOF Function
-
- Tests for the end-of-file condition
-
- SYNTAX EOF(filenumber)
-
-
- ERASE Statement
-
- Reinitializes the elements of static arrays; deallocates dynamic arrays
-
- SYNTAX ERASE arrayname [[,arrayname...]]
-
-
- ERDEV, ERDEV$ Functions
-
- Provides device-specific status information after an error
-
- SYNTAX ERDEV
- ERDEV$
-
-
- ERR, ERL Functions
-
- Return error status
-
- SYNTAX ERR
- ERL
-
-
- ERROR Statement
-
- Simulates the occurrence of a BASIC error or allows the user to define
- error codes
-
- SYNTAX ERROR integerexpression
-
-
- EXIT Statement
-
- Exits a DEF FN function, DO...LOOP or FOR...NEXT loop, FUNCTION, or SUB
-
- SYNTAX EXIT{DEF| DO| FOR| FUNCTION| SUB}
-
-
- EXP Function
-
- Calculates the exponential function
-
- SYNTAX EXP(x)
-
-
- FIELD Statement
-
- Allocates space for variables in a random-access file buffer
-
- SYNTAX FIELD[[#]]filenumber, fieldwidth AS stringvariable...
-
-
- FILEATTR Function
-
- Returns information about an open file
-
- SYNTAX FILEATTR(filenumber,attribute)
-
-
- FILES Statement
-
- Prints the names of files residing on the specified disk
-
- SYNTAX FILES[[filespec]]
-
-
- FIX Function
-
- Returns the truncated integer part of x
-
- SYNTAX FIX(x)
-
-
- FOR...NEXT Statement
-
- Repeats a group of instructions a specified number of times
-
- SYNTAX FOR counter = start TO end [[STEP increment]]
- .
- .
- .
- NEXT[[counter[[,counter...]]]]
-
-
- FRE Function
-
- Returns the amount of available memory
-
- SYNTAX 1 FRE(numeric-expression)
-
- SYNTAX 2 FRE(stringexpression)
-
-
- FREEFILE Function
-
- Returns the next free BASIC file number
-
- SYNTAX FREEFILE
-
-
- FUNCTION Statement
-
- Declares the name, the parameters, and the code that form the body of a
- FUNCTION procedure
-
- SYNTAX FUNCTION name [[(parameter-list)]][[STATIC]]
- .
- .
- .
- name = expression
- .
- .
- .
- END FUNCTION
-
-
- GET Statement──File I/O
-
- Reads from a disk file into a random-access buffer or variable
-
- SYNTAX GET[[#]]filenumber[[,[[recordnumber]][[,variable]]]]
-
-
- GET Statement──Graphics
-
- Stores graphic images from the screen
-
- SYNTAX GET[[STEP]](x1,y1) -[[STEP]](x2,y2),arrayname[[(indices)]]
-
-
- GOSUB...RETURN Statements
-
- Branches to, and returns from, a subroutine
-
- SYNTAX GOSUB{linelabel1| linenumber1 }
- .
- .
- .
- RETURN[[linelabel2| linenumber2 ]]
-
-
- GOTO Statement
-
- Branches unconditionally to the specified line
-
- SYNTAX GOTO{linelabel| linenumber}
-
-
- HEX$ Function
-
- Returns a string that represents the hexadecimal value of the decimal
- argument expression
-
- SYNTAX HEX$(expression)
-
-
- IF...THEN...ELSE Statements
-
- Allows conditional execution, based on the evaluation of a Boolean
- expression
-
- SYNTAX 1 (SINGLE LINE) IF booleanexpression THEN thenpart [[ELSE
- elsepart]]
-
- SYNTAX 2 (BLOCK) IF booleanexpression1 THEN
- [[statementblock-1]]
- [[ELSEIF booleanexpression2 THEN
- [[statementblock-2]]]]
- .
- .
- .
- [[ELSE
- [[statement-blockn]]]]
- END IF
-
-
- INKEY$ Function
-
- Reads a character from the keyboard
-
- SYNTAX INKEY$
-
-
- INP Function
-
- Returns the byte read from an I/O port
-
- SYNTAX INP(port)
-
-
- INPUT$ Function
-
- Returns a string of characters read from the specified file
-
- SYNTAX INPUT$(n[[,[[#]]filenumber]])
-
-
- INPUT Statement
-
- Allows input from the keyboard during program execution
-
- SYNTAX INPUT[[;]][["promptstring"{; | ,}]] variablelist
-
-
- INPUT # Statement
-
- Reads data items from a sequential device or file and assigns them to
- variables
-
- SYNTAX INPUT # filenumber, variablelist
-
-
- INSTR Function
-
- Returns the character position of the first occurrence of a string in
- another string
-
- SYNTAX INSTR([[start,]]stringexpression1,stringexpression2)
-
-
- INT Function
-
- Returns the largest integer less than or equal to numeric-expression
-
- SYNTAX INT(numeric-expression)
-
-
- IOCTL$ Function
-
- Receives a control data string from a device driver
-
- SYNTAX IOCTL$ ([[#]]filenumber)
-
-
- IOCTL Statement
-
- Transmits a control data string to a device driver
-
- SYNTAX IOCTL[[#]]filenumber, string
-
-
- KEY Statements
-
- Assign soft-key string values to function keys, then display the values
- and enable or disable the FUNCTION key display line
-
- SYNTAX KEY n, stringexpression
- KEY LIST
- KEY ON
- KEY OFF
-
-
- KEY(n) Statements
-
- Start or stop trapping of specified keys
-
- SYNTAX KEY(n) ON
- KEY(n) OFF
- KEY(n) STOP
-
-
- KILL Statement
-
- Deletes a file from disk
-
- SYNTAX KILL filespec
-
-
- LBOUND Function
-
- Returns the lower bound (smallest available subscript) for the indicated
- dimension of an array
-
- SYNTAX LBOUND(array[[,dimension]])
-
-
- LCASE$ Function
-
- Returns a string expression with all letters in lower-case
-
- SYNTAX LCASE$ (stringexpression)
-
-
- LEFT$ Function
-
- Returns a string consisting of the leftmost n characters of a string
-
- SYNTAX LEFT$(stringexpression,n)
-
-
- LEN Function
-
- Returns the number of characters in a string or the number of bytes
- required by a variable
-
- SYNTAX LEN(stringexpression)
- LEN(variable)
-
-
- LET Statement
-
- Assigns the value of an expression to a variable
-
- SYNTAX [[LET]]variable=expression
-
-
- LINE Statement
-
- Draws a line or box on the screen
-
- SYNTAX LINE[[[[STEP]] (x1,y1)]] -[[STEP]]
- (x2,y2)[[,[[color]][[,[[B[[F]]]][[,style]]]]]]
-
-
- LINE INPUT Statement
-
- Inputs an entire line (up to 255 characters) to a string variable, without
- the use of delimiters
-
- SYNTAX LINE INPUT[[;]] [["promptstring";]] stringvariable
-
-
- LINE INPUT # Statement
-
- Reads an entire line without delimiters from a sequential file to a string
- variable
-
- SYNTAX LINE INPUT #filenumber,stringvariable
-
-
- LOC Function
-
- Returns the current position within the file
-
- SYNTAX LOC(filenumber)
-
-
- LOCATE Statement
-
- Moves the cursor to the specified position
-
- SYNTAX LOCATE[[row]][[,[[column]][[,[[cursor]][[,[[start,stop]]]]]]]]
-
-
- LOCK...UNLOCK Statement
-
- Controls access by other processes to all or part of an opened file
-
- SYNTAX LOCK[[#]] filenumber [[,{record | [[start]] TO end}]]
- .
- .
- .
- UNLOCK[[#]] filenumber [[,{record | [[start]] TO end}]]
-
-
- LOF Function
-
- Returns the length of the named file in bytes
-
- SYNTAX LOF(filenumber)
-
-
- LOG Function
-
- Returns the natural logarithm of a numeric expression
-
- SYNTAX LOG(n)
-
-
- LPOS Function
-
- Returns the current position of the line printer's print head within the
- printer buffer
-
- SYNTAX LPOS(n)
-
-
- LPRINT, LPRINT USING Statements
-
- Prints data on the printer LPT1:
-
- SYNTAX 1 LPRINT[[expressionlist]] [[{;|,}]]
-
- SYNTAX 2 LPRINT USING formatstring; expression-list [[{;|,}]]
-
-
- LSET Statement
-
- Moves data from memory to a random-access file buffer (in preparation for
- a PUT statement), copies one record variable to another, or left-justifies
- the value of a string in a string variable
-
- SYNTAX
- LSET{stringvariable=stringexpression|stringexpression1=stringexpre
- ssion2}
-
-
- LTRIM$ Function
-
- Returns a copy of a string with leading spaces removed
-
- SYNTAX LTRIM$(stringexpression)
-
-
- MID$ Function
-
- Returns a substring of a string
-
- SYNTAX MID$(stringexpression,start[[,length]])
-
-
- MID$ Statement
-
- Replaces a portion of a string variable with another string
-
- SYNTAX MID$(stringvariable,start[[,length]])=stringexpression
-
-
- MKD$, MKI$, MKL$, MKS$ Functions
-
- Converts numeric values to string values
-
- SYNTAX MKI$(integerexpression)
- MKS$(single-precision-expression)
- MKL$(long-integer-expression)
- MKD$(double-precision-expression)
-
-
- MKDIR Statement
-
- Creates a new directory
-
- SYNTAX MKDIR pathname
-
-
- MKSMBF$, MKDMBF$ Functions
-
- Converts an IEEE-format number to a string containing a Microsoft Binary
- format number
-
- SYNTAX MKSMBF$(single-precision-expression)
- MKDMBF$(double-precision-expression)
-
-
- NAME Statement
-
- Changes the name of a disk file or directory
-
- SYNTAX NAME oldfilename AS newfilename
-
-
- OCT$ Function
-
- Returns a string representing the octal value of the numeric argument
-
- SYNTAX OCT$(numeric-expression)
-
-
- ON ERROR Statement
-
- Enables error handling and specifies the first line of the error-handling
- routine
-
- SYNTAX ON ERROR GOTO line
-
-
- ON event Statements
-
- Indicates the first line of an event-trapping subroutine
-
- SYNTAX ON event GOSUB{linenumber | linelabel }
-
-
- ON UEVENT GOSUB Statement
-
- Defines the event-handler for a user-defined event
-
- SYNTAX ON UEVENT GOSUB { linenumber| linelabel }
-
-
- ON...GOSUB, ON...GOTO Statements
-
- Branches to one of several specified lines, depending on the value of an
- expression
-
- SYNTAX 1 ON expression GOSUB{line-number-list | line-label-list }
-
- SYNTAX 2 ON expression GOTO{line-number-list | line-label-list }
-
-
- OPEN Statement
-
- Enables I/O to a file or device
-
- SYNTAX 1 OPEN file[[FOR mode1]] [[ACCESS access]] [[lock]] AS[[#]]
- filenum[[LEN=reclen]]
-
- SYNTAX 2 OPEN mode2,[[#]]filenum, file [[,reclen]]
-
-
- OPEN COM Statement
-
- Opens and initializes a communications channel for I/O
-
- SYNTAX OPEN "COMn: optlist1 optlist2" [[FOR mode]] AS[[#]]filenum
- [[LEN=reclen]]
-
-
- OPTION BASE Statement
-
- Declares the default lower bound for array subscripts
-
- SYNTAX OPTION BASE n
-
-
- OUT Statement
-
- Sends a byte to a machine I/O port
-
- SYNTAX OUT port, data
-
-
- PAINT Statement
-
- Fills a graphics area with the color or pattern specified
-
- SYNTAX PAINT[[STEP]] (x,y)[[,[[paint]] [[,[[bordercolor]]
- [[,background]]]]]]
-
-
- PALETTE, PALETTE USING Statements
-
- Changes one or more of the colors in the palette
-
- SYNTAX PALETTE[[attribute,color]]
- PALETTE USING array-name [[(array-index)]]
-
-
- PCOPY Statement
-
- Copies one screen page to another
-
- SYNTAX PCOPY sourcepage, destinationpage
-
-
- PEEK Function
-
- Returns the byte stored at a specified memory location
-
- SYNTAX PEEK(address)
-
-
- PEN Function
-
- Reads the lightpen coordinates
-
- SYNTAX PEN(n)
-
-
- PEN ON, OFF, and STOP Statements
-
- Enables, disables, or suspends lightpen event trapping
-
- SYNTAX PEN ON
- PEN OFF
- PEN STOP
-
-
- PLAY Function
-
- Returns the number of notes currently in the background-music queue
-
- SYNTAX PLAY (n)
-
-
- PLAY Statement
-
- Plays music as specified by a string
-
- SYNTAX PLAY commandstring
-
-
- PLAY ON, OFF, and STOP Statements
-
- PLAY ON enables play event trapping, PLAY OFF disables play event
- trapping, and PLAY STOP suspends play event trapping.
-
- SYNTAX PLAY ON
- PLAY OFF
- PLAY STOP
-
-
- PMAP Function
-
- Maps view-coordinate expressions to physical locations, or maps physical
- expressions to a view-coordinate location
-
- SYNTAX PMAP (expression, function)
-
-
- POINT Function
-
- Reads the color number of a pixel from the screen or returns the pixel's
- coordinates
-
- SYNTAX POINT (x,y)
- POINT (number)
-
-
- POKE Statement
-
- Writes a byte into a memory location
-
- SYNTAX POKE address,byte
-
-
- POS Function
-
- Returns the current horizontal position of the cursor
-
- SYNTAX POS(0)
-
-
- PRESET Statement
-
- Draws a specified point on the screen
-
- SYNTAX PRESET[[STEP]](xcoordinate,ycoordinate) [[,color]]
-
-
- PRINT Statement
-
- Outputs data on the screen
-
- SYNTAX PRINT[[expressionlist]] [[{,| ;}]]
-
-
- PRINT #, PRINT # USING Statements
-
- Writes data to a sequential file
-
- SYNTAX PRINT #filenumber,[[USING stringexpression;]] expressionlist [[{,
- | ;}]]
-
-
- PRINT USING Statement
-
- Prints strings or numbers using a specified format
-
- SYNTAX PRINT USING formatstring; expressionlist [[{,| ;}]]
-
-
- PSET Statement
-
- Draws a point on the screen
-
- SYNTAX PSET[[STEP]](xcoordinate,ycoordinate) [[,color]]
-
-
- PUT Statement──File I/O
-
- Writes from a variable or a random-access buffer to a file
-
- SYNTAX PUT[[#]]filenumber[[,[[recordnumber]][[,variable]]]]
- PUT[[#]]filenumber[[,{recordnumber|recordnumber,
- variable|,variable}]]
-
-
- PUT Statement──Graphics
-
- Places a graphic image obtained by a GET statement onto the screen
-
- SYNTAX PUT[[STEP]] (x,y), arrayname[[(indices)]] [[,actionverb]]
-
-
- RANDOMIZE Statement
-
- Initializes (reseeds) the random-number generator
-
- SYNTAX RANDOMIZE[[expression]]
-
-
- READ Statement
-
- Reads values from a DATA statement and assigns the values to variables
-
- SYNTAX READ variablelist
-
-
- REDIM Statement
-
- Changes the space allocated to an array that has been declared $DYNAMIC
-
- SYNTAX REDIM[[SHARED]] variable(subscripts)[[AS type]]
- [[,variable(subscripts)[[AS
- type]]]]...
-
-
- REM Statement
-
- Allows explanatory remarks to be inserted in a program
-
- SYNTAX 1 REM remark
-
- SYNTAX 2 ' remark
-
-
- RESET Statement
-
- Closes all disk files
-
- SYNTAX RESET
-
-
- RESTORE Statement
-
- Allows DATA statements to be reread from a specified line
-
- SYNTAX RESTORE[[{linenumber | linelabel }]]
-
-
- RESUME Statement
-
- Continues program execution after an error-trapping routine has been
- invoked
-
- SYNTAX RESUME[[0]]
- RESUME NEXT
- RESUME { linenumber| linelabel }
-
-
- RETURN Statement
-
- Returns control from a subroutine
-
- SYNTAX RETURN[[{linenumber | linelabel }]]
-
-
- RIGHT$ Function
-
- Returns the rightmost n characters of a string
-
- SYNTAX RIGHT$(stringexpression,n)
-
-
- RMDIR Statement
-
- Removes an existing directory
-
- SYNTAX RMDIR pathname
-
-
- RND Function
-
- Returns a single-precision random number between 0 and 1
-
- SYNTAX RND[[(n)]]
-
-
- RSET Statement
-
- Moves data from memory to a random-access file buffer (in preparation for
- a PUT statement) or right-justifies the value of a string in a string
- variable
-
- SYNTAX RSET stringvariable=stringexpression
-
-
- RTRIM$ Function
-
- Returns a string with trailing (right-hand) spaces removed
-
- SYNTAX RTRIM$(stringexpression)
-
-
- RUN Statement
-
- Restarts the program currently in memory or executes a specified program
-
- SYNTAX RUN[[{ linenumber | commandline }]]
-
-
- SADD Function
-
- Returns the address of the specified string expression
-
- SYNTAX SADD(stringvariable)
-
-
- SCREEN Function
-
- Reads a character's ASCII value or its color from a specified screen
- location
-
- SYNTAX SCREEN(row,column[[,colorflag]])
-
-
- SCREEN Statement
-
- Sets the specifications for the display screen
-
- SYNTAX SCREEN[[mode]] [[,[[colorswitch]] ]][[,[[apage]] ]][[,[[vpage]]]]
-
-
- SEEK Function
-
- Returns the current file position
-
- SYNTAX SEEK(filenumber)
-
-
- SEEK Statement
-
- Sets the position in a file for the next read or write
-
- SYNTAX SEEK[[#]]filenumber,position
-
-
- SELECT CASE Statement
-
- Executes one of several statement blocks depending on the value of an
- expression
-
- SYNTAX SELECT CASE testexpression
- CASE expressionlist1
- [[statementblock-1]]
- [[CASE expressionlist2
- [[statementblock-2]]]]
- .
- .
- .
- [[CASE ELSE
- [[statementblock-n]]]]
- END SELECT
-
-
- SETMEM Function
-
- Changes the amount of memory used by the far heap──the area where far
- objects and internal tables are stored
-
- SYNTAX SETMEM(numeric-expression)
-
-
- SGN Function
-
- Indicates the sign of a numeric expression
-
- SYNTAX SGN(numeric-expression)
-
-
- SHARED Statement
-
- Gives a SUB or FUNCTION procedure access to variables declared at the
- module level without passing them as parameters
-
- SYNTAX SHARED variable [[AS type]] [[,variable [[AS type]]]]...
-
-
- SHELL Statement
-
- Exits the BASIC program, runs a .COM, .EXE, or .BAT program or a DOS
- command, and returns to the program at the line following the SHELL
- statement
-
- SYNTAX SHELL[[commandstring]]
-
-
- SIN Function
-
- Returns the sine of the angle x, where x is in radians
-
- SYNTAX SIN(x)
-
-
- SLEEP Statement
-
- Suspends execution of the calling program
-
- SYNTAX SLEEP[[ seconds ]]
-
-
- SOUND Statement
-
- Generates sound through the speaker
-
- SYNTAX SOUND frequency,duration
-
-
- SPACE$ Function
-
- Returns a string of spaces of length n
-
- SYNTAX SPACE$(n)
-
-
- SPC Function
-
- Skips n spaces in a PRINT statement
-
- SYNTAX SPC(n)
-
-
- SQR Function
-
- Returns the square root of n
-
- SYNTAX SQR(n)
-
-
- STATIC Statement
-
- Makes simple variables or arrays local to either a DEF FN function, a
- FUNCTION, or a SUB and preserves values between calls
-
- SYNTAX STATIC variablelist
-
-
- STICK Function
-
- Returns the x and y coordinates of the two joysticks
-
- SYNTAX STICK(n)
-
-
- STOP Statement
-
- Terminates the program
-
- SYNTAX STOP
-
-
- STR$ Function
-
- Returns a string representation of the value of a numeric expression
-
- SYNTAX STR$(numeric-expression)
-
-
- STRIG Function and Statement
-
- Returns the status of a specified joystick trigger
-
- SYNTAX 1 (FUNCTION) STRIG(n)
-
- SYNTAX 2 (STATEMENT) STRIG{ON| OFF}
-
-
- STRIG ON, OFF, and STOP Statements
-
- Enable, disable, or inhibit trapping of joystick activity
-
- SYNTAX STRIG(n) ON
- STRIG(n) OFF
- STRIG(n) STOP
-
-
- STRING$ Function
-
- Returns a string whose characters all have a given ASCII code or whose
- characters are all the first character of a string expression
-
- SYNTAX STRING$(m,n)
- STRING$(m,stringexpression)
-
-
- SUB Statements
-
- Marks the beginning and end of a subprogram
-
- SYNTAX SUB globalname[[(parameterlist)]] [[STATIC]]
- .
- .
- .
- [[EXIT SUB]]
- .
- .
- .
- END SUB
-
-
- SWAP Statement
-
- Exchanges the values of two variables
-
- SYNTAX SWAP variable1,variable2
-
-
- SYSTEM Statement
-
- Closes all open files and returns control to the operating system
-
- SYNTAX SYSTEM
-
-
- TAB Function
-
- Moves the print position
-
- SYNTAX TAB(column)
-
-
- TAN Function
-
- Returns the tangent of the angle x, where x is in radians
-
- SYNTAX TAN(x)
-
-
- TIME$ Function
-
- Returns the current time from the operating system
-
- SYNTAX TIME$
-
-
- TIME$ Statement
-
- Sets the time
-
- SYNTAX TIME$=stringexpression
-
-
- TIMER Function
-
- Returns the number of seconds elapsed since midnight
-
- SYNTAX TIMER
-
-
- TIMER ON, OFF, and STOP Statements
-
- Enables, disables, or inhibits timer event trapping
-
- SYNTAX TIMER ON
- TIMER OFF
- TIMER STOP
-
-
- TRON/TROFF Statements
-
- Traces the execution of program statements
-
- SYNTAX TRON
- TROFF
-
-
- TYPE Statement
-
- Defines a data type containing one or more elements
-
- SYNTAX TYPE usertype
- elementname AS typename
- elementname AS typename
- .
- .
- .
- END TYPE
-
-
- UBOUND Function
-
- Returns the upper bound (largest available subscript) for the indicated
- dimension of an array
-
- SYNTAX UBOUND(array[[,dimension]])
-
-
- UCASE$ Function
-
- Returns a string expression with all letters in uppercase
-
- SYNTAX UCASE$ (stringexpression)
-
-
- UEVENT Statement
-
- Enables, disables, or suspends event trapping for a user-defined event
-
- SYNTAX UEVENT ON
- UEVENT OFF
- UEVENT STOP
-
-
- UNLOCK Statement
-
- Releases locks applied to parts of a file
-
- SYNTAX UNLOCK[[#]] filenumber [[,{record | [[start]] TO end}]]
-
-
- VAL Function
-
- Returns the numeric value of a string of digits
-
- SYNTAX VAL(stringexpression)
-
-
- VARPTR, VARSEG Functions
-
- Return the address of a variable
-
- SYNTAX VARPTR(variablename)
- VARSEG(variablename)
-
-
- VARPTR$ Function
-
- Returns a string representation of a variable's address for use in DRAW
- and PLAY statements
-
- SYNTAX VARPTR$(variablename)
-
-
- VIEW Statement
-
- Defines screen limits for graphics output
-
- SYNTAX VIEW[[[[SCREEN]] (x1,y1)-(x2,y2)[[,[[color]] [[,border]]]]]]
-
-
- VIEW PRINT Statement
-
- Sets the boundaries of the screen text viewport
-
- SYNTAX VIEW PRINT[[topline TO bottomline]]
-
-
- WAIT Statement
-
- Suspends program execution while monitoring the status of a machine input
- port
-
- SYNTAX WAIT portnumber,and-expression[[,xor-expression]]
-
-
- WHILE...WEND Statement
-
- Executes a series of statements in a loop, as long as a given condition is
- true
-
- SYNTAX WHILE condition
- .
- .
- .
- [[statements]]
- .
- .
- .
- WEND
-
-
- WIDTH Statement
-
- Assigns an output-line width to a file or device or changes the number of
- columns and lines displayed on the screen
-
- SYNTAX WIDTH[[columns]][[,lines]]
- WIDTH{# filenumber | device} , width
- WIDTH LPRINT width
-
-
- WINDOW Statement
-
- Defines the logical dimensions of the current viewport
-
- SYNTAX WINDOW[[[[SCREEN]] (x1,y1)-(x2,y2)]]
-
-
- WRITE Statement
-
- Sends data to the screen
-
- SYNTAX WRITE[[expressionlist]]
-
-
- WRITE # Statement
-
- Writes data to a sequential file
-
- SYNTAX WRITE #filenumber,expressionlist
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- Chapter 9 Quick-Reference Tables
-
- Each section in this chapter summarizes a group of statements or functions
- that you typically use together. Each group is presented in a table, which
- lists the type of task performed (for example, looping or searching), the
- statement or function name, and the statement action.
-
- The following topics are summarized in tabular form:
-
- ■ Control-flow statements
-
- ■ Statements used in BASIC procedures
-
- ■ Standard I/O statements
-
- ■ File I/O statements
-
- ■ String-processing statements and functions
-
- ■ Graphics statements and functions
-
- ■ Trapping statements and functions
-
- You can use these tables both as a reference guide to what each statement
- or function does and as a way to identify related statements.
-
-
- 9.1 Summary of Control-Flow Statements
-
- Table 9.1 lists the BASIC statements used to control the flow of a
- program's execution.
-
- Table 9.1 Statements Used in Looping and Decision-Making
- ╓┌─┌────────────────────┌────────────────────┌───────────────────────────────╖
- Task Statement Action
- ──────────────────────────────────────────────────────────────────────────
- Looping FOR...NEXT Repeats statements between FOR
- and NEXT a specific number of
- times.
-
- EXIT FOR Provides an alternative way to
- exit a FOR...NEXT loop.
-
- DO...LOOP Repeats statements between DO
- and LOOP, either until a given
- condition is true (DO...LOOP
- UNTIL condition), or while a
- given condition is true
- Task Statement Action
- ──────────────────────────────────────────────────────────────────────────
- given condition is true
- (DO...LOOP WHILE condition).
-
- EXIT DO Provides an alternative way to
- exit a DO...LOOP loop.
-
- WHILE...WEND Repeats statements between WHILE
- and WEND while a given condition
- is true (similar to DO WHILE
- condition...LOOP).
-
- Making decisions IF...THEN...ELSE Conditionally executes or
- branches to different
- statements.
-
- SELECT CASE Conditionally executes different
- statements.
- ──────────────────────────────────────────────────────────────────────────
-
- Task Statement Action
- ──────────────────────────────────────────────────────────────────────────
-
-
- 9.2 Summary of Statements Used in BASIC Procedures
-
- Table 9.2 lists the statements used in BASIC to define, declare, call,
- and pass arguments to BASIC procedures. Table 9.2 also lists the
- statements used to share variables among procedures, modules, and separate
- programs in a chain.
-
- Table 9.2 Statements Used in Procedures
- ╓┌─┌────────────────────┌────────────────────┌───────────────────────────────╖
- Task Statement Action
- ──────────────────────────────────────────────────────────────────────────
- Defining a procedure FUNCTION...END Mark the beginning and end,
- FUNCTION respectively, of a FUNCTION
- procedure.
-
- SUB...END SUB Mark the beginning and end,
- Task Statement Action
- ──────────────────────────────────────────────────────────────────────────
- SUB...END SUB Mark the beginning and end,
- respectively, of a SUB
- procedure.
-
- Calling a procedure CALL Transfers control to a BASIC SUB
- procedure, or to a procedure
- written in another programming
- language and compiled
- separately. (The CALL keyword is
- optional.)
-
- Exiting from a EXIT FUNCTION Provides another way to exit a
- procedure FUNCTION procedure.
-
- EXIT SUB Provides an alternative way to
- exit a SUB procedure.
-
- Referencing a DECLARE Declares a FUNCTION or SUB and,
- procedure before it optionally, specifies the number
- Task Statement Action
- ──────────────────────────────────────────────────────────────────────────
- procedure before it optionally, specifies the number
- is defined and type of its parameters.
-
- Sharing variables COMMON Shares variables among separate
- among modules, modules. When used with the
- procedures, or SHARED attribute, it shares
- programs variables among different
- procedures in the same module.
- Also, passes variable values
- from current program to new
- program when control is
- transferred with the CHAIN
- statement.
-
- SHARED When used with the COMMON, DIM,
- or REDIM statement at the module
- level (for example, DIM SHARED),
- shares variables with every SUB
- or FUNCTION in a single module.
- Task Statement Action
- ──────────────────────────────────────────────────────────────────────────
- or FUNCTION in a single module.
-
- When used by itself within a
- procedure, shares variables
- between that procedure and the
- module-level code.
-
- Preserving variable STATIC Forces variables to be local to
- values a procedure or DEF FN function
- and preserves the value stored
- in the variable if the procedure
- or function is exited, then
- called again.
-
- Defining a multiline DEF FN...END DEF Mark the beginning and end,
- function respectively, of a multiline DEF
- FN function. (This is the old
- style for functions in BASIC──
- FUNCTION procedures provide a
- Task Statement Action
- ──────────────────────────────────────────────────────────────────────────
- FUNCTION procedures provide a
- powerful alternative.)
-
- Exiting from a EXIT DEF Provides an alternative way to
- multiline function exit a multiline DEF FN
- function.
-
- Calling a BASIC GOSUB Transfers control to a specific
- subroutine line in a module. Control is
- returned from the subroutine to
- the line following the GOSUB
- statement with a RETURN
- statement. (This is the old
- style for subroutines in BASIC──
- SUB procedures provide a
- powerful alternative.)
-
- Transferring to CHAIN Transfers control from current
- another program program in memory to another
- Task Statement Action
- ──────────────────────────────────────────────────────────────────────────
- another program program in memory to another
- program; use COMMON to pass
- variables to the new program.
- ──────────────────────────────────────────────────────────────────────────
-
-
-
- 9.3 Summary of Standard I/O Statements
-
- Table 9.3 lists the statements and functions used in BASIC for standard
- I/O (typically, input from the keyboard and output to the screen).
-
- Table 9.3 Statements and Functions Used for Standard I/O
- ╓┌─┌────────────────────┌────────────────────┌───────────────────────────────╖
- Statement or
- Task Function Action
- ──────────────────────────────────────────────────────────────────────────
- Printing text on the PRINT Outputs text to the screen.
- screen Using PRINT with no arguments
- Statement or
- Task Function Action
- ──────────────────────────────────────────────────────────────────────────
- screen Using PRINT with no arguments
- creates a blank line.
-
- PRINT USING Outputs formatted text to the
- screen.
-
- Changing the width WIDTH Changes the width of the screen
- of the output line to either 40 columns or 80
- columns and, on computers with
- an EGA or VGA, controls the
- number of lines on the screen
- (25 or 43).
-
- WIDTH "SCRN:" Assigns a maximum length to
- lines output to the screen when
- used before an OPEN "SCRN:"
- statement.
-
- Statement or
- Task Function Action
- ──────────────────────────────────────────────────────────────────────────
- Getting input from INKEY$ Reads a character from the
- the keyboard keyboard (or a null string if no
- character is waiting).
-
- INPUT$ Reads a specified number of
- characters from the keyboard and
- stores them in a single string
- variable.
-
- INPUT Reads input from the keyboard
- and stores it in a list of
- variables.
-
- LINE INPUT Reads a line of input from the
- keyboard and stores it in a
- single string variable.
-
- Statement or
- Task Function Action
- ──────────────────────────────────────────────────────────────────────────
- Positioning the LOCATE Moves the cursor to a specified
- cursor on the screen row and column.
-
- SPC Skips spaces in printed output.
-
- TAB Displays printed output in a
- given column.
-
- Getting information CSRLIN Tells which row or line position
- on cursor location the cursor is in.
-
- POS(n) Tells which column the cursor is
- in.
-
- Creating a text VIEW PRINT Sets the top and bottom rows for
- viewport displaying text output.
- ──────────────────────────────────────────────────────────────────────────
- Statement or
- Task Function Action
- ──────────────────────────────────────────────────────────────────────────
- ──────────────────────────────────────────────────────────────────────────
-
-
-
- 9.4 Summary of File I/O Statements
-
- Table 9.4 lists the statements and functions used in BASIC data-file
- programming.
-
- Table 9.4 Statements and Functions Used for Data-File I/O
- ╓┌─┌────────────────────┌────────────────────┌───────────────────────────────╖
- Statement or
- Task Function Action
- ──────────────────────────────────────────────────────────────────────────
- Creating a new file OPEN Opens a file for retrieving or
- or accessing an storing records (I/O).
- existing file
- Closing a file CLOSE Ends I/O to a file.
- Statement or
- Task Function Action
- ──────────────────────────────────────────────────────────────────────────
- Closing a file CLOSE Ends I/O to a file.
- Storing data in a PRINT # Stores a list of variables as
- file record fields in a previously
- opened file.
- PRINT USING # Similar to PRINT #, except PRINT
- USING # formats the record
- fields.
- WRITE # Stores a list of variables as
- record fields in a previously
- opened file.
- WIDTH Specifies a standard length for
- each record in a file.
- PUT Stores the contents of a
- user-defined variable in a
- previously opened file.
- Retrieving data from INPUT # Reads fields from a record and
- a file assigns each field in the record
- to a program variable.
- Statement or
- Task Function Action
- ──────────────────────────────────────────────────────────────────────────
- to a program variable.
- INPUT$ Reads a string of characters
- from a file.
- LINE INPUT # Reads a record and stores it in
- a single string variable.
- GET Reads data from a file and
- assigns the data to elements of
- a user-defined variable.
- Managing files on FILES Prints a listing of the files in
- disk a specified directory.
- FREEFILE Returns the next available file
- number.
- KILL Deletes a file from the disk.
- NAME Changes a file's name.
- Getting information EOF Tests whether all of the data
- about a file have been read from a file.
- FILEATTR Returns the number assigned by
- the operating system to an open
- Statement or
- Task Function Action
- ──────────────────────────────────────────────────────────────────────────
- the operating system to an open
- file and a number that indicates
- the mode in which the file was
- opened (INPUT, OUTPUT, APPEND,
- BINARY, or RANDOM).
- LOC Gives the current position
- within a file. With binary
- access, this is the byte
- position. With sequential
- access, this is the byte
- position divided by 128. With
- random access, this is the
- record number of the last record
- read or written.
- LOF Gives the number of bytes in an
- open file.
- SEEK (function) Gives the location where the
- next I/O operation will take
- Statement or
- Task Function Action
- ──────────────────────────────────────────────────────────────────────────
- next I/O operation will take
- place. With random access, this
- is the number of the next record
- to be read or written. With all
- other kinds of file access, this
- is the byte position of the next
- byte to be read or written.
- Moving around in a SEEK (statement) Sets the byte position for the
- file next read or write operation in
- an open file.
- ──────────────────────────────────────────────────────────────────────────
-
-
-
- 9.5 Summary of String-Processing Statements and Functions
-
- Table 9.5 lists the statements and functions available in BASIC for
- working with strings.
-
- Table 9.5 Statements and Functions Used for Processing Strings
- ╓┌─┌────────────────────┌────────────────────┌───────────────────────────────╖
- Statement or
- Task Function Action
- ──────────────────────────────────────────────────────────────────────────
- Getting part of a LEFT$ Returns a given number of
- string characters from the left side of
- a string.
-
- RIGHT$ Returns a given number of
- characters from the right side
- of a string.
-
- LTRIM$ Returns a copy of a string with
- leading blank spaces stripped
- away.
-
- RTRIM$ Returns a copy of a string with
- trailing blank spaces stripped
- away.
- Statement or
- Task Function Action
- ──────────────────────────────────────────────────────────────────────────
- away.
-
- MID$ (function) Returns a given number of
- characters from anywhere in a
- string.
-
- Searching strings INSTR Searches for a string within
- another string.
-
- Converting to LCASE$ Returns a copy of a string with
- uppercase or all uppercase letters (A-Z)
- lowercase letters converted to lower-case letters
- (a-z); leaves lowercase letters
- and other characters unchanged.
-
- UCASE$ Returns a copy of a string with
- all lowercase letters (a-z)
- converted to upper-case letters
- Statement or
- Task Function Action
- ──────────────────────────────────────────────────────────────────────────
- converted to upper-case letters
- (A-Z); leaves uppercase letters
- and other characters unchanged.
-
- Changing strings MID$ (statement) Replaces part of a string with
- another string.
-
- LSET Left justifies a string within a
- fixed-length string.
-
- RSET Right justifies a string within
- a fixed-length string.
-
- Converting between STR$ Returns the string
- numbers and strings representation of the value of a
- numeric expression.
-
- VAL Returns the numeric value of a
- Statement or
- Task Function Action
- ──────────────────────────────────────────────────────────────────────────
- VAL Returns the numeric value of a
- string expression.
-
- Converting numbers CVtype Changes numbers stored as
- to data-file strings back to Microsoft Binary
- strings, and format numbers in programs
- data-file strings to working with random-access files
- numbers created with older versions of
- BASIC.
-
- CVtypeMBF Changes numbers stored as
- Microsoft Binary format strings
- to IEEE-format numbers.
-
- MKtype$ Changes Microsoft Binary format
- numbers to strings suitable for
- storing in random-access files
- created with older versions of
- Statement or
- Task Function Action
- ──────────────────────────────────────────────────────────────────────────
- created with older versions of
- BASIC.
-
- MKtypeMBF$ Changes IEEE-format numbers to
- Microsoft Binary format strings.
-
- Creating strings of SPACE$ Returns a string of blank
- repeating characters characters of a specified
- length.
-
- STRING$ Returns a string consisting of
- one repeated character.
-
- Getting the length LEN Tells how many characters are in
- of a string a string.
-
- Working with ASCII ASC Returns the ASCII value of the
- values given character.
- Statement or
- Task Function Action
- ──────────────────────────────────────────────────────────────────────────
- values given character.
-
- CHR$ Returns the character with the
- given ASCII value.
- ──────────────────────────────────────────────────────────────────────────
-
-
-
- 9.6 Summary of Graphics Statements and Functions
-
- Table 9.6 lists the statements and functions used in BASIC for pixel-based
- graphics.
-
- Table 9.6 Statements and Functions Used for Graphics Output
- ╓┌─┌────────────────────┌────────────────────┌───────────────────────────────╖
- Statement or
- Task Function Action
- ──────────────────────────────────────────────────────────────────────────
- Statement or
- Task Function Action
- ──────────────────────────────────────────────────────────────────────────
- Setting SCREEN Specifies a BASIC screen mode,
- screen-display which determines screen
- characteristics characteristics such as
- resolution and ranges for color
- numbers.
-
- Plotting or erasing PSET Gives a pixel on the screen a
- a single point specified color using the
- screen's foreground color by
- default.
-
- PRESET Gives a pixel on the screen a
- specified color using the
- screen's background color by
- default, effectively erasing the
- pixel.
-
- Drawing shapes LINE Draws a straight line or a box.
- Statement or
- Task Function Action
- ──────────────────────────────────────────────────────────────────────────
- Drawing shapes LINE Draws a straight line or a box.
-
- CIRCLE Draws a circle or ellipse.
-
- DRAW Combines many of the features of
- other BASIC graphics statements
- (drawing lines, moving the
- graphics cursor, scaling images)
- into an all-in-one graphics
- macro language.
-
- Defining screen VIEW Specifies a rectangle on the
- coordinates screen (or viewport) as the area
- for graphics output.
-
- WINDOW Allows the user to choose new
- view coordinates for a viewport
- on the screen.
- Statement or
- Task Function Action
- ──────────────────────────────────────────────────────────────────────────
- on the screen.
-
- PMAP Maps physical pixel coordinates
- to view coordinates specified by
- the user in the current window,
- or vice versa.
-
- POINT(number) Returns the current physical or
- view coordinates of the graphics
- cursor, depending on the value
- for number.
-
- Using color COLOR Sets the default colors used in
- graphics output.
-
- PALETTE Assigns different colors to
- color numbers. Works only on
- systems equipped with an EGA or
- Statement or
- Task Function Action
- ──────────────────────────────────────────────────────────────────────────
- systems equipped with an EGA or
- VGA.
-
- POINT(x, y) Returns the color number of a
- single pixel whose screen
- coordinates are x and y.
-
- Painting enclosed PAINT Fills an area on the screen with
- shapes a color or pattern.
-
- Animating GET Copies a rectangular area on the
- screen by translating the image
- to numeric data and storing the
- data in a numeric array.
-
- PUT Displays an image on the screen
- that was previously copied with
- GET.
- Statement or
- Task Function Action
- ──────────────────────────────────────────────────────────────────────────
- GET.
-
- PCOPY Copies one screen page to
- another.
- ──────────────────────────────────────────────────────────────────────────
-
-
-
- 9.7 Summary of Trapping Statements and Functions
-
- Table 9.7 lists the statements and functions used by BASIC to trap and
- process errors and events.
-
- Table 9.7 Statements and Functions Used in Error and Event Trapping
- ╓┌─┌────────────────────┌────────────────────┌───────────────────────────────╖
- Task Statement or Action
- Function
- ──────────────────────────────────────────────────────────────────────────
- Task Statement or Action
- Function
- ──────────────────────────────────────────────────────────────────────────
- Trapping errors ON ERROR GOTO line Causes a program to branch to
- while a program is the given line, where line
- running refers either to a line number
- or line label. Branching takes
- place whenever an error occurs
- during execution.
-
- RESUME Returns control to the program
- after executing an
- error-handling routine. The
- program resumes at either the
- statement causing the error
- (RESUME [[0]]), the statement
- after the one causing the error
- (RESUME NEXT), or the line
- identified by line (RESUME
- line).
-
- Task Statement or Action
- Function
- ──────────────────────────────────────────────────────────────────────────
- Getting error-status ERR Returns the code for an error
- data that occurs at run time.
-
- ERL Returns the number of the line
- on which an error occurred (if
- program has line numbers).
-
- ERDEV Returns a device-specific error
- code for the last device (such
- as a printer) for which DOS
- detected an error.
-
- ERDEV$ Returns the name of the last
- device for which DOS detected an
- error.
-
- Defining your own ERROR Simulates the occurrence of a
- Task Statement or Action
- Function
- ──────────────────────────────────────────────────────────────────────────
- Defining your own ERROR Simulates the occurrence of a
- error codes BASIC error; can also be used to
- define an error not trapped by
- BASIC.
-
- Trapping events ON event GOSUB line Causes a branch to the
- while a program is subroutine starting with line,
- running where line refers either to a
- line number or line label,
- whenever the given event occurs
- during execution.
-
- event ON Enables trapping of the given
- event.
-
- event OFF Disables trapping of the given
- event.
-
- Task Statement or Action
- Function
- ──────────────────────────────────────────────────────────────────────────
- event STOP Suspends trapping of the given
- event.
-
- RETURN Returns control to the program
- after executing an
- event-handling subroutine. The
- program resumes at either the
- statement immediately following
- the place in the program where
- the event occurred (RETURN), or
- the line that is identified by
- line (RETURN line).
- ──────────────────────────────────────────────────────────────────────────
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- Appendix A Converting BASICA Programs to QuickBASIC
-
- QuickBASIC generally accepts BASIC language statements written for the
- BASIC interpreters used on IBM Personal Computers and compatibles: IBM
- Advanced Personal Computer BASIC Version A3.00 (BASICA) and Microsoft
- GW-BASIC(R). However, a few changes are required because of internal
- differences between QuickBASIC and these BASIC interpreters. Since the
- changes apply equally to both interpreters, this appendix uses the term
- BASICA to refer to both GW-BASIC and BASICA.
-
- This appendix provides information on:
-
- ■ Compatible source-file format
-
- ■ Statements and functions prohibited or requiring modification for
- QuickBASIC use
-
- ■ Editor differences in handling tabs
-
- The following sections describe only the changes required to compile and
- run a BASICA program with QuickBASIC Version 4.5. The chapters in this
- book provide information on how to use QuickBASIC features to enhance your
- existing BASICA programs.
-
-
- A.1 Source-File Format
-
- QuickBASIC Version 4.5 expects the source file to be in ASCII format or in
- QuickBASIC's own format. If you create a file with BASICA, it must be
- saved with the ,A option; otherwise, BASICA compresses the text of your
- program in a special format that QuickBASIC cannot read. If this happens,
- reload BASICA and resave the file in ASCII format, using the ,A option.
- For example, the following BASICA command saves the file MYPROG.BAS in
- ASCII format:
-
- SAVE "MYPROG.BAS",A
-
-
- A.2 Statements and Functions Prohibited in QuickBASIC
-
- The statements and functions listed below cannot be used in a QuickBASIC
- program because they perform editing operations on the source file,
- interfere with program execution, refer to a cassette device (not
- supported by QuickBASIC), or duplicate support provided by the QuickBASIC
- environment:
-
-
- ──────────────────────────────────────────────────────────────────────────
- AUTO LIST NEW
-
- CONT LLIST RENUM
-
- DEFUSR LOAD SAVE
-
- DELETE MERGE USR
-
- EDIT MOTOR
- ──────────────────────────────────────────────────────────────────────────
-
-
- A.3 Statements Requiring Modification
-
- If your BASICA program contains any of the statements listed in Table A.1,
- you probably need to modify your source code before you can run your
- program in QuickBASIC.
-
- Table A.1 Statements Requiring Modification
- ╓┌─┌──────────────────┌──────────────────────────────────────────────────────╖
- Statement Modification
- ──────────────────────────────────────────────────────────────────────────
- BLOAD/BSAVE Memory locations may be different in QuickBASIC.
-
- CALL The argument is the name of the SUB procedure being
- called.
-
- CHAIN QuickBASIC does not support the ALL, MERGE, DELETE, or
- linenumber options.
-
- COMMON COMMON statements must appear before any executable
- statements.
-
- DEFtype DEFtype statements should be moved to the beginning of
- the BASICA source file.
-
- Statement Modification
- ──────────────────────────────────────────────────────────────────────────
- DIM All DIM statements declaring static arrays must appear
- at the beginning of QuickBASIC programs.
-
- DRAW, PLAY QuickBASIC requires that the VARPTR$ function be used
- with embedded variables.
-
- RESUME If an error occurs in a single-line function,
- QuickBASIC attempts to resume program execution at the
- line containing the function.
-
- RUN For executable files produced by QuickBASIC, the object
- of a RUN or CHAIN statement cannot be a .BAS file; it
- must be an executable file. The R option in BASICA is
- not supported. While in the QuickBASIC environment, the
- object of a RUN or CHAIN statement is still a .BAS
- file.
-
- RUN{linenumber| linelabel}, however, is supported in
- Statement Modification
- ──────────────────────────────────────────────────────────────────────────
- RUN{linenumber| linelabel}, however, is supported in
- QuickBASIC; this statement restarts the program at the
- specified line.
- ──────────────────────────────────────────────────────────────────────────
-
-
-
- A.4 Editor Differences in Handling Tabs
-
- QuickBASIC uses individual spaces (rather than the literal tab character,
- ASCII 9) to represent indentation levels. The Tab Stops option in the
- Option menu's Display dialog box set the number of spaces per indentation
- level. (See Chapter 20, "The Options Menu," in Learning to Use Microsoft
- QuickBASIC for more information.)
-
- Some text editors use the literal tab character to represent multiple
- spaces when storing text files. The QuickBASIC editor treats literal tab
- characters in such files as follows:
-
- 1. Literal tab characters inside quoted strings appear as the character
- shown for ASCII character 9 in the ASCII table in Appendix D,
- "Keyboard Scan Codes and ASCII Character Codes."
-
- 2. Outside quoted strings, tab characters indent the text following them
- to the next indentation level.
-
- If you try to change the Tab Stops setting while such a program is loaded,
- QuickBASIC gives the following error message:
-
- Cannot change tab stops while file is loaded
-
- This is to prevent you from inadvertently reformatting old source files
- created with other editors. If you load such a file and then decide you
- prefer a different indentation, reset the indentation using the following
- procedure:
-
- 1. Save your file to preserve any changes, then choose the New Program
- command from the File menu.
-
- 2. Choose the Display command from the Options menu and set the Tab Stops
- option as described above.
-
- 3. Choose the Open Program command from the File menu and reload your
- program. When your program is reloaded, the indentations will reflect
- the new setting of the Tab Stops option.
-
- Note that this procedure works only for old programs. Text created within
- QuickBASIC cannot be reformatted this way.
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- Appendix B Differences from Previous Versions of QuickBASIC
-
- QuickBASIC Version 4.5 contains many new features and enhancements over
- previous versions of QuickBASIC. This appendix describes the differences
- between Versions 2.0 and 4.5 of QuickBASIC. Unless otherwise stated,
- differences between Versions 2.0 and 4.5 also apply as differences between
- Versions 3.0 and 4.5. Differences between Versions 4.0 and 4.5 are
- primarily in the QuickBASIC environment.
-
- This appendix provides information on the following improvements in
- QuickBASIC Version 4.5:
-
- ■ Product capabilities and features
-
- ■ Environment enhancements
-
- ■ Improvements in compiling and debugging capabilities
-
- ■ Language changes
-
- ■ File compatibility
-
-
- B.1 QuickBASIC Features
-
- This section compares the features of Microsoft QuickBASIC Versions 4.5
- with those of previous versions. The features are listed in Table B.1 and
- described below.
-
- Table B.1 Features of Microsoft QuickBASIC Version 4.5
- ╓┌─┌───────────────────────────────┌─────────┌──────────┌─────────┌──────────╖
- QuickBASIC Version
- Feature 2.0 3.0 4.0 4.5
- ──────────────────────────────────────────────────────────────────────────
- On-line QB Advisor (detailed No No No Yes
- reference)
-
- Selectable right mouse button No No No Yes
- function
-
- Instant Watches for variables No No No Yes
- and expressions
-
- Set default search paths No No No Yes
-
- User-defined types No No Yes Yes
-
- IEEE format, math coprocessor No Yes Yes Yes
- support
-
- On-line help No No Yes Yes
- QuickBASIC Version
- Feature 2.0 3.0 4.0 4.5
- ──────────────────────────────────────────────────────────────────────────
- On-line help No No Yes Yes
-
- Symbol help No No No Yes
-
- Long (32-bit) integers No No Yes Yes
-
- Fixed-length strings No No Yes Yes
-
- Syntax checking on entry No No Yes Yes
-
- Binary file I/O No No Yes Yes
-
- FUNCTION procedures No No Yes Yes
-
- CodeView(R) support No No Yes Yes
-
- Compatibility with other No No Yes Yes
- languages
- QuickBASIC Version
- Feature 2.0 3.0 4.0 4.5
- ──────────────────────────────────────────────────────────────────────────
- languages
-
- Multiple modules in memory No No Yes Yes
-
- ProKey TM, SideKick(R), and No Yes Yes Yes
- SuperKey(R) compatibility
-
- Insert/overtype modes No Yes Yes Yes
-
- WordStar(R)-style keyboard No No Yes Yes
- interface
-
- Recursion No No Yes Yes
-
- Error listings during separate No Yes Yes Yes
- compilation
-
- Assembly-language listings No Yes Yes Yes
- QuickBASIC Version
- Feature 2.0 3.0 4.0 4.5
- ──────────────────────────────────────────────────────────────────────────
- Assembly-language listings No Yes Yes Yes
- during separate compilation
- ──────────────────────────────────────────────────────────────────────────
-
-
- B.1.1 Features New to QuickBASIC 4.5
-
- You can now access on-line help for QuickBASIC's keywords, commands, and
- menus, as well as general topics and your own variables. Examples shown on
- help screens can be copied and pasted directly into your own program,
- reducing development time.
-
- For mouse users, you can now set the function of the right mouse button
- with the Right Mouse command from the Options menu. Use the function that
- best suits your needs. For more information see Chapter 19, "The Calls
- Menu," in Learning to Use Microsoft QuickBASIC.
-
- For faster debugging, QuickBASIC now offers an Instant Watch command for
- immediately identifying the value of a variable or the condition (true or
- false) of an expression. For more information see Chapter 18, "The Debug
- Menu," in Learning to Use Microsoft QuickBASIC.
-
- Version 4.5 also lets you set default search paths to specific types of
- files. This lets you organize your files by type and keep them in separate
- directories. QuickBASIC will search the correct directory after you set
- the new default search path. You can set default paths for executable,
- include, library, and help files.
-
- B.1.2 Features Introduced in QuickBASIC 4.0
-
- If you are new to QuickBASIC or unfamiliar with Version 4.0, you will want
- to review the following features introduced in QuickBASIC 4.0 and
- supported in the current version.
-
- B.1.2.1 User-Defined Types
-
- The TYPE statement allows you to create composite data types from simple
- data elements. Such data types are similar to C-language structures.
- User-defined types are discussed in Chapter 3, "File and Device I/O."
-
- B.1.2.2 IEEE Format and Math-Coprocessor Support
-
- Microsoft QuickBASIC provides IEEE-format numbers and math-coprocessor
- support. When no coprocessor is present, QuickBASIC emulates the
- coprocessor.
-
- Calculations done by programs compiled with QuickBASIC are generally more
- accurate and may produce results different from programs run under BASICA
- or versions of QuickBASIC prior to 4.0. Single-precision IEEE-format
- numbers provide an additional decimal digit of accuracy. When compared to
- Microsoft Binary format double-precision numbers, IEEE-format
- double-precision numbers provide an additional one to two digits in the
- mantissa and extend the range of the exponent.
-
- There are two ways to use QuickBASIC 4.0 and 4.5 with your old programs
- and existing data:
-
- 1. Use the /MBF option. This way, you can use your old programs and data
- files without rewriting your programs or changing your files.
-
- 2. Modify your data files and use the new QuickBASIC to recompile your
- programs. In the long run, this ensures compatibility with future
- versions of QuickBASIC and may produce faster programs. Only
- random-access files containing binary format real numbers need to be
- changed. Files containing only integers or string data can be used
- without modification. More information on these options is provided
- below.
-
- ──────────────────────────────────────────────────────────────────────────
- NOTE
- If assembly-language procedures that use real numbers are called from
- your program, they must be written so that they use IEEE-format numbers.
- This is the default for Microsoft Macro Assembler (MASM) Version 5.0 and
- later versions. With earlier versions, be sure to use the /R
- command-line option or the 8087 assembler directive.
- ──────────────────────────────────────────────────────────────────────────
-
- B.1.2.3 Ranges of IEEE-Format Numbers
-
- IEEE-format numbers have a wider range than Microsoft Binary format
- numbers, as shown in the following list:
-
- Type of Number Range of Values
- ──────────────────────────────────────────────────────────────────────────
- Single precision -3.37 * 10^38 to -8.43 * 10^-37
- True zero
-
- 8.43 * 10^-37 to 3.37 * 10^38
-
- Double precision -1.67 * 10^308 to -4.19 * 10^-307
- True zero
-
- 4.19 * 10^-307 to 1.67 * 10^308
- ──────────────────────────────────────────────────────────────────────────
-
- Single-precision values are accurate to approximately seven digits.
- Double-precision values are accurate to either 15 or 16 digits.
-
- Note that double-precision values may have three digits in the exponent.
- This may cause problems in PRINT USING statements.
-
- B.1.2.4 PRINT USING and IEEE-Format Numbers
-
- Because double-precision IEEE-format numbers can have larger exponents
- than Microsoft Binary format double-precision numbers, you may need to use
- a special exponential format in PRINT USING statements. Use the new format
- if your program prints values with three-digit exponents. To print numbers
- with three-digit exponents, use five carets (^^^^^) instead of four carets
- to indicate exponential format:
-
- PRINT USING "+#.######^^^^^", Circumference#
-
- If an exponent is too large for a field, QuickBASIC replaces the first
- digit with a percent sign (%) to indicate the problem.
-
- B.1.3 Recompiling Old Programs with /MBF
-
- Old programs and files work with QuickBASIC Version 4.5 without
- modification if you recompile the programs with the /MBF command-line
- option. For example, to compile the program named multrgrs.bas, enter the
- following at the DOS prompt:
-
- BC multrgrs /MBF;
-
- Then link the program as you usually do. To recompile using the Make EXE
- File command, be sure to use the /MBF option when you start QuickBASIC.
- Then compile as you normally would.
-
- The /MBF option converts Microsoft Binary format numbers to IEEE format as
- they are read from a random-access file and converts them back to
- Microsoft Binary format before writing them to a file. This lets you do
- calculations with IEEE-format numbers while keeping the numbers in
- Microsoft Binary format in your files.
-
- B.1.4 Converting Files and Programs
-
- If you decide to convert your programs and data files rather than use the
- /MBF command-line option, you need to do two things:
-
- 1. Recompile your programs.
-
- 2. Convert your data files.
-
- Your old QuickBASIC programs should compile without modification. However,
- do not use the /MBF option when recompiling. Your program will not work
- with your new data files if you use the /MBF option.
-
- Data files containing real numbers need to be converted so that real
- numbers are stored in IEEE format. QuickBASIC Version 4.5 includes eight
- functions that help you do this.
-
- ──────────────────────────────────────────────────────────────────────────
- NOTE
- You do not need to convert your data files if they contain only integer
- and string data. Only files containing real numbers must be converted.
- ──────────────────────────────────────────────────────────────────────────
-
- Version 4.5 has the familiar CVS, CVD, MKS$, and MKD$ functions for
- reading and writing real numbers from or to random-access files. However,
- these functions now handle real numbers stored in your files in IEEE
- format, not Microsoft Binary format. To handle numbers in Microsoft Binary
- format, Version 4.5 includes the functions CVSMBF, CVDMBF, MKSMBF$, and
- MKDMBF$.
-
- With these functions, you can write a short program that reads records
- from the old file (using Microsoft Binary format as necessary), converts
- the real-number fields to IEEE format, places the fields in a new record,
- and writes out the new record.
-
- Examples
-
- The following program copies an old data file to a new file, making the
- necessary conversions:
-
- ' Define types for old and new file buffers:
- TYPE Oldbuf
- ObsId AS STRING * 20
- XPos AS STRING * 4
- YPos AS STRING * 4
- FuncVal AS STRING * 8
- END TYPE
-
- TYPE NewBuf
- ObsId AS STRING * 20
- XPos AS SINGLE
- YPos AS SINGLE
- FuncVal AS DOUBLE
- END TYPE
-
- ' Declare buffers:
- DIM OldFile AS Oldbuf, NewFile AS NewBuf
-
- ' Open the old and new data files:
- OPEN "OLDMBF.DAT" FOR RANDOM AS #1 LEN=LEN(OldFile)
- OPEN "NEWIEEE.DAT" FOR RANDOM AS #2 LEN=LEN(NewFile)
-
- I=1
-
- ' Read the first old record:
- GET #1,I,OldFile
-
- DO UNTIL EOF(1)
-
- ' Move the fields to the new record fields, converting
- ' the real-number fields:
- NewFile.ObsId=OldFile.ObsId
- NewFile.XPos=CVSMBF(OldFile.XPos)
- NewFile.YPos=CVSMBF(OldFile.YPos)
- NewFile.FuncVal=CVDMBF(OldFile.FuncVal)
-
- ' Write the converted fields to the new file:
- PUT #2,I,NewFile
- I=I+1
-
- ' Read next record from the old file:
- GET #1,I,OldFile
- LOOP
-
- CLOSE #1, #2
-
- Each record in the two files has four fields: an identifier field, two
- fields containing single-precision real numbers, and a final field
- containing a double-precision real number.
-
- Most of the conversion work is done with the functions CVDMBF and CVSMBF.
- For example, the following program line converts the double-precision
- field:
-
- NewFile.FuncVal=CVDMBF(OldFile.FuncVal)
-
- The eight bytes in the record field OldFile.FuncVal are converted from a
- Microsoft Binary format double-precision value to an IEEE-format
- double-precision value by the function CVDMBF. This value is stored in the
- corresponding field in the new record, which is later written to the new
- file by the PUT statement.
-
- B.1.5 Other QuickBASIC Features
-
- QuickBASIC 4.0 introduced the following features and tools that made
- QuickBASIC a development package appreciated by the professional without
- overwhelming the novice. QuickBASIC 4.5 supports all these same features,
- along with some additional refinements.
-
- B.1.5.1 Long (32-Bit) Integers
-
- Long (32-bit) integers eliminate rounding errors in calculations with
- numbers in the range -2,147,483,648 to 2,147,483,647, and they provide
- much faster whole-number calculations in this range than do floating-point
- types.
-
- B.1.5.2 Fixed-Length Strings
-
- Fixed-length strings let you incorporate string data into user-defined
- types. See Chapter 4, "String Processing," for more information.
-
- B.1.5.3 Syntax Checking on Entry
-
- If syntax checking is turned on, QuickBASIC checks each line as you enter
- it for syntax and duplicate-definition errors. See Chapter 12, "Using the
- Editor," in Learning to Use Microsoft QuickBASIC for an explanation of
- syntax checking and other smart-editor features.
-
- B.1.5.4 Binary File I/O
-
- Versions 4.0 and 4.5 provide binary access to files. This is useful for
- reading and modifying files saved in non-ASCII format. The major benefit
- of binary access is that it does not force you to treat a file as a
- collection of records. If a file is opened in binary mode, you can move
- forward or backward to any byte position in the file, then read or write
- as many bytes as you want. Thus, different I/O operations on the same file
- can GET or PUT a varying number of bytes──unlike with random access, where
- the number of bytes is fixed by the predefined length of a single record.
-
- See Chapter 3, "File and Device I/O," for more information about
- accessing binary files.
-
- B.1.5.5 FUNCTION Procedures
-
- FUNCTION procedures allow you to place a function in one module and call
- it from a different module. See Chapter 2, "SUB and FUNCTION Procedures,"
- for more information about using FUNCTION procedures.
-
- In versions prior to 4.0, a SUB procedure and a variable could have the
- same name. Now, SUB and FUNCTION procedure names must be unique.
-
- B.1.5.6 Support for the CodeView(R) Debugger
-
- You can use the command-line tools BC.EXE and LINK.EXE to create
- executable files compatible with the Microsoft CodeView debugger, a
- powerful tool included with the Microsoft Macro Assembler (Version 5.0 or
- later) and with Microsoft C (Version 5.0 or later). Modules compiled with
- BC can be linked with modules compiled with other Microsoft languages in
- such a way that the final executable file can be debugged using the
- CodeView debugger. See Appendix G, "Compiling and Linking from DOS," for
- more information.
-
- B.1.5.7 Other-Language Compatibility
-
- QuickBASIC Version 4.5 allows you to call routines written in other
- Microsoft languages using C or Pascal calling conventions. Arguments are
- passed by NEAR or FAR reference, or by value. Other-language code may be
- placed in Quick libraries or linked into executable files.
-
- The PTR86 routine is not supported in QuickBASIC, Version 4.5; use the
- VARPTR and VARSEG functions instead.
-
- B.1.5.8 Multiple Modules in Memory
-
- You can load multiple program modules into memory simultaneously. Versions
- previous to 4.0 permitted only one module to be in memory at a time. Now
- you can edit, execute, and debug multiple-module programs within the
- QuickBASIC environment. See Chapter 2, "SUB and FUNCTION Procedures," and
- Chapter 7, "Programming with Modules," for more information about using
- multiple modules.
-
- B.1.5.9 ProKey TM, SideKick(R), and SuperKey(R) Compatibility
-
- You can use ProKey, SideKick, and SuperKey within the QuickBASIC
- environment. Other keyboard-reprogramming or desktop software may not work
- with QuickBASIC. Check with the suppliers or manufacturers of other
- products to find out about the product's compatibility with QuickBASIC
- Version 4.5.
-
- B.1.5.10 Insert and Overtype Modes
-
- Pressing INS toggles the editing mode between insert and overtype. When
- overtype mode is on, the cursor changes from a blinking underline to a
- block. Note that INS replaces the CTRL+O insert/overtype toggle in Version
- 3.0.
-
- In insert mode, the editor inserts a typed character at the cursor
- position. In overtype mode, the editor replaces the character under the
- cursor with the character you type. Insert mode is the default mode.
-
- B.1.5.11 WordStar(R)-Style Keyboard Commands
-
- QuickBASIC supports many of the key sequences familiar to WordStar users.
- A complete list of WordStar-style key commands appears in Chapter 12,
- "Using the Editor," in Learning to Use Microsoft QuickBASIC.
-
- B.1.5.12 Recursion
-
- QuickBASIC Versions 4.0 and 4.5 support recursion, which is the ability of
- a procedure to call itself. Recursion is useful for solving certain
- problems, such as sorting. See Chapter 2, "SUB and FUNCTION Procedures,"
- for more information about using recursion.
-
- B.1.5.13 Error Listings during Separate Compilation
-
- QuickBASIC displays descriptive error messages when you compile programs
- using the BC command. Using BC, you can redirect the error messages to a
- file or device to get a copy of the compilation errors. See Appendix G,
- "Compiling and Linking from DOS," for more information about the BC
- command.
-
- Examples
-
- The following examples show how to use the BC command line for error
- display:
-
- Command Line Action
- ──────────────────────────────────────────────────────────────────────────
- BC TEST.BAS; Compiles the file named TEST.BAS and displays
- errors on the screen
-
- BC TEST.BAS; > TEST.ERR Compiles the file TEST.BAS and redirects error
- messages to the file named TEST.ERR
- ──────────────────────────────────────────────────────────────────────────
-
- B.1.5.14 Assembly-Language Listings during Separate Compilation
-
- The BC command's /A option produces a listing of the assembly-language
- code produced by the compiler. See Appendix G, "Compiling and Linking
- from DOS," for more information.
-
-
- B.2 Differences in the Environment
-
- The QuickBASIC programming environment now provides more flexible command
- selection, additional window options, and more menu commands. Sections
- B.2.1-B.2.5 describes the differences in the programming environment
- between Version 4.5 and earlier versions.
-
- B.2.1 Choosing Commands and Options
-
- QuickBASIC Version 4.5 gives you flexibility in how you choose commands
- from menus and options from dialog boxes.
-
- Version 4.5 allows you to select any menu by pressing the ALT key followed
- by a mnemonic key. Each menu command and dialog box option also has its
- own mnemonic key, which immediately executes the command or selects the
- item. The mnemonic keys appear in intense video.
-
- In Version 4.5 the ENTER key functions the same way as the SPACEBAR did in
- versions 3.0 and earlier. You can press ENTER to execute a command from a
- dialog box.
-
- B.2.2 Windows
-
- Version 4.5 allows up to two work-area windows (referred to as View
- windows), a Help window, and a separate Immediate window. Versions prior
- to 4.0 supported only two windows: one work area and the error-message
- window.
-
- B.2.3 New Menu
-
- QuickBASIC Version 4.5 has a new menu, the Options menu. The Options menu
- accesses special QuickBASIC controls that manipulate the screen display
- attributes, the function of the right mouse button, the default path to
- specific file types, syntax checking, and Full Menus control.
-
- B.2.4 Menu Commands
-
- The Debug and Help menus, which appeared in earlier versions of
- QuickBASIC, have some new commands. Table B.2 lists the new commands in
- these menus, as well as the commands from the new Options menu.
-
- Table B.2 Menus with New Commands in QuickBASIC Version 4.5
- ╓┌─┌───────────┌────────────────────────┌────────────────────────────────────╖
- Menu Command Description
- ──────────────────────────────────────────────────────────────────────────
- Debug Add Watch Adds variable or expression to Watch
- window
-
- Instant Watch (New) Immediately checks the value of a
- variable or expression
-
- Watchpoint Adds a watchpoint to the Watch window
-
- Delete Watch Selectively removes item from Watch
- window
-
- Delete All Watch Removes all items from the Watch
- window
-
- Trace On Toggles tracing on and off
-
- History On Records last 20 executed statements
- Menu Command Description
- ──────────────────────────────────────────────────────────────────────────
- History On Records last 20 executed statements
-
- Toggle Breakpoint Toggles a breakpoint on the current
- line on and off
-
- Clear All Breakpoints Removes all breakpoints
-
- Break on Errors (New) Halts program execution if an error
- occurs, regardless of any error
- handling
-
- Set Next Statement Sets the next statement to execute
- when a suspended program continues
- running
-
- Option Display (New) Customizes the screen elements
- (New)
- Set Paths (New) Alters default search paths for
- specific types of files
- Menu Command Description
- ──────────────────────────────────────────────────────────────────────────
- specific types of files
-
- Right Mouse (New) Selects the function for the right
- mouse button
-
- Syntax Checking Toggles automatic syntax checking on
- and off
-
- Full Menus (New) Toggles between Full Menus and Easy
- Menus
-
- Help Index (New) Displays an alphabetical list of
- QuickBASIC keywords and a brief
- description of each
-
- Contents (New) Displays a visual outline of contents
-
- Topic Provides information on variables,
- keywords
- Menu Command Description
- ──────────────────────────────────────────────────────────────────────────
- keywords
-
- Help on Help (New) Describes how to use Help and common
- keyword shortcuts
- ──────────────────────────────────────────────────────────────────────────
-
-
- The Version 3.0 Debug option is removed from the Run menu. In Version 4.5
- you can debug at any time, using the debugging commands in the Debug menu.
-
- B.2.5 Editing-Key Changes
-
- The QuickBASIC keyboard interface has been extended to include editing key
- sequences similar to those in the WordStar editor. (See Chapter 12, "Using
- the Editor," and Chapter 13, "The Edit Menu," in Learning to Use Microsoft
- QuickBASIC for more information about editing.) The functions performed by
- the QuickBASIC Version 2.0 key sequences listed in Table B.3 are changed
- in QuickBASIC Versions 4.0 and 4.5.
-
- Table B.3 Editing-Key Changes
- QuickBASIC QuickBASIC
- Function 2.0 Key 4.5 Key
- ──────────────────────────────────────────────────────────────────────────
- Undo SHIFT+ESC ALT+BKSP
-
- Cut DEL SHIFT+DEL
-
- Copy F2 CTRL+INS
-
- Paste INS SHIFT+INS
-
- Clear ── DEL
-
- Overtype ── INS
- ──────────────────────────────────────────────────────────────────────────
-
-
- B.3 Differences in Compiling and Debugging
-
- In the QuickBASIC 4.5 programming environment, compiling and debugging are
- not separate operations. Your program is always ready to run, and you can
- debug your code in several ways while you program. This section describes
- the differences in compiling and debugging features between QuickBASIC
- Versions 4.0 and 4.5 and previous versions.
-
- B.3.1 Command-Line Differences
-
- QuickBASIC Versions 4.0 and 4.5 support Version 2.0 command-line options
- only for the QB command, not the BC command. To compile a program outside
- of the QuickBASIC environment, use the BC command, which is described in
- Appendix G, "Compiling and Linking from DOS."
-
- Versions 4.0 and 4.5 do not require any of the Compile options listed in
- Table 4.1 of the Microsoft QuickBASIC Version 2.0 manual. If you attempt
- to invoke QuickBASIC using these as command-line options, an error message
- appears. Similarly, it was necessary to choose certain compiler options
- from the Compile dialog box in Version 3.0; this is now done
- automatically. Table B.4 describes the way in which QuickBASIC now
- supports the functionality of these options.
-
- Table B.4 QB and BC Options Not Used in QuickBASIC Versions 4.0 or 4.5
- Version 2.0 Version 4.5
- ──────────────────────────────────────────────────────────────────────────
- On Error (/E) Automatically set whenever an ON ERROR statement
- is present.
-
- Debug (/D) Always on when you run a program within the
- QuickBASIC environment. When producing executable
- programs on disk or Quick libraries, use the
- Produce Debug Code option.
-
- Checking between Automatically set whenever an ON event statement
- Statements (/V) and is present.
- Event Trapping (/W)
-
- Resume Next (/X) Automatically set whenever a RESUME NEXT
- statement is present.
-
- Arrays in Row Order (/R) Available only when compiling with BC.
-
- Minimize String Data The default for QB. To turn off this option, you
- (/S) must compile from the command line with BC.
- ──────────────────────────────────────────────────────────────────────────
-
- The options listed in Table B.5 are now available for the QB and BC
- commands.
-
- Table B.5 Options Introduced in Version 4.0 for the QB and BC Commands
- ╓┌─┌────────────────────────┌────────────────────────────────────────────────╖
- Option Description
- ──────────────────────────────────────────────────────────────────────────
- /AH Allows dynamic arrays of records, fixed-length
- strings, and numeric data to be larger than 64K
- each. If this option is not specified, the
- maximum size for each array is 64K. Note that
- this option has no effect on the way data items
- are passed to procedures. (This option is used
- with the QB and BC commands.)
-
- /H Displays the highest resolution possible on your
- hardware. For example, if you have an EGA,
- QuickBASIC displays 43 lines and 80 columns of
- text. (This option is used only with the QB
- Option Description
- ──────────────────────────────────────────────────────────────────────────
- text. (This option is used only with the QB
- command.)
-
- /MBF Converts Microsoft Binary format numbers to IEEE
- format. See Section B.1.2.3 for more information
- about this option (used with the QB and BC
- commands).
-
- /RUN sourcefile Runs sourcefile immediately, without first
- displaying the QuickBASIC programming
- environment. (This option is used only with the
- QB command.)
- ──────────────────────────────────────────────────────────────────────────
-
-
- B.3.2 Separate Compilation Differences
-
- Versions 4.0 and 4.5 do not allow separate compilation with the QB command.
- Use the BC command described in Appendix G, "Compiling and Linking from
- DOS" to compile and link files without entering the programming environment.
-
- B.3.3 User Libraries and BUILDLIB
-
- User libraries created for previous versions are not compatible with
- Versions 4.0 and 4.5. You must rebuild the library from the original
- source files.
-
- User libraries are now called Quick libraries. There is no change in their
- function or use. The file-name extension of these libraries is now .QLB
- instead of .EXE. The BUILDLIB utility is no longer required. Quick
- libraries are now created from within the programming environment or from
- the link command line. See Appendix H, "Creating and Using Quick
- Libraries," for more information on this topic.
-
- B.3.4 Restrictions on Include Files
-
- Include files can contain SUB or FUNCTION procedure declarations but not
- definitions. If you need to use an old include file with procedure
- definitions in it, use the Merge command from the File menu to insert the
- include file into the current module. When you merge an include file
- containing a SUB procedure, the text of the procedure does not appear in
- the currently active window. To view or edit its text, choose the SUBs
- command from the View menu, then select the procedure name in the list
- box. Once the text is merged, you can run the program.
-
- Alternatively, you may decide to put your SUB procedure in a separate
- module. In this case, you must take one of the following two steps for any
- shared variables (variables declared in a COMMONSHARED or [[RE]]DIM SHARED
- statement outside the SUB procedure, or in a SHARED statement inside the
- SUB procedure), because variables declared this way are shared only within
- a single module:
-
- 1. Share the variables between the modules by listing them in COMMON
- statements at the module level in both modules.
-
- 2. Pass the variables to the SUB procedure in an argument list.
-
- See Chapter 2, "SUB and FUNCTION Procedures," and Chapter 7,
- "Programming with Modules," for additional information on modules and
- procedures.
-
- B.3.5 Debugging
-
- QuickBASIC now helps you debug your programs faster by providing the
- following debugging features:
-
- 1. Multiple breakpoints
-
- 2. Watch expressions, watchpoints, and instant watches
-
- 3. Improved program tracing
-
- 4. Full-screen window that displays program text during single-stepping
-
- 5. The ability to change variable values during execution, then continue
-
- 6. The ability to edit the program, then continue execution without
- restarting
-
- 7. History feature
-
- 8. Calls menu
-
- 9. Symbol help
-
- The debugging function-key sequences listed in Table B.6 are changed from
- QuickBASIC Version 2.0:
-
- Table B.6 Debugging-Key Changes
- QuickBASIC QuickBASIC
- Function Version 2.0 Key Version 4.5 Key
- ──────────────────────────────────────────────────────────────────────────
- Trace ALT+F8 F8
-
- Step ALT+F9 F10
- ──────────────────────────────────────────────────────────────────────────
-
- Note that animation is turned on when you toggle on the Trace On command
- from the Debug menu, then run your program.
-
- See Chapter 9, "Debugging While You Program," in Learning to Use Microsoft
- QuickBASIC for more information.
-
-
- B.4 Changes to the BASIC Language
-
- This section describes enhancements and changes to the BASIC language in
- Version 4.5 and earlier versions of QuickBASIC. Table B.7 lists the
- keywords affected by these changes and shows which version of QuickBASIC
- is affected by each change. A more detailed explanation of the changes
- appears after the table.
-
- Table B.7 Changes to the BASIC Language
- ╓┌─┌───────────────────────────────┌─────────┌──────────┌─────────┌──────────╖
- QuickBASIC Version
- Keyword 2.0 3.0 4.0 4.5
- ──────────────────────────────────────────────────────────────────────────
- AS No No Yes Yes
-
- CALL No No Yes Yes
-
- CASE No Yes Yes Yes
-
- CLEAR No No Yes Yes
- QuickBASIC Version
- Keyword 2.0 3.0 4.0 4.5
- ──────────────────────────────────────────────────────────────────────────
- CLEAR No No Yes Yes
-
- CLNG No No Yes Yes
-
- CLS No Yes Yes Yes
-
- COLOR No No Yes Yes
-
- CONST No Yes Yes Yes
-
- CVL No No Yes Yes
-
- CVSMBF, CVDMBF No Yes Yes Yes
-
- DECLARE No No Yes Yes
-
- DEFLNG No No Yes Yes
-
- QuickBASIC Version
- Keyword 2.0 3.0 4.0 4.5
- ──────────────────────────────────────────────────────────────────────────
- DIM No No Yes Yes
-
- DO...LOOP No Yes Yes Yes
-
- EXIT No Yes Yes Yes
-
- FILEATTR No No Yes Yes
-
- FREEFILE No No Yes Yes
-
- FUNCTION No No Yes Yes
-
- GET No No Yes Yes
-
- LCASE$ No No Yes Yes
-
- LEN No No Yes Yes
- QuickBASIC Version
- Keyword 2.0 3.0 4.0 4.5
- ──────────────────────────────────────────────────────────────────────────
- LEN No No Yes Yes
-
- LSET No No Yes Yes
-
- LTRIM$ No No Yes Yes
-
- MKL$ No No Yes Yes
-
- MKSMBF$, MKDMBF$ No Yes Yes Yes
-
- OPEN No No Yes Yes
-
- ON UEVENT No No No Yes
-
- PALETTE No No Yes Yes
-
- PUT No No Yes Yes
-
- QuickBASIC Version
- Keyword 2.0 3.0 4.0 4.5
- ──────────────────────────────────────────────────────────────────────────
- RTRIM$ No No Yes Yes
-
- SCREEN No No Yes Yes
-
- SEEK No No Yes Yes
-
- SELECT CASE No Yes Yes Yes
-
- SETMEM No No Yes Yes
-
- SLEEP No No No Yes
-
- STATIC No No Yes Yes
-
- TYPE No No Yes Yes
-
- UCASE$ No No Yes Yes
- QuickBASIC Version
- Keyword 2.0 3.0 4.0 4.5
- ──────────────────────────────────────────────────────────────────────────
- UCASE$ No No Yes Yes
-
- UEVENT No No No Yes
-
- VARPTR No No Yes Yes
-
- VARSEG No No Yes Yes
-
- WIDTH No Yes Yes Yes
- ──────────────────────────────────────────────────────────────────────────
-
-
- The following section explains in more detail the differences in the
- keywords summarized above.
-
- ╓┌─┌──────────────────┌──────────────────────────────────────────────────────╖
- Keywords Explanation
- ──────────────────────────────────────────────────────────────────────────
- Keywords Explanation
- ──────────────────────────────────────────────────────────────────────────
- AS The AS clause allows the use of user-defined types in
- DIM, COMMON, and SHARED statements and in DECLARE, SUB,
- and FUNCTION parameter lists.
-
- CALL The use of CALL is optional for calling subprograms
- declared with the DECLARE statement.
-
- CLEAR The CLEAR statement no longer sets the total size of
- the stack; it sets only the stack size required by the
- program. QuickBASIC sets the stack size to the amount
- specified by the CLEAR statement plus what QuickBASIC
- itself requires.
-
- CLNG The CLNG function rounds its argument and returns a
- long (four-byte) integer that is equal to the argument.
-
- CLS The CLS statement has been modified to give you greater
- flexibility in clearing the screen. Note that
- QuickBASIC no longer clears the screen automatically at
- Keywords Explanation
- ──────────────────────────────────────────────────────────────────────────
- QuickBASIC no longer clears the screen automatically at
- the beginning of each program, as was true in earlier
- versions.
-
- COLOR, SCREEN, The COLOR, SCREEN, PALETTE, and WIDTH statements are
- PALETTE, WIDTH extended to include screen modes available with the IBM
- PS/2(R) VGA and Multicolor Graphics Array (MCGA) cards.
-
- CONST The CONST statement lets you define symbolic constants
- to improve program readability and ease program
- maintenance.
-
- CVL The CVL function is used to read long integers stored
- as strings in random-access data files. CVL converts a
- four-byte string created with the MKL$ function back to
- a long integer for use in your BASIC program.
-
- CVSMBF, CVDMBF The CVSMBF and CVDMBF functions convert strings
- containing Microsoft Binary format numbers to
- Keywords Explanation
- ──────────────────────────────────────────────────────────────────────────
- containing Microsoft Binary format numbers to
- IEEE-format numbers. Although QuickBASIC Version 4.5
- supports these statements, they are considered obsolete
- since the IEEE-format is now the QuickBASIC standard.
-
- DECLARE The DECLARE statement allows you to call procedures
- from different modules, check the number and type of
- arguments passed, and call procedures before they are
- defined.
-
- DEFLNG The DEFLNG statement declares all variables, DEF FN
- functions, and FUNCTION procedures as having the
- long-integer type. That is, unless a variable or
- function has been declared in an AS type clause, or it
- has an explicit type-definition suffix such as % or $,
- it is a long integer by default.
-
- DIM The DIM statement's TO clause lets you specify
- subscripts of any integer value, giving you greater
- Keywords Explanation
- ──────────────────────────────────────────────────────────────────────────
- subscripts of any integer value, giving you greater
- flexibility in array declarations.
-
- DO...LOOP Using DO...LOOP statements gives you more powerful
- loops that allow you to write programs with better
- structure.
-
- EXIT The use of EXIT {DEF | DO | FOR | FUNCTION | SUB}
- statements provides convenient exits from loops and
- procedures.
-
- FREEFILE, FILEATTR The FREEFILE and FILEATTR functions help you write
- applications that do file I/O in a multiple-module
- environment.
-
- FUNCTION The FUNCTION...END FUNCTION procedure allows you to
- define a multiline procedure that you call from within
- an expression. These procedures behave much like
- intrinsic functions such as ABS or multiline DEF FN
- Keywords Explanation
- ──────────────────────────────────────────────────────────────────────────
- intrinsic functions such as ABS or multiline DEF FN
- functions from QuickBASIC Versions 1.0-3.0. However,
- unlike a DEF FN function, a FUNCTION procedure can be
- defined in one module and called from another. Also,
- FUNCTION procedures have local variables and support
- recursion.
-
- GET, PUT For I/O operations, the syntax of the GET and PUT
- statements is expanded to include records defined with
- TYPE...END TYPE statements. This makes use of the FIELD
- statement unnecessary.
-
- LCASE$, UCASE$, The following string-handling functions are available
- LTRIM$, RTRIM$ in Version 4.5:
-
- Function Return Value
- LCASE$ A copy of the string with all letters
- converted to lowercase
- UCASE$ A copy of the string with all letters
- Keywords Explanation
- ──────────────────────────────────────────────────────────────────────────
- UCASE$ A copy of the string with all letters
- converted to uppercase
- LTRIM$ A copy of the string with all leading
- blanks removed
- RTRIM$ A copy of the string with all
- trailing blanks removed
- LEN The LEN function has been extended to
- return the number of bytes required
- by any scalar or record variable,
- constant, expression, or array
- element.
-
- LSET The LSET statement is extended to include record
- variables as well as string variables. This allows you
- to assign one record variable to another record
- variable even when the records are not similar.
-
- MKL$ The MKL$ function is used to convert long integers to
- strings that can be stored in random-access data files.
- Keywords Explanation
- ──────────────────────────────────────────────────────────────────────────
- strings that can be stored in random-access data files.
- Use the CVL function to change the string back to a
- long integer.
-
- MKSMBF$, MKDMBF$ The MKSMBF$ and MKDMBF$ functions convert IEEE-format
- numbers to strings containing a Microsoft Binary format
- number. They are obsolete (but supported) in Version
- 4.5, which uses the IEEE-format.
-
- ON UEVENT The ON UEVENT statement directs the program to a
- specified location when a user-defined event (a UEVENT)
- occurs. Use it in the same fashion as other
- event-handling statements.
-
- OPEN The OPEN statement now opens two files with the same
- name for OUTPUT or APPEND as long as the path names are
- different. For example, the following is now permitted:
-
- OPEN "SAMPLE" FOR APPEND AS #1
- Keywords Explanation
- ──────────────────────────────────────────────────────────────────────────
- OPEN "SAMPLE" FOR APPEND AS #1
- OPEN "TMP\SAMPLE" FOR APPEND AS #2
-
- A binary file mode has been added to the OPEN statement
- syntax. See Chapter 3, "File and Device I/O," for
- information about using this mode.
-
- SEEK The SEEK statement and function allow you to position a
- file at any byte or record. See Chapter 3, "File and
- Device I/O," for more information.
-
- SELECT CASE The use of SELECT CASE statements provides a way to
- simplify complex condition testing. The CASE clause of
- the SELECT CASE statement now accepts any expression
- (including variable expressions) as an argument; in
- previous versions, only constant expressions were
- permitted.
-
- SETMEM The SETMEM function facilitates mixed-language
- Keywords Explanation
- ──────────────────────────────────────────────────────────────────────────
- SETMEM The SETMEM function facilitates mixed-language
- programming by allowing you to decrease the amount of
- dynamic memory allocated by BASIC so it can be used by
- procedures in other languages.
-
- SLEEP The SLEEP statement causes the program to pause for an
- indicated period of time or until the user presses a
- key or an enabled event occurs. The optional argument
- indicates the length of the pause (in seconds).
-
- STATIC Omitting the STATIC attribute from SUB and FUNCTION
- statements causes variables to be allocated when the
- procedures are called, instead of when they are
- defined. Such variables do not retain their values
- between procedure calls.
-
- TYPE The TYPE...END TYPE statement lets you define a data
- type containing elements of different fundamental
- types. This simplifies defining and accessing
- Keywords Explanation
- ──────────────────────────────────────────────────────────────────────────
- types. This simplifies defining and accessing
- random-access file records.
-
- UEVENT Enables, suspends, or disables a user-defined event.
- {ON|STOP|OFF} The UEVENT statements are used in the same way as other
- event-trapping statements.
-
- VARPTR The VARPTR function now returns the 16-bit integer
- offset of the BASIC variable or array element. The
- offset is from the beginning of the segment that
- contains the variable or array element.
-
- VARSEG The VARSEG function returns the segment address of its
- argument. This allows you to set DEF SEG appropriately
- for use with PEEK, POKE, BLOAD, BSAVE, and CALL
- ABSOLUTE. It also permits you to get the appropriate
- segment for use with CALL INTERRUPT when executing
- operating-system or BIOS interrupts.
-
- Keywords Explanation
- ──────────────────────────────────────────────────────────────────────────
- WIDTH A new argument on the WIDTH statement lets your
- programs use the extended line modes on machines
- equipped with EGA, VGA, and MCGA adapter cards.
- ──────────────────────────────────────────────────────────────────────────
-
-
- ──────────────────────────────────────────────────────────────────────────
- NOTE
- You can no longer conditionally execute NEXT and WEND statements using
- the single-line IF...THEN...ELSE statement.
- ──────────────────────────────────────────────────────────────────────────
-
-
- B.5 File Compatibility
-
- All versions of QuickBASIC are source-code compatible; source code created
- for a previous version compiles under Version 4.5, except as noted in
- Section B.3.4, "Restrictions on Include Files." QuickBASIC 4.5 translates
- QuickBASIC 4.0 binary files. If you encounter difficulty translating other
- binary files, save the program as an ASCII (text) format in QuickBASIC
- 4.0, then load it with QuickBASIC 4.5. You must recompile object files and
- user libraries created with previous versions of QuickBASIC.
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- Appendix C Limits in QuickBASIC
-
- QuickBASIC and the BC compiler offer programming versatility, but both
- have limitations in order to keep file size and complexity manageable. As
- a result, you may reach these limits in some situations. This appendix
- lists the boundaries you may encounter.
-
- Table C.1 QuickBASIC Limits
- ╓┌─┌────────────────────────┌───────────────────────┌────────────────────────╖
- Maximum Minimum
- ──────────────────────────────────────────────────────────────────────────
- Names and Strings
- Variable names 40 characters 1 character
- Maximum Minimum
- ──────────────────────────────────────────────────────────────────────────
- Variable names 40 characters 1 character
-
- String length 32,767 characters 0 characters
-
- Integers 32,767 -32,768
-
- Long integers 2,147,483,647 -2,147,483,648
-
- Single-precision numbers 3.402823 E+38 1.401298 E-45
- (positive)
-
- Single-precision numbers -1.401298 E-45 -3.402823 E+38
- (negative)
-
- Double-precision numbers 1.797693134862315 D+308 4.940656458412465 D-324
- (positive)
-
- Double-precision numbers -4.940656458412465 -1.797693134862315 D+308
- (negative) D-324
- Maximum Minimum
- ──────────────────────────────────────────────────────────────────────────
- (negative) D-324
-
- Arrays
- Array size (all
- elements)
- Static 65,535 bytes (64K) 1
- Dynamic Available memory
-
- Array dimensions 8 1
-
- Array subscripts 32,767 -32,768
-
- Files and Procedures
- Number of arguments 60 interpreted 0 passed to a procedure
-
- Nesting of include files 5 levels 0
-
- Procedure size 65,535 bytes (64K) 0
- (interpreted)
- Maximum Minimum
- ──────────────────────────────────────────────────────────────────────────
- (interpreted)
-
- Module size (compiled) 65,535 bytes (64K) 0
-
- Data files open 255 0 simultaneously
-
- Data file record number 2,147,483,647 1
-
- Data file record size 32,767 bytes (32K) 1 byte
- (bytes)
-
- Data file size Available disk space 0
-
- Path names 127 characters 1 character
-
- Error message numbers 255 1
-
- Editing in the Quick-BASIC Environment
- Text box entry 128 characters 0 characters
- Maximum Minimum
- ──────────────────────────────────────────────────────────────────────────
- Text box entry 128 characters 0 characters
-
- "Search for" string 128 1
-
- "Change to" string 40 0
-
- Placemarkers 4 0
-
- Watchpoints and/or watch 8 0 expressions
-
- Number of lines in 10 0 Immediate window
-
- Characters in View 255 0 window on one line
-
- Length of COMMAND$ 124 0 string
- ──────────────────────────────────────────────────────────────────────────
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- Appendix D Keyboard Scan Codes and ASCII Character Codes
-
-
- D.1 Keyboard Scan Codes
-
- The table on the next page shows the DOS keyboard scan codes. These codes
- are returned by the INKEY$ function.
-
- Key combinations with NUL in the Char column return two bytes──a null byte
- (&H00) followed by the value listed in the Dec and Hex columns. For
- example, pressing ALT+F1 returns a null byte followed by a byte containing
- 104 (&H68).
-
- ┌────────┬───────┬────────────┬─────────────┬─────────────┬──────────────┐
- │ │ │ │ ASCII or │ ASCII or │ ASCII or │
- │ │ Scan │ ASCII or │ Extended │ Extended │ Extended │
- │ Key │ Code │ Extended │ with SHIFT │ with CTRL │ with ALT │
- ├────────┼───────┼────────────┼─────────────┼─────────────┼──────────────┤
- │ │Dec Hex│Dec Hex Char│Dec Hex Char │Dec Hex Char │ Dec Hex Char │
- ├────────┼───────┼────────────┼─────────────┼─────────────┼──────────────┤
- │ESC │ 1 01 │ 27 1B │ 27 1B │ 27 1B │ │
- │1! │ 2 02 │ 49 31 1 │ 33 21 ! │ │ 120 78 NUL │
- │2@ │ 3 03 │ 50 32 2 │ 64 40 @ │ 3 03 NUL │ 121 79 NUL │
- │3# │ 4 04 │ 51 33 3 │ 35 23 # │ │ 122 7A NUL │
- │4$ │ 5 05 │ 52 34 4 │ 36 24 $ │ │ 123 7B NUL │
- │5% │ 6 06 │ 53 35 5 │ 37 25 % │ │ 124 7C NUL │
- │6^ │ 7 07 │ 54 36 6 │ 94 5E ^ │ 30 IE │ 125 7D NUL │
- │7& │ 8 08 │ 55 37 7 │ 38 26 & │ │ 126 7E NUL │
- │8* │ 9 09 │ 56 38 8 │ 42 2A * │ │ 127 7F NUL │
- │9( │10 0A │ 57 39 9 │ 40 28 ( │ │ 128 80 NUL │
- │0) │11 0B │ 48 30 0 │ 41 29 ) │ │ 129 81 NUL │
- │-_ │12 0C │ 45 2D - │ 95 5F - │ 31 IF │ 130 82 NUL │
- │=+ │13 0D │ 61 3D = │ 43 2B + │ │ 131 83 NUL │
- │BKSP │14 0E │ 8 08 │ 8 08 │127 7F │ │
- │TAB │15 0F │ 9 09 │ 15 OF NUL│ │ │
- │Q │16 10 │113 71 q │ 81 51 Q │ 17 11 │ 16 10 NUL │
- │W │17 11 │119 77 w │ 87 57 W │ 23 17 │ 17 11 NUL │
- │E │18 12 │101 65 e │ 69 45 E │ 5 05 │ 18 12 NUL │
- │R │19 13│114 72 r │ 82 52 R │ 18 12 │ 19 13 NUL │
- │T │20 14│116 74 t │ 84 54 T │ 20 14 │ 20 14 NUL │
- │Y │21 15│121 79 y │ 89 59 Y │ 25 19 │ 21 15 NUL │
- │U │22 16│117 75 u │ 85 55 U │ 21 15 │ 22 16 NUL │
- │I │23 17│105 69 i │ 73 49 I │ 9 09 │ 23 17 NUL │
- │O │24 18│111 6F o │ 79 4F O │ 15 0F │ 24 18 NUL │
- │P │25 19│112 70 p │ 80 50 P │ 16 10 │ 25 19 NUL │
- │[{ │26 1A│ 91 5B [ │123 7B { │ 27 1B │ │
- │]} │27 1B│ 93 5D ] │125 7D } │ 29 1D │ │
- │ENTER │28 1C│ 13 OD CR│ 13 OD CR │ 10 OA LF │ │
- │CTRL │29 1D│ │ │ │ │
- │A │30 1E│ 97 61 a │ 65 41 A │ 1 01 │ 30 1E NUL │
- │S │31 1F│115 73 s │ 83 53 S │ 19 13 │ 31 1F NUL │
- │D │32 20│100 64 d │ 68 44 D │ 4 04 │ 32 20 NUL │
- │F │33 21│102 66 f │ 70 46 F │ 6 06 │ 33 21 NUL │
- │G │34 22│103 67 g │ 71 47 G │ 7 07 │ 34 22 NUL │
- │H │35 23│104 68 h │ 72 48 H │ 8 08 │ 35 23 NUL │
- │J │36 24│106 6A j │ 74 4A J │ 10 0A │ 36 24 NUL │
- │K │37 25│107 6B k │ 75 4B K │ 11 0B │ 37 25 NUL │
- │L │38 26│108 6C l │ 76 4C L │ 12 0C │ 38 26 NUL │
- │;: │39 27│ 59 3B ; │ 58 3A : │ │ │
- │'" │40 28│ 39 27 ' │ 34 22 " │ │ │
- │`~ │41 29│ 96 60 ` │126 7E ~ │ │ │
- │L SHIFT │42 2A│ │ │ │ │
- │\| │43 2B│ 92 5C \ │124 7C | │ 28 1C │ │
- │Z │44 2C │122 7A z │ 90 5A Z │ 26 1A │ 44 2C NUL │
- │X │45 2D │120 78 x │ 88 58 X │ 24 18 │ 45 2D NUL │
- │C │46 2E │ 99 63 c │ 67 43 C │ 3 03 │ 46 2E NUL │
- │V │47 2F │118 76 v │ 86 56 V │ 22 16 │ 47 2F NUL │
- │B │48 30 │ 98 62 b │ 66 42 B │ 2 OE │ 48 30 NUL │
- │N │49 31 │110 6E n │ 78 4E N │ 14 OD │ 49 31 NUL │
- │M │50 32 │109 6D m │ 77 4D M │ 13 │ 50 32 NUL │
- │,< │51 33 │ 44 2C ' │ 60 3C < │ │ │
- │.> │52 34 │ 46 2E . │ 62 3E > │ │ │
- │/? │53 35 │ 47 2F / │ 63 3F ? │ │ │
- │R SHIFT │54 36 │ │ │ │ │
- │* PRTSC │55 37 │ 42 2A * │ INT 5 │ 16 10 │ │
- │ALT │56 38 │ │ │ │ │
- │SPACE │57 39 │ 32 20 SPC│ 32 20 SPC│ 32 20 SPC │ 32 20 SPC │
- │CAPS │58 3A │ │ │ │ │
- │F1 │59 3B │ 59 3B NUL│ 84 54 NUL│ 94 5E NUL │ 104 68 NUL │
- │F2 │60 3C │ 60 3C NUL│ 85 55 NUL│ 95 5F NUL │ 105 69 NUL │
- │F3 │61 3D │ 61 3D NUL│ 86 56 NUL│ 96 60 NUL │ 106 6A NUL │
- │F4 │62 3E │ 62 3E NUL│ 87 57 NUL│ 97 61 NUL │ 107 6B NUL │
- │F5 │63 3F │ 63 3F NUL│ 88 58 NUL│ 98 62 NUL │ 108 6C NUL │
- │F6 │64 40 │ 64 40 NUL│ 89 59 NUL│ 99 63 NUL │ 109 6D NUL │
- │F7 │65 41 │ 65 41 NUL│ 90 5A NUL│100 64 NUL │ 110 6E NUL │
- │F8 │66 42 │ 66 46 NUL│ 91 5B NUL│101 65 NUL │ 111 6F NUL │
- │F9 │67 43 │ 67 43 NUL│ 92 5C NUL│102 66 NUL │ 112 70 NUL │
- │F10 │68 44 │ 68 44 NUL│ 93 5D NUL│103 67 NUL │ 113 71 NUL │
- │NUM │69 45 │ │ │ │ │
- │SCROLL │70 46 │ │ │ │ │
- │HOME │71 47 │ 71 47 NUL │ 55 37 7 │119 77 NUL │ │
- │UP │72 48 │ 72 48 NUL │ 56 38 8 │ │ │
- │PGUP │73 49 │ 73 49 NUL │ 57 39 9 │132 84 NUL │ │
- │GREY- │74 4A │ 45 2D - │ 45 2D - │ │ │
- │LEFT │75 4B │ 75 4B NUL │ 52 34 4 │115 73 NUL │ │
- │CENTER │76 4C │ │ 53 35 5 │ │ │
- │RIGHT │77 4D │ 77 4D NUL │ 54 36 6 │116 74 NUL │ │
- │GREY+ │78 4E │ 43 2B + │ 43 2b + │ │ │
- │END │79 4F │ 79 4F NUL │ 49 31 1 │117 75 NUL │ │
- │DOWN │80 50 │ 80 50 NUL │ 50 32 2 │ │ │
- │PGDN │81 51 │ 81 51 NUL │ 51 33 3 │118 76 NUL │ │
- │INS │82 52 │ 82 52 NUL │ 48 30 0 │ │ │
- │DEL │83 53 │ 83 53 NUL │ 46 2E . │ │ │
- └────────┴───────┴────────────┴─────────────┴─────────────┴──────────────┘
-
-
- D.2 ASCII Character Codes
-
- ┌─────────────────────┐ ┌────────────┐ ┌────────────┐ ┌────────────┐
- │Ctrl D H Char Code│ │Dec Hex Char│ │Dec Hex Char│ │Dec Hex Char│
- ├───┬───┬───┬────┬────┤ ├───┬───┬────┤ ├───┬───┬────┤ ├───┬───┬────┤
- │^@ │ 0│00 │ │ NUL│ │ 32│ 20│ │ │ 64│40 │ @ │ │ 96│60 │ ` │
- │^A │ 1│01 │ │ SOH│ │ 33│ 21│ ! │ │ 65│41 │ A │ │ 97│61 │ a │
- │^B │ 2│02 │ │ STX│ │ 34│ 22│ " │ │ 66│42 │ B │ │ 98│62 │ b │
- │^C │ 3│03 │ │ ETX│ │ 35│ 23│ # │ │ 67│43 │ C │ │ 99│63 │ c │
- │^D │ 4│04 │ │ EOT│ │ 36│ 24│ $ │ │ 68│44 │ D │ │100│64 │ d │
- │^E │ 5│05 │ │ ENQ│ │ 37│ 25│ % │ │ 69│45 │ E │ │101│65 │ e │
- │^F │ 6│06 │ │ ACK│ │ 38│ 26│ & │ │ 70│46 │ F │ │102│66 │ f │
- │^G │ 7│07 │ │ BEL│ │ 39│ 27│ ' │ │ 71│47 │ G │ │103│67 │ g │
- │^H │ 8│08 │ │ BS │ │ 40│ 28│ ( │ │ 72│48 │ H │ │104│68 │ h │
- │^I │ 9│09 │ │ HT │ │ 41│ 29│ ) │ │ 73│49 │ I │ │105│69 │ i │
- │^J │ 10│0A │ │ LF │ │ 42│ 2A│ * │ │ 74│4A │ J │ │106│6A │ j │
- │^K │ 11│0B │ │ VT │ │ 43│ 2B│ + │ │ 75│4B │ K │ │107│6B │ k │
- │^L │ 12│0C │ │ FF │ │ 44│ 2C│ , │ │ 76│4C │ L │ │108│6C │ l │
- │^M │ 13│0D │ │ CR │ │ 45│ 2D│ - │ │ 77│4D │ M │ │109│6D │ m │
- │^N │ 14│0E │ │ SO │ │ 46│ 2E│ . │ │ 78│4E │ N │ │110│6E │ n │
- │^O │ 15│0F │ │ SI │ │ 47│ 2F│ / │ │ 79│4F │ O │ │111│6F │ o │
- │^P │ 16│10 │ │ DLE│ │ 48│ 30│ 0 │ │ 80│50 │ P │ │112│70 │ p │
- │^Q │ 17│11 │ │ DC1│ │ 49│ 31│ 1 │ │ 81│51 │ Q │ │113│71 │ q │
- │^R │ 18│12 │ │ DC2│ │ 50│ 32│ 2 │ │ 82│52 │ R │ │114│72 │ r │
- │^S │ 19│13 │ │ DC3│ │ 51│ 33│ 3 │ │ 83│53 │ S │ │115│73 │ s │
- │^T │ 20│14 │ │ DC4│ │ 52│ 34│ 4 │ │ 84│54 │ T │ │116│74 │ t │
- │^U │ 21│15 │ │ NAK│ │ 53│ 35│ 5 │ │ 85│55 │ U │ │117│75 │ u │
- │^V │ 22│ 16│ │ SYN│ │ 54│ 36│ 6 │ │ 86│ 56│ V │ │118│ 76│ v │
- │^W │ 23│ 17│ │ ETB│ │ 55│ 37│ 7 │ │ 87│ 57│ W │ │119│ 77│ w │
- │^X │ 24│ 18│ │ CAN│ │ 56│ 38│ 8 │ │ 88│ 58│ X │ │120│ 78│ x │
- │^Y │ 25│ 19│ │ EM │ │ 57│ 39│ 9 │ │ 89│ 59│ Y │ │121│ 79│ y │
- │^Z │ 26│ 1A│ │ SUB│ │ 58│ 3A│ : │ │ 90│ 5A│ Z │ │122│ 7A│ z │
- │^[ │ 27│ 1B│ │ ESC│ │ 59│ 3B│ ; │ │ 91│ 5B│ [ │ │123│ 7B│ { │
- │^\ │ 28│ 1C│ │ FS │ │ 60│ 3C│ < │ │ 92│ 5C│ \ │ │124│ 7C│ | │
- │^} │ 29│ 1D│ │ GS │ │ 61│ 3D│ = │ │ 93│ 5D│ ] │ │125│ 7D│ } │
- │^^ │ 30│ 1E│ │ RS │ │ 62│ 3E│ > │ │ 94│ 5E│ ^ │ │126│ 7E│ ~ │
- │^_ │ 31│ 1F│ │ US │ │ 63│ 3F│ ? │ │ 95│ 5F│ _ │ │127│ 7F│ │
- └───┴───┴───┴────┴────┘ └───┴───┴────┘ └───┴───┴────┘ └───┴───┴────┘
-
-
- ┌────────────┐ ┌────────────┐ ┌────────────┐ ┌────────────┐
- │Dec Hex Char│ │Dec Hex Char│ │Dec Hex Char│ │Dec Hex Char│
- ├───┬───┬────┤ ├───┬───┬────┤ ├───┬───┬────┤ ├───┬───┬────┤
- │128│ 80│ Ç │ │160│ A0│ á │ │192│ C0│ └ │ │224│ E0│ α │
- │129│ 81│ ü │ │161│ A1│ í │ │193│ C1│ ┴ │ │225│ E1│ ß │
- │130│ 82│ é │ │162│ A2│ ó │ │194│ C2│ ┬ │ │226│ E2│ Γ │
- │131│ 83│ â │ │163│ A3│ ú │ │195│ C3│ ├ │ │227│ E3│ π │
- │132│ 84│ ä │ │164│ A4│ ñ │ │196│ C4│ ─ │ │228│ E4│ Σ │
- │133│ 85│ à │ │165│ A5│ Ñ │ │197│ C5│ ┼ │ │229│ E5│ σ │
- │134│ 86│ å │ │166│ A6│ ª │ │198│ C6│ ╞ │ │230│ E6│ µ │
- │135│ 87│ ç │ │167│ A7│ º │ │199│ C7│ ╟ │ │231│ E7│ τ │
- │136│ 88│ ê │ │168│ A8│ ¿ │ │200│ C8│ ╚ │ │232│ E8│ Φ │
- │137│ 89│ ë │ │169│ A9│ ⌐ │ │201│ C9│ ╔ │ │233│ E9│ Θ │
- │138│ 90│ è │ │170│ AA│ ¬ │ │202│ CA│ ╩ │ │234│ EA│ Ω │
- │139│ 91│ ï │ │171│ AB│ ½ │ │203│ CB│ ╦ │ │235│ EB│ δ │
- │140│ 92│ î │ │172│ AC│ ¼ │ │204│ CC│ ╠ │ │236│ EC│ ∞ │
- │141│ 93│ ì │ │173│ AD│ ¡ │ │205│ CD│ ═ │ │237│ ED│ φ │
- │142│ 94│ Ä │ │174│ AE│ « │ │206│ CE│ ╬ │ │238│ EE│ ε │
- │143│ 95│ Å │ │175│ AF│ » │ │207│ CF│ ╧ │ │239│ EF│ ∩ │
- │144│ 96│ É │ │176│ B0│ ░ │ │208│ D0│ ╨ │ │240│ F0│ ≡ │
- │145│ 97│ æ │ │177│ B1│ ▒ │ │209│ D1│ ╤ │ │241│ F1│ ± │
- │146│ 98│ Æ │ │178│ B2│ ▓ │ │210│ D2│ ╥ │ │242│ F2│ ≥ │
- │147│ 99│ ô │ │179│ B3│ │ │ │211│ D3│ ╙ │ │243│ F3│ ≤ │
- │148│ 9A│ ö │ │180│ B4│ ┤ │ │212│ D4│ ╘ │ │244│ F4│ ⌠ │
- │149│ 9B│ ò │ │181│ B5│ ╡ │ │213│ D5│ ╒ │ │245│ F5│ ⌡ │
- │150│ 96│ û │ │182│ B6│ ╢ │ │214│ D6│ ╓ │ │246│ F6│ ÷ │
- │151│ 97│ ù │ │183│ B7│ ╖ │ │215│ D7│ ╫ │ │247│ F7│ ≈ │
- │152│ 98│ ÿ │ │184│ B8│ ╕ │ │216│ D8│ ╪ │ │248│ F8│ ° │
- │153│ 99│ Ö │ │185│ B9│ ╣ │ │217│ D9│ ≈ │ │249│ F9│ ∙ │
- │154│ 9A│ Ü │ │186│ BA│ ║ │ │218│ DA│ ┌ │ │250│ FA│ · │
- │155│ 9B│ ¢ │ │187│ BB│ ╗ │ │219│ DB│ █ │ │251│ FB│ √ │
- │156│ 9C│ £ │ │188│ BC│ ╝ │ │220│ DC│ ▄ │ │252│ FC│ ⁿ │
- │157│ 9D│ ¥ │ │189│ BD│ ╜ │ │221│ DD│ ▌ │ │253│ FD│ ² │
- │158│ 9E│ ₧ │ │190│ BE│ ╛ │ │222│ DE│ ▐ │ │254│ FE│ ■ │
- │159│ 9F│ ƒ │ │191│ BF│ ┐ │ │223│ DF│ ▀ │ │255│ FF│ │
- └───┴───┴────┘ └───┴───┴─┴──┘ └───┴───┴────┘ └───┴───┴────┘
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- Appendix E BASIC Reserved Words
-
- The following is a list of Microsoft BASIC reserved words:
-
- ──────────────────────────────────────────────────────────────────────────
- ABS ELSE LOOP SEEK
- ACCESS ELSEIF LPOS SEG
- ALIAS END LPRINT SELECT
- AND ENDIF LSET SETMEM
- ANY ENVIRON LTRIM$ SGN
- APPEND ENVIRON$ MID$ SHARED
- AS EOF MKD$ SHELL
- ASC EQV MKDIR SIGNAL
- ATN ERASE MKDMBF$ SIN
- BASE ERDEV MKI$ SINGLE
- BEEP ERDEV$ MKL$ SLEEP
- BINARY ERL MKS$ SOUND
- BLOAD ERR MKSMBF$ SPACE$
- BSAVE ERROR MOD SPC
- BYVAL EXIT NAME SQR
- CALL EXP NEXT STATIC
- CALLS FIELD NOT STEP
- CASE FILEATTR OCT$ STICK
- CDBL FILES OFF STOP
- CDECL FIX ON STR$
- CHAIN FOR OPEN STRIG
- CHDIR FRE OPTION STRING
- CHR$ FREEFILE OR STRING$
- CINT FUNCTION OUT SUB
- CIRCLE GET OUTPUT SWAP
- CLEAR GOSUB PAINT SYSTEM
- CLNG GOTO PALETTE TAB
- CLOSE HEX$ PCOPY TAN
- CLS IF PEEK THEN
- COLOR IMP PEN TIME$
- COM INKEY$ PLAY TIMER
- COMMAND$ INP PMAP TO
- COMMON INPUT POINT TROFF
- CONST INPUT$ POKE TRON
- COS INSTR POS TYPE
- CSNG INT PRESET UBOUND
- CSRLIN INTEGER PRINT UCASE$
- CVD IOCTL PSET UEVENT
- CVDMBF IOCTL$ PUT UNLOCK
- CVI IS RANDOM UNTIL
- CVL KEY RANDOMIZE USING
- CVS KILL READ VAL
- CVSMBF LBOUND REDIM VARPTR
- DATA LCASE$ REM VARPTR$
- DATE$ LEFT$ RESET VARSEG
- DECLARE LEN RESTORE VIEW
- DEF LET RESUME WAIT
- DEFDBL LINE RETURN WEND
- DEFINT LIST RIGHT$ WHILE
- DEFLNG LOC RMDIR WIDTH
- DEFSNG LOCAL RND WINDOW
- DEFSTR LOCATE RSET WRITE
- DIM LOCK RTRIM$ XOR
- DO LOF RUN
- DOUBLE LOG SADD
- DRAW LONG SCREEN
- ──────────────────────────────────────────────────────────────────────────
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- Appendix F Metacommands
-
- This appendix describes the QuickBASIC metacommands──commands that direct
- QuickBASIC to handle your program in a particular way. The first section
- describes the format used for metacommands. The next two sections describe
- specific metacommands.
-
- By using the metacommands, you can:
-
- ■ Read in and compile other BASIC source files at specific points during
- compilation ($INCLUDE)
-
- ■ Control the allocation of dimensioned arrays ($STATIC and $DYNAMIC)
-
-
- F.1 Metacommand Syntax
-
- Metacommands begin with a dollar sign ($) and are always enclosed in a
- program comment. More than one metacommand can be given in one comment.
- Multiple metacommands are separated by white-space characters (space or
- tab). Metacommands that take arguments have a colon between the
- metacommand and the argument:
-
- REM $METACOMMAND [[ : argument ]]
-
- String arguments must be enclosed in single quotation marks. White-space
- characters between elements of a metacommand are ignored. The following
- are all valid forms for metacommands:
-
- REM $STATIC $INCLUDE: 'datadefs.bi'
- REM $STATIC $INCLUDE : 'datadefs.bi'
- ' $STATIC $INCLUDE: 'datadefs.bi'
- ' $STATIC $INCLUDE : 'datadefs.bi'
-
- Note that no spaces appear between the dollar sign and the rest of the
- metacommand.
-
- If you want to refer to a metacommand in a description but do not want it
- to execute, place a character that is not a tab or space before the first
- dollar sign on the line. For example, on the following line both
- metacommands are ignored:
-
- REM x$STATIC $INCLUDE: 'datadefs.bi'
-
-
- F.2 Processing Additional Source Files: $INCLUDE
-
- The $INCLUDE metacommand instructs the compiler to temporarily switch from
- processing one file and instead to read program statements from the BASIC
- file named in the argument. When the end of the included file is reached,
- the compiler returns to processing the original file. Because compilation
- begins with the line immediately following the line in which $INCLUDE
- occurred, $INCLUDE should be the last statement on a line. The following
- statement is correct:
-
- DEFINT I-N ' $INCLUDE: 'COMMON.BAS'
-
- There are two restrictions on using include files:
-
- 1. Included files must not contain SUB or FUNCTION statements.
-
- 2. Included files created with BASICA must be saved with the ,A option.
-
-
- F.3 Dimensioned Array Allocation: $STATIC and $DYNAMIC
-
- The $STATIC and $DYNAMIC metacommands tell the compiler how to allocate
- memory for arrays. Neither of these metacommands takes an argument:
-
- 'Make all arrays dynamic.
-
- '$DYNAMIC
-
- $STATIC sets aside storage for arrays during compilation. When the $STATIC
- metacommand is used, the ERASE statement reinitializes all array values to
- zero (numeric arrays) or the null string (string arrays) but does not
- remove the array. The REDIM statement has no effect on $STATIC arrays.
-
- $DYNAMIC allocates storage for arrays while the program is running. This
- means that the ERASE statement removes the array and frees the memory it
- took for other uses. You can also use the REDIM statement to change the
- size of a $DYNAMIC array.
-
- The $STATIC and $DYNAMIC metacommands affect all arrays except implicitly
- dimensioned arrays (arrays not declared in a DIM statement). Implicitly
- dimensioned arrays are always allocated as if $STATIC had been used.
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- Appendix G Compiling and Linking from DOS
-
- This appendix explains how to compile and link outside the QuickBASIC
- environment. You might want to do this for some of the following reasons:
-
- ■ To use a different text editor
-
- ■ To create executable programs that can be debugged with the Microsoft
- CodeView debugger
-
- ■ To create listing files for use in debugging a stand-alone executable
- program
-
- ■ To use options not available within the QuickBASIC environment, such as
- storing arrays in row order
-
- ■ To link with NOCOM.OBJ or NOEM.OBJ (files supplied with QuickBASIC),
- which reduce the size of executable files in programs that do not use
- the COM statement or are always used with a math coprocessor
-
- When you finish this appendix you will understand how to
-
- ■ Compile from the DOS command line with the BC command
-
- ■ Create executable files and link program object files with the LINK
- command
-
- ■ Create and maintain stand-alone (.LIB) libraries with the LIB command
-
-
- G.1 BC, LINK, and LIB
-
- The Microsoft QuickBASIC package includes BC, LINK, and LIB. The following
- list describes how these special tools are used when compiling and linking
- outside of the QuickBASIC environment:
-
- ╓┌─┌──────────────────┌──────────────────────────────────────────────────────╖
- Program Function
- ──────────────────────────────────────────────────────────────────────────
- BC.EXE When you choose the Make EXE File or Make Library
- command from the Run menu, QuickBASIC invokes the BASIC
- command-line compiler (BC) to produce intermediate
- program files called object files. These object files
- will be linked together to form your program or Quick
- library. BC is also available any time you want to
- compile programs outside of the QuickBASIC environment.
- You may prefer to use BC if you want to compile
- programs you have written with another text editor.
- However, you only need to use BC from the command line
- if your program is too large to compile in memory
- within the QuickBASIC environment or if you want your
- executable files to be compatible with the Microsoft
- CodeView debugger.
-
- LINK.EXE QuickBASIC uses the Microsoft Overlay Linker (LINK) to
- link object files produced by BC with the appropriate
- Program Function
- ──────────────────────────────────────────────────────────────────────────
- link object files produced by BC with the appropriate
- libraries to produce an executable file. You can use
- LINK directly whenever you want to link object files or
- make Quick libraries.
-
- LIB.EXE The Microsoft Library Manager (LIB) creates stand-alone
- libraries from the object files produced by BC.
- QuickBASIC itself uses LIB to create such libraries and
- then uses them when you choose the Make EXE File
- command from the Run menu.
-
- ──────────────────────────────────────────────────────────────────────────
-
-
-
- G.2 The Compiling and Linking Process
-
- To create a stand-alone program from a BASIC source file when you are
- outside of the QuickBASIC environment, follow these steps:
-
- 1. Compile each source file, creating an object file.
-
- 2. Link the object files using LINK. LINK includes one or more stand-alone
- libraries and creates an executable file. LINK makes sure that all the
- procedure calls in the source files match up with the procedures in the
- libraries or with procedures in other object files before it creates an
- executable file.
-
- You can use either of the following methods of compiling and linking:
-
- ■ Compile and link in separate steps by using the BC and LINK commands.
-
- ■ Create a batch file containing all the compiling and linking commands.
- This method is most useful if you use the same options whenever you
- compile and link your programs.
-
- ──────────────────────────────────────────────────────────────────────────
- NOTE
- When QuickBASIC compiles and links your program from within the
- environment, the /E linker option is set automatically. However, when
- you use the LINK command outside the QuickBASIC environment, you must
- explicitly specify the /E option to minimize the size of the executable
- file and maximize program-loading speed.
- ──────────────────────────────────────────────────────────────────────────
-
- When compiling and linking from DOS, the paths you defined in the Options
- menu are not used. To search for include and library files the way you
- specified on the Options menu, you must set the DOS environment variables
- LIB and INCLUDE to point to the appropriate directories. Otherwise the
- compiler and/or linker might generate File not found errors.
-
- Sections G.3 and G.4 explain how to compile and link in separate steps.
-
-
- G.3 Compiling with the BC Command
-
- You can compile with the BC command in either of the following ways:
-
- ■ Type all information on a single command line, using the following
- syntax:
-
- BC sourcefile [[,[[objectfile]] [[,[[listingfile]]]]]]
- [[optionslist]][[;]]
-
- ■ Type
-
- BC
-
- and respond to the following prompts:
-
- Source Filename [.BAS]:
- Object Filename [basename.OBJ]:
- Source Listing: [NUL.LST]:
-
- Table G.1 shows the input you must give on the BC command line or in
- response to each prompt:
-
- Table G.1 Input to the BC Command
- Field Prompt Input
- ──────────────────────────────────────────────────────────────────────────
- sourcefile "Source Filename" The name of your source file
-
- objectfile "Object Filename" The name of the object file you are
- creating
-
- listingfile "Source Listing" The name of the file containing a
- source listing. The source-listing
- file contains the address of each
- line in your source file, the text of
- the source file, its size, and any
- error messages produced during
- compilation.
-
- optionslist Gives options Any of the compiler options described
- after any in Section G.3.2, "Using BC Command
- response Options"
- ──────────────────────────────────────────────────────────────────────────
-
- G.3.1 Specifying File Names
-
- The BC command makes certain assumptions about the files you specify,
- based on the path names and extensions you use for the files. The
- following sections describe these assumptions and other rules for
- specifying file names to the BC command.
-
- G.3.1.1 Uppercase and Lowercase Letters
-
- You can use any combination of uppercase and lowercase letters for file
- names; the compiler accepts uppercase and lowercase letters
- interchangeably.
-
- Example
-
- The BC command considers the following three file names to be equivalent:
-
- abcde.BAS
- ABCDE.BAS
- aBcDe.Bas
-
- G.3.1.2 File-Name Extensions
-
- A DOS file name has two parts: the "base name," which includes everything
- up to (but not including) the period (.), and the "extension," which
- includes the period and up to three characters following the period. In
- general, the extension identifies the type of file (for example, whether
- the file is a BASIC source file, an object file, an executable file, or a
- stand-alone library).
-
- BC and LINK use the file-name extensions described in the following list:
-
- Extension File Description
- ──────────────────────────────────────────────────────────────────────────
- .BAS BASIC source file
-
- .OBJ Object file
-
- .LIB Stand-alone library file
-
- .LST Listing file produced by BC
-
- .MAP File of symbols from the linked program
-
- .EXE Executable file
-
- ──────────────────────────────────────────────────────────────────────────
-
- G.3.1.3 Path Names
-
- Any file name can include a full or partial path name. A full path name
- starts with the drive name; a partial path name has one or more directory
- names preceding the file name, but does not include a drive name.
-
- Giving a full path name allows you to specify files in different paths as
- input to the BC command and lets you create files on different drives or
- in different directories on the current drive.
-
- ──────────────────────────────────────────────────────────────────────────
- NOTE
- For files that you are creating with BC, you can give a path name ending
- in a backslash (\) to create the file in that path. When it creates the
- file, BC uses the default name for the file.
- ──────────────────────────────────────────────────────────────────────────
-
- G.3.2 Using BC Command Options
-
- Options to the BC command consist of either a forward-slash character (/)
- or a dash (-) followed by one or more letters. (The forward slash and the
- dash can be used interchangeably. In this manual, forward slashes are used
- for options.)
-
- The BC command-line options are explained in the following list:
-
- ╓┌─┌──────────────────┌──────────────────────────────────────────────────────╖
- Option Description
- ──────────────────────────────────────────────────────────────────────────
- /A Creates a listing of the disassembled object code for
- each source line and shows the assembly-language code
- generated by the compiler.
-
- /AH Allows dynamic arrays of records, fixed-length strings,
- and numeric data to occupy all of available memory. If
- this option is not specified, the maximum size is 64K
- per array. Note that this option has no effect on the
- way data items are passed to procedures.
-
- /C:buffersize Sets the size of the buffer receiving remote data for
- each communications port when using an asynchronous
- Option Description
- ──────────────────────────────────────────────────────────────────────────
- each communications port when using an asynchronous
- communications adapter. (The transmission buffer is
- allocated 128 bytes for each communications port and
- cannot be changed on the BC command line.) This option
- has no effect if the asynchronous communications card
- is not present. The default buffer size is 512 bytes
- total for both ports; the maximum size is 32,767 bytes.
-
- /D Generates debugging code for run-time error checking
- and enables CTRL+BREAK. This option is the same as the
- Produce Debug Code option from the Run menu's Make EXE
- File command within the QuickBASIC environment.
-
- /E Indicates presence of ON ERROR with RESUME linenumber
- statements. (See also the discussion of the /X option
- in this list.)
-
- /MBF The intrinsic functions MKS$, MKD$, CVS, and CVD are
- converted to MKSMBF$, MKDMBF$, CVSMBF, and CVDMBF,
- Option Description
- ──────────────────────────────────────────────────────────────────────────
- converted to MKSMBF$, MKDMBF$, CVSMBF, and CVDMBF,
- respectively. This allows your QuickBASIC program to
- read and write floating-point values stored in
- Microsoft Binary format.
-
- /O Substitutes the BCOM45.LIB run-time library for
- BRUN45.LIB. See Chapter 16, "The Run Menu," in Learning
- to Use Microsoft QuickBASIC for more information about
- using these libraries.
-
- /R Stores arrays in row-major order. BASIC normally stores
- arrays in column-major order. This option is useful if
- you are using other-language routines that store arrays
- in row order.
-
- /S Writes quoted strings to the object file instead of the
- symbol table. Use this option when an Out of memory
- error message occurs in a program that has many string
- constants.
- Option Description
- ──────────────────────────────────────────────────────────────────────────
- constants.
-
- /V Enables event trapping for communications (COM),
- lightpen (PEN), joystick (STRIG), timer (TIMER), music
- buffer (PLAY) and function keys (KEY). Use this option
- to check between statements for an occurrence of an
- event.
-
- /W Enables event trapping for the same statements as /V,
- but checks at each line number or label for occurrence
- of an event.
-
- /X Indicates presence of ON ERROR with RESUME, RESUME
- NEXT, or RESUME 0.
-
- /ZD Produces an object file containing line-number records
- corresponding to the line numbers of the source file.
- This option is useful when you want to perform
- source-level debugging using the Microsoft Symbolic
- Option Description
- ──────────────────────────────────────────────────────────────────────────
- source-level debugging using the Microsoft Symbolic
- Debug Utility (SYMDEB), available with the Microsoft
- Macro Assembler, Version 4.0.
-
- /ZI Produces an object file of debugging information used
- by the Microsoft CodeView debugger, available with
- Microsoft C, Version 5.0 and later and Microsoft Macro
- Assembler, Version 5.0 and later.
- ──────────────────────────────────────────────────────────────────────────
-
-
- G.4 Linking
-
- After compiling your program, you must link the object file with the
- appropriate libraries to create an executable program. You can use the
- LINK command in any of the following ways:
-
- ■ Give the input on a command line of the following form:
-
- LINK objfile [[,[[exefile]][[,[[mapfile]][[,[[lib]]]]]]
- [[linkopts]][[;]]]]
-
- The command line cannot be longer than 128 characters.
-
- ■ Type
-
- LINK
-
- and respond to the following prompts:
-
- Object Modules [.OBJ]:
- Run File [basename.EXE]:
- List File [NUL.MAP]:
- Libraries [.LIB]:
-
- To give more files for any prompt, type a plus sign (+) at the end of
- the line. The prompt reappears on the next line, and you can continue
- typing input for the prompt.
-
- ■ Set up a "response file" (a file containing responses to the LINK
- command prompts), and then type a LINK command of the following form:
-
- LINK @filename
-
- Here, filename is the name of the response file. You can append linker
- options to any response or give options on one or more separate lines.
- The responses must be in the same order as the LINK command prompts
- discussed above. You can also enter the name of a response file after
- any linker prompt, or at any position in the LINK command line.
-
- Table G.2 shows the input you must give on the LINK command line, or in
- response to each prompt.
-
- Table G.2 Input to the LINK Command
- ╓┌─┌────────────────────────┌────────────────────────────────────────────────╖
- Field Prompt
- Input
- ──────────────────────────────────────────────────────────────────────────
- objfile "Object Modules"
- One or more object files that you are linking.
- The object files should be separated by either
- Field Prompt
- Input
- ──────────────────────────────────────────────────────────────────────────
- The object files should be separated by either
- plus signs or spaces.
-
- exefile "Run File"
- Name of the executable file you are creating, if
- you want to give it a name or extension other
- than the default. You should always use the .EXE
- extension, since DOS expects executable files to
- have this extension.
-
- mapfile "List File"
- Name of the file containing a symbol map listing,
- if you are creating one. You can also specify
- one of the following DOS device names to direct
- the map file to that device: AUX for an auxiliary
- device, CON for the console (terminal), PRN for a
- printer device, or NUL for no device (so that no
- map file is created). See Section G.4.6.11 for a
- Field Prompt
- Input
- ──────────────────────────────────────────────────────────────────────────
- map file is created). See Section G.4.6.11 for a
- sample map file and information about its
- contents.
-
- lib "Libraries"
- One or more stand-alone libraries (or directories
- to be searched for stand-alone libraries)
- separated by plus signs or spaces. The
- "Libraries" prompt allows you to specify up to 16
- libraries; any additional libraries are ignored.
- See Section G.4.3 for rules for specifying
- library names to the linker.
-
- linkopts Gives options after any response
- Any of the LINK options described in Sections
- G.4.6.2-G.4.6.15. You can specify LINK options
- anywhere on the command line.
-
- Field Prompt
- Input
- ──────────────────────────────────────────────────────────────────────────
- ──────────────────────────────────────────────────────────────────────────
-
-
- If you are using a response file, each response must follow the rules
- outlined in Table G.2.
-
- G.4.1 Defaults for LINK
-
- You can choose defaults for any of the information that LINK needs in any
- of the following ways:
-
- ■ To choose the default for any command-line entry, omit the file name or
- names before the entry and type only the required comma. The only
- exception to this is the default for the mapfile entry: if you use a
- comma as a placeholder for this entry, LINK creates a map file.
-
- ■ To choose the default for any prompt, press ENTER.
-
- ■ To choose the defaults for all remaining command-line entries or
- prompts, type a semicolon after any entry or prompt. The only required
- input is one or more object-file names.
-
- The following list shows the defaults that LINK uses for executable files,
- map files, and libraries:
-
- ╓┌─┌────────────────────────┌────────────────────────────────────────────────╖
- File Type Default
- ──────────────────────────────────────────────────────────────────────────
- Executable Base name of the first object file given, plus
- the .EXE extension. To rename the executable
- file, you are required to specify only the new
- base name; if you give a file name with no
- extension, LINK automatically appends the .EXE
- extension.
-
- Map The special file name NUL.MAP, which tells LINK
- not to create a map file. To create a map file,
- you are required to specify only the base name;
- File Type Default
- ──────────────────────────────────────────────────────────────────────────
- you are required to specify only the base name;
- if you give a file name with no extension, LINK
- automatically appends the .MAP extension.
-
- Libraries Libraries named in the given object files. If you
- choose the Stand-Alone EXE File option,
- BCOM45.LIB is the default library; otherwise, the
- default is BRUN45.LIB. If you specify a library
- other than a default library, you must give only
- the base name; if you give a library name with no
- extension, LINK automatically appends the .LIB
- extension. See Section G.4.3 for information
- about specifying libraries other than the default
- libraries.
- ──────────────────────────────────────────────────────────────────────────
-
-
- ──────────────────────────────────────────────────────────────────────────
- NOTE
- When linking a stand-alone executable file, if your program does not use
- the COM statement, your program will be about 4K smaller if you link
- with NOCOM.OBJ, a file supplied with QuickBASIC.
- ──────────────────────────────────────────────────────────────────────────
-
- Examples
-
- The following example shows a response file. It tells LINK to link
- together the four object modules FRAME, TEXT, TABLE, and LINEOUT. The
- executable file FRAME.EXE and the map file named FRAMESYM.MAP are
- produced. The /PAUSE option causes LINK to pause before producing the
- executable file to permit disk swapping, if necessary. The /MAP option
- tells LINK to include public symbols and addresses in the map file. LINK
- also links any needed routines from the library file GRAF.LIB. See
- Sections G.4.6.2 and G.4.6.11 for more information on /PAUSE and /MAP
- options.
-
- FRAME TEXT TABLE LINEOUT
- /PAUSE /MAP
- FRAMESYM
- GRAF.LIB
-
- In the following example, LINK loads and links the object files FRAME.OBJ,
- TEXT.OBJ, TABLE.OBJ, and LINEOUT.OBJ, searching for unresolved references
- in the library file COBLIB.LIB. By default, the executable file is named
- FRAME.EXE. A map file called FRAMESYM.MAP is also produced.
-
- LINK FRAME+TEXT+TABLE+LINEOUT, ,FRAMESYM, COBLIB.LIB
-
- The example that follows illustrates how to continue any prompt by typing
- a plus sign (+) at the end of your response. The example links all of the
- given object files, then creates an executable file. Since a semicolon is
- typed as a response to the "Run File" prompt, the executable file is given
- the default name, which is the base name of the first object file given
- (FRAME), plus the .EXE extension. The defaults are also used for the
- remaining prompts. As a result, no map file is created, and the default
- libraries named in the object files are used for linking.
-
- LINK
-
- Object Modules [.OBJ]: FRAME TEXT TABLE LINEOUT+
- Object Modules [.OBJ]: BASELINE REVERSE COLNUM+
- Object Modules [.OBJ]: ROWNUM
- Run File [FRAME.EXE]: ;
-
- G.4.2 Specifying Files to LINK
-
- The rules for specifying file names to the linker are the same as for
- specifying file names to the BC command: uppercase and lowercase letters
- can be used interchangeably, and file names can include path names to tell
- LINK to look for files or create files in the given path. See Section
- G.3.1 for more information.
-
- G.4.3 Specifying Libraries to LINK
-
- Ordinarily, you do not need to give LINK a stand-alone-library name. When
- the BC command creates object files, it places in each object file the
- name of the correct stand-alone library for that object file. When the
- object file is passed to the linker, LINK looks for a library with the
- same name as the name in the object file and links the object file with
- that library automatically.
-
- To link object files with a stand-alone library other than the default,
- give the name of the nondefault library to LINK. You can give the library
- name in either of the following ways:
-
- ■ After the third comma on the LINK command line. Commas follow the list
- of object-file names, the executable-file name, and the listing-file
- name. The final name is the library name.
-
- ■ In response to the "Libraries" prompt of the LINK command.
-
- LINK searches libraries you specify to resolve external references before
- it searches default libraries.
-
- You might want to link with a stand-alone library other than the default
- to
-
- ■ Link with additional stand-alone libraries.
-
- ■ Link with libraries in different paths. If you specify a complete path
- name for the library, LINK only looks in that path for the library.
- Otherwise, it looks in the following three locations:
-
- 1. The current working directory
-
- 2. Any paths or drives you specify after the third comma on the LINK
- command line
-
- 3. The locations given by the LIB environment variable
-
- ■ Ignore the library named in the object file. In this case, you must give
- the LINK option /NOD in addition to specifying the library you want to
- use for linking. See Section G.4.6.8 for more information about the
- /NOD option.
-
- G.4.4 Memory Requirements for LINK
-
- LINK uses available memory for the linking session. If the files to be
- linked create an output file that exceeds available memory, LINK creates a
- temporary disk file to serve as memory. This temporary file is handled in
- one of the following ways, depending on the DOS version:
-
- ■ LINK uses the directory specified by the TMP environment variable from
- DOS for the purpose of creating a temporary file. For example, if the
- TMP variable was set to C:\TEMPDIR, then LINK would put the temporary
- file in C:\TEMPDIR.
-
- If there is no TMP environment variable, or if the directory specified
- by TMP does not exist, then LINK puts the temporary file in the current
- working directory.
-
- ■ If LINK is running on DOS Version 3.0 or later, it uses a DOS system
- call to create a temporary file with a unique name in the temporary-file
- directory.
-
- ■ If LINK is running on a version of DOS prior to 3.0, it creates a
- temporary file named VM.TMP.
-
- When the linker creates a temporary disk file, you see the message
-
- Temporary file tempfile has been created.
- Do not change diskette in drive, letter
-
- where tempfile is ".\" followed by either the file name VM.TMP or a name
- generated by DOS, and letter is the drive containing the temporary file.
-
- The message
-
- Do not change diskette in drive
-
- does not appear unless the drive named letter is a floppy-disk drive. If
- this message appears, do not remove the disk from the drive until the
- linking session ends. If you remove the disk, linker operations will be
- unpredictable, and you may see the following message:
-
- unexpected end-of-file on scratch file
-
- If you see this message, rerun the linking session.
-
- The temporary file that LINK creates is a working file only. LINK deletes
- it at the end of the session.
-
- ──────────────────────────────────────────────────────────────────────────
- NOTE
- Do not give any of your own files the name VM.TMP. LINK displays an
- error message if it finds an existing file with this name.
- ──────────────────────────────────────────────────────────────────────────
-
- G.4.5 Linking with Mixed-Language Programs
-
- You can link mixed-language programs with LINK. However, problems can
- result from linking .OBJ files from within the other language. Different
- assumptions by different linkers can corrupt QuickBASIC files.
-
- The following sections discuss linking with modules written in Pascal,
- FORTRAN, and assembly language.
-
- G.4.5.1 Pascal and FORTRAN Modules in QuickBASIC Programs
-
- Modules compiled with Microsoft Pascal or FORTRAN can be linked with BASIC
- programs, as described in the Microsoft Mixed-Language Programming Guide.
- They can also be incorporated in Quick libraries. However, QuickBASIC
- programs containing code compiled with Microsoft Pascal must allocate at
- least 2K near-heap space for Pascal. The following example does this by
- using the DIM statement to allocate a static array of 2K or greater in a
- named common block called NMALLOC:
-
- DIM name%(2048) : COMMON SHARED /NMALLOC/ name%()
-
- The Pascal run-time module assumes it always has at least 2K of near-heap
- space available. If the Pascal code cannot allocate the required space,
- QuickBASIC may crash. This applies to Pascal code in Quick libraries and
- to Pascal code linked into executable files. The situation is similar for
- FORTRAN I/O, which also requires near buffer space, and which can be
- provided by using an NMALLOC common block.
-
- G.4.5.2 STATIC Array Allocation in Assembly-Language Routines
-
- Use the SEG or CALLS keywords or far pointers to pass static array data to
- assembly-language routines. You cannot assume data is in a particular
- segment. Alternatively, you can declare all arrays dynamic (still using
- far pointers) since BC and the QuickBASIC environment handle dynamic
- arrays identically.
-
- G.4.5.3 References to DGROUP in Extended Run-Time Modules
-
- For mixed-language programs that use the CHAIN command, you should make
- sure that any code built into an extended run-time module does not contain
- any references to DGROUP. (The CHAIN command causes DGROUP to move, but
- does not update references to DGROUP.) This rule applies only to
- mixed-language programs; because BASIC routines never refer to DGROUP, you
- can ignore this caution for programs written entirely in BASIC.
-
- To avoid this problem, you can use the value of SS, since BASIC always
- assumes that SS coincides with DGROUP.
-
- G.4.6 Using LINK Options
-
- LINK options begin with the linker's option character, which is the
- forward slash (/).
-
- Case is not significant in LINK options; for example, /NOI and /noi are
- equivalent.
-
- You can abbreviate LINK options to save space and effort. The minimum
- valid abbreviation for each option is indicated in the syntax of the
- option. For example, several options begin with the letters "NO";
- therefore, abbreviations for those options must be longer than "NO" to be
- unique. You cannot use "NO" as an abbreviation for the /NOIGNORECASE
- option, since LINK cannot tell which of the options beginning with "NO"
- you intend. The shortest valid abbreviation for this option is /NOI.
-
- Abbreviations must begin with the first letter of the option and must be
- continuous through the last letter typed. No gaps or transpositions are
- allowed.
-
- Some LINK options take numeric arguments. A numeric argument can be any of
- the following:
-
- ■ A decimal number from 0 to 65,535.
-
- ■ An octal number from 0 to 0177777. A number is interpreted as octal if
- it starts with a zero (0). For example, the number 10 is a decimal
- number, but the number 010 is an octal number, equivalent to 8 in
- decimal.
-
- ■ A hexadecimal number from 0 to 0xFFFF. A number is interpreted as
- hexadecimal if it starts with a zero followed by an x or an X. For
- example, 0x10 is a hexadecimal number, equivalent to 16 in decimal.
-
- LINK options affect all files in the linking process, regardless of where
- the options are specified.
-
- If you usually use the same set of LINK options, you can use the LINK
- environment variable in DOS to specify certain options each time you link.
- If you set this variable, LINK checks it for options and expects to find
- options listed exactly as you would type them on the command line. You
- cannot specify file-name arguments in the LINK environment variable.
-
- ──────────────────────────────────────────────────────────────────────────
- NOTE
- A command-line option overrides the effect of any environment-variable
- option with which it conflicts. For example, the command-line option
- /SE:256 cancels the effect of the environment-variable option /SE:512.
- To prevent an option in the environment variable from being used, you
- must reset the environment variable itself.
- ──────────────────────────────────────────────────────────────────────────
-
- Example
-
- In the following example, the file TEST.OBJ is linked with the options
- /SE:256 and /CO. After that, the file PROG.OBJ is linked with the option
- /NOD, as well as with the options /SE:256 and /CO.
-
- SET LINK=/SE:256 /CO
- LINK TEST;
- LINK /NOD PROG;
-
- G.4.6.1 Viewing the Options List (/HE)
-
- /HE[[LP]]
-
- The /HE option tells LINK to display a list of the available LINK options
- on the screen.
-
- G.4.6.2 Pausing during Linking (/PAU)
-
- /PAU[[SE]]
-
- The /PAU option tells LINK to pause in the link session and display a
- message before it writes the executable file to disk. This allows you to
- insert a new disk to hold the executable file.
-
- If you specify the /PAUSE option, LINK displays the following message
- before it creates the executable file:
-
- About to generate .EXE file
- Change diskette in drive letterand press <ENTER>
-
- The letter corresponds to the current drive. LINK resumes processing when
- you press the ENTER key.
-
- ──────────────────────────────────────────────────────────────────────────
- NOTE
- Do not remove the disk on which the list file is created or the disk
- used for the temporary file. If a temporary file is created on the disk
- you plan to swap, press CTRL+C to terminate the linking session.
- Rearrange your files so that the temporary file and the executable file
- can be written to the same disk. Then try linking again.
- ──────────────────────────────────────────────────────────────────────────
-
- G.4.6.3 Displaying Linker Process Information (/I)
-
- /I[[NFORMATION]]
-
- The /I option displays information about the linking process, including
- the phase of linking and the names of the object files being linked.
-
- This option helps you determine the locations of the object files being
- linked and the order in which they are linked.
-
- G.4.6.4 Preventing Linker Prompting (/B)
-
- /B[[ATCH]]
-
- The /B option tells LINK not to prompt you for a new path name whenever it
- cannot find a library or object file that it needs. When this option is
- used, the linker simply continues to execute without using the file in
- question.
-
- This option can cause unresolved external references. It is intended
- primarily to let you use batch or MAKE files to link many executable files
- with a single command if you do not want LINK to stop processing if it
- cannot find a required file. It is also useful when you are redirecting
- the LINK command line to create a file of linker output for future
- reference. However, this option does not prevent LINK from prompting for
- arguments missing from the LINK command line.
-
- G.4.6.5 Creating Quick Libraries (/Q)
-
- /Q[[UICKLIB]]
-
- The /Q option tells LINK to combine the object files you specify into a
- Quick library. When you start the QuickBASIC environment, you can give the
- /L option on the QB command line to load the Quick library. If you use the
- /Q option, be sure to specify BQLB45.LIB in the library list in order to
- include QuickBASIC Quick-library support routines.
-
- See Appendix H, "Creating and Using Quick Libraries," for more
- information about creating and loading Quick libraries.
-
- ──────────────────────────────────────────────────────────────────────────
- NOTE
- You cannot use the /EXEPACK option with the /Q option.
- ──────────────────────────────────────────────────────────────────────────
-
- G.4.6.6 Packing Executable Files (/E)
-
- /E[[XEPACK]]
-
- The /E option removes sequences of repeated bytes (typically null
- characters) and optimizes the "load-time relocation table" before creating
- the executable file. The load-time relocation table is a table of
- references relative to the start of the program. Each reference changes
- when the executable image is loaded into memory and an actual address for
- the entry point is assigned.
-
- ──────────────────────────────────────────────────────────────────────────
- NOTE
- Executable files linked with this option may be smaller and load faster
- than files linked without this option.
- ──────────────────────────────────────────────────────────────────────────
-
- G.4.6.7 Disabling Segment Packing (/NOP)
-
- /NOP[[ACKCODE]]
-
- The /NOP option is normally not necessary because code-segment packing is
- normally turned off. However, if a DOS environment variable such as LINK
- turns on code-segment packing automatically, you can use the /NOP option
- to turn segment packing back off again.
-
- G.4.6.8 Ignoring the Usual BASIC Libraries (/NOD)
-
- /NOD[[EFAULTLIBRARYSEARCH]]
-
- When it creates an object file, BC includes the names of the "standard"
- libraries──libraries that LINK searches to resolve external references.
- The /NOD option tells LINK not to search any library specified in an
- object file to resolve external references.
-
- In general, QuickBASIC programs do not work correctly without the standard
- QuickBASIC libraries (BRUN45.LIB and BCOM45.LIB). Thus, if you use the
- /NOD option, you should explicitly give the path name of the required
- standard library.
-
- G.4.6.9 Ignoring Dictionaries (/NOE)
-
- /NOE[[XTDICTIONARY]]
-
- If LINK suspects that a public symbol has been redefined, it prompts you
- to link again with the /NOE option. When you do so, it searches the
- individual object files, rather than "dictionaries" it has created, to
- resolve conflicts. For example, when linking a program with 87.LIB or
- NOCOM.OBJ, you must use the /NOE option.
-
- G.4.6.10 Setting Maximum Number of Segments (/SE)
-
- /SE[[GMENTS]]:number
-
- The /SE option controls the number of segments that LINK allows a program
- to have. The default is 128, but you can set number to any value
- (specified as decimal, octal, or hexadecimal) in the range 1-1024
- (decimal).
-
- For each segment, LINK must allocate space to keep track of segment
- information. When you set the segment limit higher than 128, LINK
- allocates more space for segment information. For programs with fewer than
- 128 segments, you can minimize the amount of storage LINK needs by setting
- number to reflect the actual number of segments in the program. LINK
- displays an error message if this number is too high for the amount of
- memory it has available.
-
- G.4.6.11 Creating a Map File (/M)
-
- /M[[AP]]
-
- The /M option creates a map file. A map file lists the segments of a
- program and the program's public symbols. LINK always tries to allocate
- all of the available memory for sorting public symbols. If the number of
- symbols exceeds the memory limit, then LINK generates an unsorted list.
- The map file mapfile contains a list of symbols sorted by address;
- however, it does not contain a list sorted by name. A sample map file is
- shown below:
-
- Start Stop Length Name Class
- 00000H 01E9FH 01EA0H _TEXT CODE
- 01EA0H 01EA0H 00000H C_ETEXT ENDCODE
- .
- .
- .
-
- The information in the columns Start and Stop shows the 20-bit address (in
- hexadecimal) of each segment, relative to the beginning of the load
- module. The load module begins at location zero. The column Length gives
- the length of the segment in bytes. The column Name gives the name of the
- segment; the column Class gives information about the segment type. See
- the Microsoft MS-DOS Programmer's Reference for information about groups,
- segments, and classes.
-
- The starting address and name of each group appear after the list of
- segments. A sample group listing is shown below:
-
- Origin Group
- 01EA:0 DGROUP
-
- In this example, DGROUP is the name of the data group.
-
- The map file shown below contains two lists of global symbols: the first
- list is sorted in ASCII-character order by symbol name; the second, by
- symbol address. The notation Abs appears next to the names of absolute
- symbols (symbols containing 16-bit constant values that are not associated
- with program addresses).
-
- Many of the global symbols that appear in the map file are symbols used
- internally by the compiler and linker. These symbols usually begin with
- the characters B$ or end with QQ.
-
- Address Publics by Name
-
- 01EA:0096 STKHQQ
- 0000:1D86 B$Shell
- 01EA:04B0 _edata
- 01EA:0910 _end
- .
- .
- .
- 01EA:00EC __abrkp
- 01EA:009C __abrktb
- 01EA:00EC __abrktbe
- 0000:9876 Abs __acrtmsg
- 0000:9876 Abs __acrtused
- .
- .
- .
- 01EA:0240 ___argc
- 01EA:0242 ___argv
-
- Address Publics by Value
-
- 0000:0010 _main
- 0000:0047 _htoi
- .
- .
- .
-
- The addresses of the external symbols are in the frame:offset format,
- showing the location of the symbol relative to zero (the beginning of the
- load module).
-
- Following the lists of symbols, the map file gives the program entry
- point, as shown in the following example:
-
- Program entry point at 0000:0129
-
- A map file can also be specified by giving a map-file name on the LINK
- command line or by giving a map-file name in response to the "List File"
- prompt.
-
- G.4.6.12 Including Line Numbers in a Map File (/LI)
-
- /LI[[NENUMBERS]]
-
- The /LI option creates a map file and includes the line numbers and
- associated addresses of the source program. If you are compiling and
- linking in separate steps, this option has an effect only if you are
- linking object files compiled with the /M option.
-
- G.4.6.13 Packing Contiguous Segments (/PAC)
-
- /[[NO]]PAC[[KCODE]][[:number]]
-
- The /PAC option tells LINK to group neighboring code segments. Code
- segments in the same group share the same segment address; all offset
- addresses are then adjusted upward as needed. As a result, many
- instructions that would otherwise have different segment addresses share
- the same segment address.
-
- If specified, number is the size limit of groups formed by /PAC. LINK
- stops adding segments to a particular group as soon as it cannot add a
- segment to the group without exceeding number. At that point, LINK starts
- forming a new group with the remaining code segments. If number is not
- given, the default is 65,530.
-
- Although LINK does not pack neighboring segments unless you explicitly ask
- for it, you can use the /NOPACKCODE option to turn off segment packing if,
- for example, you have given the /PAC option in the LINK environment
- variable in DOS.
-
- G.4.6.14 Using the CodeView Debugger (/CO)
-
- /CO[[DEVIEW]]
-
- The /CO option prepares an executable file for debugging using the
- CodeView debugger. If you are compiling and linking in separate steps,
- this option has an effect only if you are linking object files compiled
- with the /ZI option of the BC command. Similarly, it should not be used in
- conjunction with the LINK command's /Q option, because a Quick library
- cannot be debugged with the CodeView debugger.
-
- G.4.6.15 Distinguishing Case (/NOI)
-
- /NOI[[GNORECASE]]
-
- The /NOI option tells LINK to distinguish between uppercase and lowercase
- letters; for example, LINK would consider the names ABC, abc, and Abc to
- be three separate names. When you link, do not specify the /NOI option on
- the LINK command line.
-
- G.4.7 Other LINK Command-Line Options
-
- Not all options of the LINK command are suitable for use with QuickBASIC
- programs. The following LINK options can be used with Microsoft QuickBASIC
- programs; however, they are never required, since they request actions
- that the BC command or QuickBASIC performs automatically:
-
- ╓┌─┌─────────────────────────────┌───────────────────────────────────────────╖
- Option Action
- ──────────────────────────────────────────────────────────────────────────
- /CP[[ARMAXALLOC]]:number Sets the maximum number of 16-byte
- paragraphs needed by the program when it is
- loaded into memory to number, an integer
- between 1 and 65,535, inclusive. The
- operating system uses this value when
- allocating space for the program before
- loading it. Although you can use this option
- on the LINK command line, it has no effect
- because, while it is running, your BASIC
- program controls memory.
-
- /DO[[SSEG]] Forces segments to be ordered using the
- defaults for Microsoft high-level language
- products. QuickBASIC programs always use
- this segment order by default.
-
- /ST[[ACK]]:number Specifies the size of the stack for your
- Option Action
- ──────────────────────────────────────────────────────────────────────────
- /ST[[ACK]]:number Specifies the size of the stack for your
- program, where number is any positive value
- (decimal, octal, or hexadecimal) up to
- 65,535 (decimal) representing the size, in
- bytes, of the stack. The standard BASIC
- library sets the default stack size to 2K.
-
- /DS[[ALLOCATE]] Loads all data starting at the high end of
- the default data segment.
-
- /HI[[GH]] Places the executable file as high in memory
- as possible.
-
- /NOG[[ROUPASSOCIATION]] Tells LINK to ignore group associations when
- assigning addresses to data and code items.
-
- /O[[VERLAYINTERRUPT]]:number Specifies an interrupt number other than
- 0x3F for passing control to overlays.
- ──────────────────────────────────────────────────────────────────────────
- Option Action
- ──────────────────────────────────────────────────────────────────────────
- ──────────────────────────────────────────────────────────────────────────
-
-
- ──────────────────────────────────────────────────────────────────────────
- NOTE
- Do not use the /DS, /HI, /NOG, or /O options when linking object files
- compiled with BC. They are suitable only for object files created by the
- Microsoft Macro Assembler (MASM).
- ──────────────────────────────────────────────────────────────────────────
-
-
- G.5 Managing Stand-Alone Libraries: LIB
-
- The Microsoft Library Manager (LIB) manages the contents of stand-alone
- libraries. A stand-alone library is made up of "object modules"──that is,
- object files combined to form a library. Unlike an object file, an object
- module does not exist independently of its library, and does not have a
- path name or extension associated with its file name. Using LIB, you can:
-
- ■ Combine object files to create a new library
-
- ■ Add object files to an existing library
-
- ■ Delete or replace the object modules of an existing library
-
- ■ Extract object modules from an existing library and place them in
- separate object files
-
- ■ Combine the contents of two existing libraries into a new library
-
- When updating an existing library, LIB performs all of its operations on a
- copy of the library. This mechanism ensures that you have a backup copy of
- any library you update in case of problems with the updated version of the
- library.
-
- G.5.1 Running LIB
-
- You can give the LIB command input in any of the following ways:
-
- ■ Specify the input on a command line of the following form:
-
- LIB oldlib [[/P[[AGESIZE]]:number]]
- [[commands]][[,[[listfile]][[,[[newlib]]]]]][[;]]
-
- The command line has a maximum length of 128 characters.
-
- ■ Type
-
- lib
-
- and respond to the following prompts:
-
- Library name:
- Operations:
- List file:
- Output library:
-
- To give more files for any prompt, type an ampersand (&) at the end of
- the line. The prompt reappears on the next line, and you can continue
- typing input for the prompt.
-
- ■ Set up a response file, a file with responses to LIB command prompts,
- then type a LIB command of the following form:
-
- LIB @filename
-
- Here, filename is the name of the response file. The responses must be in
- the same order as the LIB prompts discussed above. You can also enter the
- name of a response file after any LINK prompt, or at any position in the
- LIB command line.
-
- Table G.3 shows the input you must give on the LIB command line, or in
- response to each prompt. If you are using a response file, each response
- must follow the rules outlined in this table.
-
- Table G.3 Input to the LIB Command
- ╓┌─┌───────────┌────────────────────────┌────────────────────────────────────╖
- Field Prompt Input
- ──────────────────────────────────────────────────────────────────────────
- oldlib "Library name" Name of the library you are changing
- or creating. If this library does not
- exist, LIB asks if you want to create
- Field Prompt Input
- ──────────────────────────────────────────────────────────────────────────
- exist, LIB asks if you want to create
- it. Type the letter y to create a new
- library or the letter n to terminate
- LIB. This message is suppressed if
- you type command characters, a comma,
- or a semicolon after the library
- name. A semicolon tells LIB to
- perform a consistency check on the
- library; in this case, it displays a
- message if it finds errors in any
- library module.
-
- /P:number /P:number after "Library The library page size. This sets the
- name" prompt page size for the library to number,
- where number is an integer power of 2
- between 16 and 32,768, inclusive. The
- default page size for a new library
- is 16 bytes. Modules in the library
- are always aligned to start at a
- Field Prompt Input
- ──────────────────────────────────────────────────────────────────────────
- are always aligned to start at a
- position that is a multiple of the
- page size (in bytes) from the
- beginning of the file.
-
- /I None Tells LIB to ignore case when
- comparing symbols (default). Use when
- combining with libraries that are
- case sensitive.
-
- /NOE None Tells LIB not to generate an extended
- dictionary.
-
- /NOI None Tells LIB to compare case when
- comparing symbols (LIB remains case
- sensitive).
-
- commands "Operations" Command symbols and object files that
- tell LIB what changes to make in the
- Field Prompt Input
- ──────────────────────────────────────────────────────────────────────────
- tell LIB what changes to make in the
- library.
-
- listfile "List file" Name of a cross-reference-listing
- file. No listing file is created if
- you do not give a file name.
-
- newlib "Output library" Name of the changed library that LIB
- creates as output. If you do not give
- a new library name, the original,
- unchanged library is saved in a
- library file with the same name but
- with a .BAK extension replacing the
- .LIB extension.
- ──────────────────────────────────────────────────────────────────────────
-
-
- G.5.2 Usual Responses for LIB
-
- LIB has its own built-in (default) responses. You can choose these usual
- responses for any of the information that LIB needs, in any the following
- ways:
-
- ■ To choose the default for any command-line entry, omit the file name or
- names before the entry and type only the required comma. The only
- exception to this is the default for the listfile entry: if you omit
- this entry, LIB creates a cross-reference-listing file.
-
- ■ To choose the default for any prompt, press ENTER.
-
- ■ To choose the defaults for all command-line entries or prompts that
- follow an entry or prompt, type a semicolon (;) after that entry or
- prompt. The semicolon should be the last character on the command line.
-
- The following list shows the defaults that LIB uses for
- cross-reference-listing files and output libraries:
-
- File Default
- ──────────────────────────────────────────────────────────────────────────
- Cross-reference The special file name NUL, which tells the linker not
- listing to create a cross-reference-listing file
-
- Output library The oldlib entry or the response to the "Library name"
- prompt
- ──────────────────────────────────────────────────────────────────────────
-
- G.5.3 Cross-Reference-Listing Files
-
- A cross-reference-listing file tracks which routines are contained in a
- stand-alone library and the original object files they came from. A
- cross-reference-listing file contains the following lists:
-
- ■ An alphabetical list of all public symbols in the library. Each symbol
- name is followed by the name of the module in which it is defined.
-
- ■ A list of the modules in the library. Under each module name is an
- alphabetical listing of the public symbols defined in that module.
-
- G.5.4 Command Symbols
-
- To tell LIB what changes you want to make to a library, type a command
- symbol such as +, -, -+, *, or -*, followed immediately by a module name,
- object-file name, or library name. You can specify more than one
- operation, in any order.
-
- The following list shows each LIB command symbol, the type of file name to
- specify with the symbol, and what the symbol does:
-
- ╓┌─┌────────────────────────┌────────────────────────────────────────────────╖
- Command Meaning
- ──────────────────────────────────────────────────────────────────────────
- +{objfile | lib} Adds the given object file to the input library
- and makes that object file the last module in the
- library, if given with an object-file name. You
- can use a path name for the object file name.
- Since LIB automatically supplies the .OBJ
- extension, you can omit the extension from the
- object-file name.
-
- If given with a library name, the plus sign (+)
- adds the contents of that library to the input
- library. The library name must have the .LIB
- Command Meaning
- ──────────────────────────────────────────────────────────────────────────
- library. The library name must have the .LIB
- extension.
-
- -module Deletes the given module from the input library.
- A module name does not have a path name or an
- extension.
-
- -+module Replaces the given module in the input library.
- Module names have no path names and no
- extensions. LIB deletes the given module, then
- appends the object file that has the same name as
- the module. The object file is assumed to have an
- .OBJ extension and to reside in the current
- working directory.
-
- *module Copies the given module from the library to an
- object file in the current working directory. The
- module remains in the library file. When LIB
- copies the module to an object file, it adds the
- Command Meaning
- ──────────────────────────────────────────────────────────────────────────
- copies the module to an object file, it adds the
- .OBJ extension. You cannot override the .OBJ
- extension, drive designation, or path name given
- to the object file. However, you can later rename
- the file or copy it to whatever location you
- like.
-
- -*module Moves the given object module from the library to
- an object file. This operation is equivalent to
- copying the module to an object file, as
- described above, then deleting the module from
- the library.
- ──────────────────────────────────────────────────────────────────────────
-
-
- Examples
-
- The example below uses the replace command symbol (-+) to instruct LIB to
- replace the HEAP module in the library LANG.LIB. LIB deletes HEAP from the
- library, then appends the object file HEAP.OBJ as a new module in the
- library. The semicolon at the end of the command line tells LIB to use the
- default responses for the remaining prompts. This means that no listing
- file is created and that the changes are written to the original library
- file instead of creating a new library file.
-
- LIB LANG-+HEAP;
-
- The examples below perform the same function as the first example in this
- section, but in two separate operations, using the add (+) and delete (-)
- command symbols. The effect is the same for these examples because delete
- operations are always carried out before add operations, regardless of the
- order of the operations in the command line. This order of execution
- prevents confusion when a new version of a module replaces an old version
- in the library file.
-
- LIB LANG-HEAP+HEAP;
-
- LIB LANG+HEAP-HEAP;
-
- The example below causes LIB to perform a consistency check of the library
- file FOR.LIB. No other action is performed. LIB displays any consistency
- errors it finds and returns to the operating-system level.
-
- LIB FOR;
-
- The following example tells LIB to perform a consistency check on the
- library file LANG.LIB and then create the cross-reference-listing file
- LCROSS.PUB.
-
- LIB LANG,LCROSS.PUB
-
- The next example instructs LIB to move the module STUFF from the library
- FIRST.LIB to an object file called STUFF.OBJ. The module STUFF is removed
- from the library in the process. The module MORE is copied from the
- library to an object file called MORE.OBJ; the module remains in the
- library. The revised library is called SECOND.LIB. It contains all the
- modules in the library FIRST.LIB except STUFF, which was removed by using
- the move command symbol (-*). The original library, FIRST.LIB, remains
- unchanged.
-
- LIB FIRST -*STUFF *MORE, ,SECOND
-
- The contents of the response file below cause LIB to delete the module
- HEAP from the LIBFOR.LIB library file, extract (without deleting) FOIBLES
- and place it in an object file named FOIBLES.OBJ, and append the object
- files CURSOR.OBJ and HEAP.OBJ as the last two modules in the library.
- Finally, LIB creates the cross-reference-listing file CROSSLST.
-
- LIBFOR
- +CURSOR+HEAP-HEAP*FOIBLES
- CROSSLST
-
- G.5.5 LIB Options
-
- LIB has four options. Specify options on the command line following the
- required library-file name and preceding any commands.
-
- G.5.5.1 Ignoring Case for Symbols
-
- /I[[GNORECASE]]
-
- The /I option tells LIB to ignore case when comparing symbols, as LIB does
- by default. Use this option when you are combining a library that is
- marked /NOI (described below) with others that are unmarked and you want
- the new library to be unmarked.
-
- G.5.5.2 Ignoring Extended Dictionaries
-
- /NOE[[XTDICTIONARY]]
-
- The /NOE option tells LIB not to generate an extended dictionary. The
- extended dictionary is an extra part of the library that helps the linker
- process libraries faster.
-
- Use the /NOE option if you get errors U1171 or U1172, or if the extended
- dictionary causes problems with LINK. See Section G.4.6.9 for more
- information on how LINK uses the extended dictionary.
-
- G.5.5.3 Distinguishing Case for Symbols
-
- /NOI[[GNORECASE]]
-
- The /NOI option tells LIB not to ignore case when comparing symbols; that
- is, /NOI makes LIB case sensitive. By default, LIB ignores case. Using
- this option allows symbols that are the same except for case, such as
- SPLINE and Spline, to be put in the same library.
-
- Note that when you create a library with the /NOI option, LIB marks the
- library internally to indicate that /NOI is in effect. Earlier version of
- LIB did not mark libraries in this way. If you combine multiple libraries,
- and any one of them is marked /NOI, then /NOI is assumed to be in effect
- for the output library.
-
- G.5.5.4 Setting Page Size
-
- /P[[AGESIZE]]:number
-
- The page size of a library affects the alignment of modules stored in the
- library. Modules in the library are always aligned to start at a position
- that is a multiple of the page size (in bytes) from the beginning of the
- file. The default page size for a newly created library is 16 bytes.
-
- You can set a different library page size while you are creating a library
- or change the page size of an existing library by adding the following
- option after the oldlib entry on the LIB command line or after the name
- you type in response to the "Library name" prompt:
-
- The number specifies the new library page size. It must be an integer
- value representing a power of 2 between the values 16 and 32,768.
-
- The library page size determines the number of modules the library can
- hold. Thus, increasing the page size allows you to include more modules in
- the library. However, the larger the page size, the larger the amount of
- wasted storage space in the library (on the average, pagesize/2 bytes). In
- most cases you should use a small page size unless you need to put a very
- large number of modules in a library.
-
- The page size also determines the maximum possible size of the library.
- This limit is number * 65,536. For example, if you invoke LIB with the
- option /P:16, the library must be smaller than one megabyte (16 * 65,536
- bytes).
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- Appendix H Creating and Using Quick Libraries
-
- This appendix describes how to create and maintain libraries from within
- the QuickBASIC programming environment. A library is a file containing the
- contents of several modules under a single file name. When you finish this
- appendix you will know how to:
-
- ■ Make libraries from within the QuickBASIC environment
-
- ■ Load a Quick library when running a QuickBASIC program
-
- ■ View the contents of a Quick library
-
- ■ Add routines written in other languages to a Quick library
-
-
- H.1 Types of Libraries
-
- QuickBASIC provides tools for creating two different types of libraries,
- which are identified by different file-name extensions:
-
- Extension Function
- ──────────────────────────────────────────────────────────────────────────
- .QLB The .QLB extension characterizes a Quick library,
- a special kind of library that permits easy
- addition of frequently used procedures to your
- programs. A Quick library can contain procedures
- written in QuickBASIC or other Microsoft
- languages such as Microsoft C.
-
- .LIB The .LIB extension characterizes a stand-alone
- (.LIB) library, one that is created with the
- Microsoft Library Manager, LIB. When QuickBASIC
- makes a Quick library, it simultaneously creates
- a .LIB library containing the same procedures in
- a somewhat different form.
- ──────────────────────────────────────────────────────────────────────────
-
- You can generate both types of libraries from within the programming
- environment or from the command line. You can think of a Quick library as
- a group of procedures appended to QuickBASIC when the library is loaded
- with QuickBASIC. Libraries with the .LIB extension are essentially
- independent, compiled procedures. They can either be added to a Quick
- library or linked with a main module to create a file that is executable
- from the DOS command line.
-
- This appendix discusses the use of command-line utilities for some common
- cases, but you should refer to Appendix G, "Compiling and Linking from
- DOS," for a full explanation of using those utilities.
-
-
- H.2 Advantages of Quick Libraries
-
- Quick libraries facilitate program development and maintenance. As
- development progresses on a project and modules become stable components
- of your program, you can add them to a Quick library, then set aside the
- source files for the original modules until you want to improve or
- maintain those source files. Thereafter you can load the library along
- with QuickBASIC, and your program has instant access to all procedures in
- the library.
-
- Procedures in a Quick library behave like QuickBASIC's own statements. If
- properly declared, a SUB procedure in a Quick library can even be invoked
- without a CALL statement. See Chapter 2, "SUB and FUNCTION Procedures,"
- for more information on calling a SUB procedure with or without the CALL
- keyword.
-
- Procedures in a Quick library can be executed directly from the Immediate
- window, just like BASIC statements. This means that you can test their
- effects before using them in other programs.
-
- If you codevelop programs with others, Quick libraries make it easy to
- update a pool of common procedures. If you wish to offer a library of
- original procedures for commercial distribution, all QuickBASIC
- programmers will be able to use them immediately to enhance their own
- work. You could leave your custom Quick library on a bulletin board for
- others to try before purchasing. Because Quick libraries contain no source
- code and can only be used within the QuickBASIC programming environment,
- your proprietary interests are protected while your marketing goals are
- advanced.
-
- ──────────────────────────────────────────────────────────────────────────
- NOTE
- Quick libraries have the same function as user libraries in QuickBASIC
- Versions 2.0 and 3.0. However, you cannot load a user library as a Quick
- library. You must recreate the library from the original source code, as
- described below.
- ──────────────────────────────────────────────────────────────────────────
-
-
- H.3 Creating a Quick Library
-
- A Quick library automatically contains all modules, both main and nonmain,
- present in the QuickBASIC environment when you create the new library. It
- also contains the contents of any other Quick library that you loaded when
- starting QuickBASIC. If you load a whole program but only want certain
- modules to be put in the library, you must explicitly unload those you
- don't want. You can unload modules with the File menu's Unload File
- command.
-
- You can quickly determine which modules are loaded by checking the list
- box of the SUBs command on the View menu. However, this method does not
- show which procedures a loaded library contains. The QLBDUMP.BAS utility
- program, described in Section H.4.3, "Viewing the Contents of a Quick
- Library," allows you to list all the procedures in a library.
-
- Only whole modules can be put into a library. That is, you cannot select
- one procedure from among many in a module. If you want to enter only
- certain procedures from a module, put the procedures you want in a
- separate module, then put that module into a library.
-
- A Quick library must be self-contained. A procedure in a Quick library can
- only call other procedures within the same Quick library. Procedure names
- must be unique within the library.
-
- With large programs, you can reduce loading time by putting as many
- routines as possible in Quick libraries. Putting many routines in Quick
- libraries is also an advantage if you plan to make the program into a
- stand-alone executable file later, since the contents of libraries are
- simply linked without recompiling.
-
- ──────────────────────────────────────────────────────────────────────────
- NOTE
- Your main module may or may not contain procedures. If it does and you
- incorporate those procedures in the library, the entire main module goes
- in the library, too. This does not cause an error message, but the
- module-level code in the library can never be executed unless one of its
- procedures contains a routine (such as ON ERROR) that explicitly passes
- control to the module level. Even if that is the case, much of the
- module-level code may be extraneous. If you organize your procedures in
- modules that are frequently used together, your Quick libraries are
- likely to be less cluttered with useless code.
- ──────────────────────────────────────────────────────────────────────────
-
- H.3.1 Files Needed to Create a Quick Library
-
- To create a Quick library, make sure that the proper files are available
- before you begin. If you don't have a hard disk, you should keep your
- files and the other programs on several floppy disks. QuickBASIC prompts
- you for a path name when it cannot find a file; when this happens, insert
- the correct disk and respond to the prompt.
-
- Make sure that the following files are in the current working directory or
- accessible to QuickBASIC through the appropriate DOS environment
- variables:
-
- File Purpose
- ──────────────────────────────────────────────────────────────────────────
- QB.EXE Directs the process of creating a Quick library.
- If you are working only with QuickBASIC modules,
- you can do everything in one step from within the
- QuickBASIC environment.
-
- BC.EXE Creates object files from source code.
-
- LINK.EXE Links object files.
-
- LIB.EXE Manages stand-alone libraries of object modules.
-
- BQLB45.LIB Supplies routines needed by your Quick library.
- This library is a stand-alone library that is
- linked with objects in your library to form a
- Quick library.
- ──────────────────────────────────────────────────────────────────────────
-
- H.3.2 Making a Quick Library
-
- Most of the time you create Quick libraries from within the QuickBASIC
- environment. Occasionally, you may want to update a library or include
- routines from other Microsoft languages in your Quick library. In these
- cases, begin by constructing a base library of the non-BASIC routines from
- outside the environment by invoking LINK and LIB directly. Then you can
- add the most current QuickBASIC modules from within QuickBASIC.
-
- H.3.3 Making a Quick Library from within the Environment
-
- When making a library from within the QuickBASIC environment, the first
- consideration is whether the library to be made is totally new or an
- update of an existing library. If it is to be an update, you should start
- QuickBASIC with the /L command-line option, supplying the name of the
- library to be updated as a command-line argument. At the same time, you
- can also include the name of a program whose modules you want to put in
- the library. In this case QuickBASIC loads all the modules specified in
- that program's .MAK file.
-
- H.3.3.1 Unloading Unwanted Files
-
- If you load your program when starting QuickBASIC, be sure to unload any
- modules you don't want in the Quick library, including the main module
- (unless it contains procedures you want in the library).
-
- Follow these steps to unload modules:
-
- 1. Choose the Unload File command from the File menu.
-
- 2. Select the module you want to unload from the list box, then press
- ENTER.
-
- 3. Repeat steps 1 and 2 until you have unloaded all unwanted modules.
-
- H.3.3.2 Loading Desired Files
-
- Alternatively, you can simply start QuickBASIC, with or without a library
- specification, and load the modules you want one at a time from within the
- environment. In this case, you load each module using the Load File
- command from the File menu.
-
- To load one module at a time with QuickBASIC:
-
- 1. Choose the File menu's Load File command.
-
- 2. Select the name of a module you want to load from the list box.
-
- 3. Repeat steps 1 and 2 until all you have loaded all the modules you
- want.
-
- H.3.3.3 Creating a Quick Library
-
- Once you have loaded the previous library (if any) and all the new modules
- you want to include in the Quick library, choose the Make Library command
- from the Run menu. The dialog box shown in Figure H.1 appears.
-
-
- Type Quick-library file name here.
- │
- ┌────────────────────────────┼─Make Library───────────────────────────┐
- │ ┌─┼─────────────────────────────────────┐ │
- │ Quick-Library File Name: │ │ │
- │ └───────────────────────────────────────┘ │
- │ [X] Produce Debug Code │
- ├─────────────────────────────────────────────────────────────────────┤
- │ < Make Library > <Make Library and Exit > < Cancel > < Help > │
- └───────────────────────────────┼─────────────────────────────────────┘
- │
- │Makes a library
- and exits to DOS
-
- Figure H.1 Make Library Dialog Box
-
- To create a Quick library, perform the following steps:
-
- 1. Enter the name of the library you wish to create in the Quick-Library
- File Name text box.
-
- If you enter only a base name (that is, a file name with no extension),
- QuickBASIC automatically appends the extension .QLB when it creates the
- library. If you want your library to have no extension, add a
- terminating period (.) to the base name. Otherwise, you may enter any
- base name and extension you like (except the name of a loaded Quick
- library), consistent with DOS file-name rules.
-
- 2. Select the Produce Debug Code check box only if you are specifically
- trying to track a bug you believe to be in a library that you are
- updating. It makes your library larger, slows program execution and
- gives only a small amount of error control, mostly in regard to
- checking of array bounds.
-
- 3. Create the Quick library:
-
- ■ Choose the Make Library command button if you want to remain in the
- environment after the Quick library is created.
-
- ■ Choose the Make Library and Exit command button if you want to return
- to the DOS command level after the Quick library is created.
-
- ──────────────────────────────────────────────────────────────────────────
- NOTE
- When you make a Quick library, be aware that if it is ever to be used
- with a nonlibrary module that needs to trap events such as keystrokes,
- then one of the modules in the library must contain at least one
- event-trapping statement. This statement can be as simple as TIMER OFF,
- but without it events are not trapped correctly in the Quick library.
- ──────────────────────────────────────────────────────────────────────────
-
-
- H.4 Using Quick Libraries
-
- This section explains how to load a Quick library when you start
- QuickBASIC and how to view the contents of a Quick library. It also gives
- facts that you should remember when procedures within a Quick library
- perform floating-point arithmetic.
-
- H.4.1 Loading a Quick Library
-
- To load a Quick library, you must specify the name of the desired library
- on the command line when you start QuickBASIC using the following syntax:
-
- QB[[programname]] /L [[libraryname]]
-
- If you start QuickBASIC with the /L option and supply the name of a
- library (libraryname), QuickBASIC loads the specified library and places
- you in the programming environment. The contents of the library are now
- available for use. If you start QuickBASIC with the /L option but don't
- specify a library, QuickBASIC loads the library QB.QLB (see Section H.5).
-
- You can also start QuickBASIC with the /RUN option followed by both a
- program name (programname) and the /L option. In this case, QuickBASIC
- loads both the program and the specified Quick library, then runs the
- program without stopping at the programming environment.
-
- ──────────────────────────────────────────────────────────────────────────
- NOTE
- When using Quick libraries to represent program modules, remember to
- update the .MAK file to keep it consistent with the modules in the
- evolving program. (This is done with the Unload File command from the
- File menu.) If the .MAK file is not up to date, it may cause QuickBASIC
- to load a module containing a procedure definition with the same name as
- one defined in the Quick library, which in turn causes the error message
- Duplicate definition.
- ──────────────────────────────────────────────────────────────────────────
-
- You can load only one Quick library at a time. If you specify a path,
- QuickBASIC looks where you indicate; otherwise, QuickBASIC searches for
- the Quick library in the following three locations:
-
- 1. The current directory.
-
- 2. The path specified for libraries by the Set Paths command.
-
- 3. The path specified by the LIB environment variable. (See your DOS
- documentation for information about environment variables.)
-
- Example
-
- The following command starts QuickBASIC and runs the program REPORT.BAS
- using the routines in the library FIGS.QLB:
-
- QB /RUN REPORT.BAS /L FIGS.QLB
-
- H.4.2 Floating-Point Arithmetic in Quick Libraries
-
- BASIC procedures within Quick libraries represent code compiled with the
- BC command-line compiler. These procedures share significant
- characteristics with executable files. For example, both executable files
- and Quick libraries perform floating-point arithmetic faster and with a
- higher degree of accuracy than the same calculations performed within the
- QuickBASIC environment. For more information, see Chapter 16, "The Run
- Menu," in Learning to Use Microsoft QuickBASIC.
-
- H.4.3 Viewing the Contents of a Quick Library
-
- Because a Quick library is essentially a binary file, you cannot view its
- contents with a text editor to find out what it contains. Your
- distribution disk includes the QLBDUMP.BAS utility, which allows you to
- list all the procedures and data symbols in a given library. Follow these
- steps to view the contents of a Quick library:
-
- 1. Start QuickBASIC.
-
- 2. Load and run QLBDUMP.BAS.
-
- 3. Enter the name of the Quick library you wish to examine in response to
- the prompt. You do not need to include the .QLB extension when you type
- the file name; however, supplying the extension does no harm.
-
- If the specified file exists and it is a Quick library, the program
- displays a list of all the symbol names in the library. In this
- context, symbol names correspond to the names of procedures in the
- library.
-
- See Chapter 3, "File and Device I/O," for a commented listing of
- QLBDUMP.BAS.
-
-
- H.5 The Supplied Library (QB.QLB)
-
- If you invoke QuickBASIC with the /L option, but do not supply a Quick
- library name, QuickBASIC automatically loads a library named QB.QLB,
- included with the QuickBASIC package. This file contains three routines,
- INTERRUPT, INT86OLD, and ABSOLUTE, that provide software-interrupt support
- for system-service calls and support for CALL ABSOLUTE. To use the
- routines in QB.QLB, you must specify it (or another library into which
- those routines have been incorporated) on the command line when you invoke
- QuickBASIC. If you wish to use these routines along with other routines
- that you have placed in libraries, make a copy of the QB.QLB library and
- use it as a basis for building a library containing all the routines you
- need.
-
-
- H.6 The .QLB File-Name Extension
-
- The extension .QLB is just a convenient convention. You can use any
- extension for your Quick library files, or no extension at all. However,
- in processing the /L libraryname option, QuickBASIC assumes that the
- listed libraryname has the .QLB extension if no other extension is
- specified. If your Quick library has no extension, you must put a period
- after the Quick-library name (libraryname.) or QuickBASIC searches for a
- file with your base name and the .QLB extension.
-
-
- H.7 Making a Library from the Command Line
-
- After making a library from within the QuickBASIC environment, you will
- notice the appearance of extra files with the extensions .OBJ and .LIB. In
- creating Quick libraries, QuickBASIC actually directs the work of three
- other programs, BC, LINK, and LIB, and then combines what they produce
- into both a Quick library and a stand-alone (.LIB) library. Once the
- process is complete, there is one object (.OBJ) file for each module in
- your Quick library and a single library (.LIB) file containing an object
- module for each object file. The files with the extension .OBJ are now
- extraneous and can be deleted. However, files with the extension .LIB are
- very important and should be preserved. These parallel libraries are the
- files QuickBASIC uses to create executable files of your programs.
-
- You can use the programs LINK and LIB to create both Quick libraries and
- stand-alone (.LIB) libraries from the command line in batch mode. If you
- want to use routines originally written and compiled in other languages in
- QuickBASIC, you must first put the other-language routines in a Quick
- library via the command line. Once the other-language routines are in the
- library, you can incorporate your BASIC modules from the command line or
- from within the QuickBASIC environment.
-
- Professional software developers should be sure to deliver both the Quick
- (.QLB) and stand-alone (.LIB) versions of libraries to customers. Without
- the .LIB libraries, end users would not be able to use your library
- routines in executable files produced with QuickBASIC.
-
- When you create a Quick library using LINK, the library BQLB45.LIB must
- always be specified after the third comma on the LINK command line or in
- response to the "Libraries" prompt.
-
-
- H.8 Using Routines from Other Languages in a Quick Library
-
- To place routines from other languages in a Quick library, you must start
- with precompiled or preassembled object files that contain the
- other-language routines you wish to use. Several other languages are
- suitable for this purpose, including Microsoft C, Microsoft Macro
- Assembler, Microsoft Pascal, Microsoft FORTRAN, and any other language
- that creates object files compatible with the Microsoft language family.
-
- H.8.1 Building a Quick Library
-
- The following is a typical scenario for building a Quick library
- containing routines from other languages:
-
- 1. Suppose you begin with three modules, created in FORTRAN, C, and Macro
- Assembler. First you compile or assemble each module with the proper
- language translator to produce object files called here FOR.OBJ, C.OBJ,
- and ASM.OBJ.
-
- 2. You then link the object files with the LINK option /Q, which instructs
- the linker to produce a Quick library file, as shown in the following
- command line:
-
- LINK /Q FOR.OBJ C.OBJ ASM.OBJ, MIXED.QLB,,BQLB45.LIB;
-
- The linker interprets the entry that follows the names of the object
- files (in this case MIXED.QLB) as the file name by which the linked
- modules will be known. Thus, in this case, the Quick library file is
- named MIXED.QLB.
-
- 3. Now create a parallel .LIB library, using the same object files you
- just used to make the Quick library. In this case the first name
- following the LIB command is the name of the .LIB library:
-
- LIB MIXED.LIB+FOR.OBJ+C.OBJ+ASM.OBJ;
-
- It is easy to overlook this step when making a library that contains
- other-language routines, but this step is crucial if you hope to use
- the library to create a stand-alone executable file. Without these
- parallel stand-alone (.LIB) libraries, QuickBASIC cannot create an
- executable file containing their routines.
-
- 4. With the other-language routines now in a Quick library and the
- original object files in a stand-alone library having the same base
- name, you can return to the QuickBASIC environment and build as many
- BASIC modules into the library as available memory permits.
-
- See Appendix G, "Compiling and Linking from DOS," for a complete
- description of the features of LINK and LIB.
-
- H.8.2 Quick Libraries with Leading Zeros in the First Code Segment
-
- A Quick library containing leading zeros in the first code segment is
- invalid, causing the message Error in loading file filename - Invalid
- format when you try to load it in QuickBASIC. For example, this can occur
- if an assembly-language routine puts data that is initialized to zero in
- the first code segment and it is subsequently listed first on the LINK
- command line when you make a Quick library. If you have this problem, do
- one of the following two things:
-
- 1. Link with a BASIC module first on the LINK command line.
-
- 2. Make sure that, in whatever module comes first on the LINK command
- line, the first code segment starts with a nonzero byte.
-
- H.8.3 The B_OnExit Routine
-
- QuickBASIC provides a BASIC system-level function, B_OnExit. You can use
- B_OnExit when your other-language routines take special actions that need
- to be undone before leaving the program (intentionally or otherwise) or
- rerunning the program. For example, within the QuickBASIC environment, an
- executing program that calls other-language routines in a Quick library
- may not always run to normal termination. If such routines need to take
- special actions at termination (for example, deinstallation of previously
- installed interrupt vectors), you can guarantee that your termination
- routines will always be called if you include an invocation of B_OnExit in
- the routine. The following example illustrates such a call (for
- simplicity, the example omits error-handling code). Note that such a
- function would be compiled in C in large model.
-
- #include <malloc.h>
-
- extern pascal far B_OnExit(); /* Declare the routine */
-
- int *p_IntArray;
-
- void InitProc()
- {
- void TermProc(); /* Declare TermProc function */
-
- /* Allocate far space for 20-integer array: */
-
- p_IntArray = (int *)malloc(20*sizeof(int));
-
- /* Log termination routine (TermProc) with BASIC: */
-
- B_OnExit(TermProc);
- }
-
- /* The TermProc function is */
- void TermProc() /* called before any restarting */
- { /* or termination of program. */
-
- free(p_IntArray); /* Release far space allocated */
- } /* previously by InitProc. */
-
- If the InitProc function were in a Quick library, the call to B_OnExit
- would insure proper release of the space reserved in the call to malloc,
- should the program crash. The routine could be called several times, since
- the program can be executed several times from the QuickBASIC environment.
- However, the TermProc function itself would be called only once each time
- the program runs.
-
- The following BASIC program is an example of a call to the InitProc
- function:
-
- DECLARE SUB InitProc CDECL
-
- X = SETMEM(-2048) ' Make room for the malloc memory
- ' allocation in C function.
- CALL InitProc
- END
-
- If more than 32 routines are registered, B_OnExit returns NULL, indicating
- there is not enough space to register the current routine. (Note that
- B_OnExit has the same return values as the Microsoft C run-time-library
- routine onexit.)
-
- B_OnExit can be used with any other-language (including assembly-language)
- routines you place in a Quick library. With programs compiled and linked
- completely from the command line, B_OnExit is optional.
-
-
- H.9 Memory Considerations with Quick Libraries
-
- Because a Quick library is essentially an executable file (although it
- cannot be invoked by itself from the DOS command line), it is quite large
- in comparison to the sum of the sizes of its source files. This puts an
- upper limit on the number of routines you can put in a Quick library. To
- determine how large your Quick library can be, add up the memory required
- for DOS, QB.EXE, and your program's main module. An easy way to estimate
- these factors is to boot your machine, start QuickBASIC with your program,
- and enter this command in the Immediate window:
-
- PRINT FRE (-1)
-
- This command shows you the number of bytes of free memory. This indicates
- the maximum size for any Quick library associated with this program. In
- most cases the amount of memory required for a Quick library is about the
- same as the size of its disk file. One exception to this rule of thumb is
- a library with procedures that use a lot of strings; such a program may
- require somewhat more memory.
-
-
- H.10 Making Compact Executable Files
-
- As discussed above, when QuickBASIC creates a Quick library, it also
- creates a stand-alone (.LIB) library of object modules in which each
- object module corresponds to one of the modules in the Quick library. When
- you make an executable file, QuickBASIC searches the stand-alone (.LIB)
- library for object modules containing the procedures referenced in the
- program.
-
- If an object module in the library does not contain procedures referenced
- in the program, it is not included in the executable file. However, a
- single module may contain many procedures, and if even one of them is
- referenced in the program all are included in the executable file.
- Therefore, even if a program uses only one of four procedures in a certain
- module, that entire module becomes part of the final executable file.
-
- To make your executable files as compact as possible, you should maintain
- a library in which each module contains only closely related procedures.
- If you have any doubts about what a library contains, list its contents
- with the utility QLBDUMP.BAS, described in Section H.4.3, "Viewing the
- Contents of a Quick Library."
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- Appendix I Error Messages
-
- During development of a BASIC program with QuickBASIC, the following types
- of errors can occur:
-
- ■ Invocation errors
-
- ■ Compile-time errors
-
- ■ Link-time errors
-
- ■ Run-time errors
-
- Each type of error is associated with a particular step in the program
- development process. Invocation errors occur when you invoke QuickBASIC
- with the QB or BC commands. Compile-time errors (and warnings) occur
- during compilation, and run-time errors occur when the program is
- executing. Link-time errors occur only when you use the LINK command to
- link object files created with BC or other language compilers.
-
- Section I.2 lists alphabetically the invocation, compile-time, and
- run-time error messages, along with any error codes that are assigned.
- Table I.1 lists the run-time error messages and error codes in numerical
- order. Section I.3 lists the Microsoft Overlay Linker error messages, and
- Section I.4, the Microsoft Library Manager error messages.
-
-
- I.1 Error-Message Display
-
- When a run-time error occurs within the QuickBASIC environment (with
- default screen options), the error message appears in a dialog box and the
- cursor is placed on the line where the error occurred.
-
- In stand-alone executable programs (that is, programs that are executed by
- entering the base name of the executable file at the system prompt), the
- run-time system prints the error messages followed by an address, unless
- the /D, /E, or /W option is specified on the BC command line. In those
- cases, the error message is followed by the number of the line in which
- the error occurred. The standard forms of this type of error message are
- as follows:
-
- Error n in module module-name at address segment:offset
-
- and
-
- Error n in line linenumber of module module-name at
- address segment:offset
-
- An ERR code is listed for some errors. If an error occurs, the value
- returned by ERR is set to the appropriate code when an error-trapping
- subroutine is entered. (Error-trapping routines are entered via the ON
- ERROR statement.) The ERR value remains unchanged until a RESUME statement
- returns control to the main program. See Chapter 6, "Error and Event
- Trapping," for more information.
-
- Table I.1 lists the error codes in numerical order. See the alphabetical
- listing for explanations of the errors.
-
- Table I.1 Run-Time Error Codes
- ╓┌─┌────────┌───────────────────────────┌────────┌───────────────────────────╖
- Code Description Code Description
- ──────────────────────────────────────────────────────────────────────────
- 2 Syntax error 53 File not found
-
- 3 RETURN without GOSUB 54 Bad file mode
-
- 4 Out of DATA 55 File already open
-
- 5 Illegal function call 56 FIELD statement active
-
- 6 Overflow 57 Device I/O error
- Code Description Code Description
- ──────────────────────────────────────────────────────────────────────────
- 6 Overflow 57 Device I/O error
-
- 7 Out of memory 58 File already exists
-
- 9 Subscript out of range 59 Bad record length
-
- 10 Duplicate definition 61 Disk full
-
- 11 Division by zero 62 Input past end of file
-
- 13 Type mismatch 63 Bad record number
-
- 14 Out of string space 64 Bad file name
-
- 16 String formula too complex 67 Too many files
-
- 19 No RESUME 68 Device unavailable
-
- 20 RESUME without error 69 Communication-buffer
- Code Description Code Description
- ──────────────────────────────────────────────────────────────────────────
- 20 RESUME without error 69 Communication-buffer
- overflow
-
- 24 Device timeout 70 Permission denied
-
- 25 Device fault 71 Disk not ready
-
- 27 Out of paper 72 Disk-media error
-
- 39 CASE ELSE expected 73 Advanced feature unavailable
-
- 40 Variable required 74 Rename across disks
-
- 50 FIELD overflow 75 Path/File access error
-
- 51 Internal error 76 Path not found
-
- 52 Bad file name or number
- ──────────────────────────────────────────────────────────────────────────
- Code Description Code Description
- ──────────────────────────────────────────────────────────────────────────
- ──────────────────────────────────────────────────────────────────────────
-
-
-
- I.2 Invocation, Compile-Time, and Run-Time Error Messages
-
- Advanced feature unavailable
-
- You are attempting to use a feature of QuickBASIC that is available with
- another version of BASIC, or supported only under a later version of DOS.
- (Compile-time or run-time error)
-
- ERR code: 73
-
- Argument-count mismatch
-
- You are using an incorrect number of arguments with a BASIC subprogram or
- function. (Compile-time error)
-
- Array already dimensioned
-
- This error can be caused by any of the following:
-
- ■ More than one DIM statement for the same static array.
-
- ■ A DIM statement after the initial use of an array. Dynamic arrays must
- be deallocated with the ERASE statement before they can be redimensioned
- with DIM; dynamic arrays may also be redimensioned with the REDIM
- statement.
-
- ■ An OPTION BASE statement that occurs after an array is dimensioned.
-
- (Compile-time or run-time error)
-
- Array not defined
-
- An array is referenced but never defined. (Compile-time error)
-
- Array not dimensioned
-
- An array is referenced but not dimensioned. If you are compiling the
- program with BC, this error is not "fatal"; the program will execute,
- although program results may be incorrect. (Compile-time warning)
-
- Array too big
-
- There is not enough user data space to accommodate the array declaration.
- Reduce the size of the array or use the $DYNAMIC metacommand. You may also
- get this error if the array size exceeds 64K, the array is not dynamic,
- and the /AH option is not used. Reduce the size of the array, or make the
- array dynamic and use the /AH command-line option. (Compile-time error)
-
- AS clause required
-
- A variable declared with an AS clause is referenced without one. If the
- first declaration of a variable has an AS clause, every subsequent DIM,
- REDIM, SHARED, and COMMON statement that references that variable must
- have an AS clause. (Compile-time error)
-
- AS clause required on first declaration
-
- A variable that has not been declared using an AS clause is being
- referenced with an AS clause. (Compile-time error)
-
- AS missing
-
- The compiler expects an AS keyword, as in OPEN "FILENAME" FOR INPUT AS #1.
- (Compile-time error)
-
- Asterisk missing
-
- The asterisk is missing from a string definition in a user type.
- (Compile-time error)
-
- Bad file mode
-
- This error occurs in the following situations:
-
- ■ The program tries to use PUT or GET with a sequential file or execute an
- OPEN statement with a file mode other than I, O, or R.
-
- ■ The program tries to use a FIELD statement with a file not opened for
- random access.
-
- ■ The program tries to print to a file opened for input.
-
- ■ The program tries to read from a file opened for output or appending.
-
- ■ QuickBASIC tries to use an include file previously saved in compressed
- format. Include files must be saved in text format. Reload the include
- file, save it in text format, then try to run the program again.
-
- ■ You try to load a corrupt binary program.
-
- (Run-time error)
-
- ERR code: 54
-
- Bad file name
-
- An illegal form is used for the file name with LOAD, SAVE, KILL, or OPEN
- (for example, the file name has too many characters). (Run-time error)
-
- ERR code: 64
-
- Bad file name or number
-
- A statement or command references a file with a file name or number that
- is not specified in the OPEN statement or is out of the range of file
- numbers specified earlier in the program. (Run-time error)
-
- ERR code: 52
-
- Bad record length
-
- A GET or PUT statement that specified a record variable whose length did
- not match the record length specified in the corresponding OPEN statement
- was executed. (Run-time error)
-
- ERR code: 59
-
- Bad record number
-
- In a PUT or GET statement, the record number is less than or equal to
- zero. (Run-time error)
-
- ERR code: 63
-
- BASE missing
-
- QuickBASIC expected the keyword BASE here, as in OPTION BASE.
- (Compile-time error)
-
- Binary source file
-
- The file you have attempted to compile is not an ASCII file. All source
- files saved by BASICA should be saved with the ,A option. QuickBASIC also
- uses this message to warn you when you try to use the /ZI or /ZD CodeView
- options with binary source files. (Compile-time error)
-
- Block IF without END IF
-
- There is no corresponding END IF in a block IF construct. (Compile-time
- error)
-
- Buffer size expected after /C:
-
- You must specify a buffer size after the /C option. (BC invocation error)
-
- BYVAL allowed only with numeric arguments
-
- BYVAL does not accept string or record arguments. (Compile-time error)
-
- /C: buffer size too large
-
- The maximum size of the communications buffer is 32,767 bytes. (BC
- invocation error)
-
- Cannot continue
-
- While debugging, you have made a change that prevents execution from
- continuing. (Run-time error)
-
- Cannot find file (filename). Input path:
-
- This error occurs when QuickBASIC cannot find a Quick library or utility
- (BC.EXE, LINK.EXE, LIB.EXE, or QB.EXE) required by the program. Enter the
- correct path name, or press CTRL+C to return to the DOS prompt. (QB
- invocation error)
-
- Cannot generate listing for BASIC binary source files
-
- You are attempting to compile a binary source file with the BC command and
- the /A option. Recompile without the /A option. (BC invocation error)
-
- Cannot start with `FN'
-
- You used "FN" as the first two letters of a subprogram or variable name.
- "FN" can only be used as the first two letters when calling a DEF FN
- function. (Compile-time error)
-
- CASE ELSE expected
-
- No matching case was found for an expression in a SELECT CASE statement.
- (Run-time error)
-
- ERR code: 39
-
- CASE without SELECT
-
- The first part of a SELECT CASE statement is missing or misspelled.
- (Compile-time error)
-
- Colon expected after /C
-
- A colon is required between the option and the buffer size argument. (BC
- invocation error)
-
- Comma missing
-
- QuickBASIC expects a comma. (Compile-time error)
-
- COMMON and DECLARE must precede executable statements
-
- A COMMON statement or a DECLARE statement is misplaced. COMMON and DECLARE
- statements must appear before any executable statements. All BASIC
- statements are executable except the following:
-
- ■ COMMON
-
- ■ DEFtype
-
- ■ DIM (for static arrays)
-
- ■ OPTION BASE
-
- ■ REM
-
- ■ TYPE
-
- ■ All metacommands
-
- (Compile-time error)
-
- COMMON in Quick library too small
-
- More common variables are specified in the module than in the currently
- loaded Quick library. (Compile-time error)
-
- COMMON name illegal
-
- QuickBASIC encountered an illegal /blockname/ specification (for example,
- a blockname that is a BASIC reserved word) in a named COMMON block.
- (Compile-time error).
-
- Communication-buffer overflow
-
- During remote communications, the receive buffer overflowed. The size of
- the receive buffer is set by the /C command line option or the RB option
- in the OPEN COM statement. Try checking the buffer more frequently (with
- the LOC function) or emptying it more often (with the INPUT$ function).
- (Run-time error)
-
- ERR code: 69
-
- CONST/DIM SHARED follows SUB/FUNCTION
-
- CONST and DIM SHARED statements should appear before any subprogram or
- FUNCTION procedure definitions. If you are compiling your program with BC,
- this error is not "fatal"; the program will execute, although the results
- may be incorrect. (Compile-time warning)
-
- Control structure in IF...THEN...ELSE incomplete
-
- An unmatched NEXT, WEND, END IF, END SELECT, or LOOP statement appears in
- a single-line IF...THEN...ELSE statement. (Compile-time error)
-
- Data-memory overflow
-
- There is too much program data to fit in memory. This error is often
- caused by too many constants, or too much static array data. If you are
- using the BC command, or the Make EXE File or Make Library commands, try
- turning off any debugging options. If memory is still exhausted, break
- your program into parts and use the CHAIN statement or use the $DYNAMIC
- metacommand. (Compile-time error)
-
- DECLARE required
-
- An implicit SUB or FUNCTION procedure call appears before the procedure
- definition. (An implicit call does not use the CALL statement.) All
- procedures must be defined or declared before they are implicitly called.
- (Compile-time error)
-
- DEF FN not allowed in control statements
-
- DEF FN function definitions are not permitted inside control constructs
- such as IF...THEN...ELSE and SELECT CASE. (Compile-time error)
-
- DEF without END DEF
-
- There is no corresponding END DEF in a multiline function definition.
- (Compile-time error)
-
- DEFtype character specification illegal
-
- A DEFtype statement is entered incorrectly. DEF can only be followed by
- LNG, DBL, INT, SNG, STR, or (for user-defined functions) a blank space.
- (Compile-time error)
-
- Device fault
-
- A device has returned a hardware error. If this message occurs while data
- are being transmitted to a communications file, it indicates that the
- signals being tested with the OPEN COM statement were not found in the
- specified period of time. (Run-time error)
-
- ERR code: 25
-
- Device I/O error
-
- An I/O error occurred on a device I/O operation. The operating system
- cannot recover from the error. (Run-time error)
-
- ERR code: 57
-
- Device timeout
-
- The program did not receive information from an I/O device within a
- predetermined amount of time. (Run-time error)
-
- ERR code: 24
-
- Device unavailable
-
- The device you are attempting to access is not on line or does not exist.
-
- (Run-time error)
-
- ERR code: 68
-
- Disk full
-
- There is not enough room on the disk for the completion of a PRINT, WRITE,
- or CLOSE operation. This error can also occur if there is not enough room
- for QuickBASIC to write out an object or executable file. (Run-time error)
-
- ERR code: 61
-
- Disk-media error
-
- Disk-drive hardware has detected a physical flaw on the disk. (Run-time
- error)
-
- ERR code: 72
-
- Disk not ready
-
- The disk-drive door is open, or no disk is in the drive. (Run-time error)
-
- ERR code: 71
-
- Division by zero
-
- A division by zero is encountered in an expression, or an exponentiation
- operation results in zero being raised to a negative power. (Compile-time
- or run-time error)
-
- ERR code: 11
-
- DO without LOOP
-
- The terminating LOOP clause is missing from a DO...LOOP statement.
- (Compile-time error)
-
- Document too large
-
- Your document exceeds QuickBASIC's internal limit. Divide the document
- into separate files.
-
- Duplicate definition
-
- You are using an identifier that has already been defined. For example,
- you are attempting to use the same name in a CONST statement and as a
- variable definition, or the same name for a procedure and a variable.
-
- This error also occurs if you attempt to redimension an array. You must
- use DIM or REDIM when redimensioning dynamic arrays. (Compile-time or
- run-time error)
-
- ERR code: 10
-
- Duplicate label
-
- Two program lines are assigned the same number or label. Each line number
- or label in a module must be unique. (Compile-time error)
-
- Dynamic array element illegal
-
- Dynamic array elements are not allowed with VARPTR$. (Compile-time error)
-
- Element not defined
-
- A user-defined type element is referenced but not defined. For example, if
- the user-defined type MYTYPE contained elements A, B, and C, then an
- attempt to use the variable D as an element of MYTYPE would cause this
- message to appear. (Compile-time error)
-
- ELSE without IF
-
- An ELSE clause appears without a corresponding IF. Sometimes this error is
- caused by incorrectly nested IF statements. (Compile-time error)
-
- ELSEIF without IF
-
- An ELSEIF statement appears without a corresponding IF. Sometimes this
- error is caused by incorrectly nested IF statements. (Compile-time error)
-
- END DEF without DEF
-
- An END DEF statement has no corresponding DEF statement. (Compile-time
- error)
-
- END IF without block IF
-
- The beginning of an IF block is missing. (Compile-time error)
-
- END SELECT without SELECT
-
- The end of a SELECT CASE statement appears without a beginning SELECT
- CASE. The beginning of the SELECT CASE statement may be missing or
- misspelled. (Compile-time error)
-
- END SUB or END FUNCTION must be last line in window
-
- You are attempting to add code after a procedure. You must either return
- to the main module or open another module. (Compile-time error)
-
- END SUB/FUNCTION without SUB/FUNCTION
-
- You deleted the SUB or FUNCTION statement. (Compile-time error)
-
- END TYPE without TYPE
-
- An END TYPE statement is used outside a TYPE declaration. (Compile-time
- error)
-
- Equal sign missing
-
- QuickBASIC expects an equal sign. (Compile-time error)
-
- Error during QuickBASIC initialization
-
- Several conditions can cause this error. It is most commonly caused when
- there is not enough memory in the machine to load QuickBASIC. If you are
- loading a Quick library, try reducing the size of the library.
-
- This error may occur when you attempt to use QuickBASIC on unsupported
- hardware. (QB invocation error)
-
- Error in loading file (filename)──Cannot find file
-
- This error occurs when redirecting input to QuickBASIC from a file. The
- input file is not at the location specified on the command line. (QB
- invocation error)
-
- Error in loading file (filename)──Disk I/O error
-
- This error is caused by physical problems accessing the disk, for example,
- if the drive door is left open. (QB invocation error)
-
- Error in loading file (filename)──DOS memory-area error
-
- The area of memory used by DOS has been written to, either by an assembly
- language routine or with the POKE statement. (QB invocation error)
-
- Error in loading file (filename)──Invalid format
-
- You are attempting to load a Quick library that is not in the correct
- format. This error can occur if you are attempting to use a Quick library
- created with a previous version of QuickBASIC, if you are trying to use a
- file that has not been processed with QuickBASIC's Make Library command or
- the /QU option from LINK, or if you are trying to load a stand-alone
- (.LIB) library with QuickBASIC. (QB invocation error)
-
- Error in loading file (filename)──Out of memory
-
- More memory is required than is available. For example, there may not be
- enough memory to allocate a file buffer. Try reducing the size of your DOS
- buffers, getting rid of any terminate-and-stay resident programs, or
- eliminating some device drivers. If you have large arrays, try placing a
- $DYNAMIC metacommand at the top of your program. If you have documents
- loaded, then unloading them will free some memory. (Run-time error)
-
- EXIT DO not within DO...LOOP
-
- An EXIT DO statement is used outside of a DO...LOOP statement.
- (Compile-time error)
-
- EXIT not within FOR...NEXT
-
- An EXIT FOR statement is used outside of a FOR...NEXT statement.
- (Compile-time error)
-
- Expected: item
-
- This is a syntax error. The cursor is positioned at the unexpected item.
- (Compile-time error)
-
- Expression too complex
-
- This error is caused when certain internal limitations are exceeded. For
- example, during expression evaluation, strings that are not associated
- with variables are assigned temporary locations. A large number of such
- strings can cause this error to occur. Try simplifying expressions, and
- assigning strings to variables. (Compile-time error)
-
- Extra file name ignored
-
- You specified too many files on the command line; the last file name on
- the line is ignored. (BC invocation error)
-
- Far heap corrupt
-
- The far-heap memory has been corrupted by one of the following:
-
- ■ The QB compiler does not support a terminate-and-stay-resident program
- resident in DOS.
-
- ■ The POKE statement modified areas of memory used by QuickBASIC. (This
- may modify the descriptor for a dynamic array of numbers or fixed-length
- strings.)
-
- ■ The program called an other-language routine that modified areas of
- memory used by QuickBASIC. (This may modify the descriptor for a dynamic
- array of numbers or fixed-length strings.
-
- (Compile-time error)
-
- FIELD overflow
-
- A FIELD statement is attempting to allocate more bytes than were specified
- for the record length of a random file. (Run-time error)
-
- ERR code: 50
-
- FIELD statement active
-
- A GET or PUT statement referred to a record variable used in a a file with
- space previously allocated by the FIELD statement. GET or PUT with a
- record variable argument may only be used on files where no FIELD
- statements have been executed. (Run-time error)
-
- ERR code: 56
-
- File already exists
-
- The file name specified in a NAME statement is identical to a file name
- already in use on the disk. (Run-time error)
-
- ERR code: 58
-
- File already open
-
- A sequential-output-mode OPEN statement is issued for a file that is
- already open, or a KILL statement is given for a file that is open.
- (Run-time error)
-
- ERR code: 55
-
- File not found
-
- A FILES, KILL, NAME, OPEN or RUN statement references a file that does not
- exist. (Run-time error)
-
- ERR code: 53
-
- File not found in module module-name at address segment:offset
-
- A FILES, KILL, NAME, OPEN or RUN statement references a file that does not
- exist. This error message is equivalent to the File not found message, but
- it occurs during execution of compiled programs. The module-name is the
- name of the calling module. The address is the location of the error in
- the code. (Run-time error)
-
- ERR code: 53
-
- File previously loaded
-
- You are attempting to load a file that is already in memory. (Compile-time
- error)
-
- Fixed-length string illegal
-
- You are attempting to use a fixed-length string as a formal parameter.
- (Compile-time error)
-
- FOR index variable already in use
-
- This error occurs when an index variable is used more than once in nested
- FOR loops. (Compile-time error)
-
- FOR index variable illegal
-
- This error is usually caused when an incorrect variable type is used in a
- FOR-loop index. A FOR-loop index variable must be a simple numeric
- variable. (Compile-time error)
-
- FOR without NEXT
-
- Each FOR statement must have a matching NEXT statement. (Compile-time
- error)
-
- Formal parameter specification illegal
-
- There is an error in a function or subprogram parameter list.
- (Compile-time error)
-
- Formal parameters not unique
-
- A FUNCTION or SUB declaration contains duplicate parameters, as in this
- example: SUB GetName(A,B,C,A) STATIC. (Compile-time error)
-
- Function already defined
-
- This error occurs when a previously defined FUNCTION is redefined.
- (Compile-time error)
-
- Function name illegal
-
- A BASIC reserved word is used as a user-defined FUNCTION name.
- (Compile-time error)
-
- Function not defined
-
- You must declare or define a FUNCTION before using it. (Compile-time
- error)
-
- GOSUB missing
-
- The GOSUB is missing from an ON event statement. (Compile-time error)
-
- GOTO missing
-
- The GOTO is missing from an ON ERROR statement. (Compile-time error)
-
- GOTO or GOSUB expected
-
- QuickBASIC expects a GOTO or GOSUB statement. (Compile-time error)
-
- Help not found
-
- Help was requested but not found, and the program contains errors
- prohibiting QuickBASIC from building a variable table. Press F5 to view
- the line that caused the error.
-
- Identifier cannot end with %, &, !, #, or $
-
- The above suffixes are not allowed in type identifiers, subprogram names,
- or names appearing in COMMON statements. (Compile-time error)
-
- Identifier cannot include period
-
- User-defined type identifier and record element names cannot contain
- periods. The period should only be used as a record variable separator. In
- addition, a variable name cannot contain a period if the part of the name
- before the period has been used in an identifier AS usertype clause
- anywhere in the program. If you have programs that use the period in
- variable names, it is recommended that you change them to use mixed case
- instead. For example, variable ALPHA.BETA would become AlphaBeta.
- (Compile-time error)
-
- Identifier expected
-
- You are attempting to use a number or a BASIC reserved word where an
- identifier is expected. (Compile-time error)
-
- Identifier too long
-
- Identifiers must not be longer than 40 characters. (Compile-time error)
-
- Illegal function call
-
- A parameter that is out of range is passed to a math or string function. A
- function-call error can also occur for the following reasons:
-
- ■ A negative or unreasonably large subscript is used.
-
- ■ A negative number is raised to a power that is not an integer.
-
- ■ A negative record number is given when using GET file or PUT file.
-
- ■ An improper or out-of-range argument is given to a function.
-
- ■ A BLOAD or BSAVE operation is directed to a nondisk device.
-
- ■ An I/O function or statement (LOC or LOF, for example) is performed on a
- device that does not support it.
-
- ■ Strings are concatenated to create a string greater than 32,767
- characters in length.
-
- (Run-time error)
-
- ERR code: 5
-
- Illegal in direct mode
-
- The statement is valid only within a program and cannot be used in the
- Immediate window. (Compile-time error)
-
- Illegal in procedure or DEF FN
-
- The statement is not allowed inside a procedure. (Compile-time error)
-
- Illegal number
-
- The format of the number does not correspond to a valid number format. You
- have probably made a typographical error. For example, the number 2p3 will
- produce this error. (Compile-time error)
-
- Illegal outside of SUB, FUNCTION, or DEF FN
-
- This statement is not allowed in module-level code. (Compile-time error)
-
- Illegal outside of SUB/FUNCTION
-
- The statement is not allowed in module-level code or DEF FN functions.
- (Compile-time error)
-
- Illegal outside of TYPE block
-
- The element AS type clause is permitted only within a TYPE...END TYPE
- block. (Compile-time error)
-
- Illegal type character in numeric constant
-
- A numeric constant contains an inappropriate type-declaration character.
- (Compile-time error)
-
- $INCLUDE-file access error
-
- The include file named in the $INCLUDE metacommand cannot be located.
- (Compile-time error)
-
- Include file too large
-
- Your include file exceeds QuickBASIC's internal limit. Break the file into
- separate files. (Compile-time error)
-
- Input file not found
-
- The source file you gave on the command line is not in the specified
- location. (BC invocation error)
-
- INPUT missing
-
- The compiler expects the keyword INPUT. (Compile-time error)
-
- Input past end of file
-
- An INPUT statement reads from a null (empty) file or from a file in which
- all data have already been read. To avoid this error, use the EOF function
- to detect the end of file. (Run-time error)
-
- ERR code: 62
-
- Input runtime module path:
-
- This prompt appears if the run-time module BRUN45.EXE is not found. Enter
- the correct path specification. This error is severe and cannot be
- trapped. (Run-time error)
-
- Integer between 1 and 32767 required
-
- The statement requires an integer argument. (Compile-time error)
-
- Internal error
-
- An internal malfunction occurred in QuickBASIC. Use the Product Assistance
- Request form included with your documentation to report to Microsoft the
- conditions under which the message appeared. (Run-time error)
-
- ERR code: 51
-
- Internal error near xxxx
-
- An internal malfunction occurred in QuickBASIC at location xxxx. Use the
- Product Assistance Request form included with your documentation to report
- the conditions under which the message appeared. (Compile-time error)
-
- Invalid character
-
- QuickBASIC found an invalid character, such as a control character, in the
- source file. (Compile-time error)
-
- Invalid constant
-
- An invalid expression is used to assign a value to a constant. Remember
- that expressions assigned to constants may contain numeric constants,
- symbolic constants, and any of the arithmetic or logical operators except
- exponentiation. A string expression assigned to a constant may consist
- only of a single literal string. (Compile-time error)
-
- Invalid DECLARE for BASIC procedure
-
- You are attempting to use the DECLARE statement keywords ALIAS, CDECL, or
- BYVAL with a BASIC procedure. ALIAS, CDECL, and BYVAL can only be used
- with non-BASIC procedures. (Compile-time error)
-
- Label not defined
-
- A line label is referenced (in a GOTO statement, for example), but does
- not occur in the program. (Compile-time error)
-
- Label not defined: label
-
- A GOTO linelabel statement refers to a nonexistent line label.
- (Compile-time error)
-
- Left parenthesis missing
-
- QuickBASIC expected a left parenthesis, or a REDIM statement tried to
- reallocate space for a scalar. (Compile-time error)
-
- Line invalid. Start again
-
- An invalid file-name character was used following the path characters "\"
- (backslash) or ":" (colon). (BC invocation error)
-
- Line number or label missing
-
- A line number or label is missing from a statement that requires one, for
- example, GOTO. (Compile-time error)
-
- Line too long
-
- Lines are limited to 255 characters. (Compile-time error)
-
- LOOP without DO
-
- The DO starting a DO...LOOP statement is missing or misspelled.
- (Compile-time error)
-
- Lower bound exceeds upper bound
-
- The lower bound exceeds the upper bound defined in a DIM statement.
- (Compile-time error)
-
- Math overflow
-
- The result of a calculation is too large to be represented in BASIC number
- format. (Compile-time error)
-
- $Metacommand error
-
- A metacommand is incorrect. If you are compiling the program with BC this
- error is not "fatal"; the program will execute, although the results may
- be incorrect. (Compile-time warning)
-
- Minus sign missing
-
- QuickBASIC expects a minus sign. (Compile-time error)
-
- Missing Event Trapping (/W) or Checking Between Statements (/V) option
-
- The program contains an ON event statement requiring one of these options.
- (Compile-time error)
-
- Missing On Error (/E) option
-
- When using the BC command, programs containing ON ERROR statements must be
- compiled with the On Error (/E) option. (Compile-time error)
-
- Missing Resume Next (/X) option
-
- When using the BC command, programs containing RESUME, RESUME NEXT, and
- RESUME 0 statements must be compiled with the Resume Next (/X) option.
- (Compile-time error)
-
- Module level code too large
-
- Your module-level code exceeds QuickBASIC's internal limit. Try moving
- some of the code into SUB or FUNCTION procedures. (Compile-time error)
-
- Module not found. Unload module from program?
-
- When loading the program, QuickBASIC did not find the file containing the
- indicated module. QuickBASIC created an empty module instead. You must
- delete the empty module before you can run the program.
-
- Must be first statement on the line
-
- In block IF...THEN...ELSE constructs, IF, ELSE, ELSEIF, and END IF can be
- preceded only by a line number or label. (Compile-time error)
-
- Name of subprogram illegal
-
- The error is caused when a subprogram name is a BASIC reserved word, or a
- subprogram name is used twice. (Compile-time error)
-
- Nested function definition
-
- A FUNCTION definition appears inside another FUNCTION definition, or
- inside an IF...THEN...ELSE clause. (Compile-time error)
-
- NEXT missing for variable
-
- A FOR statement is missing a corresponding NEXT statement. The variable is
- the FOR-loop index variable. (Compile-time error)
-
- NEXT without FOR
-
- Each NEXT statement must have a matching FOR statement. (Compile-time
- error)
-
- No line number in module-name at address segment:offset
-
- This error occurs when the error address cannot be found in the
- line-number table during error trapping. This happens if there are no
- integer line numbers between 0 and 65,527. It may also occur if the
- line-number table has been accidentally overwritten by the user program.
- This error is severe and cannot be trapped. (Run-time error)
-
- No main module. Choose Set Main Module from the Run menu to select one
-
- You are attempting to run the program after you have unloaded the main
- module. Every program must have a main module. (Compile-time error)
-
- No RESUME
-
- The end of the program was encountered while the program was in an
- error-handling routine. A RESUME statement is needed to remedy this
- situation. (Run-time error)
-
- ERR code: 19
-
- Not watchable
-
- This error occurs when you are specifying a variable in a watch
- expression. Make sure the module or procedure in the active View window
- has access to the variable you want to watch. For example, module-level
- code cannot access variables that are local to a SUB or FUNCTION.
- (Run-time error)
-
- Numeric array illegal
-
- Numeric arrays are not allowed as arguments to VARPTR$. Only simple
- variables and string array elements are permitted. (Compile-time error)
-
- Only simple variables allowed
-
- User-defined types and arrays are not permitted in READ and INPUT
- statements. Array elements that are not of a user-defined type are
- permitted. (Compile-time error)
-
- Operation requires disk
-
- You are attempting to load from, or save to, a nondisk device such as the
- printer or keyboard. (Compile-time error)
-
- Option unknown: option
-
- You have given an illegal option. (BC invocation error)
-
- Out of DATA
-
- A READ statement is executed when there are no DATA statements with unread
- data remaining in the program. (Run-time error)
-
- ERR code: 4
-
- Out of data space
-
- Try modifying your data space requirements as follows:
-
- ■ Use a smaller file buffer in the OPEN statement's LEN clause.
-
- ■ Use the $DYNAMIC metacommand to create dynamic arrays. Dynamic array
- data can usually be much larger than static array data.
-
- ■ Use fixed-length string arrays instead of variable-length string arrays.
-
- ■ Use the smallest data type that will accomplish your task. Use integers
- whenever possible.
-
- ■ Try not to use many small procedures. QuickBASIC must create several
- bytes of control information for each procedure.
-
- ■ Use CLEAR to modify the size of the stack. Use only enough stack space
- to accomplish your task.
-
- ■ Do not use source lines longer than 255 characters. Such lines require
- allocation of additional text buffer space.
-
- (Compile-time or run-time error)
-
- Out of memory
-
- More memory is required than is available. For example, there may not be
- enough memory to allocate a file buffer. Try reducing the size of your DOS
- buffers, or getting rid of any terminate-and-stay-resident programs, or
- eliminating some device drivers. If you have large arrays, try placing a
- $DYNAMIC metacommand at the top of your program. If you have documents
- loaded, unloading them will free some memory. (BC invocation,
- compile-time, or run-time error)
-
- ERR code: 7
-
- Out of paper
-
- The printer is out of paper or is not turned on. (Run-time error)
-
- ERR code: 27
-
- Out of stack space
-
- This error can occur when a recursive FUNCTION procedure nests too deeply,
- or there are too many active subroutine, FUNCTION, and SUB calls. You can
- use the CLEAR statement to increase the program's allotted stack space.
- This error cannot be trapped. (Run-time error)
-
- Out of string space
-
- String variables exceed the allocated amount of string space. (Run-time
- error)
-
- ERR code: 14
-
- Overflow
-
- The result of a calculation is too large to be represented within the
- range allowed for either floating-point or integer numbers. (Run-time
- error)
-
- ERR code: 6
-
- Overflow in numeric constant
-
- The numeric constant is too large. (Compile-time error)
-
- Parameter type mismatch
-
- A subprogram or FUNCTION parameter type does not match the DECLARE
- statement argument or the calling argument. (Compile-time error)
-
- Path not found
-
- During an OPEN, MKDIR, CHDIR, or RMDIR operation, DOS was unable to find
- the path specified. The operation is not completed. (Run-time error)
-
- ERR code: 76
-
- Path/File access error
-
- During an OPEN, MKDIR, CHDIR, or RMDIR operation, DOS was unable to make a
- correct connection between the path and file name. The operation is not
- completed. (Compile-time or run-time error)
-
- ERR code: 75
-
- Permission denied
-
- An attempt was made to write to a write-protected disk, or to access a
- locked file. (Run-time error)
-
- ERR code: 70
-
- Procedure already defined in Quick library
-
- A procedure in the Quick library has the same name as a procedure in your
- program. (Compile-time error)
-
- Procedure too large
-
- The procedure has exceeded QuickBASIC's internal limit. Make the procedure
- smaller by dividing it into several procedures. (Compile-time error)
-
- Program-memory overflow
-
- You are attempting to compile a program whose code segment is larger than
- 64K. Try splitting the program into separate modules, or use the CHAIN
- statement. (Compile-time error)
-
- Read error on standard input
-
- A system error occurred while reading from the console or a redirected
- input file. (BC invocation error)
-
- Record/string assignment required
-
- The string or record variable assignment is missing from the LSET
- statement. (Compile-time error)
-
- Redo from start
-
- You have responded to an INPUT prompt with the wrong number or type of
- items. Retype your response in the correct form. (Run-time error)
-
- Rename across disks
-
- An attempt was made to rename a file with a new drive designation. This is
- not allowed. (Run-time prompt)
-
- ERR code: 74
-
- Requires DOS 2.10 or later
-
- You are attempting to use QuickBASIC with an incorrect version of DOS. (QB
- invocation or run-time error)
-
- RESUME without error
-
- A RESUME statement is encountered before an error-trapping routine is
- entered. (Run-time error)
-
- ERR code: 20
-
- RETURN without GOSUB
-
- A RETURN statement is encountered for which there is no previous,
- unmatched GOSUB statement. (Run-time error)
-
- ERR code: 3
-
- Right parenthesis missing
-
- QuickBASIC expects a right (closing) parenthesis. (Compile-time error)
-
- SEG or BYVAL not allowed in CALLS
-
- BYVAL and SEG are permitted only in a CALL statement. (Compile-time error)
-
- SELECT without END SELECT
-
- The end of a SELECT CASE statement is missing or misspelled. (Compile-time
- error)
-
- Semicolon missing
-
- QuickBASIC expects a semicolon. (Compile-time error)
-
- Separator illegal
-
- There is an illegal delimiting character in a PRINT USING or WRITE
- statement. Use a semicolon or a comma as a delimiter. (Compile-time error)
-
- Simple or array variable expected
-
- The compiler expects a variable argument. (Compile-time error)
-
- Skipping forward to END TYPE statement
-
- An error in the TYPE statement has caused QuickBASIC to ignore everything
- between the TYPE and END TYPE statement. (Compile-time error)
-
- Statement cannot occur within "CLUDE file
-
- SUB...END SUB and FUNCTION...END FUNCTION statement blocks are not
- permitted in include files. Use the Merge command from the File menu to
- insert the include file into the current module, or load the include file
- as a separate module. If you load the include file as a separate module,
- some restructuring may be necessary because shared variables are shared
- only within the scope of the module. (Compile-time error)
-
- Statement cannot precede SUB/FUNCTION definition
-
- The only statements allowed before a procedure definition are the
- statements REM and DEFtype. (Compile-time error)
-
- Statement ignored
-
- You are using the BC command to compile a program that contains TRON and
- TROFF statements without using the /D option. This error is not "fatal" ;
- the program will execute, although the results may be incorrect.
- (Compile-time warning)
-
- Statement illegal in TYPE block
-
- The only statements allowed between the TYPE and END TYPE statements are
- REM and element AS typename. (Compile-time error)
-
- Statement unrecognizable
-
- You have probably mistyped a BASIC statement. (Compile-time error)
-
- Statements/labels illegal between SELECT CASE and CASE
-
- Statements and line labels are not permitted between SELECT CASE and the
- first CASE statement. Comments and statement separators are permitted.
- (Compile-time error)
-
- STOP in module name at address segment:offset
-
- A STOP statement was encountered in the program. (Run-time error)
-
- String assignment required
-
- The string assignment is missing from an RSET statement. (Compile-time
- error)
-
- String constant required for ALIAS
-
- The DECLARE statement ALIAS keyword requires a string-constant argument.
- (Compile-time error)
-
- String expression required
-
- The statement requires a string-expression argument. (Compile-time error)
-
- String formula too complex
-
- Either a string formula is too long or an INPUT statement requests more
- than 15 string variables. Break the formula or INPUT statement into parts
- for correct execution. (Run-time error)
-
- ERR code: 16
-
- String space corrupt
-
- This error occurs when an invalid string in string space is being deleted
- during heap compaction. The probable causes of this error are as follows:
-
- ■ A string descriptor or string back pointer has been improperly modified.
- This may occur if you use an assembly-language subroutine to modify
- strings.
-
- ■ Out-of-range array subscripts are used and string space is inadvertently
- modified. The Produce Debug Code option can be used at compile time to
- check for array subscripts that exceed the array bounds.
-
- ■ Incorrect use of the POKE and/or DEF SEG statements may modify string
- space improperly.
-
- ■ Mismatched COMMON declarations may occur between two chained programs.
-
- (Run-time error)
-
- String variable required
-
- The statement requires a string-variable argument. (Compile-time error)
-
- SUB or FUNCTION missing
-
- A DECLARE statement has no corresponding procedure. (Compile-time error)
-
- SUB/FUNCTION without END SUB/FUNCTION
-
- The terminating statement is missing from a procedure. (Compile-time
- error)
-
- Subprogram error
-
- This is a SUB or FUNCTION definition error and is usually caused by one of
- the following:
-
- ■ The SUB or FUNCTION is already defined.
-
- ■ The program contains incorrectly nested FUNCTION or SUB statements.
-
- ■ The SUB or FUNCTION does not terminate with an END SUB or END FUNCTION
- statement.
-
- (Compile-time error)
-
- Subprogram not defined
-
- A subprogram is called but never defined. (Compile-time error)
-
- Subprograms not allowed in control statements
-
- Subprogram FUNCTION definitions are not permitted inside control
- constructs such as IF...THEN...ELSE and SELECT CASE. (Compile-time error)
-
- Subscript out of range
-
- An array element was referenced with a subscript that was outside the
- dimensions of the array, or an element of an undimensioned dynamic array
- was accessed. This message may be generated if the Debug (/D) option was
- specified at compile time. You may also get this error if the array size
- exceeds 64K, the array is not dynamic, and the /AH option was not used.
- Reduce the size of the array, or make the array dynamic and use the /AH
- command-line option. (Run-time error)
-
- ERR code: 9
-
- Subscript syntax illegal
-
- An array subscript contains a syntax error: for example, an array
- subscript contains both string and integer data types. (Compile-time
- error)
-
- Syntax error
-
- Several conditions can cause this error. The most common cause at compile
- time is a mistyped BASIC keyword or argument. At run-time, it is often
- caused by an improperly formatted DATA statement. (Compile-time or
- run-time error)
-
- ERR code: 2
-
- Syntax error in numeric constant
-
- A numeric constant is not properly formed. (Compile-time error)
-
- THEN missing
-
- QuickBASIC expects a THEN keyword. (Compile-time error)
-
- TO missing
-
- QuickBASIC expects a TO keyword. (Compile-time error)
-
- Too many arguments in function call
-
- Function calls are limited to 60 arguments. (Compile-time error)
-
- Too many dimensions
-
- Arrays are limited to 60 dimensions. (Compile-time error)
-
- Too many files
-
- At compile time, this error occurs when include files are nested more than
- five levels deep. It occurs at run time when the 255-file directory
- maximum is exceeded by an attempt to create a new file with a SAVE or OPEN
- statement. (Compile-time or run-time error)
-
- ERR code: 67
-
- Too many labels
-
- The number of lines in the line list following an ON...GOTOor ON...GOSUB
- statement exceeds 255 (Compile-time error) or 59 (Run-time error in
- compiled applications).
-
- Too many named COMMON blocks
-
- The maximum number of named COMMON blocks permitted is 126. (Compile-time
- error)
-
- Too many TYPE definitions
-
- The maximum number of user-defined types permitted is 240. (Compile-time
- error)
-
- Too many variables for INPUT
-
- An INPUT statement is limited to 60 variables. (Compile-time error)
-
- Too many variables for LINE INPUT
-
- Only one variable is allowed in a LINE INPUT statement. (Compile-time
- error)
-
- Type mismatch
-
- The variable is not of the required type. For example, you are trying to
- use the SWAP statement with a string variable and a numeric variable.
- (Compile-time or run-time error)
-
- ERR code: 13
-
- TYPE missing
-
- The TYPE keyword is missing from an END TYPE statement. (Compile-time
- error)
-
- Type more than 65535 bytes
-
- A user-defined type cannot exceed 64K. (Compile-time error)
-
- Type not defined
-
- The usertype argument to the TYPE statement is not defined. (Compile-time
- error)
-
- TYPE statement improperly nested
-
- User-defined type definitions are not allowed in procedures. (Compile-time
- error)
-
- TYPE without END TYPE
-
- There is no END TYPE statement associated with a TYPE statement.
- (Compile-time error)
-
- Typed variable not allowed in expression
-
- Variables that are user-defined types are not permitted in expressions
- such as CALL ALPHA((X)), where Xis a user-defined type. (Compile-time
- error)
-
- Unexpected end of file in TYPE declaration
-
- There is an end-of-file character inside a TYPE...END TYPE block.
-
- Unprintable error
-
- An error message is not available for the error condition that exists.
- This may be caused by an ERROR statement that doesn't have a defined error
- code. (Run-time error)
-
- Unrecognized switch error: "QU"
-
- You are attempting to create an .EXE file or Quick library with an
- incorrect version of the Microsoft Overlay Linker. You must use the linker
- supplied on the QuickBASIC distribution disks to create an .EXE file or
- Quick library. (Compile-time error)
-
- Valid options: [/RUN] file /AH /B /C:buf /G /NOHI /H /L [lib] /MBF /CMD
- string
-
- This message appears when you invoke QuickBASIC with an invalid option.
- (QB invocation error)
-
- Variable-length string required
-
- Only variable-length strings are permitted in a FIELD statement.
- (Compile-time error)
-
- Variable name not unique
-
- You are attempting to define the variable x as a user-defined type after
- x.y has been used. (Compile-time error)
-
- Variable required
-
- QuickBASIC encountered an INPUT, LET, READ, or SHARED statement without a
- variable argument. (Compile-time error)
-
- Variable required
-
- A GET or PUT statement didn't specify a variable when an operation is
- performed on a file opened in BINARY mode. (Run-time error)
-
- ERR code: 40
-
- WEND without WHILE
-
- This error is caused when a WEND statement has no corresponding WHILE
- statement. (Compile-time error)
-
- WHILE without WEND
-
- This error is caused when a WHILE statement has no corresponding WEND
- statement. (Compile-time error)
-
- Wrong number of dimensions
-
- An array reference contains the wrong number of dimensions. (Compile-time
- error)
-
-
- I.3 LINK Error Messages
-
- This section lists and describes error messages generated by the Microsoft
- Overlay Linker, LINK.
-
- Fatal errors cause the linker to stop execution. Fatal error messages have
- the following format:
-
- location : fatal error L1xxx:messagetext
-
- Nonfatal errors indicate problems in the executable file. LINK produces
- the executable file. Nonfatal error messages have the following format:
-
- location : error L2xxx: messagetext
-
- Warnings indicate possible problems in the executable file. LINK produces
- the executable file. Warnings have the following format:
-
- location : warning L4xxx: messagetext
-
- In these messages, location is the input file associated with the error,
- or LINK if there is no input file.
-
- The following error messages may appear when you link object files with
- LINK:
-
- ╓┌─┌──────────────┌──────────────────────────────────────────────────────────╖
- Number LINK Error Message
- ──────────────────────────────────────────────────────────────────────────
- L1001 option : option name ambiguous
-
- A unique option name did not appear after the option
- indicator (/). For example, the command
-
- LINK /N main;
- Number LINK Error Message
- ──────────────────────────────────────────────────────────────────────────
- LINK /N main;
-
- generates this error, since LINK cannot tell which of the
- three options beginning with the letter "N" was intended.
-
- L1002 option : unrecognized option name
-
- An unrecognized character followed the option indicator
- (/), as in the following example:
-
- LINK /ABCDEF main;
-
- L1003 /QUICKLIB, /EXEPACK incompatible
-
- You specified two options that cannot be used together:
- /QUICKLIB and /EXEPACK.
-
- L1004 option : invalid numeric value
-
- Number LINK Error Message
- ──────────────────────────────────────────────────────────────────────────
- An incorrect value appeared for one of the LINK options.
- For example, a character string was given for an option
- that requires a numeric value.
-
- L1006 option : stack size exceeds 65535 bytes
-
- The value given as a parameter to the /STACKSIZE option
- exceeds the maximum allowed.
-
- L1007 option : interrupt number exceeds 255
-
- For the /OVERLAYINTERRUPT option, a number greater than 255
- was given as a value.
-
- L1008 option : segment limit set too high
-
- The limit on the number of segments allowed was set to
- greater than 3072 using the /SEGMENTS option.
- Number LINK Error Message
- ──────────────────────────────────────────────────────────────────────────
- greater than 3072 using the /SEGMENTS option.
-
- L1009 number : CPARMAXALLOC : illegal value
-
- The number specified in the /CPARMAXALLOC option was not in
- the range 1-65,535.
-
- L1020 no object modules specified
-
- No object-file names were specified to LINK.
-
- L1021 cannot nest response files
-
- A response file occurred within a response file.
-
- L1022 response line too long
-
- A line in a response file was longer than 127 characters.
-
- Number LINK Error Message
- ──────────────────────────────────────────────────────────────────────────
- L1023 terminated by user
-
- You entered CTRL+C or CRTL+BREAK
-
- L1024 nested right parentheses
-
- The contents of an overlay were typed incorrectly on the
- command line.
-
- L1025 nested left parentheses
-
- The contents of an overlay were typed incorrectly on the
- command line.
-
- L1026 unmatched right parenthesis
-
- A right parenthesis was missing from the contents
- specification of an overlay on the command line.
- Number LINK Error Message
- ──────────────────────────────────────────────────────────────────────────
- specification of an overlay on the command line.
-
- L1027 unmatched left parenthesis
-
- A left parenthesis was missing from the contents
- specification of an overlay on the command line.
-
- L1043 relocation table overflow
-
- More than 32,768 long calls, long jumps, or other long
- pointers appeared in the program.
-
- Try replacing long references with short references, where
- possible, and recreate the object module.
-
- L1045 too many TYPDEF records
-
- An object module contained more than 255 TYPDEF records.
- These records describe communal variables. This error can
- Number LINK Error Message
- ──────────────────────────────────────────────────────────────────────────
- These records describe communal variables. This error can
- appear only with programs produced by the Microsoft FORTRAN
- Compiler or other compilers that support communal
- variables. (TYPDEF is a DOS term. It is explained in the
- Microsoft MS-DOS Programmer's Reference and in other
- reference books on DOS.)
-
- L1046 too many external symbols in one module
-
- An object module specified more than the limit of 1023
- external symbols.
-
- Break the module into smaller parts.
-
- L1047 too many group, segment, and class names in one module
-
- The program contained too many group, segment, and class
- names.
-
- Number LINK Error Message
- ──────────────────────────────────────────────────────────────────────────
- Reduce the number of groups, segments, or classes, and
- recreate the object file.
-
- L1048 too many segments in one module
-
- An object module had more than 255 segments.
-
- Split the module or combine segments
-
- L1049 too many segments
-
- The program had more than the maximum number of segments.
- Use the /SEGMENTS option, which has a default value of 128,
- to specify the maximum legal number of segments. The
- default is 128 in the /SEGMENTS option, which specifies the
- maximum legal number.
-
- Relink using the /SEGMENTS option with an appropriate
- Number LINK Error Message
- ──────────────────────────────────────────────────────────────────────────
- Relink using the /SEGMENTS option with an appropriate
- number of segments.
-
- L1050 too many groups in one module
-
- LINK encountered over 21 group definitions (GRPDEF) in a
- single module.
-
- Reduce the number of group definitions or split the module.
- (Group definitions are explained in the Microsoft MS-DOS
- Programmer's Reference and in other reference books on
- DOS.)
-
- L1051 too many groups
-
- The program defined more than 20 groups, not counting
- DGROUP.
-
- Reduce the number of groups.
- Number LINK Error Message
- ──────────────────────────────────────────────────────────────────────────
- Reduce the number of groups.
-
- L1052 too many libraries
-
- An attempt was made to link with more than 32 libraries.
-
- Combine libraries, or use modules that require fewer
- libraries.
-
- L1053 out of memory for symbol table
-
- There is no fixed limit to the size of the symbol table.
- However, it is limited by the amount of available memory.
-
- Combine modules or segments and recreate the object files.
- Eliminate as many public symbols as possible.
-
- L1054 requested segment limit too high
-
- Number LINK Error Message
- ──────────────────────────────────────────────────────────────────────────
- LINK did not have enough memory to allocate tables
- describing the number of segments requested. (The default
- is 128 or the value specified with the /SEGMENTS option.)
-
- Try linking again using the /SEGMENTS option to select a
- smaller number of segments (for example, use 64 if the
- default was used previously), or free some memory by
- eliminating resident programs or shells.
-
- L1056 too many overlays
-
- The program defined more than 63 overlays.
-
- L1057 data record too large
-
- A LEDATA record (in an object module) contained more than
- 1024 bytes of data. This is a translator error. (LEDATA is
- a DOS term, which is explained in the Microsoft MS-DOS
- Number LINK Error Message
- ──────────────────────────────────────────────────────────────────────────
- a DOS term, which is explained in the Microsoft MS-DOS
- Programmer's Reference and in other DOS reference books.)
-
- Note which translator (compiler or assembler) produced the
- incorrect object module and the circumstances. Please
- report this error to Microsoft Corporation using the
- Product Assistance Request form included with the
- documentation.
-
- L1063 out of memory for CodeView information
-
- Too many linked object (".OBJ") files contain debugging
- information. Turn off the Produce Debug Code option in the
- Make EXE file dialog box.
-
- L1070 segment size exceeds 64K
-
- A single segment contained more than 64K of code or data.
-
- Number LINK Error Message
- ──────────────────────────────────────────────────────────────────────────
- Try compiling and linking using the large model.
-
- L1071 segment _TEXT larger than 65520 bytes
-
- This error is likely to occur only in small-model C
- programs, but it can occur when any program with a segment
- named _TEXT is linked using the /DOSSEG option. Small-model
- C programs must reserve code addresses 0 and 1; this range
- is increased to 16 for alignment purposes.
-
- L1072 common area longer than 65536 bytes
-
- The program had more than 64K of communal variables. This
- error occurs only with programs produced by compilers that
- support communal variables.
-
- L1080 cannot open list file
-
- Number LINK Error Message
- ──────────────────────────────────────────────────────────────────────────
- The disk or the root directory was full.
-
- Delete or move files to make space.
-
- L1081 out of space for run file
-
- The disk on which the executable file was being written was
- full.
-
- Free more space on the disk and restart LINK.
-
- L1083 cannot open run file
-
- The disk or the root directory was full.
-
- Delete or move files to make space.
-
- L1084 cannot create temporary file
- Number LINK Error Message
- ──────────────────────────────────────────────────────────────────────────
- L1084 cannot create temporary file
-
- The disk or root directory was full.
-
- Free more space in the directory and restart LINK.
-
- L1085 cannot open temporary file
-
- The disk or the root directory was full.
-
- Delete or move files to make space.
-
- L1086 scratch file missing
-
- An internal error has occurred.
-
- Note the circumstances of the problem and contact Microsoft
- Corporation using the Product Assistance Request form
- included with the documentation.
- Number LINK Error Message
- ──────────────────────────────────────────────────────────────────────────
- included with the documentation.
-
- L1087 unexpected end-of-file on scratch file
-
- The disk with the temporary output file from LINK was
- removed.
-
- L1088 out of space for list file
-
- The disk where the listing file is being written is full.
-
- Free more space on the disk and restart LINK.
-
- L1089 filename : cannot open response file
-
- LINK could not find the specified response file.
-
- This usually indicates a typing error.
-
- Number LINK Error Message
- ──────────────────────────────────────────────────────────────────────────
- L1090 cannot reopen list file
-
- The original disk was not replaced at the prompt.
-
- Restart LINK.
-
- L1091 unexpected end-of-file on library
-
- The disk containing the library probably was removed.
-
- Replace the disk containing the library and run LINK again.
-
- L1093 object not found
-
- One of the object files specified in the input to LINK was
- not found.
-
- Restart LINK and specify the object file.
- Number LINK Error Message
- ──────────────────────────────────────────────────────────────────────────
- Restart LINK and specify the object file.
-
- L1101 invalid object module
-
- One of the object modules was invalid.
-
- If the error persists after recompiling, please contact
- Microsoft Corporation using the Product Assistance Request
- form included with the documentation.
-
- L1102 unexpected end-of-file
-
- An invalid format for a library was encountered.
-
- L1103 attempt to access data outside segment bounds
-
- A data record in an object module specified data extending
- beyond the end of a segment. This is a translator error.
-
- Number LINK Error Message
- ──────────────────────────────────────────────────────────────────────────
- Note which translator (compiler or assembler) produced the
- incorrect object module and the circumstances in which it
- was produced. Please report this error to Microsoft
- Corporation using the Product Assistance Request form
- included with the documentation.
-
- L1104 filename : not valid library
-
- The specified file was not a valid library file. This error
- causes LINK to abort.
-
- L1113 unresolved COMDEF; internal error
-
- Note the circumstances of the failure and contact Microsoft
- Corporation using the Product Assistance Request form
- included with the documentation.
-
- L1114 file not suitable for /EXEPACK; relink without
- Number LINK Error Message
- ──────────────────────────────────────────────────────────────────────────
- L1114 file not suitable for /EXEPACK; relink without
-
- For the linked program, the size of the packed load image
- plus packing overhead was larger than that of the unpacked
- load image.
-
- Relink without the /EXEPACK option.
-
- L1115 /QUICKLIB, overlays incompatible
-
- You specified overlays and used the /QUICKLIB option. These
- cannot be used together.
-
- L2001 fixup(s) without data
-
- A FIXUPP record occurred without a data record immediately
- preceding it. This is probably a compiler error. (See the
- Microsoft MS-DOS Programmer's Reference for more
- information on FIXUPP.)
- Number LINK Error Message
- ──────────────────────────────────────────────────────────────────────────
- information on FIXUPP.)
-
- L2002 fixup overflow near number in frame seg segname target seg
- segname target offset number
-
- The following conditions can cause this error:
-
- ■ A group is larger than 64K.
-
- ■ The program contains an intersegment short jump or
- intersegment short call.
-
- ■ The name of a data item in the program conflicts with the
- name of a library subroutine included in the link.
-
- ■ An EXTRN declaration in an assembly-language source file
- appeared inside the body of a segment, as in the following
- example:
-
- Number LINK Error Message
- ──────────────────────────────────────────────────────────────────────────
- code SEGMENT public 'CODE'
- EXTRN main:far
- start PROC far
- call main
- ret
- start ENDP
- code ENDS
-
- The following construction is preferred:
-
- EXTRN main:far
- code SEGMENT public 'CODE'
- start PROC far
- call main
- ret
- start ENDP
- code ENDS
-
- Number LINK Error Message
- ──────────────────────────────────────────────────────────────────────────
- Revise the source file and recreate the object file. (See
- the Microsoft MS-DOS Programmer's Reference for information
- about frame and target segments.
-
- L2003 intersegment self-relative fixup at offset in segment
- segname
-
- You tried to make a near call or jump to a far entry in
- segment segname at offset.
-
- Change the call or jump to far or make the entry near.
-
- L2004 LOBYTE-type fixup overflow
-
- A LOBYTE fixup generated an address overflow. (See the
- Microsoft MS-DOS Programmer's Reference for more
- information.)
-
- Number LINK Error Message
- ──────────────────────────────────────────────────────────────────────────
- L2005 fixup type unsupported
-
- A fixup type occurred that is not supported by the
- Microsoft linker. This is probably a compiler error.
-
- Note the circumstances of the failure and contact Microsoft
- Corporation using the Product Assistance Request form
- included with the documentation.
-
- L2011 name : NEAR/HUGE conflict
-
- Conflicting NEAR and HUGE attributes were given for a
- communal variable. This error can occur only with programs
- produced by compilers that support communal variables.
-
- L2012 name : array-element size mismatch
-
- A far communal array was declared with two or more
- Number LINK Error Message
- ──────────────────────────────────────────────────────────────────────────
- A far communal array was declared with two or more
- different array-element sizes (for instance, an array was
- declared once as an array of characters and once as an
- array of real numbers). This error occurs only with
- compilers that support far communal arrays.
-
- L2013 LIDATA record too large
-
- A LIDATA record contains more than 512 bytes. This error is
- usually caused by a compiler error.
-
- L2024 name : symbol already defined
-
- LINK has found a public-symbol redefinition. Remove extra
- definition(s).
-
- L2025 name : symbol defined more than once
-
- Remove the extra symbol definition from the object file.
- Number LINK Error Message
- ──────────────────────────────────────────────────────────────────────────
- Remove the extra symbol definition from the object file.
-
- L2029 unresolved externals
-
- One or more symbols were declared to be external in one or
- more modules, but they were not publicly defined in any of
- the modules or libraries. A list of the unresolved external
- references appears after the message, as shown in the
- following example:
-
- unresolved externals
- EXIT in file(s):
- MAIN.OBJ (main.for)
- OPEN in file(s):
- MAIN.OBJ (main.for)
-
- The name that comes before in file(s) is the unresolved
- external symbol. On the next line is a list of object
- modules that have made references to this symbol. This
- Number LINK Error Message
- ──────────────────────────────────────────────────────────────────────────
- modules that have made references to this symbol. This
- message and the list are also written to the map file, if
- one exists.
-
- L2041 stack plus data exceed 64K
-
- The total size of near data and the stack exceeds 64K.
- Reduce the stack size to control the error.
-
- LINK tests for this condition only if the /DOSSEG option is
- enabled. This option is automatically enabled by the
- library startup module.
-
- L2043 Quick library support module missing
-
- You did not specify, or LINK could not find, the object
- module or library required for creating a Quick library. In
- the case of QuickBASIC, the library provided is BQLB45.LIB.
-
- Number LINK Error Message
- ──────────────────────────────────────────────────────────────────────────
- L2044 name : symbol multiply defined, use /NOE
-
- LINK has found a possible public-symbol redefinition. This
- error is often caused by redefining a symbol defined in a
- library.
-
- Relink using the /NOEXTDICTIONARY option.
-
- This error in combination with error L2025 for the same
- symbol indicates a real redefinition error.
-
- L4011 PACKCODE value exceeding 65500 unreliable
-
- Packcode segment sizes that exceed 65,500 bytes may be
- unreliable on the Intel(R) 80286 processor.
-
- L4012 load-high disables EXEPACK
-
- Number LINK Error Message
- ──────────────────────────────────────────────────────────────────────────
- The /HIGH and /EXEPACK options cannot be used at the same
- time.
-
- L4015 /CODEVIEW disables /DSALLOCATE
-
- The /CODEVIEW and /DSALLOCATE options cannot be used at the
- same time.
-
- L4016 /CODEVIEW disables /EXEPACK
-
- The /CODEVIEW and /EXEPACK options cannot be used at the
- same time.
-
- L4020 name : code-segment size exceeds 65500
-
- Code segments of 65,501-65,536 bytes in length may be
- unreliable on the Intel 80286 processor.
-
- Number LINK Error Message
- ──────────────────────────────────────────────────────────────────────────
- L4021 no stack segment
-
- The program did not contain a stack segment defined with
- STACK combine type. This message should not appear for
- modules compiled with Microsoft QuickBASIC, but it could
- appear for an assembly-language module.
-
- Normally, every program should have a stack segment with
- the combine type specified as STACK. You can ignore this
- message if you have a specific reason for not defining a
- stack or for defining one without the STACK combine type.
- Linking with versions of LINK earlier than Version 2.40
- might cause this message, since these linkers search
- libraries only once.
-
- L4031 name : segment declared in more than one group
-
- A segment was declared to be a member of two different
- Number LINK Error Message
- ──────────────────────────────────────────────────────────────────────────
- A segment was declared to be a member of two different
- groups.
-
- Correct the source file and recreate the object files.
-
- L4034 more than 239 overlay segments; extra put in root
-
- The program designates more than 239 segments to go in
- overlays. When this error occurs, segments beginning with
- number 234 are placed in the root, the permanently resident
- portion.
-
- L4045 name of output file is name
-
- The prompt for the run-file field gave an inaccurate
- default because the /QUICKLIB option was not used early
- enough. The output will be a Quick library with the name
- given in the error message.
-
- Number LINK Error Message
- ──────────────────────────────────────────────────────────────────────────
- L4050 too many public symbols for sorting
-
- The number of public symbols exceeds the space available
- for sorting the symbols as requested by the /MAP option.
- The symbols are left unsorted.
-
- L4051 filename : cannot find library
-
- LINK could not find the specified file.
-
- Enter a new file name, a new path specification, or both.
-
- L4053 VM.TMP : illegal file name; ignored
-
- VM.TMP appeared as an object-file name. Rename the file and
- rerun LINK.
-
- L4054 filename : cannot find file
- Number LINK Error Message
- ──────────────────────────────────────────────────────────────────────────
- L4054 filename : cannot find file
-
- LINK could not find the specified file. Enter a new file
- name, a new path specification, or both.
- ──────────────────────────────────────────────────────────────────────────
-
-
-
- I.4 LIB Error Messages
-
- Error messages generated by the Microsoft Library Manager, LIB, have one
- of the following formats:
-
- {filename| LIB} : fatal error U1xxx: messagetext
- {filename| LIB} : error U2xxx: messagetext
- {filename| LIB} : warning U4xxx: messagetext
-
- The message begins with the input-file name (filename), if one exists, or
- with the name of the utility. If possible, LIB prints a warning and
- continues operation. In some cases errors are fatal, and LIB terminates
- processing.
-
- LIB may display the following error messages:
-
-
- Number LIB Error Message
- ──────────────────────────────────────────────────────────────────────────
- U1150 page size too small
-
- The page size of an input library was too small,
- which indicates an invalid input .LIB file.
-
- U1151 syntax error : illegal file specification
-
- A command operator such as a minus sign (-) was
- given without a following module name.
-
- U1152 syntax error : option name missing
-
- A forward slash (/) was given without an option
- after it.
-
- U1153 syntax error : option value missing
-
- The /PAGESIZE option was given without a value
- following it.
-
- U1154 option unknown
-
- An unknown option was given. Currently, LIB
- recognizes only the /PAGESIZE option.
-
- U1155 syntax error : illegal input
-
- The given command did not follow correct LIB
- syntax as specified in Appendix G, "Compiling
- and Linking from DOS."
-
- U1156 syntax error
-
- The given command did not follow correct LIB
- syntax as specified in Appendix G, "Compiling
- and Linking from DOS."
-
- U1157 comma or new line missing
-
- A comma or carriage return was expected in the
- command line but did not appear. This may
- indicate an inappropriately placed comma, as in
- the line that follows:
-
- LIB math.lib,-mod1+mod2;
-
- The line should have been entered as follows:
-
- LIB math.lib -mod1+mod2;
-
- U1158 terminator missing
-
- Either the response to the "Output library"
- prompt or the last line of the response file used
- to start LIB did not end with a carriage return.
-
- U1161 cannot rename old library
-
- LIB could not rename the old library to have a
- .BAK extension because the .BAK version already
- existed with read-only protection.
-
- Change the protection on the old .BAK version.
-
- U1162 cannot reopen library
-
- The old library could not be reopened after it
- was renamed to have a .BAK extension.
-
- U1163 error writing to cross-reference file
-
- The disk or root directory was full.
-
- Delete or move files to make space.
-
- U1170 too many symbols
-
- More than 4609 symbols appeared in the library
- file.
-
- U1171 insufficient memory
-
- LIB did not have enough memory to run.
-
- Remove any shells or resident programs and try
- again, or add more memory.
-
- U1172 no more virtual memory
-
- Note the circumstances of the failure and notify
- Microsoft Corporation using the Product Assistant
- Request form included with the documentation.
-
- U1173 internal failure
-
- Note the circumstances of the failure and notify
- Microsoft Corporation using the Product Assistant
- Request form included with the documentation.
-
- U1174 mark: not allocated
-
- Note the circumstances of the failure and notify
- Microsoft Corporation using the Product
- Assistance Request form included with the
- documentation.
-
- U1175 free: not allocated
-
- Note the circumstances of the failure and notify
- Microsoft Corporation using the Product
- Assistance Request form included with the
- documentation.
-
- U1180 write to extract file failed
-
- The disk or root directory was full.
-
- Delete or move files to make space.
-
- U1181 write to library file failed
-
- The disk or root directory was full.
-
- Delete or move files to make space.
-
- U1182 filename : cannot create extract file
-
- The disk or root directory was full, or the
- specified extract file already existed with
- read-only protection.
-
- Make space on the disk or change the protection
- of the extract file.
-
- U1183 cannot open response file
-
- The response file was not found.
-
- U1184 unexpected end-of-file on command input
-
- An end-of-file character was received prematurely
- in response to a prompt.
-
- U1185 cannot create new library
-
- The disk or root directory was full, or the
- library file already existed with read-only
- protection.
-
- Make space on the disk or change the protection
- of the library file.
-
- U1186 error writing to new library
-
- The disk or root directory was full.
-
- Delete or move files to make space.
-
- U1187 cannot open VM.TMP
-
- The disk or root directory was full.
-
- Delete or move files to make space.
-
- U1188 cannot write to VM
-
- Note the circumstances of the failure and notify
- Microsoft Corporation using the Product
- Assistance Request form.
-
- U1189 cannot read from VM
-
- Note the circumstances of the failure and notify
- Microsoft Corporation using the Product
- Assistance Request form.
-
- U1190 interrupted by user
-
- The user pressed CTRL+C or CTRL+BREAK.
-
- U1200 name : invalid library header
-
- The input library file had an invalid format. It
- was either not a library file, or it had been
- corrupted.
-
- U1203 name : invalid object module near location
-
- The module specified by name was not a valid
- object module.
-
- U2152 filename : cannot create listing
-
- The directory or disk was full, or the
- cross-reference-listing file already existed with
- read-only protection.
-
- Either make space on the disk or change the
- protection of the cross-reference-listing file.
-
- U2155 modulename : module not in library; ignored
-
- The specified module was not found in the input
- library.
-
- U2157 filename : cannot access file
-
- LIB was unable to open the specified file.
-
- U2158 libraryname : invalid library header; file
- ignored
-
- The input library had an incorrect format.
-
- U2159 filename : invalid format hexnumber; file ignored
-
- The signature byte or word hexnumber of the given
- file was not one of the following recognized
- types: Microsoft library, Intel library,
- Microsoft object, or XENIX(R) archive.
-
- U4150 modulename : module redefinition ignored
-
- A module was specified to be added to a library
- but a module with the same name was already in
- the library. Or, a module with the same name was
- found more than once in the library.
-
- U4151 symbol : symbol redefined in module modulename,
- redefinition ignored
-
- The specified symbol was defined in more than one
- module.
-
- U4153 number : page size too small; ignored
-
- The value specified in the /PAGESIZE option was
- less than 16.
-
- U4155 modulename: module not in library
-
- A module to be replaced is not in the library.
- LIB adds the module to the library.
-
- U4156 libraryname : output-library specification
- ignored
-
- An output library was specified in addition to a
- new library name. For example, specifying
-
- LIB new.lib+one.obj,new.lst,new.lib
-
- where new.lib does not already exist causes this
- error.
-
- U4157 Insufficient memory, extended dictionary not
- created.
-
- LIB was unable to create the extended dictionary.
- The library is still valid, but LINK cannot take
- advantage of extended dictionaries to link
- faster.
-
- U4158 Internal error, extended dictionary not created.
-
- LIB was unable to create the extended dictionary.
- The library is still valid, but LINK cannot take
- advantage of extended dictionaries to link
- faster.
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- Index
-
-
- Symbols
-
- #
- (+)
- operator, combining strings
- '
- *
- * (asterisk)
- AS,
- LIB command symbol
- , (comma)
- fields, ending
- variable separator
- $ (dollar sign), string-type suffix
- " (double quotes), ending
- / (forward slash), LINK option character
- (/), LINK option character
- - (minus sign)
- - (minus sign), LIB command symbol
- -* (minus sign-asterisk, LIB
- -+ (minus sign-plus sign), LIB command symbol
- "" (null string)
- + (plus)
- operator, combining strings
- sign, LIB command
- ; (semicolon)
- LIB
- ; (semicolon),
- ; (semicolon), LIB command symbol
- # USING
-
- A
-
- ,A option
- BASICA
- #INCLUDE files
- /A option (BC)
- ABS function
- ABSOLUTE
- Absolute
- ABSOLUTE statement
- access, contrasted with
- after input
- /AH option
- ALIAS, DECLARE
- aliasing
- Aliasing, variable
- all in a module
- allowable
- allowed
- Alphabetizing
- alternative
- among versions
- AND
- operator
- and functions. See individual statement and function names
- FIELD
- GET
- INPUT #
- PUT
- WRITE #
- and GW-BASIC
- AND option
- PUT
- and replacing
- Angle measurements
- Animate mode
- Animation
- GET and PUT
- graphics statements, simple
- image flicker,
- PALETTE USING
- screen pages
- Apostrophe (')
- entering
- introducing comments
- (apostrophe), introducing comments
- Arc
- Arctangent,
- Arguments
- correct type and number, checking for
- LINK options
- parameters
- agreement
- distinguished from
- passing
- by
- by value
- described
- limits on
- SUB procedures,
- arguments by reference
- Array-bound
- Array-bound functions
- Arrays
- dynamic
- ERASE
- REDIM statement
- elements, passing
- format
- argument list
- FUNCTION statement
- parameter
- parameter list
- SHARED statement
- SUB statement
- LBOUND function
- limits (table)
- lower-bound function
- memory allocation
- procedures
- passing
- passing to
- sharing
- row-order option
- static, ERASE statement
- subscripts,
- subscripts, specifying
- lower
- UBOUND (upper-bound) function
- variables
- arrays
- limits
- Arrow keys. See DIRECTION keys
- ASC function
- ASCII
- character
- character codes
- CHR$
- determining
- (table)
- files, reading as sequential
- Aspect ratio
- CIRCLE
- correction for
- defined
- screen size, computing for
- squares,
- Assembly-language listings
- Assignment statements
- (asterisk)
- AS, fixed-length string with
- Asterisk (*)
- fixed-length
- Asterisk (*)
- ATN function
- attribute
- described
- DIM
- described
- sharing
- REDIM
- variables, making global
- Attributes
- colors, assigning
- screen
- screen modes, EGA and VGA
- STATIC
- attributes. See Attributes
- automatic
- Automatic
- Automatic variables
- AUX (device name)
-
- B
-
- Background color default
- Background music
- .BAS file, execution by QuickBASIC
- BASIC
- error codes
- reserved words
- run-time errors
- BASIC, compatibility
- BASICA
- compatibility
- QuickBASIC, converting to
- /BATCH option (LINK)
- Batch file, when to use
- Baud rate
- BC command
- options
- /V
- BC
- BC command
- command line, invoking from
- file-name usage
- options
- /A
- /AH
- /C
- /D
- /E
- (list)
- /MBF
- new (table)
- not used (table)
- /O
- /R
- /S
- /V
- /W
- /X
- /ZD
- /ZI
- versions, differences among
- BC.EXE
- BEEP statement
- Binary
- file access
- OPEN statement syntax
- random
- versions, differences among
- input
- numbers, converting to hexadecimal
- Binary, differences from
- Binary format
- IEEE format, differences from
- Binary-access
- Binary-access files
- creating
- opening
- reading
- writing to
- Bit
- Bitwise operators. See Logical operators
- Blank COMMON block
- BLOAD statement
- block
- Block IF...THEN...ELSE
- Bold text, indicating keywords
- B_OnExit routine
- Boolean
- constants
- expressions
- definition
- logical operators
- other
- relational operators (table)
- bound
- bound for
- Boxes,
- Boxes, LINE statement
- BRUN40.LIB, default for linker
- BSAVE statement
- buffer
- BUILDLIB utility
- by QuickBASIC
- by value
- defined
-
- C
-
- /C option (BC)
- CALL
- CALL ABSOLUTE
- CALL INT86OLD statement
- CALL INT86XOLD statement
- CALL INTERRUPT
- CALL INTERRUPT statement
- CALL INTERRUPTX statement
- CALL statement
- DECLARE, used with
- described
- optional
- QuickBASIC/interpreter differences
- SUB procedure, calling
- calls
- CALLS statement
- CALLS statement (non-BASIC)
- Carriage-return-line-feed
- Cartesian coordinates. See View coordinates
- Case
- sensitivity
- significance,
- CASE clause. See SELECT CASE statement
- CASE$ function
- CDBL function
- CDECL, use in DECLARE statement
- CGA
- palette, changing
- screen modes supported by
- CHAIN
- CHAIN statement
- described
- QuickBASIC/interpreter differences
- Chaining programs,
- Chaining programs, statements used. See individual
- changing number of
- changing with
- Characters
- how stored
- limits
- CHDIR statement
- Checking between statements option
- Choosing
- commands,
- options, differences among versions
- CHR$ function
- CINT function
- CIRCLE
- CIRCLE statement
- arcs
- circles
- described
- ellipses
- pie shapes
- Circles, drawing
- clause
- CLEAR
- CLEAR statement
- CLNG function
- CLOSE statement
- CLS statement
- /CODEVIEW option (LINK)
- codes
- determining with the ASC function
- storing characters in memory
- CodeView
- COLOR
- Color
- Color Graphics Adapter. See CGA
- COLOR statement
- background color, controlling
- described
- foreground color, controlling
- palette, changing with
- screen mode 1, syntax in
- Colors
- background,
- CGA, using with
- clarity, tradeoff with
- foreground,
- foreground, controlling
- graphics statements, specifying in
- PALETTE
- PALETTE,
- Columns
- changing
- skipping
- COM
- COM devices
- COM statements
- Comma (,)
- ending fields
- variable separator
- command
- option
- /MBF
- /RUN option
- COMMAND$
- command, DRAW
- COMMAND$ function
- limits
- Command line
- BASIC program passing to
- Quick
- command line
- command symbol
- command-line
- Commands
- BC. See BC command
- Linker. See LINK
- versions,
- commands
- Commands QB. See QB command
- Comments
- REM statement
- Comments, introducing with apostrophe
- COMMON
- COMMON block
- blank
- named
- COMMON statement
- AS clause
- chaining programs
- QuickBASIC/interpreter differences
- SHARED
- SHARED attribute
- defined
- described
- variables, sharing across
- variables,
- compared with
- Comparing
- Comparing strings
- relational operators, with
- Compatibility
- BASICA
- versions,
- compatibility among
- Compile options
- Compile-time error messages
- Compiling from DOS
- Complex numbers, defined
- CON (device name)
- Concatenation, defined
- CONS
- CONST statement
- Constants
- input list
- procedures, passing to
- string, literal and symbolic
- symbolic
- constants
- format in program examples
- string
- contrasted with
- Control-flow
- Control-flow statements. See individual
- CALL
- CALL ABSOLUTE
- CALLS
- CHAIN
- DO...LOOP
- FUNCTION
- GOSUB...RETURN
- GOTO
- IF...THEN...ELSE
- ON GOTO
- ON...GOTO
- RETURN
- SELECT CASE
- Control-flow structures
- BASIC, used in (table)
- decision
- defined
- indenting
- new
- Controlling
- linker
- segments
- stack size
- controlling
- conventions
- BASIC programs
- Converting
- BASICA and GW-BASIC programs
- data
- IEEE format, program for
- converting to QuickBASIC
- Coordinates
- absolute
- STEP, specifying
- VIEW SCREEN, specifying
- physical
- GET
- pixels,
- view
- pixels, locating
- relative
- defined
- STEP
- VIEW
- view
- GET statement
- physical coordinates, translating
- WINDOW,
- viewport,
- coordinates. See Coordinates, absolute
- WINDOW statement
- coordinates, translating to
- COS
- (/CP)
- /CPARMAXALLOC option (LINK)
- creating outside QuickBASIC environment
- Cross-reference-file
- CSNG function
- CSRLIN function
- Cursor
- graphics
- text
- defined
- LOCATE, positioning
- location, finding
- shape, changing
- cursor
- CVD function
- CVDMBF
- CVDMBF function
- CVI function
- CVL
- CVL function
- CVS
- CVSMBF function
- CVtype statement
-
- D
-
- /D option (BC)
- Data
- Data files
- closing
- creating
- defined
- file numbers
- file-access errors,
- opening
- organization
- random-access
- reading
- records, adding
- sequential
- data, preventing
- DATA statement
- Data types
- TYPE statement
- Data-file buffer
- DATE$
- Date and time
- functions
- DATE$
- TIME$
- statements
- DATE$
- TIME$
- DATE$ statement
- Debug option
- debugger, debugging with
- debugger, LINK option for
- Debugging
- /CODEVIEW (LINK) option
- statements
- versions, differences among
- Decision
- Decision structures
- defined
- IF...THEN...ELSE
- block
- single-line
- SELECT CASE
- Declarations. See individual statement names
- CONST
- DECLARE statement (BASIC procedures)
- DECLARE statement (non-BASIC
- DEFtype
- DIM statement
- DECLARE
- DECLARE statement
- described
- include
- QuickBASIC,
- versions, differences among
- where required
- Declaring arrays
- limits
- DEF FN functions
- exit from, alternative
- FUNCTION procedure, contrasted with
- local
- DEF FN statement
- DEF SEG statement
- DEFDBL statement
- defining with
- definitions
- DEFINT statement
- DEFLNG statement
- DEFSNG statement
- DEFSTR
- DEFtype
- QuickBASIC/interpreter differences
- DEFtype
- Degrees
- compared with
- converting to radians
- deleting from, including, and replacing
- Device I/O, contrasted with file I/O
- (device name)
- Devices
- COM
- CONS
- function
- function handling
- IOCTL$
- PEN
- I/O modes, valid
- KEYBD
- LPT
- names
- SCRN
- statement handling
- IOCTL
- OPEN
- OUT
- WAIT
- Device-status information
- differences among
- Differences among versions
- file compatibility
- (table)
- differences among versions
- DIM
- DIM statement
- AS
- described
- QuickBASIC/interpreter differences
- SHARED attribute
- defined
- example,
- variables,
- TO clause
- Dimensioning
- DIRECTION
- keys, trapping
- Directory
- Directory statements
- CHDIR
- FILES
- MKDIR
- RMDIR
- Display memory, PCOPY statement
- displaying
- DO UNTIL statement
- DO WHILE statement
- Document conventions
- Dollar
- DO...LOOP
- DO...LOOP statement
- described
- exit from,
- exit from, alternative
- keyword
- UNTIL
- WHILE
- loop test, location of
- syntax
- WHILE...WEND,
- DOS
- DOS-level
- option (LINK)
- /DOSSEG
- Dotted lines, drawing
- Double quotes ("), ending fields
- Double-precision
- Double-precision numbers
- size limits
- DRAW statement
- described
- figures
- rotating
- scaling
- macro commands in
- QuickBASIC/interpreter differences
- VARPTR$
- drawing
- Dumb terminal, defined
- Dummy arguments, POS function
- #DYNAMIC metacommand
- Dynamic arrays
- #DYNAMIC metacommand
- ERASE
- REDIM
-
- E
-
- /E option
- BC
- QB
- /E option
- BC
- Editing, differences
- EGA, changing palette
- elements
- Ellipses, drawing
- ELSE clause
- ELSEIF clause
- END
- END DEF
- END FUNCTION statement
- END IF statement
- END SELECT
- END statement
- END SUB statement
- END TYPE statement
- End-of-line markers
- Enhanced Graphics Adapter. See EGA
- key, equivalent to SPACEBAR
- ENTER
- ENVIRON$ function
- ENVIRON statement
- environment variable
- Environment variables
- described
- LIB
- LINK
- TMP, used by LINK
- Environment-string
- EOF
- EOF function
- EQV
- ERASE statement
- Erasing
- ERDEV$
- ERDEV$ function
- ERL function
- ERR
- code
- function
- ERR
- ERRDEV function
- ERRDEV$ function
- Error
- Error codes
- Error messages
- compile-time
- described
- invocation
- LIB
- LINK
- numbers, limits (table)
- redirection
- run-time
- ERROR statement
- Error trapping
- ERR, identifying errors with
- ERROR statement
- error-handling routine
- file-access errors
- multiple modules
- Quick libraries
- screen modes, inappropriate
- SUB or FUNCTION procedures
- syntax,
- Error-handling
- Error-handling routines
- parts
- specifying
- Error-handling statements
- ERDEV
- ERR, ERL
- Error-message window
- event
- Event polling, event trapping, contrasted with
- Event trapping. See specific
- activating
- background music
- described
- disabling
- keystrokes
- multiple modules
- options,
- polling, contrasted with
- routines, event-handling
- statements and functions, summary of (table)
- SUB
- suspending
- syntax, error-trapping
- trappable events
- types
- types of
- COM
- KEY
- PEN
- PLAY
- TIMER
- event trapping
- PLAY ON statement
- Event trapping, Quick library
- Event-handling
- Event-handling routine
- Event-trapping
- Event-trapping option
- Event-trapping statements. See individual
- COM
- KEY LIST
- KEY OFF
- ON
- ON event
- PEN ON, OFF, and STOP
- PLAY ON, OFF, and STOP
- TIMER ON, OFF, and STOP
- UEVENT
- event-trapping syntax, contrasted with
- examples
- Executable
- /EXEPACK option (LINK)
- EXIT
- EXIT DEF statement
- EXIT DO statement
- EXIT FOR statement
- EXIT FUNCTION statement
- EXIT statement
- EXIT SUB statement
- Exiting, functions and procedures
- EXP function
- Expressions
- Boolean
- false
- lists
- procedures, passing to
- true
- expressions, comparing with
- Expressions, string. See Strings
- Extensions, file-name
- Extra files produced
- extracting and deleting
-
- F
-
- Factorial function
- False expressions
- FIELD
- FIELD statement
- described
- random-access
- TYPE...END
- Fields
- defined
- records
- random-access
- sequential
- sequential files, delimited
- fields
- fields, delimiting
- figures with DRAW
- File
- names
- characters,
- OPEN statement
- numbers
- CLOSE, freeing with
- FREEFILE, getting with
- freeing
- OPEN statement
- values, allowable
- pointers
- file
- LIB
- File
- File access
- LOCK statement
- UNLOCK
- UNLOCK statement
- File conversion
- File handling. See statements;individual statement names
- functions
- EOF
- FILEATTR
- FREEFILE
- LOC
- LOF
- SEEK
- statements
- CHDIR
- CLOSE
- FIELD
- GET
- INPUT #
- KILL
- LOCK
- NAME
- OPEN
- RESET
- SEEK
- File I/O
- defined
- device I/O contrasted
- File names
- case sensitivity
- described
- restrictions
- truncation
- file, temporary
- File-access
- File-access modes
- APPEND
- BINARY
- INPUT
- OUTPUT
- RANDOM
- FILEATTR function
- File-name extensions
- File-naming
- File-naming conventions
- BC command
- DOS
- LINK
- Quick libraries
- Files
- ASCII format
- attributes
- extra, produced by QuickBASIC
- #INCLUDE
- length,
- limits (table)
- map
- map (LINK)
- random-access,
- random-access, statements
- random-access, statements and functions. See individual statement and
- function names
- sequential,
- sequential, statements and functions. See individual
- INPUT
- WRITE
- versions,
- files
- adding to
- advantages of
- appending
- compact
- creating
- format
- number storage
- opening
- packing
- random-access files, contrasted with
- records
- statements and functions
- FIELD
- PRINT #
- PUT
- RSET
- statements not allowed
- FILES
- files, closing
- files, contrasted with
- files (LINK)
- files, placing in
- FILES statement
- Filling. See Painting
- filling
- FIX function
- fixed-length string with
- Fixed-length strings
- parameter lists
- record
- variable length, contrasted with
- variables, stand-alone
- Floating-point
- precision, within Quick libraries
- FOR statement
- Foreground color
- default
- screen mode 1
- form
- format
- numbers
- converting from
- Formatting text output
- FOR...NEXT
- FOR...NEXT loops
- described
- execution,
- exit from, alternative
- STEP keyword
- FOR...NEXT statement
- Forward reference problem
- Forward reference problem, DECLARE,
- Forward slash
- Fractal
- FRE function
- FRE statement
- FREEFILE
- FREEFILE function
- from, alternative
- FUNCTION
- function
- function
- data, reading
- files
- described
- DRAW, use with
- PLAY, use with
- FUNCTION
- function, arguments to
- function (cosine)
- Function keys, trapping
- function name
- function name
- function names
- FUNCTION procedures
- calling
- DECLARE statements
- described
- error
- event trapping
- FUNCTION statement
- AS
- described
- include files,
- include files, restrictions with
- function, using
- FUNCTION...END FUNCTION statements. See FUNCTION procedures
- Functions. See individual
- user defined
- functions
- CDBL
- CVL
- INPUT$
- INT
- SIN
-
- G
-
- GET
- GET statement
- described
- file I/O
- binary-access
- random-access
- graphics
- array, calculating size of
- syntax
- records, user-defined
- Global variables
- DEF FN function
- FUNCTION procedure
- GOSUB routine
- SHARED attribute
- variable aliasing
- GOSUB
- GOSUB, contrasted with
- GOSUB statement
- GOSUB subroutines
- SUB procedures,
- GOTO statement
- described
- #INCLUDE metacommand
- Graphics. See statements;individual statement names
- functions. See individual statement names
- PALETTE
- PMAP
- POINT
- VIEW
- WINDOW
- statements
- BLOAD
- BSAVE
- CIRCLE
- COLOR
- DRAW
- GET
- LINE
- PAINT
- PALETTE
- PALETTE
- PRESET
- PSET
- PUT
- VIEW
- WINDOW
- graphics
- Graphics Adapter), changing palette
- Graphics cursor. See Cursor, graphics
- Graphics screen modes. See Screen modes
- graphics statement, with
- Graphics statements and functions, summary (table)
- Graphics viewport. See Viewport,
- GW-BASIC
-
- H
-
- /H option (QB)
- handling
- functions. See individual function names
- LPOS
- statements. See individual statement names
- UNLOCK
- /HELP option (LINK)
- HEX$ function
- Hexadecimal
- High-resolution-display
-
- I
-
- IEEE
- IEEE format
- accuracy
- converting to
- /MBF
- numbers
- converting
- exponential,
- Microsoft
- printing
- ranges
- IF...THEN...ELSE
- IF...THEN...ELSE statement
- described
- SELECT CASE
- IF...THEN...ELSE statement, block
- IF...THEN...ELSE statement, block form
- (IGN)
- /IGNORECASE option (LIB)
- Ignore case
- LIB
- LINK
- ignoring
- Images
- GET, saving to memory with
- PUT, copying to screen with
- Immediate window, limits
- IMP operator
- in
- in map files
- #INCLUDE metacommand
- COMMON
- description
- procedure declarations
- restrictions
- Include
- Include files
- COMMON
- procedures
- declaring
- not allowed
- /INFORMATION option (LINK)
- INKEY$ function
- INP function
- INPUT
- input
- reading
- INPUT
- INPUT #
- INPUT$
- Input
- INPUT$ function
- data, reading
- communications device
- standard input
- described
- example
- INPUT #, contrasted with
- LINE INPUT #, contrasted with
- modem, communicating with
- Input functions. See individual
- COMMAND$
- INKEY$
- INP
- Input past end error
- INPUT # statement
- described
- example
- INPUT$,
- LINE INPUT #, contrasted with
- INPUT statement
- carriage-return-line-feed sequence, suppressing
- defined
- described
- error
- example
- LINE INPUT,
- variable
- Input statements. See individual
- DATA
- INPUT
- LINE
- READ
- RESTORE
- Input/Output. See I/O
- Insert mode, differences
- INSTR function
- INT function
- INT86, INT86X replacements
- CALL
- CALL INT86OLD statements
- INT86OLD
- Integers
- converting
- converting to
- FIX function
- limits, (table)
- Interpreted
- INTERRUPT
- Interrupt
- INTERRUPT statements
- Invocation error
- I/O
- binary-access
- defined
- devices, from and to
- files, from and to
- ports
- standard
- IOCTL$ function
- IOCTL statement
- Italic text, showing placeholders
- items
-
- J
-
- Joysticks
-
- K
-
- Key
- KEY LIST
- KEY OFF statement
- KEY ON statement
- KEY statement
- Key trapping
- activating
- keys
- DIRECTION
- user-defined
- key trapping
- KEYBD
- Keyboard, reading input from
- Keyboard scan codes
- KEY(n) statements
- Keys
- debugging, differences among versions
- DIRECTION,
- editing, differences among versions
- ENTER
- SPACEBAR
- Keywords, format in program examples
- KILL statement
-
- L
-
- (QB)
- /L option
- Labels
- Language differences among
- Last
- Last point referenced
- LBOUND function
- LCASE$
- LCASE$ function
- leading blank
- LEFT$
- LEFT$ function
- LEN
- LEN function
- described
- sample
- sample program application
- use of
- LET statement
- letters
- file names
- .LIB files. See Libraries, stand-alone
- LIB
- case sensitivity
- command
- command symbols
- plus
- plus sign (+)
- default responses
- described
- invoking
- libraries, combining
- library
- library modules
- listing files
- options
- case sensitivity
- dictionary, no extended
- /IGNORECASE (/P)
- /NOEXTDICTIONARY
- /NOIGNORECASE
- page size, specifying
- /PAGESIZE
- response file
- search path
- LIB command symbol
- LIB error messages
- LIB.EXE
- Libraries. See Quick libraries
- default,
- default, ignoring
- described
- LINK, specifying for
- search
- stand-alone
- combining
- defined
- described
- LIB
- listing
- modules,
- object
- object modules,
- object modules, deleting from, including,
- parallel
- types, contrasted
- user.
- libraries. See Quick Libraries
- CALL INT86OLD statement
- compatibility among versions
- compilation
- contents
- described
- use of
- libraries, creating
- library, creating from
- Library Manager. See LIB
- Limits, file size and complexity (table)
- /LINENUMBERS option (LINK)
- Line
- LINE INPUT
- LINE INPUT # statement
- described
- INPUT #, contrasted
- INPUT$, contrasted
- LINE INPUT statement
- described
- Line printer
- LINE statement
- coordinate pairs, order of
- described
- lines and boxes, drawing
- sample applications
- syntax
- Lines, drawing
- (LINK)
- LINK. See Libraries
- command line, invoking from
- defaults
- libraries, specifying
- options
- abbreviations
- arguments, numerical
- /BATCH (/B)
- BC, unsuitable for
- case sensitivity
- CodeView
- /CODEVIEW (/CO)
- command line, order
- /CPARMAXALLOC
- default libraries, ignoring
- displaying
- /DOSSEG (/DO)
- /EXEPACK (/E)
- /HELP (/HE)
- /IGNORECASE
- information,
- /INFORMATION (/I)
- line
- /LINENUMBERS (/LI)
- LINK
- linker
- map
- /MAP (/M)
- /NODEFAULTLIBRARYSEARCH
- /NOIGNORECASE
- /NOPACKCODE (/NOP)
- /PACKCODE (/PAC)
- paragraph space, allocating
- /PAUSE
- pausing
- Quick
- /QUICKLIB (/Q)
- segments
- /SEGMENTS
- segments,
- stack
- /STACK (/ST)
- output
- output file, temporary
- Quick libraries, other language routines
- response file
- LINK environment variable
- LINK error messages
- LINK options
- Linker. See LINK
- LINK.EXE
- Linking. See LINK
- Linking from DOS
- list
- list, format of
- listing
- Listing files, cross-reference (LIB)
- Literal constants,
- Loading Quick libraries
- LOC function
- described
- devices, with
- modem, communicating with
- SEEK,
- local
- Local variables
- LOCATE statement
- cursor
- changing
- positioning
- described
- example
- locating
- LOCK statement
- LOF
- LOF function
- described
- devices
- example
- files
- LOG function
- Logical
- Logical coordinates
- physical coordinates,
- Logical operators
- Long integers
- advantages of
- converting
- converting to
- limits (table)
- Looping
- Looping structures
- defined
- DO...LOOP
- WHILE...WEND
- loops
- nesting
- Lowercase
- Lowercase letters
- uppercase, converting to
- LPOS function
- LPRINT statement, SPC function
- LPRINT USING statement
- LPT devices
- LSET
- LSET statement
- .LST files. See Listing files
- LTRIM$ function
- blanks, leading, printing numbers without
- described
- spaces, leading, stripping
- spaces, leading, stripping
-
- M
-
- Macro
- Main module
- libraries, use with
- .MAK files, Quick
- Make Library command
- making global
- Mandelbrot set
- .MAP files. See Map files
- /MAP option (LINK)
- Map
- Map files
- Map files (LINK)
- mapping to
- Math functions
- ABS
- ATN
- COS
- CVSMBF
- EXP
- LOG
- MKSMBF$, MKDMBF$
- SIN
- SQR
- TAN
- /MBF option
- BC
- QB
- option, using with old programs
- Memory
- available, calculating
- requirements, Quick libraries
- Memory functions
- Memory management
- functions. See individual
- FRE
- SETMEM
- statements
- CLEAR
- DEF
- ERASE
- individual
- PCOPY
- Menu commands, differences among versions
- message, invalid-input
- messages
- Metacommands
- described
- #DYNAMIC
- #INCLUDE See also #INCLUDE metacommand
- #STATIC
- Microsoft
- Microsoft Binary format
- numbers
- Microsoft Library Manager. See LIB
- MID$
- function
- MID$
- MID$ function
- MID$ statement
- Minimize String Data option
- Mixed-language
- Mixed-language programming
- ALIAS, use of
- CALL,
- CDECL,
- DECLARE
- Quick libraries
- MKD$ function
- MKDIR statement
- MKDMBF$ function
- MKI$ function
- MKL$
- MKS$ function
- MKSMBF$ function
- MKtype statement
- MKtype$ statement
- MKtypeMBF$ statement
- mode 1
- Modem, communicating with
- modes
- BINARY
- INPUT
- OUTPUT
- modes, EGA and VGA
- Module-level code
- Modules. See Multiple
- modules
- event trapping
- modules
- modules, deleting from, including, and replacing
- monochrome
- Monochrome screen mode
- Moving images with PUT
- Multiple
- Multiple modules
- advantages
- error
- error trapping
- event trapping
- loading
- main module
- programming style
- Quick libraries
- size limits (table)
- variables,
- variables, sharing
- versions, differences among
- Music
- background
- statements
- Music
- Music event trapping
- ON PLAY GOSUB statement
- music option
-
- N
-
- NAME statement
- Named COMMON
- Named COMMON block
- names
- Names, devices
- nclude files
- nesting limits (table)
- New line. See Carriage-return-line-feed sequence
- NEXT statement
- No extended dictionary, library
- NOCOM.OBJ file
- (/NOD)
- /NODEFAULTLIBRARYSEARCH option (LINK)
- /NOEXTDICTIONARY option (LIB)
- (/NOI)
- /NOIGNORECASE option (LIB)
- /NOIGNORECASE option (LINK)
- non-BASIC procedures
- /NOPACKCODE option (LINK)
- NOT
- not generated by
- NOT operator
- notation
- placeholders
- Notational
- NUL (device name)
- Null
- NUL.MAP file
- number, displaying
- number of on screen
- Numbers
- positive, printing without leading blank
- random-access files, storage in
- screen,
- screen, printing on
- strings, representing as
- numbers
- converting to
- Numeric
- Numeric conversions
- CVD
- CVI
- CVL function
- CVS function
- double-precision
- integer
- single-precision
- Numeric functions. See individual function names
- CINT
- CLNG
- CSNG
- CVD
- CVI
- CVS
- FIX
- RND
- SGN
-
- O
-
- /O option (BC)
- Object
- files
- modules
- OCT$ function
- Octal conversion
- of
- STRIG
- of, printing
- on
- ON
- ON COM statement
- ON ERROR
- ON ERROR GOTO statement
- described
- example
- syntax
- ON event
- ON event GOSUB statements
- ON event statements
- ON expression statement
- ON PEN statement
- ON PLAY GOSUB statement
- ON PLAY statement
- ON statement
- ON STRIG
- ON TIMER statement
- ON UEVENT statement
- ON...GOSUB statement
- ON...GOTO statement
- OPEN
- OPEN COM statement
- OPEN statement
- described
- file names in
- file-access
- file-access modes
- APPEND
- INPUT
- OUTPUT
- LEN
- opening for I/O
- operator
- Operators
- logical
- relational
- relational,
- operators
- string comparisons
- option
- OPTION BASE statement
- option (QB)
- option required
- Options, BC. See BC command
- Options, LIB. See LIB
- Options, LINK. See LINK
- or FUNCTION procedures, within
- OR operator
- ordering
- OUT statement
- Output. See statements;individual function names
- functions. See individual function names
- LPOS
- POS
- TAB
- line
- statements
- BEEP
- CLS
- LPRINT
- OUT
- PRINT
- PRINT
- PRINT #
- PRINT USING
- PUT
- WRITE
- WRITE #
- Overlay linker. See LINK
- Overtype mode, differences among versions
-
- P
-
- (/P)
- /PACKCODE option (LINK)
- /PAGESIZE option (LIB)
- Page size, library
- Pages. See Screen
- pages
- pages
- PAINT
- PAINT statement
- argument
- background
- border
- described
- numeric expression
- shapes, filling
- colored
- patterned
- string expression
- tiling
- monochrome, defining
- multicolor, defining
- Painting
- colors
- exterior
- interior
- patterns,
- patterns
- described
- multicolor
- PALETTE
- PALETTE statement
- PALETTE USING statement
- Palettes
- COLOR, changing with
- PALETTE, changing with
- screen
- Paragraph space
- Parameter list, defined
- Parameters
- arguments
- agreement with
- distinguished from
- DECLARE, format in
- number and
- Passing
- Passing by reference
- Passing by value
- DEF FN, used in
- passing to
- path
- Path names, limits (table)
- Pattern tiles, editing on screen
- Patterns
- monochrome
- multicolor
- shapes,
- tile size
- (/PAU)
- /PAUSE option (LINK)
- pausing
- Pausing program execution, FOR...NEXT statement
- PCOPY
- PCOPY statement
- PEEK function
- PEN function
- PEN OFF statement
- PEN ON statement
- PEN STOP
- Peripheral devices
- Physical coordinates
- Pie shapes, drawing
- Pixels
- coordinates, locating with
- defined
- PRESET,
- PSET, plotting with
- text
- Place markers, limits (table)
- planes
- PLAY
- PLAY function
- PLAY OFF statement
- PLAY statement
- background
- described
- QuickBASIC/interpreter differences
- VARPTR$ function, using
- PLAY STOP
- plotting with
- Plus
- Plus (+)
- sign, LIB command symbol
- PMAP function
- PMAP statement
- POINT function
- point referenced
- POKE statement
- Polling
- POS function
- Positive numbers, printing without
- PRESET
- PRESET option, with PUT graphics statement
- PRESET statement
- color option, using with
- described
- previous
- PRINT
- PRINT # statement
- described
- record
- WRITE #, contrasted with
- PRINT statement
- described
- example
- text, wrapping
- PRINT # USING statement
- PRINT USING # statement
- PRINT USING statement
- Print zone
- Printing
- numbers
- negative
- positive
- text
- printer,
- screen, to
- printing
- printing on
- PRN
- Procedures
- arguments
- passing by reference
- passing by value
- arrays
- benefits
- calling
- constants
- defining
- described
- expressions
- format
- argument-list
- parameter-list
- include files, declarations in
- libraries, user
- limits (table)
- modules, multiple
- moving
- passing
- Quick
- records
- recursive
- statements
- FUNCTION...END
- FUNCTION...END FUNCTION
- SUB...END
- SUB...END SUB
- summary (table)
- statements not allowed
- STATIC variables
- variables
- global
- local
- sharing
- variables,
- variables, automatic
- procedures
- DEF FN function, contrasted with
- exit from, alternative
- procedures)
- procedures
- Procedures-only module
- Program
- suspension
- termination
- program application
- programming
- Quick libraries
- Programming environment, differences in versions
- Programming style
- multiple
- Programs
- BASICA, GW-BASIC,
- ProKey, using QuickBASIC with
- prompting, preventing
- PSET
- PSET statement
- described
- example
- STEP option
- PUT
- PUT statement
- described
- file
- file I/O
- binary-access
- random-access
- graphics
- animation
- interaction with background, controlling
- syntax
- records,
-
- Q
-
- QB
- QB command
- /AH
- /H option
- /L option
- /MBF
- /MBF option
- /RUN option
- versions, differences among
- QB.QLB
- library
- loading, automatic
- QLBDUMP.BAS
- Quick
- Quick libraries
- advantages
- CALL ABSOLUTE statement
- CALL INTERRUPT
- contents
- described
- listing
- reading
- creating
- command line, from
- described
- files needed
- LINK, using
- QuickBASIC, from within
- default
- described
- end user, delivery to
- errors, trapping in
- executable files, making compact
- files
- needed to create
- produced by
- floating-point precision
- include files, declaring procedures with
- loading
- .MAK file, updating
- memory
- mixed languages
- naming
- object code, linking
- routines, other languages
- search
- updating
- option (LINK)
- /QUICKLIB
-
- R
-
- /R option (BC)
- Radians
- radians
- Random access, contrasted with binary access
- Random numbers
- Random-access
- Random-access files
- opening
- records
- adding
- organizing
- reading
- sequential
- sequential files, contrasted with
- statements
- RANDOMIZE statement
- READ statement
- Record numbers
- limits (table)
- random-access files, indexing in
- Record numbers, random-access files
- indexing in
- Records
- binary-access files, writing
- data, overwriting
- defined
- defining
- described
- fixed-length
- procedures,
- procedures, passing to
- random-access
- random-access files
- reading
- storing
- writing
- sequential
- sequential files
- appending
- reading
- storing
- variable length
- records, defining
- Rectangles, specifying coordinates
- Recursive
- Recursive procedures
- REDIM
- REDIM statement
- described
- SHARED
- SHARED attribute
- reducing
- reference
- Relational
- Relational operators
- Boolean expressions
- SELECT CASE statement
- relative
- Relative coordinates. See Coordinates,
- REM statement
- representing as
- requirements
- RESET statement
- Response
- Response file
- example
- LINK
- RESTORE statement
- restrictions with
- RESUME
- Resume Next option
- RESUME NEXT statement
- described
- example
- RESUME,
- RESUME statement
- compiler
- compiler option required
- described
- example
- QuickBASIC/interpreter differences
- RESUME NEXT, contrasted with
- retrieving
- right side
- RETURN statement
- RIGHT$ function
- RMDIR statement
- RND function
- Rotating
- Rotating figures with DRAW
- routine
- Routine, B_OnExit
- routines
- ERR, identifying errors with
- Rows, changing number of
- RSET
- RSET statement
- RTRIM$
- RTRIM$ function
- /RUN option (QB)
- Run menu, Make Library command
- RUN statement
- data
- Run-time error messages
-
- S
-
- /S option (BC)
- SADD function
- SAVE statement (BASICA)
- Saving
- images, with GET
- programs, ASCII format
- Scan codes
- keyboard
- trapping keys, use
- Screen
- configuration
- graphics mode
- text mode
- functions
- CSRLIN
- individual function
- POS
- SCREEN
- resolution,
- statements. See individual statement names
- CLS
- COLOR
- LOCATE
- PCOPY
- SCREEN
- VIEW PRINT
- WIDTH
- Screen
- SCREEN function
- Screen modes
- Screen pages
- SCREEN statement
- aspect ratio, effect on
- described
- example
- screen
- page
- resolution, adjusting
- text mode, rows in
- SCRN
- Scrolling
- (/SE)
- Search paths
- libraries
- Quick libraries
- Searching
- strings
- See Quick libraries
- SEEK function
- SEEK statement
- SEG
- /SEGMENTS option (LINK)
- Segments
- lists, map files
- number
- order
- packing
- SELECT CASE
- SELECT CASE statement
- CASE clause
- CASE ELSE clause
- described
- END SELECT
- IF...THEN...ELSE
- ON expression
- routine, error-handling
- syntax
- versions, differences among
- Semicolon (;), LIB command symbol
- Separate-compilation method. See BC command
- sequence
- Sequential
- Sequential files
- creating
- fields
- opening
- random-access files, contrasted
- records
- statements
- statements and functions
- LINE INPUT #
- Serial communication
- defined
- input
- input buffer
- Serial ports,
- Set Main Module command, differences among versions
- SETMEM function
- setting
- SGN function
- shape of
- SHARED
- SHARED attribute
- COMMON
- DIM
- described
- example
- prohibited
- REDIM
- SHARED statement
- Shared variables, between modules
- sharing
- Shell escape (SHELL statement)
- Shifted keys, trapping
- SideKick,
- sign (+)
- sign ($), string-type suffix
- SIN function
- Sine, SIN function
- Sine wave, graphing
- Single-precision
- Single-precision numbers
- size limits (table)
- size
- size, setting
- Skipping
- columns
- spaces
- SLEEP statement
- Sorting,
- Sorting, examples
- SOUND statement
- Source
- Source files
- versions, compatibility among
- SPACE$
- SPACE$ function
- Spaces
- skipping
- trimming
- SPC
- SPC function
- SPC statement
- specifying
- maximum value
- number of
- specifying values outside
- SQR function
- Squares, drawing
- /STACK option (LINK)
- Stack size,
- Stack size, recursive procedures, adjusting for
- Stand-alone programs,
- Standard
- Standard input
- defined
- reading
- redirecting
- Standard I/O
- statements
- Standard output
- Standard places, libraries
- Statement
- modification required
- statement
- statement
- statement. See Painting
- arcs
- arguments, checking with
- AS clause
- BASIC procedures
- buffer allocation, FIELD statement
- CASE clause
- color option
- coordinates
- described
- exit from, alternative
- FIELD statement
- file numbers in
- file-access modes
- APPEND
- BINARY
- RANDOM
- flow control
- foreground color, controlling
- graphics
- animation
- images, copying to screen
- memory, copying images to
- #INCLUDE metacommand, used with
- INPUT, contrasted with INPUT
- prompting
- SHARED attribute
- prohibited
- single-line form
- SPC function
- STATIC attribute
- SUB procedure, calling
- TYPE...END TYPE, contrasted with
- statement and function names
- Statement block
- statement, block form
- statement, contrasted with
- statement names
- statement (non-BASIC)
- statement, use in
- Statements. See individual statement names
- statements. See Individual statement names; individual statement names
- DEF FN
- described
- ERROR
- FOR...NEXT
- INPUT #
- KEY ON
- KEY(n)
- NAME
- ON ERROR
- ON GOSUB
- ON...GOSUB
- RESUME
- STRIG
- WAIT
- WHILE...WEND
- statements and functions
- LINE INPUT #
- LSET
- PRINT #
- RSET
- statements used
- CHAIN
- COMMON
- #STATIC
- statement
- variables
- #STATIC metacommand
- arrays, dimensioned, implicitly
- arrays, memory allocation
- STATIC
- attribute
- statement
- Static arrays
- ERASE statement
- #STATIC metacommand
- STEP
- option
- STICK function
- Stop bits
- STOP statement
- STR$ function
- STRIG function
- STRIG OFF
- STRIG ON statement
- STRIG(n) statements
- STRING
- String
- expressions
- defined
- sequential files, delimiting in
- functions. See individual function names
- ASC
- CHR$
- DATE$
- HEX$
- INPUT$
- INSTR
- LCASE$
- LEFT$
- LEN
- LTRIM$
- MID$
- RIGHT$
- RTRIM$
- SADD
- SPACE$
- STR$
- STRING$
- UCASE$
- VAL
- statements. See individual statement names
- LSET
- MID$
- RSET
- variables. See Strings
- string
- STRING$
- string ("")
- STRING$ function
- String, processing. See Strings
- string with AS
- String-handling functions, new
- Strings
- alphabetizing
- characters,
- characters, retrieving
- left side
- middle
- combining
- comparing
- constants
- defined
- expressions
- fixed-length
- AS STRING
- record elements
- variable length, contrasted
- generating
- limits (table)
- numbers,
- replacing
- spaces,
- spaces, trimming
- right side
- statements and functions, summary of (table)
- substring, searching for
- variable-length
- AS
- defined
- fixed-length,
- maximum
- variables
- strings
- fixed- and variable-length
- structures
- FOR...NEXT
- IF...THEN...ELSE
- single-line
- looping
- SELECT CASE
- styling
- SUB
- procedures
- CALL
- DECLARE
- error trapping in
- event trapping in
- exit
- GOSUB, compared
- include
- #INCLUDE metacommand
- variables,
- statement
- AS clause
- described
- include files, not allowed in
- STATIC attribute
- SUB procedure. See SUB procedures
- SUB statement
- SUB...END
- Subprograms. See SUB
- CALL statement
- CALLS
- SUB statement
- variables
- Subroutines. See GOSUB...RETURN subroutine
- subroutines
- drawbacks in using
- Subscripts
- arrays, limits (table)
- lower bound, specifying
- maximum value, specifying
- number, specifying
- upper
- SuperKey,
- support routines
- SWAP statement
- symbol
- Symbol tables,
- Symbolic
- Symbolic constants
- CONST
- defined
- string
- symbols
- asterisk (*)
- minus sign-plus sign (-+)
- Syntax
- Syntax Checking command, differences
- syntax, contrasted with
- Syntax notation
- choices
- optional
- System
- System calls
- SYSTEM statement
-
- T
-
- TAB function
- TAB statement
- (table)
- table
- Text
- screen, printing on
- wrapping
- Text
- Text boxes, limits (table)
- Tiling. See Painting
- Time and date functions. See Date and time, functions
- TIME$ function
- TIME$ statement
- TIMER
- TIMER function
- TIMER OFF statement
- TIMER STOP statement
- Timing function
- TMP environment variable, LINK, used by
- to
- translating to
- Trapping. See Error trapping, Event trapping
- errors
- events
- multiple modules
- options, command-line, required by compiler
- trapping
- activating
- keys
- function
- statements and functions (table)
- trapping in
- Trigonometric
- Trigonometric functions
- ATN
- COS
- TAN
- trimming
- left side
- TROFF statement
- TRON statement
- True expressions
- TYPE command (DOS)
- TYPE, contrasted with
- type, declaring
- TYPE statement
- described
- FIELD, contrasted with
- versions, differences among
- TYPE...END
- TYPE...END TYPE statement
- example
- fixed-length strings in
- random-access records, defining
- Typeface
- key names
- keywords
- placeholders
- program
- types
- specifying
- Typographic conventions
-
- U
-
- UBOUND
- UBOUND function
- UCASE$
- UCASE$ function
- UEVENT
- UEVENT statement
- UNLOCK statement
- Uppercase letters
- file names
- lowercase, converting
- use of
- used in BASIC (table)
- User
- User libraries
- User-defined
- data
- events
- types
- user-defined
- USING
- USING, changing with
- using QuickBASIC with
- using to circumvent
- Utility, BUILDLIB
-
- V
-
- /V compiler option
- described
- /V option (BC)
- described
- versions, differences among
- VAL function
- Variable aliasing
- variable aliasing
- Variable-length strings
- defined
- fixed-length, compared with
- GET statement
- maximum size
- PUT
- Variables
- arrays
- described
- elements of, passing
- entire, passing
- automatic
- data type
- global
- described
- function
- sharing
- subprograms
- variable
- local
- described
- function definitions
- subprograms
- multiple modules, sharing
- names
- limits (table)
- program examples, format in
- procedures
- sharing
- sharing all in a module
- procedures, passing to
- programs, sharing
- simple, passing
- STATIC
- string. See Strings
- type, declaring
- values, exchanging, SWAP
- variables
- variables in
- VARPTR$
- VARPTR function
- described
- versions, differences among
- VARPTR$ function
- described
- VARSEG function
- described
- versions, differences among
- Version differences, file compatibility
- versions
- VGA (Video
- VIEW
- View coordinates
- physical coordinates,
- WINDOW, defining with
- VIEW PRINT statement
- VIEW SCREEN statement
- VIEW statement
- Viewport
- graphics
- advantages
- VIEW,
- VIEW SCREEN, defining with
- text
- viewport. See Viewport
- VM.TMP file
-
- W
-
- /W option (BC)
- described
- versions, differences among
- WAIT statement
- Watch expressions, limits
- Watchpoints, limits (table)
- WEND statement
- described
- versions, differences among
- WHILE statement
- WHILE...WEND
- WHILE...WEND statement
- DO...LOOP, contrasted with
- syntax
- width
- WIDTH
- WIDTH statement
- columns, changing number of
- described
- rows,
- WINDOW
- WINDOW SCREEN statement, WINDOW contrasted with
- WINDOW statement
- example
- GET, effect on
- Windows
- error-message
- Immediate, limits (table)
- versions, differences among
- with
- with CLOSE
- with the ASC function
- WordStar keys, similarity to
- Wrapping text
- WRITE # statement
- described
- PRINT #, contrasted
- WRITE statement
-
- X
-
- /X option
- described
- /X option (BC)
- described
- differences among versions
- XOR operator
- XOR option, PUT graphics
-
- Z
-
- /ZD option (BC)
- /ZI option (BC)
-