Libraries and Packages: The VOS Interface

2.4 Formatted I/O -- fmtio


SPP includes
complete facilities for formatting numeric and text data for input, output, and internal use.

printf and its relatives

Text and binary numbers formatted as text may be directed to the standard output (STDOUT), the standard error stream (STDERR), a text file, or a string. Note that STDOUT may be redirected to a file or piped to another task in the IRAF cl. Binary values may be formatted via a format specification string. The values to format must be passed in separate procedure calls. The printf() family of procedures performs formatted output. These are similar to the C <stdio> library procedures except that the values to format are not included in the calling sequence because SPP (Fortran) does not handle variable numbers of calling arguments in a portable manner.

Table 2.20: Formatted Output Functions.

The values to format and print are passed via pargT() procedures. There is a separate procedure for each of the SPP data types: bool, char, short, int, long, real, double, and complex. For example, for numerical values, pargr() is used for floating point, pargi() for integer, while pargstr() would be used for strings. Note that the data type specified by the name of the procedure represents the data type of the parameter passed to the format, not the format itself. In general, any SPP data type variable may be formatted by any printf() format specification.

Format Codes

A format specification is a string that describes how values are to be represented in the output. The string may include any text, but fields may be included to format values. These fields have the form %w.dCn. Any text not preceded by a percent character will be written to the output unchanged. The percent character is a required part of the format field and the remainder of the word specifies the form of the output. w is the field width, d is the number of decimal places or the number of digits of precision, C is the format code, and n is radix character (for format code r only). The w and d fields are optional. The string may be a literal, a string variable, or a predefined parameter constant. Therefore, run-time formats are possible. The format codes C are shown in Table 2.21.



Table 2.21: Output Format Codes.

The conventions for the w (field width) specification are as follows:

Table 2.22: Field Width Specifications.

Escape sequences (e.g., \n for newline) are replaced by the appropriate character value on output:

Table 2.23: Escape Sequences.

Note that a newline is not automatically written for every printf() call, as with a Fortran WRITE. Use \n in the format text to explicitly write a newline. (See Example 2.18).



Additional Output Procedures

Substituting eprintf() for printf() would write to the standard error stream STDERR instead of standard output. These two streams are treated separately by the cl. To write to an arbitrary text file, use fprintf(), specifying a file descriptor for an open text file, see Example 2.19.

Similarly, formatted text may be written to a text string variable using sprintf(). This is particularly useful for error messages or runtime formats, i.e., generating a format string to use in another printf() call. Note that sprintf() includes an argument specifying the maximum size of the output character string.



Formatted Input -- scan, et. al.

Formatted input may be read from the standard input stream STDIN, a text file, a string variable, or a cl parameter using the scan family of procedures. Each scan procedure returns an integer status as the function value. This status will contain EOF upon reading end of file.

Table 2.24: Formatted Input Functions.

Note that as with the output (printf() family) procedures, variables are not changed by the scan() procedures. Values read are placed in variables using the gargT() family of procedures.

Table 2.25: Input Functions.

There is a separate gargT() procedure for each of the SPP data types: bool, char, short, int, long, real, double, and complex. A word, as recognized by gargwrd(), is any string separated by white space.



Internal Formatting

These procedures convert a string representation of a number into its binary value. They perform the same function as the garg...() procedures, but do I/O internally. That is, they read from a character string variable, not an input stream or file. Each function may be called repeatedly to decode a string of values delimited by white space or embedded in non-numeric characters.



Table 2.26: Internal Formatting Functions.

There is a separate ctoT() procedure for each of the SPP numeric data types: int, long, real, double, and complex. All of the procedures except ctotok() return the number of non-white input characters converted as the integer function value.

ctotok() returns an integer code identifying the type of token returned. Tokens represent the smallest substrings recognized in the string. The values assigned to the token returned by ctotok() are defined in the include file ctotok.h.

While ctowrd() nominally recognizes words separated by white space, any string enclosed in quotes is treated as a single word.

The dtoc() format (see Table 2.27) is one of the characters e, f, g, h, or m. See "Format Codes" on page 79 for their meaning.





Table 2.27: Conversion Functions.

Character and String Functions

SPP characters are implemented as integers. Character strings are implemented as fixed length arrays of characters (integers) with the element following the last character set to zero to indicate the end of the string. Therefore they cannot be treated simply as scalar variables in assignment statements. There is a family of procedures for assigning and otherwise manipulating strings. The chr...() family of functions convert a single character (type char) to upper or lower case. The converted character is returned as the function value.

Table 2.28: Character Case Conversion Functions.

Note that there are macro definitions to accomplish the same purpose. The macro TO_UPPER() converts a single character to upper case and TO_LOWER() converts a character to lower case. However, these assume that the character is already the appropriate case. These macros are defined in <ctype.h>. The str...() family of procedures deal with character strings (char arrays).

Table 2.29: Basic String Functions.

Note that strlen() returns the number of characters actually occupying the string, not including the EOS character but including any blanks, not the declared size. This is different from the Fortran len function, which returns the declared size of a string, implicitly padded with blanks to the declared size.

Table 2.30: String Index Functions.

Note that the argument char in stridx() and strldx() is not a string (a double quoted literal or char array) but an integer representing a single character. If it's a literal, it should be in single quotes. Otherwise, it should be a scalar char variable.

Table 2.31: Complex String Functions.

Note that macro expansion in strmac() is not recursive.

String Comparisons



Table 2.32: String Comparison Functions.

The strcmp() procedure returns -n if s1 < s2, 0 if s1 = s2, and +n if s1 > s2. The bool procedure strop() determines whether two strings satisfy a logical operation. The function is selected by replacing op with an operator from the list.

For example, to test whether strings are equal, use streq(). Pattern matching characters or metacharacters are defined in the include file <pattern.h>:

Table 2.33: Pattern Matching Metacharacters.

Evaluating Expressions -- evexpr

The evexpr()
procedure is a function which takes an algebraic expression as input, evaluates the expression, and returns the value of the expression as the function value.

Table 2.34: Evaluating Expressions.

The input expression is a character string. It is parsed and reduced to a single value. The operands to the expression may be either constants or identifiers (strings). If an identifier is encountered the user supplied get operand procedure is called to return the value of the operand. Operands are described by the operand structure, and operands are passed about by a pointer to such a structure. The value of the expression is returned as a pointer to an operand structure containing the function value. Operands of different data types may be mixed in an expression with the usual automatic type coercion rules. All SPP data types are supported including strings (char arrays). All SPP operators and intrinsic functions are recognized. (See "Intrinsic Functions" on page 35).

Output is a pointer to an operand structure containing the computed value of the expression. The output operand structure is dynamically allocated by evexpr() and must be freed explicitly by the user with mfree().

Note that the second and third arguments are the int entry point addresses of procedures. The function locpr() is used to return the address of a function. If there is no function supplied, use NULL for the address. A generic example is:

op = evexpr (expr, locpr(getop), locpr(ufcn)) 
with the user-supplied procedures having the calling sequences shown in Table 2.35:

Table 2.35: Calling User-Supplied Procedures.

If a syntax error occurs while parsing the expression evexpr() will take the error action syntax error. The NULL arguments could be replaced by the locpr() addresses of get operand and/or user function procedures if required by the application.

The lexical form of the input expression is the same as that of SPP and the cl for all numeric, character, and string constants and operators. Any other sequence of characters is considered an identifier and will be passed to the user supplied get operand function to be turned into an operand.

This procedure requires the include file <evexpr.h> that defines the operand structure. The operand structure is used to represent all operands in expressions and on the parser stack. Operands are passed to and from the outside world by means of a pointer to an operand structure. The caller is responsible for string storage of string operands passed to evexpr(). evexpr() manages string storage for temporary string operands created during expression evaluation, as well as storage for the final string value if the expression is string valued. In the latter case the value string should be used before evexpr() is called again.

Table 2.36: Evaluating Procedure Data Types.

The following simple example (Example 2.23) evaluates a constant expression and prints the value on the standard output. An only slightly more complicated example (Example 2.24) uses the procedure get_op() to return an operand value.



printf and its relatives
Table 2.20: - Formatted Output Functions.
Format Codes
Table 2.21: - Output Format Codes.
Table 2.22: - Field Width Specifications.
Table 2.23: - Escape Sequences.
Additional Output Procedures
Formatted Input -- scan, et. al.
Table 2.24: - Formatted Input Functions.
Table 2.25: - Input Functions.
Internal Formatting
Table 2.26: - Internal Formatting Functions.
Table 2.27: - Conversion Functions.
Character and String Functions
Table 2.28: - Character Case Conversion Functions.
Table 2.29: - Basic String Functions.
Table 2.30: - String Index Functions.
Table 2.31: - Complex String Functions.
String Comparisons
Table 2.32: - String Comparison Functions.
Table 2.33: - Pattern Matching Metacharacters.
Evaluating Expressions -- evexpr
Table 2.34: - Evaluating Expressions.
Table 2.35: - Calling User-Supplied Procedures.
Table 2.36: - Evaluating Procedure Data Types.

Generated with CERN WebMaker