Previous | Table of Contents | Next |
As previously constructed, this subroutine performs the actual printing of characters in groups of five. Now we will modify this subroutine so that it fills the last group with Xs if there are less than five characters in the group. Listing 2.13 shows the statement in this modified subroutine.
Listing 2.13 The modified GROUPBY5 subroutine.
GROUPBY5: L = 1 FOR I = 1 TO MSGLEN PRINT MID$(TEXT$, I, 1); IF I / 5 = L THEN GOTO AGROUP GOTO NGROUP AGROUP: PRINT " "; L = L + 1 NGROUP: NEXT I NUMX = 5 - MSGLEN MOD 5 IF NUMX = 5 OR NUMX = 0 THEN GOTO PRTBLK FOR I = 1 TO NUMX PRINT "X"; NEXT I PRTBLK: PRINT RETURN
When the subroutine is invoked, the variable L is set to 1 and the FOR-NEXT loop cycles through the contents of the string variable TEXT$, printing one character at a time. If the index I of the FOR-NEXT loop divided by 5 equals L, five characters have been printed and a branch to the label AGROUP occurs. At that location, the PRINT statement prints a space, providing a space between groups of five characters. Next, the variable L is incremented and the loop ends. If a group of five characters was not printed, a branch to the label NGROUP occurs, bypassing the printing of the space.
Once the FOR-NEXT loop is completed, you must determine if a group did not have five characters, a condition that can only occur when the last line in the enciphered message is processed. Here, the value of the variable NUMX determines the number of Xs that must be added to fill the last group. Only if NUMX is greater than 0 or less than 5 do we invoke the next FOR-NEXT loop to print the terminating Xs. Otherwise, a branch to the label PRTBLK occurs, which terminates a previous PRINT statement ending with a semicolon so that the next cycle through the subroutine GROUPBY5 will have succeeding groups placed on a new line.
The entire program previously developed as modules will be listed to facilitate recognizing how the previously mentioned subroutines and calling program relate to each other. This program is contained in the directory BASIC in the file CIPHER4.BAS on the CD-ROM and is given in Listing 2.14.
Listing 2.14 The CIPHER4.BAS program listing.
REM PROGRAM CIPHER4.BAS DIM PLAINTEXT$(26), CIPHERTEXT$(26) CLS GOSUB INITIALIZE PRINT "CIPHER4.BAS PROGRAM accepts spaces between words in a plaintext " PRINT "message and selectively enciphers the message using a simple" PRINT "monoalphabetic substitution process." 1 INPUT "Enter UPPERCASE Alphabetic Shift Key: ", K$ FOR I = 0 TO 25 IF K$ = PLAINTEXT$(I) GOTO 2 NEXT I PRINT "You must enter a letter from A to Z" GOTO 1 2 REM Position I represents shift key letter GOSUB FORMCIPHER 'create cipher alphabet GOSUB MSGFILE 'assign I/O files, place message on a file GOSUB CONVERTSTORE 'convert and store ciphertext on a file GOSUB PRTOUT 'print results STOP INITIALIZE: REM Initialize plaintext values FOR I = 0 TO 25 READ PLAINTEXT$(I) NEXT I DATA "A","B","C","D","E","F","G","H","I","J","K","L","M","N" DATA "O","P","Q","R","S","T","U","V","W","X","Y","Z" RETURN FORMCIPHER: REM Routine to form CIPHERTEXT alphabet based upon defined shift key J = I + 1 FOR K = 0 TO 25 CIPHERTEXT$(K) = PLAINTEXT$((K + J) MOD 26) NEXT K RETURN MSGFILE: REM Routine to assign I/O files and accept keyboard or file input REM and remove spaces between words INPUT "Enter filename to store plaintext message, default=MESSAGE.DAT", INFILE$ IF INFILE$ = "" THEN INFILE$ = "MESSAGE.DAT" INPUT "Enter filename to store enciphered message, default=CIPHERTX.DAT", OUTFILE$ IF OUTFILE$ = "" THEN OUTFILE$ = "CIPHERTX.DAT" INPUT "Select keyboard (k) or file (f) message input: ", IN$ IF IN$ = "F" OR IN$ = "f" THEN RETURN OPEN INFILE$ FOR OUTPUT AS #1 REM Routine to place message on a file removing spaces between words PRINT "Enter your message - place a / at the beginning of each line" PRINT "that should remain in plaintext and a \ on a separate line" PRINT "to indicate the end of the enciphered message" PRINT AGN: LINE INPUT TEXT$ IF MID$(TEXT$, 1, 1) = "/" THEN GOTO XT NTEXT$ = "" FOR I = 1 TO LEN(TEXT$) NTEXT$ = NTEXT$ + LTRIM$(MID$(TEXT$, I, 1)) NEXT I WRITE #1, NTEXT$ IF MID$(TEXT$, 1, 1) = "\" GOTO DONE GOTO AGN XT: WRITE #1, TEXT$ GOTO AGN DONE: CLOSE #1 RETURN CONVERTSTORE: REM Routine to convert and store ciphertext on a file OPEN INFILE$ FOR INPUT AS #1 OPEN OUTFILE$ FOR OUTPUT AS #2 DO UNTIL EOF(1) INPUT #1, TEXT$ MSGLEN = LEN(TEXT$) IF MID$(TEXT$, 1, 1) = "/" THEN GOTO CLEARTXT IF MID$(TEXT$, 1, 1) = "\" THEN GOTO DONE1 REM Convert plaintext to ciphertext FOR I = 1 TO MSGLEN FOR J = 0 TO 25 IF MID$(TEXT$, I, 1) = PLAINTEXT$(J) THEN GOTO GOTIT NEXT J GOTIT: MID$(TEXT$, I, 1) = CIPHERTEXT$(J) NEXT I CLEARTXT WRITE #2, TEXT$ LOOP DONE1: CLOSE #2 RETURN PRTOUT: REM Subroutine to print results INPUT "Press Return key to display resulting enciphered message", p$ CLS: TEMP$ = "" PRINT "Resulting enciphered message is:" OPEN OUTFILE$ FOR INPUT AS #2 DO UNTIL EOF(2) INPUT #2, TEXT$ IF MID$(TEXT$, 1, 1) = "/" THEN PRINT RIGHT$(TEXT$, LEN(TEXT$) - 1) IF MID$(TEXT$, 1, 1) = "/" THEN GOTO NOGROUP IF TEMP$ = "" GOTO BLANK 'blank string TEMP$ = TEMP$ + TEXT$ 'concatenate TEXT$ = TEMP$ TEMP$ = "" BLANK: MSGLEN = LEN(TEXT$) IF MSGLEN >= 25 THEN GOTO BIG TEMP$ = TEXT$ GOTO NOGROUP 'less than 25 characters BIG: FOR I = 26 TO MSGLEN 'place remainder of string 'into temp TEMP$ = TEMP$ + MID$(TEXT$, I, 1) NEXT I MSGLEN = 25 GOSUB GROUPBY5: 'print 25 characters NOGROUP: LOOP TEXT$ = TEMP$ 'print remainder MSGLEN = LEN(TEXT$) IF MSGLEN <= 25 THEN GOSUB GROUPBY5 IF MSGLEN <= 25 THEN RETURN 'done printing WHILE MSGLEN > 25 TEMP$ = LEFT$(TEXT$, 25) 'get first 25 characters 'in string TEMPR$ = RIGHT$(TEXT$, MSGLEN - 25) TEXT$ = TEMP$ MSGLEN = LEN(TEXT$) GOSUB GROUPBY5 TEXT$ = TEMPR$ MSGLEN = LEN(TEXT$) WEND TEXT$ = TEMPR$ MSGLEN = LEN(TEXT$) GOSUB GROUPBY5 RETURN GROUPBY5: L = 1 FOR I = 1 TO MSGLEN PRINT MID$(TEXT$, I, 1); IF I / 5 = L THEN GOTO AGROUP GOTO NGROUP AGROUP: PRINT " "; L = L + 1 NGROUP:NEXT I NUMX = 5 - MSGLEN MOD 5 IF NUMX = 5 OR NUMX = 0 THEN GOTO PRTBLK FOR I = 1 TO NUMX PRINT "X"; NEXT I PRTBLK: PRINT RETURN END
Note that the main portion of CIPHER4.BAS very closely resembles CIPHER3.BAS. However, calls using the GOSUB statement were added to access the subroutines MSGFILE, CONVERTSTORE, and PRTOUTthe latter subroutine accesses the subroutine GROUPBY5 as previously discussed. You should also note the inclusion of several PRINT statements at the beginning of the program to better describe its operation.
Previous | Table of Contents | Next |