JES: Just Educational Services

Jonathan E. Sisk's
Pick/BASIC: A Programmer's Guide

Chapter 8 - Numeric Data Conversion and Output Routing

Click to enlarge

In program example 5, two of the types of information were discussed that must be converted internally before they are stored. The third, and perhaps most common, type of data that requires internal conversion is money.

There's an important rule for you to commit to memory here:

Money is always stored internally as the number of pennies!

That's because the Pick report writer, ACCESS, needs it this way. So, in Example 6, the conversion process for handling dollar amounts is covered.

In all of the preceding examples, each PRINT statement that was used to output a literal, variable, or expression to the screen simply printed at the next available screen line. In other words, no special screen formatting took place. Example 6 illustrates formatting screens using a set of PICK/BASIC intrinsic functions. Additionally, the MC and MR conversion cedes are introduced. Topics, statements, and functions covered include the "@" function, ICONV, and OCONV (MR/MC).

Using the listing in Fig. 8-1, enter Program Example 6.


Fig. 8-1. Program Example 6.


001 * EX.006
002 * TERMINAL OUTPUT FORMATTING, MONEY CONVERSIONS
003 * mm/dd/yy: date last modified
004 * JES: author's initials
005 *
006 PROMPT "·"
007 *
008 PRINT @(-1): @(15,0): "EXAMPLE 6": @(58,0): TIMEDATE()
009 *
010 * GET FIRST NAME
011 *
012 LOOP
013 PRINT @(5,3): "FIRST NAME": @(35,3): STR("_",25): @(35,3):
014 INPUT FIRST.NAME,25
015 UNTIL FIRST.NAME # "" DO REPEAT
016 IF FIRST.NAME = "QUIT" THEN STOP
017 *
018 * GET LAST NAME
019 *
020 LOOP
021 PRINT @(5,5): "LAST NAME": @(35,5): STR("_",25): @(35,5):
022 INPUT LAST.NAME,25
023 UNTIL LAST.NAME # "" DO REPEAT
024 IF LAST.NAME = "QUIT" THEN STOP
025 *
026 * PUT NAMES TOGETHER AND CONVERT TO UPPER AND LOWER CASE
027 *
028 WHOLE.NAME = FIRST.NAME : " " : LAST.NAME
029 WHOLE.NAME = OCONV(WHOLE.NAME,"MCT")
030 *
031 * GET ANNUAL SALARY
032 *
033 LOOP
034 PRINT @(5,7): "ANNUAL SALARY": @(35,7): STR("_",9): @(35,7):
035 INPUT SALARY,9
036 UNTIL SALARY = "QUIT" OR NUM(SALARY) DO REPEAT
037 IF SALARY = "QUIT" THEN STOP
038 *
039 * GET NUMBER OF PAYCHECKS
040 *
041 LOOP
042 PRINT @(5,9) : "HOW MANY PAYCHECKS DO YOU GET EACH YEAR?"
043 PRINT @(5,10): "ENTER A NUMBER BETWEEN 1 & 52": @(-4):
044 INPUT CHECKS
045 UNTIL (CHECKS >= 1 AND CHECKS <= 52) DO REPEAT
046 IF CHECKS = "QUIT" THEN STOP
047 *
048 PRINT @(5,11): "THANKS. NO MORE QUESTIONS"
049 *
050 * START CALCULATIONS
051 *
052 INTERNAL.SALARY = ICONV(SALARY,"MR2") ; * CONVERT
053 PAYCHECK.AMOUNT = INTERNAL.SALARY / CHECKS; * CALC. AMT
054 *
055 * PRINT PSEUDO- CHECK
056 *
057 PRINT @(5,15): STR("*",50) ; * PRINT STARS
058 PRINT @(10,16): "CHECK 123" "L#20": ; * PRINT CHECK #
059 PRINT "DATE" : OCONV(DATE() ,"D") ; * TODAY'S DATE
060 PRINT @(10,17) : "PAY TO THE ORDER OF":
061 PRINT WHOLE.NAME ; * PRINT NAME
062 PRINT @(10,18) : "THE AMOUNT OF" :
063 PRINT OCONV(PAYCHECK.AMOUNT,"MR2,$*15") ; * EXTERNAL AMT
064 PRINT @(5,19): STR("*",50)
065 *
066 * DONE.
067 *
068 PRINT
069 END


THE @ FUNCTION

There are a number of special cursor control functions in PICK/BASIC. These include a function that positions the cursor to a specific coordinate on the screen and a function that clears the screen. Each of these functions is enclosed in a set of parentheses and is preceded immediately by the @ ("at") character.

008 PRINT @(-1) :@(15,0) :"EXAMPLE 6" :@(58,0) : TIMEDATE()

The @ functions produce a string of characters. This string is most often printed immediately, but it may also be stored in a variable. Multiple @ functions may be concatenated, just like any other string. Figure 8-2 lists the most common functions used in conjunction with the PRINT statement. A more complete listing appears in Appendix B. Line 8 of the example does the following: First, it clears the screen, using @(- 1).

It then moves the cursor to column position 15 on screen line (row) 0, the top of the screen.

Function         Description
@(-1)            Clears the screen.
@(-3)            Clears from the current cursor position to
                 the end of the screen.
@(-4)            Clears from the current cursor position to
                 the end of the current line.
@(x,y)           Positions the cursor at column (horizontal
                 axis) "x" on row (vertical axis) "y".

Fig. 8-2. Commonly used "@" functions.


Next, it outputs "EXAMPLE 6" at the current cursor position, then moves the cursor to position 58 on screen line 0, where it next outputs the current system time and date.

Line 13 moves the cursor to position 5 on screen line 3, displays the prompt "FIRST NAME," then moves the cursor to position 35 on screen line 3, where it outputs a string of 25 "_" (underscore) characters. It then moves the cursor back to position 35 on screen line 3.

CONCATENATION

On Line 28, the two variables you had entered earlier, FIRST.NAME and LAST. NAME, are joined together (concatenated), separated by a space. The joined string is then stored in the variable WHOLE.NAME:

028 WHOLE.NAME = FIRST.NAME : " " : LAST.NAME

This is done because, on the next line of code, a conversion on the entire string is performed.

Figure 8-3 shows two examples of concatenation. Effectively, these two examples produce the same output. In Case 1, the variables are output in five separate PRINT statements. In Case 2, the variables are concatenated together and then output in one PRINT statement. There are several different schools of thought as to which of these is more efficient; I suggest that you use the one with which you feel more comfortable.

CHARACTER MASKING WITH THE OCONV FUNCTION

So far, you have seen the conversions for dates and times. A unique conversion, called the "MC" (for "Mask Character"), allows various conversions on alphabetic and/or numeric strings. For example, the "MCT" conversion converts the first alphabetic character in each word of a string to its uppercase form:

029 WHOLE.NAME = OCONV(WHOLE.NAME,"MCT")

Case 1:

001 PRINT NAME "L#20":
002 PRINT ADDRESS "L#25" :
003 PRINT CITY "L#20" :
004 PRINT STATE "L#10" :
005 PRINT ZIP "L#11"

Case 2:

001 PRINT.LINE = NAME "L#20"
002 PRINT.LINE = PRINT.LINE : ADDRESS "L#25"
003 PRINT.LINE = PRINT.LINE : CITY "L#20"
004 PRINT.LINE = PRINT.LINE : STATE "L#10"
005 PRINT.LINE = PRINT.LINE : ZIP "L#11"
006 PRINT PRINT.LINE

Fig. 8-3. Examples of concatenation.


Figure 8-4 illustrates some of the MC conversions and their effects on data. The MCU code converts all of the alphabetic characters to uppercase. The MCL code converts all of the alphabetic characters to lowercase. The MCN code retrieves all the numeric characters from the string, while the MC/N code retrieves all the nonnumeric characters. Similarly, the MCA code retrieves all the alphabetic characters (upper- or lowercase) from the string, and the MC/A code retrieves all the non-alphabetic characters. Finally, the MCT conversion capitalizes the first character of each word. Note that this conversion works fine for O'Brien, but not for McDonald.

MORE ON THE @ FUNCTION

Another twist on the @ function is shown in line 43:

043 PRINT @(5,10) :"ENTER A NUMBER BETWEEN 1 & 52" :@(-4):

Note that the last function directed to the screen before pausing to wait for user input is the intrinsic function, "@(-4)". Its purpose is to clear from the current cursor position (in this case, from two spaces to the right of the number "52") to the end of the line. This cleans up any "leftover" input when and if it is necessary to prompt the operator for this information again.

MONEY CONVERSIONS WITH ICONV

In Example 5 you examined the effect of date and time conversions. Here, the money conversion is introduced. The MR conversion is used to convert numeric amounts to their internal equivalents (remember that on dollar amounts the internal format represents the number of pennies):

052 INTERNAL.SALARY = ICONV(SALARY,"MR2")    ; * CONVERT



Internal
format                  Conversion       Result
123 Main Street            MCU           123 MAIN STREET
123 MAIN STREET            MCL           123 main street
123 MAIN STREET            MCN           123
123 MAIN STREET            MCA           MAINSTREET
123 MAIN STREET            MCT           123 Main Street
SEAN O'BRIEN               MCT           Sean O'Brien
MEAGAN MCDONALD            MCT           Meagan Mcdonald

Fig. 8-4. MC conversions and their effects on data.


Money amounts are converted to internal format for several reasons. First, and probably the most important, is the fact that storing this way can save hundreds of hours in programming time, since it allows most output reports to be produced with the ACCESS language. (ACCESS does not work well when the data is not stored in internal format). Second, many powerful output conversion codes may be used when writing PICK/BASIC and/or ACCESS reports.

The MR conversion has quite a few forms. It is almost always followed by a number, which indicates the number of decimal positions expected. This number is normally "2" for dollar amounts. Another way of thinking about this number is that it represents the number of positions that the decimal point has to move to the right to convert this number to its internal equivalent. Figure 8-5 illustrates what happens when numbers are converted from external to internal format.

Figure 8-6 illustrates some of the numeric conversions that may be applied to internal numbers. The MR2 conversion places the decimal point two positions from the right end of the numeric string; when "MR2" is followed by a comma, the conversion places the decimal point two positions from the right end of the numeric string and puts commas in every third position to the left of the decimal point. Following "MR2," with a dollar sign ($) places the decimal point two positions from the right end of the numeric string and puts commas in every third position to the left of the decimal point and precedes the string with a dollar sign.



External
format               Conversion     Result
100.22                  MR2         10022
100.3                   MR2         10030
100                     MR2         10000
10                      MR2         1000
0                       MR2         0
-100.3                  MR2         -10030
-100.22                 MR2         -10022

Fig. 8-5. Converting money from external to internal format.




Internal               OCONV
format               conversion     Result

123456789                MR2        1234567.89
123456789                MR2,       1,234,567.89
123456789                MR2,$      $1,234,567.89

Fig. 8-6. Numeric conversions that can be applied to internal numbers.


Using Signcodes in MR Conversions

There are five special codes to activate special features on numeric amounts, four of which are for handling negative numbers. These special signcodes always appear in the same parametric position illustrated in Fig. 8- 7.

The D signcode instructs the conversion processor to output the literal "DB," for debit, after positive numbers; the other codes modify negative numbers. Conversion B in Fig. 8-7 shows the effect of not using a signcode on negative numbers. The C signcode outputs the literal "CR," for credit, after negative numbers, and the E signcode "encloses" negative amounts in the "< >" angular brackets. The M signcode "moves" the negative sign, which normally precedes negative numbers, to the right end of the number. Finally, the N signcode suppresses the leading minus sign on negative numbers. Yes, this does make negative numbers look like positive numbers. (There are applications for this, other than printing totals on profit and loss reports for failing companies.)

Fill Characters (Format Masking) in MR Conversions

The MR conversion provides a feature which fills the print field with either blanks, zeros, or asterisks; this is essentially the same as print (format) masking. The three fill operators are:

%	For filling with zeros
#	For filling with blanks
*	For filling with asterisks



Internal          OCONV           Result
format          conversion        provided

123456789         MR2,D$          $1,234,567,89DB
-123456789        MR2,$           -$1,234,567.89
-123456789        MR2,C$          $1,234,567.89CR
-123456789        MR2,E$          <$1,234,567.89>
-123456789        MR2,M$          $1,234,567.89-
-123456789        MR2,N$          $1,234,567,89
123456789         MR2,$*17        ****$1,234,567.89
123456789         MR2,$*10      $34,567.89

Fig. 8-7. Effects on data of signcodes and format masks used with the MR conversion.


The mask operator must be preceded by an integer number which tells it the number of characters to pad the field with. For example, the next-to-last line of Fig. 8-7 shows the use of format masks with the money conversion. The only "new" feature added here is the format mask itself (*17), which prints the number left-padded with * characters, so that the field is exactly 17 character positions wide.

Just for fun, watch what happens when the format mask is not wide enough to handle the number being printed, as in the last line of Fig. 8-7. In this example, the first two numbers are truncated because the number being printed is much larger than the mask allows for.

On line 52 of Example 6, the amount entered into the variable SALARY is converted to its internal equivalent. Once a number is in internal format, calculations may be performed or any of the output conversions just illustrated may be applied.

Line 53 calculates the amount of each paycheck by first taking the INTERNAL.SALARY variable and dividing it by the NUMBER.OF.PAYCHECKS variable. This result is then stored, still in internal format, in the variable PAYCHECK.AMOUNT.

The code on lines 57 through 64 prints a simulated paycheck on the screen, using functions and features previously covered. One added nuance is the treatment of the output on lines 60 and 61. Line 60 outputs the literal "PAY TO THE ORDER OF "and leaves the cursor positioned at the end of this message on the screen. It is important to remember that the colon at the end of the line means to suppress the carriage return normally printed at the end of a PRINT statement

Line 61 externally converts the variable, PAYCHECK.AMOUNT, with the "MR2, * 15" conversion. It then prints the external amount at the current cursor position.

Line 36 displays a string of 50 asterisks at position 5 on line 15.


REVIEW QUIZ 6

1) What instructions are required to:

A) Clear the terminal screen (two ways):

B) Print "HELLO THERE" on the 15th line at the 3rd position:

C) Clear from the cursor position to the end of the line?

2) What instruction is used to input a variable, and to limit the input to six characters?

3) What instruction is used to convert "123456.78" to its internal format?

4) What statement is used to print the external form of the number "5667788" so that it displays in the format $56,677.88?

5) What is concatenation?

6) As an exercise, modify EX.001 to validate more closely the numbers entered by the operator. Note that this program allows the operator to enter negative numbers. Prevent this from happening.

Previous chapter Next chapter Top

 

Creative Commons License
Jonathan E. Sisk's "Pick/BASIC: A Programmer's Guide" by Jonathan E. Sisk is licensed under a Creative Commons Attribution 3.0 Unported License.
Based on a work at jes.com.