• Tidak ada hasil yang ditemukan

Programming a Decoder

Chapter 5 Chapter 5

15.5.11 Programming a Decoder

Now that we have a program to turn a message into a sequence of numbers, it would be nice if our friend on the other end had a similar program to turn

5.5. String Methods

the numbers back into a readable message. Let's solve that problem next. Our decoder program will prompt the user for a sequence of Unicode numbers and then print out the text message with the corresponding characters. This program presents us with a couple of challenges; we'll address these as we go along.

The overall outline of the decoder program looks very similar to the encoder program. One change in structure is that the decoding version will collect the characters of the message in a string and print out the entire message at the end of the program. To do this, we need to use an accumulator variable, a pattern we saw in the factorial program from Chapter 3. Here is the decoding algorithm:

get the sequence of numbers to decode message = 11 11

for each number in the input :

convert the number to the corresponding Unicode character add the character to the end of message

print message

Before the loop, the accumulator variable

message

is initialized to be an

empty string;

that is, a string that contains no characters

( 11 11 ) .

Each time through the loop, a number from the input is converted into an appropriate character and appended to the end of the message constructed so far.

The algorithm seems simple enough, but even the first step presents us with a problem. How exactly do we get the sequence of numbers to decode? We don't even know how many numbers there will be. To solve this problem, we are going to rely on some more string manipulation operations.

First, we will read the entire sequence of numbers as a single string using

input .

Then we will split the big string into a sequence of smaller strings, each of which represents one of the numbers. Finally, we can iterate through the list of smaller strings, convert each into a number, and use that number to produce the corresponding Unicode character. Here is the complete algorithm:

get the sequence of numbers as a string, inString split inString into a sequence of smaller strings message = 11 11

for each of the smaller strings :

change the string of digits into the number it represent s append the Unicode character for that number to message print message

143

This looks complicated, but Python provides some functions that do just what we need.

You may have noticed all along that I've been talking about string objects.

Remember from the last chapter, objects have both data and operations (they

"know stuff" and "do stuff.") By virtue of being objects, strings have some built-in methods in addition to the generic sequence operations that we have used so far. We'll use some of those abilities here to solve our decoder problem.

For our decoder, we will make use of the

split

method. This method splits a string into a list of substrings. By default, it will split the string wherever a space occurs. Here's an example:

>>> myString = "Hello, string methods ! "

>>> myString . split ( )

['Hello, ' , 'string' , 'methods ! ']

Naturally, the

split

operation is called using the usual dot notation for invoking one of an object's methods. In the result, you can see how

split

has turned the original string

"Hello, string methods ! "

into a list of three substrings:

"Hello, ", " string",

and

"methods ! ".

By the way,

split

can be used to split a string at places other than spaces by supplying the character to split on as a parameter. For example, if we have a string of numbers separated by commas, we could split on the commas:

>>> " 32, 24, 25, 57 " . split ( ", " ) [' 32' ' '24' ' '25' ' '57']

This is useful for getting multiple inputs from the user without resorting to the use of

eval.

For example, we could get the x and y values of a point in a single input string, turn it into a list using the

split

method, and then index into the resulting list to get the individual component strings as illustrated in the following interaction:

>>> coords = input ( " Enter the point coordinates (x, y) : " ) . split ( ", " ) Enter the point coordinates (x, y) : 3.4, 6.25

>>> coords

[ ' 3 . 4' ' ' 6 . 25 ' ]

>>> coords [O]

'3.4'

>>coords [1]

'6 . 25'

5.5. String Methods

Of course, we still need to convert those strings into the corresponding numbers.

Recall from Chapter 3 that we can use the type conversion functions

int

and

float

to convert strings into the appropriate numeric type. In this case, we will use

float

and combine this all into a couple lines of code:

coords = input ( " Enter the point coordinates (x, y) : " ) . split ( ", " ) x, y = float (coords [O] ) , f loat ( coords [1] )

Returning to our decoder, we can use a similar technique. Since our pro­

gram should accept the same format that was produced by the encoder pro­

gram, namely a sequence of Unicode numbers with spaces between, the default version of

split

works nicely:

145

>>> " 87 104 97 1 16 32 97 32 83 1 1 1 1 17 1 14 1 12 1 17 1 15 1 15 33 " . split 0 ['87', '104', '97', '116', '32', '97', '32', '83', '1 1 1', ' 1 17',

'1 14', '1 12', ' 1 17', '1 15', '1 15', '33']

Again, the result is not a list of numbers, but a list of strings. It just so happens these strings contain only digits and

could

be interpreted as numbers. In this case, the strings are int literals, so we'll apply the

int

function to each one in order to convert it to a number.

Using

split

and

int

we can write our decoder program:

# numbers2text . py

# A program to convert a sequence of Unicode numbers into

# a string of text .

def main ( ) :

print ( " This program converts a sequence of Unicode numbers into " ) print ( " the string of text that it represents . \n" )

# Get the message to encode

inString = input ( " Please enter the Unicode-encoded message : " )

# Loop through each substring and build Unicode message message = " "

for numStr in inString . split ( ) :

codeNum - int (numStr) # convert digits to a number

message = message + chr ( codeNum) # concatentate character to message

print ( " \nThe decoded message is : ", message) main ( )

Study this program a bit and you should be able to understand exactly how it accomplishes its task. The heart of the program is the loop:

for numStr in inString . split ( ) : codeNum

=

int (numStr)

message

=

message + chr (codeNum)

The

split

method produces a list of (sub)strings, and

numStr

takes on each successive string in the list. I called the loop variable

numStr

to emphasize that its value is a string of digits that represents some number. Each time through the loop, the next substring is converted to a number by

int

ing it. This number is converted to the corresponding Unicode character via

chr

and appended to the end of the accumulator,

message.

When the loop is finished, every number in

inString

has been processed and

message

contains the decoded text.

Here is an example of the program in action:

This program converts a sequence of Unicode numbers into the string of text that it represents .

Please enter the Unicode-encoded message :

83 1 16 1 14 105 1 10 103 1 15 32 97 1 14 101 32 70 1 17 1 10 33