Learn Encryption Techniques with BASIC and C++
(Publisher: Wordware Publishing, Inc.)
Author(s): Gil Held
ISBN: 1556225989
Publication Date: 10/01/98

Previous Table of Contents Next


Modifying the GROUPBY5 Subroutine

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 X’s 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 X’s 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 X’s. 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 CIPHER4.BAS Program

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 PRTOUT—the 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