1 / 17

Formatted I/O

Formatted I/O. The read and print statements are very limited they default to using the standard input and output devices if we want to redirect I/O, we have to specify the proper input or output stream if we want to generate formatted output, we have to use the format command

valencia
Télécharger la présentation

Formatted I/O

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Formatted I/O • The read and print statements are very limited • they default to using the standard input and output devices • if we want to redirect I/O, we have to specify the proper input or output stream • if we want to generate formatted output, we have to use the format command • So we take a look at streams and format here • format is very similar to C’s printf statement • (format stream string vars) • Stream is the stream that you want to redirect the output to • use T to send it to standard output, use nil if you instead want format to return the formatted output as a string to be stored • Format returns nil unless you specify nil as the stream in which case format returns the string – confused? • string and vars are covered next

  2. Specification String • The string supplied to format specifies any literal output that you want as well as the format to be applied to any variables • the variables are optional, but you need to have one variable for every variable specifier in the specification string • Here is a simple example where ~D is the specification for an integer (decimal) value: • (format t “the value of x is ~D and the value of y is ~D” x y) • if x = 5 and y = 10, this will output • the value of x is 5 and the value of y is 10 • if you only supplied variable x, you would get an error • if you supplied more than 2 variables, the excess would be ignored • All specifications will start with ~ and be followed by one or more items: the directive (the way to interpret the datum), and optional arguments such as minimum width specification, justification specification, etc • this gets complicated, so we will look at examples as we see these various specifiers and options

  3. Simple Directives • ~~ — output a ~ • ~% — output a carriage return (start a new line) • ~& — output a fresh line (if we aren’t at the start of a new line, start a new line) • ~n% and ~n& will output n line breaks/new lines • ~| — page break, may or may not work depending on the CL system you are using • ~T – tab, ~nT – tab over n spaces • ~D – output a decimal integer • ~wD – output a decimal integer with at least w characters (pads the output with blanks) • (format t “~10D” 345)  bbbbbbb345 (b = blank) • ~w,’cD – where c is a character, is the same as ~wD except that the character supplied is used for padding • (format t “~10,’*D” 345)  *******345 • ~@D – output the decimal with a + sign for positive (- for negative is always provided with the D argument)

  4. More Directives • For floating point numbers use: • ~F – for normal floating point • ~E – for scientific notation • ~G – use ~F or ~E, which ever will provide the shorter notation • ~$ – use monetary notation (as in xxx.xx) but without a dollar sign • (format t “~$” 32.876)  32.88 • Each of the above permits two width specifiers • the first denotes the total minimum width • the second denotes the number of decimal point digits • the two specifiers are separated by a , • (format t “~10,2F” 1099.87654)  bbb1099.88 • (format t “~10,2E” 1099.87654)  bbb1.10E+3 • To translate a number into another base you can use: • ~O – octal • ~X – hex • ~B – binary • ~bR – base b integer • (format t “~6R” 987)  4323 • (format t “~X” 1000)  3E8

  5. Yet More Directives! • Here’s where things can get fun: • ~R – spell an integer out by name • (format t “~R” 987)  nine hundred and eighty-seven • ~:R – add an ending to the spelled out integer like th • (format t “~:R” 987)  nine hundred and eighty-seventh • ~@R – spell out as Roman numerals • (format t “~@R” 987)  CMLXXXVII • ~P – pluralize the output • (format t “~D bottle~P of beer on the wall” X X) • If X = 1  1 bottle of beer on the wall • If X = 10  10 bottles of beer on the wall • If you use ~:P instead of ~P, then you only need to supply the argument once as in (format t “~D bottle~:P of beer on the wall” X) • ~@P is a variation that chooses whether to use y or ies for an ending • (format t “do you trust your memor~@P?” X)

  6. Directives for Lists of Values • What if you wanted to supply a list and have each item output, but you are unsure as you write your statement how many items will appear in the list? • You could use a loop: • (dolist (x (butlast lis)) (format t “~D, ” x)) (format t “~D” (car (last lis))) • But format gives you a better way to process a list by using ~{ and ~} • (format t “~{~D, ~}~D” (butlast lis) (car (last lis))) • notice that (butlast lis) returns all but the last list item, these are all printed as ~D, or a number followed by a , and a blank, after the list directive ends, we print one more ~D for (car (last lis)) • If we didn’t care about the commas separating the numbers, we could simply to • (format t “~{~D ~}” lis)

  7. Conditional Printing • Imagine that you don’t know which item to print out of a list of options, we can use a conditional statement or a conditional directive • Example: You ask the user for a number, 0, 1 or 2, and are going to print “hello”, “hi”, or “shalom” • (cond ((= x 0) (format t “hello”)) ((= x 1) (format t “hi”)) (t (format t “shalom”))) • Or you can use the ~[ ~] directive by inserting the options inside the [ ] as value~;value~; • (format t “~[hello~;hi~;shalom~]” x) • A binary condition can be presented using ~:[falseoutput~;trueoutput~] • (format t “you ~:[may not~;may~] drink” (>= age 21)) • You may also supply ~@[format~] which takes the next argument and, if not nil, processes it, if nil, discards it • (format t “~{~@[~A~]~}” lis)  outputs all items in lis one at a time with the exception of any nil items, which are not output, merely ignored

  8. Characters, Strings and Miscellany • ~C is used to output a character • ~A is used to output strings, but can be used to output any type, so if you are unsure of the data type, use ~A • ~S is the same as ~A except that escape characters are properly output • ~( … ~) outputs any text in lower case • ~:@(...~) outputs text in upper case • ~:(…~) outputs text in lower case with each new word capitalized (title format) • ~@(...~) outputs text in lower case except the first word which is capitalized (sentence format) • ~< …~> right justifies whatever is inside the brackets, or • ~w<…~> right justifies to a width of size w (w being an int value) • ~V forces the next argument to be used as part of the next directive • (format t “~D ~VD ~VD” 10 5 100 8 1000)  10 100 1000

  9. One Last Example • Imagine that you have two lists: names and addresses • You want to output them row by row in name/address pairs • You can write a loop to accomplish this: • (dotimes (i (length names)) (format t "~%~A~10T~A" (nth i names) (nth i addresses))) • But you could not do this: • (format t “~%~{~A~10T~A~}” names addresses) • because the ~{ ~} empties one list, so you would wind up getting the first 2 names on one line, the next two on the next line, etc, and no addresses • However, you can get around that problem by pairing up the two lists • (setf temp nil) • (dotimes (i (length names)) (setf temp (append temp (list (nth i names)) (list (nth i addresses))))) • (format t “~{~%~A~10T~A~}” temp)

  10. The Last Word on Format • All of our examples to this point have used t as the first parameter to format • This indicates that the output should be sent to the standard-output stream, which is the same stream that print uses • So now we have a better way to output than print • We can use different arguments for this parameter • (setf x (format nil “…”)) returns a string which in this case is stored in x • (format *new-stream* “…”) outputs to *new-stream* • what is *new-stream*? it is a stream that has been defined elsewhere in the code and could represent other windows or files • so next, we look at defining and using streams

  11. Using Streams • All of the input and output instructions can take a stream as an argument and the input/output will be directed to that stream • Built-in streams are: • *standard-input* -- this is what read defaults to using, and is the keyboard in most systems • *standard-output* -- this is what print and format default to using, and is the REPL environment in most systems • *error-output* -- all error messages are sent here, it defaults to *standard-output* but can be redirected, to say a file or another window • *query-io* -- any user-prompt functions send output here and echo input here, this is the case with the function yes-or-no-p, defaults to a pop-up window in LispWorks • *debug-io* -- interactive debugging, defaults to *standard-output* in most cases • *trace-output* -- used by the trace function • *standard-input* and *standard-output* are usually assigned to *terminal-io*, which is the system’s default input and output (keyboard/monitor)

  12. Input Functions • We’ve seen read, but in reality it is more complex: • (read &optional input-stream eof-error-p eof-value recursive-p) • ignoring the last item, eof-error-p returns whether an error arose or not and eof-value contains the type of error • input-stream is whatever stream you want to redirect the input from, for instance a file • read-preserving-whitespace – is read but where whitespace is preserved in the input (this allows code to examine the input and see if it was terminated by a space, an enter key, or other) – whitespace by the way is not just blank spaces, it includes the tab key, enter key, etc • read-line – inputs all characters up to a new line, often used for input from text file • read-char – input a single character • unread-char – for a text file, resets the file pointer to be one previous (in effect, nullifies the most recent read-char operation) • peek-char – returns the next character, but leaves file pointer at the current location • Like read, all of these can have an optional stream to redirect the input and the non-char functions also allow the other optional params (eof, etc)

  13. Output Functions • As with input functions, all of these (including print) can take an optional output stream • Without the output stream, it defaults to *standard-output* • (print object stream) • prin1 is the same as print but print automatically outputs a new line character first, prin1 does not • princ is the same as prin1 except that all escape characters are suppressed • pprint is the same as print except that trailing space is omitted • both prin1 and print are appropriate to generate output that can be read by a read statement, princ cannot • There are also a group of write functions • (write object :stream stream) however these also have several other keyword arguments available: • :escape, :radix, :base, :circle, :pretty, :level, :length, :case, :gensym, :array • we won’t cover what most of these do, but :circle set to nil means that if a list has circularity, then the output will stop after one traversal of the list rather than infinitely repeating it! • in addition, there are write-char, write-string, write-line, prin1-to-string, princ-to-string functions

  14. Miscellany • yes-or-no-p, y-or-n-p – as stated earlier, this function allows you to send a string prompt to the user and receive a yes or no reply • the first function expects the word “yes” or “no”, the latter can take characters or words, both will return T if yes/y is typed in (or clicked if a window pops up) or nil • parse-integer – accepts a string that should be an integer in quotes and returns the appropriate integer value • permits keyword parameters :start, :end :radix, :junk-allowed • assume date stores a date as “xx/xx/xxxx”, we want to add one to the year: • (+ (parse-integer date :start 6) 1) – without :end, it goes from the start point onward • clear-input – clears any buffer associated with the given input stream • terpri – outputs a new line to the given stream • fresh-line – outputs a new line if we aren’t already at the beginning of a new line • finish-output, force-output and clear-output are all available similar to clear-input • read-byte, write-byte – to input/output bytes (binary values) from/to a binary file instead of a text file

  15. Files • Like Java, CL allows you to open, write to/read from, and close files using streams • To open a file, use (open filename) • Open has keyword arguments for :direction :element-type :if-exists and :if-does-not-exist • :direction expects one of :input, :output, :io, :probe (does the file exist? without opening it) • :element-type allows you to specify the expected type of datum to be input/output from/to this file, these types are recognized: character, integer, string-char, bit and :default • :if-exists and :if-does-not-exist allow you to specify what to do if the file exists/does not exist: :error, :new-version, :rename, :rename-and-delete, :overwrite, :append, :create, :supersede, nil (don’t do anything, simply return nil as failure) • Open returns the open stream, but in order to access it you need to store the stream as in (setf infile (open “…” :direction :input :if-does-not-exist nil)) • To close a file, (close stream) • To access the stream, use any of the input or output functions, specifying the stream in the function as in (read infile)

  16. Example • Imagine that you have an input file that consists of numeric data • You want to input each datum and output it to another text file with a description of each datum (for instance, “this is the tenth datum: 31”) • The following code will do this (setf infile (open "c:\\csc375\\data.txt")) (setf outfile (open "c:\\csc375\\output.txt" :direction :output :if-exists :supersede)) (do ((i 1 (+ 1 i)) (temp (read infile nil t) (read infile nil t))) ((not (numberp temp))) (format outfile “This is the ~:R datum: ~A~%" i temp)) (close infile) (close outfile)

  17. Other Stream Functions • with-open-file: this allows you to open a file in a block such that any I/O operations in the block default to using the stream you have opened • rename-file: allows you to rename a file to a new name • delete-file: allows you to delete a given file • file-position: returns the current position, or allows you to change the current position • probe-file: allows you to determine if a file currently exists by the given name • file-write-date: returns the file system’s date/time that a given file was created or last written to • file-author: same but returns the author of the file • file-length: returns the length of a given file as an integer (if the file is a binary file, this is the number of units as measured by the argument :element-type) • load: this loads the given filename into the CL environment, interpreting each item in the file as they are read in • this allows you to write functions and other definitions in a file and load them in prior to starting a given session

More Related