"This is a string!"Special characters can be included in a string by escaping them with a back-slash:
"Type \"stop\" to quit."
"I am very excited by the Scheme programming language!!!"Scheme regards the first character (I) as being in position 0, followed by a blank or space character in position 1. The letters 'a' and 'm' follow in positions 2 and 3, respectively.
| Procedure | Sample Call | Result of Example | Comment |
|---|---|---|---|
| string | (string #\a #\b #\c) | "abc" | make a string of the given characters |
| string? | (string? "sample string") | True (#t) | is argument a string? |
| string-length | (string-length "sample string") | 13 | number of characters in string |
| string-append | (string-append "Big" "Small") | "BigSmall" | concatenate two strings |
| substring | (substring "sample string" 3 10) | "ple str" | extract characters from first to before second designated position from string |
| string-ref | (string-ref "sample string" 4) | #\l | return character at given position |
| string->list | (string->list "example") | (#\e #\x #\a #\m #\p #\l #\e) | makes a list of the characters in a string |
| list->string | (list->string '(#\e #\x #\a #\m #\p #\l #\e)) | "example" | makes a string of the characters in a list |
| symbol->string | (symbol->string 'example) | "example" | change a given symbol to a string |
| string->symbol | (string->symbol "example") | example | convert a given string to a symbol |
| number->string | (number->string 3.141592) | "3.141592" | change a given number to a string |
| string->number | (string->number "3.141592") | 3.141592 | convert a given string to a number |
| Predicate | Comment |
|---|---|
| string=? | Are two strings equal? |
| string | Does first string come first? |
| string>? | Does first string come after? |
| string<=? | Is first string equal the second or does the first come before the second? |
| string>=? | Are the strings equal or does the first come after the second? |
| string-ci=? | Same as string=?, but ignoring case |
| string-ci | Same as string, but considering uppercase and lowercase letters to be equivalent |
| string-ci>? | Same as string>?, but ignoring case |
| string-ci<=? | Same as string<=?, but ignoring case |
| string-ci>=? | Same as string>=?, but ignoring case |
With this in mind, we might consider how to generate appropriate passwords in some random way. One approach begins by noting that it is relatively easy for a user to remember a sequence of three letters, if the first letter is a consonant, the second letter is a vowel, and the third is again a consonant. Such three-letter "words" generally are pronounceable and possible to remember.
To make passwords more secure, it also is desirable to include a mix of characters, including uppercase and lowercase letters, digits, and punctuation. The following password generator incorporates each of these ideas:
(define gen-password
(lambda ()
(let* ((consonants "bcdfghjklmnpqrstvwxyzBCDFGHJKLMNPQRSTVWXYZ")
(cons-len (string-length consonants))
(vowels "aeiouAEIOU")
(vowel-len (string-length vowels))
(digits "0123456789")
(punctuation ".,<>?/`~!@#$%^&*()_-+={[}]|")
(punc-len (string-length punctuation))
)
(string (string-ref consonants (random cons-len))
(string-ref vowels (random vowel-len))
(string-ref consonants (random cons-len))
(string-ref digits (random 10))
(string-ref punctuation (random punc-len))
(string-ref consonants (random cons-len))
(string-ref vowels (random vowel-len))
(string-ref consonants (random cons-len))
)
)
)
)
It has been estimated that a modern password-cracking program working on a medium-level personal computer can analyze about 70,000 passwords in a day to determine if a user has chosen that password. Using this estimate, about how long might it take a modern personal computer to analyze all the passwords generated by the above (gen-password) procedure?
Note: number->string returns a string of characters, and you can use the string-append procedure to put strings of characters together.
The next part of this lab develops a procedure to determine if a password satisfies this guideline. The first task is to define a procedure that checks if any letter in a string contains an uppercase letter. One approach searches subsequent characters in the string until either an uppercase letter is found or until all letters have been checked. Organizing this work into a husk-and-kernel yields the following code:
(define contains-upper?
(lambda (str)
(upper-kernel str (- (string-length str) 1))
)
)
(define upper-kernel
(lambda (str pos)
(cond ((< pos 0) #f)
((char-upper-case? (string-ref str pos)) #t)
(else (upper-kernel str (- pos 1)))
)
)
)
(good-password? "aEioU") ==> #f (only 2 categories) (good-password? "aei12U") ==> #t (good-password? "A;e") ==> #f (too short) (good-password? "abc-?B") ==> #t (good-password? ";!$XYZ") ==> #f (only 2 categories) (good-password? ";3BB45") ==> #t
This document is available on the World Wide Web as
http://www.cs.grinnell.edu/~walker/courses/151.sp99/lab-strings.html