Language > Miscellaneous Topics > Format Codes

# Format Codes

Format codes specify either how data should be transferred or how input/output is handled.

## Syntax of Format Codes

The syntax of an IDL format code is:

[n]FC[+][-][width]

Where:

n | is an optional repeat count (1 ≤ n) specifying the number of times the format code should be processed. If n is not specified, a repeat count of one is used.
FC | is the format code. See Available Format Codes, below.
+ | is an optional flag that specifies that positive numbers should be output with a “+” prefix. The “+” flag is only valid for numeric format codes. Normally, negative numbers are output with a “-” prefix and positive numbers have no sign prefix. Non-decimal numeric codes (B, O, and Z) allow the specification of the “+” flag, but ignore it.
- | is an optional flag that specifies that string or numeric values should be output with the text left-justified. Normally, output is right-justified.
width | is an optional width specification. Width specifications and default values are format-code specific, and are described in detail along with the format code. See Padding and Natural Width Formatting, below, for additional information on how output values are formatted based on the width parameter.

### Padding and Natural Width Formatting

The value being formatted may be shorter than the output width specified by the width parameter. When this happens, IDL will adjust either the contents of the output value or the width of the field, using the following mechanisms:

#### Whitespace Padding

By default, if the value being formatted uses fewer characters than specified by the width parameter, IDL pads the value with whitespace characters on the left to create a string of the specified width. For example, the following IDL statement

PRINT, FORMAT='(I12)', 300

produces the following output:

bbbbbbbbb300

where b represents a space character.

#### Zero Padding

For numeric format codes, if the first digit of the width parameter is a zero, IDL will pad the value with zeroes rather than blanks. For example:

PRINT, FORMAT='(I08)', 300

produces the following output:

00000300

When padding values with zeroes, note the following:

1. If you specify the “-” flag to left-justify the output, specifying a leading zero in the width parameter has no effect, since there are no unused spaces to the left of the output value.
2. If you specify an explicit minimum width value (via the m width parameter) for an integer format code, specifying a leading zero in the width parameter has no effect, since the output value is already padded with zeroes on the left to create an output value of the specified minimum width.

#### Natural Width Formatting

If the numeral zero is specified for the width parameter, IDL uses the “natural” width for the value. The value is read or output using a default format without any leading or trailing whitespace, in the style of the standard C library `printf()` function.

Using a value of zero for the width parameter is useful when reading tables of data in which individual elements may be of varying lengths. For example, if your data reside in tables of the following form:

26.01 92.555 344.2

101.0 6.123 99.845

23.723 200.02 141.93

Setting the format to:

FORMAT = '(3F0)'

ensures that the correct number of digits are read or output for each element.

## Available Format Codes

IDL supports the following format codes:

Format Code | Description
A Format Code | Transfers character values
: Format Code | Terminates processing
$ Format Code | Suppresses newlines in output
F, D, E, and G Format Codes | Transfer floating-point values
B, I, O, and Z Format Codes | Transfer integer values
Q Format Code | Returns the number of characters that remain to be transferred during a read operation
Quoted String and H Format Codes | Output string values directly
T Format Code | Specifies the absolute position within a record
TL Format Code | Moves the position with a record to the left
TR and X Format Codes | Move the position within a record to the right
C() Format Code | Transfers calendar data
C printf-Style Quoted String Format Code | Provides an alternative syntax for specifying the format of an output string

## Format Code Examples

For examples using different format codes, see:

- Example: Reading Formatted Table Data
- Example: Reading Records With Multiple Array Elements

## A Format Code

Available Format Codes

The `A` format code transfers character data.

The syntax is:

[n]A[-][w]

where the parameters “n” and “-” are as described in Syntax of Format Codes and the width specification is as follows:

w | is an optional width (0 ≤ w) specifying the number of characters to be transferred. If w is not specified, the entire string is transferred. On output, if w is greater than the length of the string, the string is right justified. On input, IDL strings have dynamic length, so w specifies the resulting length of input string variables. See Padding and Natural Width Formatting for additional details on the output width of a formatted value.

For example, the IDL statement,

PRINT, FORMAT = '(A6)', '123456789'

generates the following output:

123456

## : Format Code

Available Format Codes

The colon format code terminates format processing if there are no more data remaining in the argument list.

The syntax is:

:

For example, the IDL statement,

PRINT, FORMAT = '(6(I1, :, ", "))', INDGEN(6)

will output the following comma-separated list of integer values:

0, 1, 2, 3, 4, 5

The use of the colon format code prevented a comma from being output following the final item in the argument list.

## $ Format Code

Available Format Codes

When IDL completes output format processing, it normally outputs a newline to terminate the output operation. However, if a “$” format code is found in the format specification, this default newline is not output. The “$” format code is only used on output; it is ignored during input formatting.

The syntax is:

$

One use for the “$” format code is in prompting for user input in programs that run in a tty rather than in the graphical IDL Workbench. For example, the following simple program show the difference between strings formatted with and without the “$” format code. The first PRINT statement prompts the user for input without forcing the user’s response to appear on a separate line from the prompt; the second PRINT statement makes the user enter the response on a separate line.

IDL> .run

- PRO format_test

- name=''

- age=0

- PRINT, FORMAT='($, "Enter name")'

- READ, name

- PRINT, FORMAT='("Enter age")'

- READ, age

- PRINT, FORMAT='("You are ", I0, " years old, ", A0)', age, name

- END

% Compiled module: FORMAT_TEST.

Running the procedure looks like this:

IDL> format_test

Enter name: Pat

Enter age

: 29

You are 29 years old, Pat

IDL>

where the values in italics were entered by the user in response to the prompts.

## F, D, E, and G Format Codes

Available Format Codes

The F, D, E, and G format codes are used to transfer floating-point values between memory and the specified file.

The syntax is:

[n]F[+][-][w][.d]

[n]D[+][-][w][.d]

[n]E[+][-][w][.d][Ee]

[n]G[+][-][w][.d][Ee]

where the parameters “n”, “+”, and “-” are as described in Syntax of Format Codes and the width specification is as follows:

w | is an optional width specification (0 ≤ w ≤ 255). The variable w specifies the number of digits to be transferred. See Padding and Natural Width Formatting for additional details on the output width of a formatted value.
d | is an optional width specification (1 ≤ d < w). For the F, D, and E format codes, d specifies the number of positions after the decimal point. For the G format code, d specifies the number of significant digits displayed.
e | is an optional width (1 ≤ e ≤ 255) specifying the width of exponent part of the field. IDL ignores this value—it is allowed for compatibility with FORTRAN.

On input, the F, D, E, and G format codes all transfer w characters from the external field and assign them as a real value to the corresponding input/output argument list datum.

The F and D format codes are used to output values using fixed-point notation. The value is rounded to d decimal positions and right-justified into an external field that is w characters wide. The value of w must be large enough to include a minus sign when necessary, at least one digit to the left of the decimal point, the decimal point, and d digits to the right of the decimal point. The code D is identical to F (except for its default values for w and d) and exists in IDL primarily for compatibility with FORTRAN.

The E format code is used for scientific (exponential) notation. The value is rounded to d decimal positions and right-justified into an external field that is w characters wide. The value of w must be large enough to include a minus sign when necessary, at least one digit to the left of the decimal point, the decimal point, d digits to the right of the decimal point, a plus or minus sign for the exponent, the character “e” or “E”, and at least two characters for the exponent.

Note: IDL uses the standard C library function `snprintf()` to format numbers and their exponents. As a result, different platforms may print different numbers of exponent digits.

The G format code uses the F output style when reasonable and E for other values, but displays exactly d significant digits rather than d digits following the decimal point.

#### Overflow

On output, if the field provided is not wide enough, it is filled with asterisks (`*`) to indicate the overflow condition.

#### Default Values of the w, d, and e Parameters

If w, d, or e are omitted, the values specified in the following table are used.

Data Type | w | d | e
Float, Complex | 15 | 7 | 2 (3 for Windows)
Double | 25 | 16 | 2 (3 for Windows)
All Other Types | 25 | 16 | 2 (3 for Windows)

#### Format Code Examples

The following table shows the results of the application of various format codes to given data values. Note that normally, the case of the format code is ignored by IDL. However, the case of the E and G format codes determines the case used to output the exponent in scientific notation.

Format | Internal Value | Formatted Output
`F` | `100.0` | bbbb `100.0000000`
`F` | `100.0D` | bbbbb `100.0000000000000000`
`F10.0` | `100.0` | bbbbbb `100.`
`F10.1` | `100.0` | bbbbb `100.0`
`F10.4` | `100.0` | bb `100.0000`
`F2.1` | `100.0` | `**`
`e11.4` | `100.0` | b `1.0000e+02` `1.0000e+002 (Windows)` Note that “e10.4” displays “**********” under Windows because the extra “0” added after the “e” makes the string longer than 10 characters.
`E11.4` | `100.0` | b `1.0000E+02` `1.0000E+002 (Windows)`
`g10.4` | `100.0` | bbbbb `100.0`
`g10.4` | `10000000.0` | b `1.000e+07` `1.000e+007 (Windows)`
`G10.4` | `10000000.0` | b `1.000E+07` `1.000E+007 (Windows)`

## B, I, O, and Z Format Codes

Available Format Codes

The B, I, O, and Z format codes are used to transfer integer values to and from the specified file. The B format code is used to output binary values, I is used for decimal values, O is used for octal values, and Z is used for hexadecimal values.

The syntax is:

[n]B[-][w][.m]

[n]I[+][-][w][.m]

[n]O[-][w][.m]

[n]Z[-][w][.m]

where the parameters “n”, “+”, and “-” are as described in Syntax of Format Codes and the width specification is as follows:

w | is an optional width specification (0 ≤ w ≤ 255). The variable w specifies the number of digits to be transferred. See Padding and Natural Width Formatting for additional details on the output width of a formatted value.
m | is an optional minimum number (1 ≤ m ≤ 255) of nonblank digits to be shown on output. The field is zero-filled on the left if necessary. If m is omitted or zero, the output is padded with blanks to achieve the specified width. Note: The m parameter is ignored if w is zero.

#### Overflow

On output, if the field provided is not wide enough, it is filled with asterisks (`*`) to indicate the overflow condition.

#### Default Values of the w Parameter

The default values used by the I, O, and Z format codes if w is omitted are specified in the following table:

Data Type | w
Byte, Int, UInt | 7
Long, ULong, Float | 12
Long64, ULong64 | 22
Double | 23
All Other Types | 12

The default values used by the B format code if w is omitted are specified in the following table:

Data Type | w
Byte | 8
Int, UInt | 16
Long, ULong | 32
Long64, ULong64 | 64
All Other Types | 32

#### Format Code Examples

The following table shows the results of the application of various format codes to given data values. Note that normally, the case of the format code is ignored by IDL. However, the case of the Z format codes determines the case used to output the hexadecimal digits A-F.

Format | Internal Value | Formatted Output
B | 3000 | bbbb101110111000
B15 | 3000 | bbb101110111000
B14.14 | 3000 | 00101110111000
I | 3000 | bbb3000
I6.5 | 3000 | b03000
I5.6 | 3000 | *****
I2 | 3000 | **
O | 3000 | bbb5670
O6.5 | 3000 | b05670
O5.6 | 3000 | *****
O2 | 3000 | **
z | 3000 | bbbbbb8
Z | 3000 | bbbbBB8
Z6.5 | 3000 | b00BB8
Z5.6 | 3000 | *****
Z2 | 3000 | **

## Q Format Code

Available Format Codes

The Q format code returns the number of characters in the input record remaining to be transferred during the current read operation. It is ignored during output formatting.

The syntax is:

q

Format Q is useful for determining how many characters have been read on a line. For example, the following IDL statements count the number of characters in file demo.dat:

;Open file for reading.

OPENR, 1, "demo.dat"

;Create a longword integer to keep the count.

N = 0L

;Count the characters.

WHILE(~ EOF(1)) DO BEGIN

READF, 1, CUR, FORMAT = '(q)' & N = N + CUR

ENDWHILE

;Report the result.

PRINT, FORMAT = '("counted", N, "characters.")'

;Close file.

CLOSE, 1

## Quoted String and H Format Codes

Available Format Codes

On output, any quoted strings or Hollerith constants are sent directly to the output. On input, they are ignored.

The syntax for a quoted string is:

"string" or 'string'

where string is the string to be output.

Note: Quoted strings must be enclosed in either single or double quotation marks; use the type of quotation mark that is not used to enclose the entire format string.

For example, the IDL statement,

PRINT, FORMAT = '("Value: ", I0)', 23

results in the following output:

Value: 23

Note that it would have been equally correct to use double quotes around the entire format string and single quotes around the quoted string “Value: ”.

Another way to specify a quoted string is with a Hollerith constant.

The syntax for a Hollerith constant is:

nHc1c2c3... cn

where

n | is the number of characters in the constant (1 ≤ n ≤ 255).
ci | is the characters that make up the constant. The number of characters must agree with the value provided for n.

For example, the following IDL statement,

PRINT, FORMAT = '(7HValue: , I0)', 23

results in the following output:

Value: 23

See C printf-Style Quoted String Format Code for an alternate form of the Quoted String Format Code that supports C `printf`-style capabilities.

## T Format Code

Available Format Codes

The T format code specifies the absolute position in the current record.

The syntax is:

Tn

where

n | is the absolute character position within the record to which the current position should be set (1 ≤ n).

The T format code differs from the TL, TR, and X format codes primarily in that it specifies an absolute position rather than an offset from the current position. For example,

PRINT, FORMAT = '("First", 20X, "Last", T10, "Middle")'

produces the following output:

FirstbbbbMiddlebbbbbbbbbbLast

where “b” represents a blank space.

## TL Format Code

Available Format Codes

The TL format code moves the current position in the external record to the left.

The syntax is:

TLn

where

n | is the number of characters to move left from the current position (1 ≤ n). If the value of n is greater than the current position, the current position is moved to column one.

The TL format code is used to move backwards in the current record. It can be used on input to read the same data twice or on output to position the output nonsequentially. For example,

PRINT, FORMAT = '("First", 20X, "Last", TL15, "Middle")'

produces the following output:

FirstbbbbbbbbbMiddlebbbbbLast

where “b” represents a blank space.

## TR and X Format Codes

Available Format Codes

The TR and X format codes move the current position in the record to the right.

The syntax is:

TRn

nX

where

n | is the number of characters to skip (1 ≤ n). On input, n characters in the current input record will be passed over. On output, the current output position is moved n characters to the right.

The TR or X format codes can be used to leave whitespace in the output or to skip over unwanted data in the input. For example, either

PRINT, FORMAT = '("First", 15X, "Last")'

or

PRINT, FORMAT = '("First", TR15, "Last")'

results in the following output:

FirstbbbbbbbbbbbbbbbLast

where “b” represents a blank space.

These two format codes differ in one way. Using the X format code at the end of an output record will not cause any characters to be written unless it is followed by another format code that causes characters to be output. The TR format code always writes characters in this situation. Thus,

PRINT, FORMAT = '("First", 15X)'

results in the following output:

First

whereas

PRINT, FORMAT = '("First", TR15)'

results in the following output:

Firstbbbbbbbbbbbbbbb

where “b” represents a blank space. The X code does not cause the blanks to be output unless there is additional output following the blanks.

## C() Format Code

Available Format Codes

The C() format code is used to transfer calendar (Julian date and/or time) data.

The syntax is:

[n]C([c0,c1,...,cx])

where the parameter “n” is as described in Syntax of Format Codes and:

ci | represents optional calendar format subcodes, or any of the standard format codes that are allowed within a calendar specification, as described below

If no ciare provided, the data will be transferred using the standard 24-character system format that includes the day, date, time, and year, as shown in this string:

Thu Aug 13 12:01:32 1979

For input, this default is equivalent to:

C(CDwA, X, CMoA, X, CDI, X, CHI, X, CMI, X, CSI, CYI5)

For output, this default is equivalent to:

C(CDwA, X, CMoA, X, CDI2.2, X, CHI2.2, ":", CMI2.2, ":", CSI2.2, CYI5)

Note: The C() format code represents an atomic data transfer. Nesting within the parentheses is not allowed.

Note: For input using the calendar format codes, a small offset is added to each Julian date to eliminate roundoff errors when calculating the day fraction from hours, minutes, and seconds. This offset is given by the larger of EPS and EPS*Julian, where Julian is the integer portion of the Julian date, and EPS is the EPS field from MACHAR. For typical Julian dates, this offset is approximately 6x10–10 (which corresponds to 5x10–5 seconds). This offset ensures that if the Julian date is converted back to hour, minute, and second, then the hour, minute, and second will have the same integer values as were originally input.

Note: Calendar dates must be in the range 1 Jan 4716 B.C.E. to 31 Dec 5000000, which corresponds to Julian values -1095 and 1827933925, respectively.

### Calendar Format Subcodes

The following is a list of the subcodes allowed within the parenthesis of the C() format code.

Note: The calendar format subcodes are based on the A, I, and F format codes, and share the same options. See Syntax of Format Codes for additional information on the parameters not described explicitly in this section. Note that the default values of the w and d parameters are different in the calendar format subcodes than in the base A, I, and F format codes.

### CMOA Subcodes

The CMOA subcodes transfers the month portion of a date as a string. The format for an all upper case month string is:

CMOA[-][w]

The format for a capitalized month string is:

CMoA[-][w]

The format for an all lower case month string is:

CmoA[-][w]

where:

w | is an optional width (0 ≤ w) specifying the number of characters of the month name to be transferred. If w is not specified, three characters will be transferred. See Padding and Natural Width Formatting for additional details on the output width of a formatted value.

Note: The case of the ‘M’ and ‘O’ of these subcodes will be ignored on input, or if the MONTHS keyword for the current routine is explicitly set.

### CMOI Subcode

The CMOI subcode transfers the month portion of a date as an integer. The format is as follows:

CMOI[+][-][w][.m]

where:

w | is an optional width (0 ≤ w ≤ 255) specifying the width of the field in characters. The default width is 2. See Padding and Natural Width Formatting for additional details on the output width of a formatted value.
m | is an optional minimum number (1 ≤ m ≤ 255) of nonblank digits to be shown on output. The field is zero-filled on the left if necessary. If m is omitted or zero, the output is padded with blanks to achieve the specified width. Note: The m parameter is ignored if w is zero.

### CDI Subcode

The CDI subcode transfers the day portion of a date as an integer. The format is:

CDI[+][-][w][.m]

where:

w | is an optional width (0 ≤ w ≤ 255) specifying the width of the field in characters. The default width is 2. See Padding and Natural Width Formatting for additional details on the output width of a formatted value.
m | is an optional minimum number (1 ≤ m ≤ 255) of nonblank digits to be shown on output. The field is zero-filled on the left if necessary. If m is omitted or zero, the output is padded with blanks to achieve the specified width. Note: The m parameter is ignored if w is zero.

### CYI Subcode

The CYI subcode transfers the year portion of a date as an integer. The format is as follows:

CYI[+][-][w][.m]

where:

w | is an optional width (0 ≤ w ≤ 255) specifying the width of the field in characters. The default width is 4. See Padding and Natural Width Formatting for additional details on the output width of a formatted value.
m | is an optional minimum number (1 ≤ m ≤ 255) of nonblank digits to be shown on output. The field is zero-filled on the left if necessary. If m is omitted or zero, the output is padded with blanks to achieve the specified width. Note: The m parameter is ignored if w is zero.

### CHI Subcodes

The CHI subcodes transfer the hour portion of a date as an integer. The format for a 24-hour based integer is:

CHI[+][-][w][.m]

The format for a 12 hour based integer is:

ChI[+][-][w][.m]

where:

w | is an optional width (0 ≤ w ≤ 255) specifying the width of the field in characters. The default width is 2. See Padding and Natural Width Formatting for additional details on the output width of a formatted value.
m | is an optional minimum number (1 ≤ m ≤ 255) of nonblank digits to be shown on output. The field is zero-filled on the left if necessary. If m is omitted or zero, the output is padded with blanks to achieve the specified width. Note: The m parameter is ignored if w is zero.

Note: For the ChI (12 hour format), the CAPA Subcodes may be used to specify A.M. versus P.M. For CHI (24 hour format), the CAPA subcode is ignored."

### CMI Subcode

The CMI subcode transfers the minute portion of a date as an integer. The format is:

CMI[+][-][w][.m]

where:

w | is an optional width (0 ≤ w ≤ 255) specifying the width of the field in characters. The default width is 2. See Padding and Natural Width Formatting for additional details on the output width of a formatted value.
m | is an optional minimum number (1 ≤ m ≤ 255) of nonblank digits to be shown on output. The field is zero-filled on the left if necessary. If m is omitted or zero, the output is padded with blanks to achieve the specified width. Note: The m parameter is ignored if w is zero.

### CSI Subcode

The CSI subcode transfers the seconds portion of a date as an integer. The format is:

CSI[+][-][w][.m]

where:

w | is an optional width (0 ≤ w ≤ 255) specifying the width of the field in characters. The default width is 2. See Padding and Natural Width Formatting for additional details on the output width of a formatted value.
m | is an optional minimum number (1 ≤ m ≤ 255) of nonblank digits to be shown on output. The field is zero-filled on the left if necessary. If m is omitted or zero, the output is padded with blanks to achieve the specified width. Note: The m parameter is ignored if w is zero.

### CSF Subcode

The CSF subcode transfers the seconds portion of a date as a floating-point value. The format is:

CSF[+][-][w][.d]

where:

w | is an optional width specification (0 ≤ w ≤ 255). The variable w specifies the number of characters in the external field; the default is 5. See Padding and Natural Width Formatting for additional details on the output width of a formatted value.
d | is an optional width specification (1 ≤ d < w). The variable d specifies the number of positions after the decimal point; the default is 2.

#### Overflow

The value of w must be large enough to include at least one digit to the left of the decimal point, the decimal point, and d digits to the right of the decimal point. On output, if the field provided is not wide enough, it is filled with asterisks (*) to indicate the overflow condition.

### CDWA Subcodes

The CDWA subcodes transfers the day of week portion of a data as a string. The format for an all upper case day of week string is:

CDWA[-][w]

The format for a capitalized day of week string is:

CDwA[-][w]

The format for an all lower case day of week string is:

CdwA[-][w]

where:

w | is an optional width (0 ≤ w), specifying the number of characters of the day of week name to be transferred. If w is not specified, three characters will be transferred. See Padding and Natural Width Formatting for additional details on the output width of a formatted value.

Note: The case of the ‘D’ and ‘W’ of these subcodes will be ignored on input, or if the DAYS_OF_WEEK keyword for the current routine is explicitly set.

### CAPA Subcodes

The CAPA subcodes transfers the A.M. or P.M. portion of a date as a string. The format for an all-uppercase A.M. or P.M. string is:

CAPA[-][w]

The format for a capitalized A.M. or P.M. string is:

CApA[-][w]

The format for an all-lowercase A.M. or P.M. string is:

CapA[-][w]

where:

w | is an optional width (0 ≤ w), specifying the number of characters of the A.M. or P.M. string to be transferred. If w is not specified, two characters will be transferred. See Padding and Natural Width Formatting for additional details on the output width of a formatted value.

Note: The case of the first ‘A’ and ‘P’ of these subcodes will be ignored on input, or if the AM_PM keyword for the current routine is explicitly set.

Note: The CAPA subcode is only used if the ChI (12 hour format) subcode is also being used. The CAPA subcode is ignored if the CHI (24 hour format) subcode is being used.

### Standard Format Codes Allowed Within a Calendar Specification

None of these subcodes are allowed outside of a C() format specifier. In addition to the subcodes listed above, only quoted strings, “TL”, “TR”, and “X” format codes are allowed inside of the C() format specifier.

#### Example:

To print the current date in the default format:

PRINT, FORMAT='(C())', SYSTIME(/JULIAN)

The printed result should look something like:

Fri Aug 14 12:34:14 1998

#### Example:

To print the current date as a two-digit month value followed by a slash followed by a two-digit day value:

PRINT, FORMAT='(C(CMOI,"/",CDI))',SYSTIME(/JULIAN)

The printed result should look something like:

8/14

#### Example:

To print the current time in hours, minutes, and floating-point seconds, all zero-filled if necessary, and separated by colons:

PRINT, $

FORMAT='(C(CHI2.2,":",CMI2.2,":",CSF05.2))',SYSTIME(/JULIAN)

The printed result should look something like:

09:59:07.00

Note that to do zero-filling for the floating-point seconds, it is necessary to specify a leading 0 in the width to the CSF format code.

## C printf-Style Quoted String Format Code

Available Format Codes

IDL’s explicitly formatted specifications, which are based on those found in the FORTRAN language, are extremely powerful and capable of specifying almost any desired output. However, they require fairly verbose specifications, even in simple cases. In contrast, the C language (and the many languages influenced by C) have a different style of format specification used by functions such as `printf()` and `snprintf()`. Most programmers are very familiar with such formats. In this style, text and format codes (prefixed by a % character) are intermixed in a single string. User-supplied arguments are substituted into the format in place of the format specifiers. Although less powerful, this style of format is easier to read and write in common simple cases.

IDL supports the use of `printf`-style formats within format specifications, using a special variant of the Quoted String Format Code (discussed in Quoted String and H Format Codes) in which the opening quote starts with a % character (e.g. %“ or %' rather than “ or '). The presence of this % before the opening quote (with no whitespace between them) tells IDL that this is a `printf`-style quoted string and not a standard quoted string.

As a simple example, consider the following IDL statement that uses normal quoted string format codes:

PRINT, FORMAT='("I have ", I0, " monkeys, ", A, ".")', $

23, 'Scott'

Executing this statement yields the output:

I have 23 monkeys, Scott.

Using a `printf`-style quoted string format code instead, this statement could be written:

PRINT, FORMAT='(%"I have %d monkeys, %s.")', 23, 'Scott'

These two statements are completely equivalent in their action. In fact, IDL compiles both into an identical internal representation before processing them.

The `printf`-style quoted string format codes can be freely mixed with any other format code, so hybrid formats like the following are allowed:

PRINT, $

FORMAT='(%"I have %d monkeys, %s,", " and ", I0, " parrots.")',$

23, 'Scott', 5

This generates the output:

I have 23 monkeys, Scott, and 5 parrots.

### Supported “%” Formats

The following table lists the % format codes allowed within a `printf`-style quoted string format code, as well as their correspondence to the standard format codes that do the same thing. In addition to the format codes described in the table, the special sequence %% causes a single % character to be written to the output. This % is treated as a regular character instead of as a format code specifier. Finally, the flags and the width padding options described in Syntax of Format Codes are also available when using `printf`-style format codes.

Printf-Style | Normal-Style | Normal Style Described in Section
%[w.d]e or %[w.d]E | e[w.d] or E[w.d] | F, D, E, and G Format Codes
%[w]b or %[w]B %[w.m]b or %[w.m]B | B[w] B[w.m] | B, I, O, and Z Format Codes
%[w]d or %[w]D %[w.m]D or %[w.m]D %[w]i or %[w]I %[w.m]i or %[w.m]I | I[w] I[w.m] I[w] I[w.m] | B, I, O, and Z Format Codes
%[w]f or %[w]F %[w.d]f or %[w.d]F | F[w] F[w.d] | F, D, E, and G Format Codes
%[w]g or %[w]G %[w.d]g or %[w.d]G | g[w] or G[w] g[w.d] or G[w.d] | F, D, E, and G Format Codes
%[w]o or %[w]O %[w.m]o or %[w.m]O | O[w] O[w.m] | B, I, O, and Z Format Codes
%[w]s or %[w]S | A[w] | A Format Code
%[w]x or %[w]X %[w.m]x or %[w.m]X %[w]z or %[w]Z %[w.m]z or %[w.m]Z | Z[w] Z[w.m] Z[w] Z[w.m] | B, I, O, and Z Format Codes

As indicated in the above table, there is a one to one correspondence between each `printf`-style % format code and one of the normal format codes documented earlier in this chapter. When reading this table, please keep the following considerations in mind:

- The %d (or %D) format is identical to the %i (or %I) format. Note that %D does not correspond to the normal-style D format.
- The w, d, m, and e parameters listed as optional parameters (i.e. between the square brackets, [ ]) are the same values documented for the normal-style format codes, and behave identically to them.
- The default value for the w parameters for `printf`-style formatting is 0, meaning that `printf`-style output produces “natural” width by default. For example, a %d format code corresponds to a normal format code of I0 (not I, which would use the default value for w based on the data type). Similarly, a %e format code corresponds to a normal format code of e0 (not e).
- The E and G format codes allow the following styles for compatibility with FORTRAN:

E[w.dEe] or e[w.dEe]

G[w.dEe] or g[w.dEe]

These styles are not available using the `printf`-style format codes. In other words, the following formats are not allowed:

%[w.dEe]E or %[w.dEe]e

%[w.dEe]G or %[w.dEe]g

- Normal-style format codes allow repetition counts (e.g., 5I0). The
  `printf`-style format codes do not allow this. Instead, each `printf`-style format code has an implicit repetition count of 1.
- Like normal format codes (but unlike the C language `printf()` function), `printf`-style format codes are allowed to be upper or lower case (e.g. %d and %D mean the same thing). Whether or not case has an influence on the resulting output depends on the specific format code. The specific behavior is the same as with the normal-style version for each code.

### Supported “\” Character Escapes

The C programming language allows “escape sequences” that start with the backslash character, \, to appear within strings. These escapes are used in several ways:

1. To specify characters that have no printed representation. For example, \n means linefeed, and \r means carriage return.
2. To remove any special meaning that a character might normally have. For example, \" allows you to create a string containing a double-quote character even though double-quote normally delimits a string. Note that backslash can also be used to escape itself, so "\\" corresponds to a string containing a single backslash character.
3. To introduce arbitrary characters into a string using octal or hexadecimal notation. For example, if the hexadecimal value `b1` represents the ± character in the current font, then the following statement:

print, format='(%"I have \xb1%d monkeys")', 5

results in the following output:

I have ±5 monkeys

Although IDL does not normally support backslash escapes within strings, the escapes described in the following table are allowed within `printf`-style quoted string format codes. If a character not specified in this table is preceded by a backslash, the backslash is removed and the character is inserted into the output without any special interpretation. This means that \" puts a single " character into the output and that " does not terminate the string constant. Another useful example is that \% causes a single % character to be placed into the output without starting a format code. Hence, \% and %% mean the same thing: a single % character with no special meaning.

Escape Sequence | ASCII code
\a | BEL (7B)
\b | Backspace (8B)
\f | Formfeed (12B)
\n | Linefeed (10B)
\r | Carriage Return (13B)
\t | Horizontal Tab (9B)
\v | Vertical Tab (11B)
\ooo | Octal value `ooo` (Octal value of 1-3 digits)
\xhh | Hexadecimal value `hh` (Hex value of 1-2 digits)

Note: Case is ignored in escape sequences: either “\n” or “\N” specifies a linefeed character.

### Differences Between C printf() and IDL printf-Style Formats

IDL’s `printf`-style quoted string format code is very similar to a simplified C language `printf()` format string. However, there are important differences that an experienced C programmer should be aware of:

- The IDL PRINT and PRINTF procedures implicitly add an end-of-line character to the end of the line (unless suppressed by use of the $ format code). Hence, the use of \n at the end of the format string to end the line is neither necessary nor recommended.
- Only the % format sequences listed in the table under Supported “%” Formats are understood by IDL. Most C `printf` functions accept more codes than these, but those codes are not necessary in IDL.
- For example, the C `printf`/`scanf` functions require the use of the %u format code to indicate an unsigned value, and also use type modifiers (h, l, ll) to indicate the size of the data being processed. IDL uses the type of the arguments being substituted into the format to determine this information. Therefore, the u, h, l, and ll codes are not required in IDL and are not accepted.
- The % and \ sequences in IDL `printf`-style strings are case-insensitive. C `printf` is case-sensitive (e.g. \n and \N do not both mean the linefeed character as they do in IDL).
- The C `printf` function allows the use of %n$d notation to specify that arguments should be substituted into the format string in a different order than they are listed. IDL does not support this.
- The C `printf` function allows the use of %*d notation to indicate that the field width will be supplied by the next argument, and the argument following that supplies the actual value. IDL does not support this.
- IDL `printf`-style formats allow %z for hexadecimal output as well as %x. The C `printf()` function does not understand %z. This deviation from the usual implementation is allowed by IDL because IDL programmers are used to treating Z as the hexadecimal format code.
- IDL `printf`-style formats allow %b for binary output. The C `printf()` function does not understand %b.

## Example: Reading Formatted Table Data

IDL explicitly formatted input/output has the power and flexibility to handle almost any kind of formatted data. A common use of explicitly formatted input/output involves reading and writing tables of data. Consider a data file containing employee data records. Each employee has a name (String, 32 columns) and the number of years they have been employed (Integer, 3 columns) on the first line. The next two lines contain each employee’s monthly salary for the last twelve months. A sample file named employee.dat with this format might look like the following:

Bullwinkle 10

1000.0 9000.97 1100.0 2000.0

5000.0 3000.0 1000.12 3500.0 6000.0 900.0

Boris 11

400.0 500.0 1300.10 350.0 745.0 3000.0

200.0 100.0 100.0 50.0 60.0 0.25

Natasha 10

950.0 1050.0 1350.0 410.0 797.0 200.36

2600.0 2000.0 1500.0 2000.0 1000.0 400.0

Rocky 11

1000.0 9000.0 1100.0 0.0 0.0 2000.37

5000.0 3000.0 1000.01 3500.0 6000.0 900.12

The following IDL statements read data with the above format and produce a summary of the contents of the file:

;Open data file for input.

OPENR, 1, 'employee.dat'

;Create variables to hold the name, number of years, and monthly

;salary.

name = '' & years = 0 & salary = FLTARR(12)

;Output a heading for the summary.

PRINT, FORMAT='("Name", 28X, "Years", 4X, "Yearly Salary")'

;Note: The actual dashed line is longer than is shown here.

PRINT, '========'

;Loop over each employee.

WHILE (~ EOF(1)) DO BEGIN

;Read the data on the next employee.

READF, 1, $

FORMAT = '(A32,I3,2(/,6F10.2))', name, years, salary

;Output the employee information. Use TOTAL to sum the monthly

;salaries to get the yearly salary.

PRINT, FORMAT='(A32,I5,5X,F10.2)', name, years, TOTAL(salary)

ENDWHILE

CLOSE, 1

The output from executing these statements on employee.dat is as follows:

Name Years Yearly Salary

======================================================

Bullwinkle 10 32501.09

Boris 11 6805.35

Natasha 10 14257.36

Rocky 11 32500.50

## Example: Reading Records With Multiple Array Elements

Frequently, data are written to files with each record containing single elements of more than one array. One example might be a file consisting of observations of altitude, pressure, temperature, and velocity with each line or record containing a value for each of the four variables. Because IDL has no equivalent of the FORTRAN implied DO list, special procedures must be used to read or write this type of file.

The first approach, which is the simplest, may be used only if all of the variables have the same data type. An array is created with as many columns as there are variables and as many rows as there are elements. The data are read into this array, the array is transposed storing each variable as a row, and each row is extracted and stored into a variable which becomes a vector. For example, the FORTRAN program which writes the data and the IDL program which reads the data are as follows:

### FORTRAN Write:

DIMENSION ALT(100),PRES(100),TEMP(100),VELO(100)

OPEN (UNIT = 1, STATUS='NEW', FILE='TEST')

WRITE(1,'(4(1x,g15.5))')

(ALT(I),PRES(I),TEMP(I),VELO(I),I=1,100)

### IDL Read:

;Open file for input.

OPENR, 1, 'test'

;Define variable (NVARS by NOBS).

A = FLTARR(4,100)

;Read the data.

READF, 1, A

;Transpose so that columns become rows.

A = TRANSPOSE(A)

;Extract the variables.

ALT = A[*, 0]

PRES = A[*, 1]

TEMP = A[*, 2]

VELO = A[*, 3]

Note that this same example may be written without the implied DO list, writing all elements for each variable contiguously and simplifying matters considerably:

### FORTRAN Write:

DIMENSION ALT(100),PRES(100),TEMP(100),VELO(100)

OPEN (UNIT = 1, STATUS='NEW', FILE='TEST')

WRITE (1,'(4(1x,G15.5))') ALT,PRES,TEMP,VELO

### IDL Read:

;Define variables.

ALT = FLTARR(100)

PRES = ALT & TEMP = ALT & VELO = ALT

OPENR, 1, 'test'

READF, 1, ALT, PRES, TEMP, VELO

A different approach must be taken when the columns contain different data types or the number of lines or records are not known. This method involves defining the arrays, defining a scalar variable to contain each datum in one record, then writing a loop to read each line into the scalars, and then storing the scalar values into each array. For example, assume that a fifth variable, the name of an observer which is of string type, is added to the variable list. The FORTRAN output routine and IDL input routine are as follows:

### FORTRAN Write:

DIMENSION ALT(100),PRES(100),TEMP(100),VELO(100)

CHARACTER * 10 OBS(100)

OPEN (UNIT = 1, STATUS = 'NEW', FILE = 'TEST')

WRITE (1,'(4(1X,G15.5),2X,A)')

(ALT(I),PRES(I),TEMP(I),VELO(I),OBS(I),I=1,100)

### IDL Read:

;Access file. Read files containing from 1 to 200 records.

OPENR, 1, 'test'

;Define vector, make it large enough for the biggest case.

ALT = FLTARR(200)

;Define other vectors using the first.

PRES = ALT & TEMP = ALT & VELO = ALT

;Define string array.

OBS = STRARR(200)

;Define scalar string.

OBSS = ''

;Initialize counter.

I = 0

WHILE ~ EOF(1) DO BEGIN

;Read scalars.

READF, 1, $

FORMAT = '(4(1X, G15.5), 2X, A10)', $

ALTS, PRESS, TEMPS, VELOS, OBSS

;Store in each vector.

ALT[I] = ALTS & PRES[I] = PRESS & TEMP[I] = TEMPS

VELO[I] = VELOS & OBS[I] = OBSS

;Increment counter and check for too many records.

IF I LT 199 THEN I = I + 1 ELSE STOP, 'Too many records'

ENDWHILE

If desired, after the file has been read and the number of observations is known, the arrays may be truncated to the correct length using a series of statements similar to the following:

ALT = ALT[0:I-1]

The above statement represents a worst case example. Reading is greatly simplified by writing data of the same type contiguously and by knowing the size of the file. One frequently used technique is to write the number of observations into the first record so that when reading the data the size is known.

Note: It might be tempting to implement a loop in IDL which reads the data values directly into array elements, using a statement such as the following:

FOR I = 0, 99 DO READF, 1, ALT[I], PRES[I], TEMP[I], VELO[I]

This statement is incorrect. Subscripted elements (including ranges) are temporary expressions passed as values to procedures and functions (READF in this example). Parameters passed by value do not pass results back to the caller. The proper approach is to read the data into scalars and assign the values to the individual array elements as follows:

A = 0. & P = 0. & T = 0. & V = 0.
FOR I = 0, 99 DO BEGIN

READF, 1, A, P, T, V

ALT[I] = A & PRES[I] = P & TEMP[I] = T &
VELO[I] = V

ENDFOR