By default, printed values are implicitly separated by whitespace. The implicit separator character (space/blank) is a separator not a terminator for output. The rules for implicitly adding the separator are:
sout | 1 | 2 | 3; 1␣2␣3
sout | '1' | '2' | '3'; 123
sout | 1 | "" | 2 | "" | 3; 123
sout | 1 | ", x" | 2 | ". x" | 3 | "; x" | 4 | "! x" | 5 | "? x" | 6 | "% x" | 7 | "¢ x" | 8 | "» x" | 9 | ") x" | 10 | "] x" | 11 | "} x"; 1, ␣x␣2. ␣x␣3; ␣x␣4! ␣x␣5? ␣x␣6% ␣x␣7¢ ␣x␣8» ␣x␣9) ␣x␣10] ␣x␣11} ␣x
sout | "x (" | 1 | "x [" | 2 | "x {" | 3 | "x =" | 4 | "x $" | 5 | "x £" | 6 | "x ¥" | 7 | "x ¡" | 8 | "x ¿" | 9 | "x «" | 10; x␣( 1␣x␣[ 2␣x␣{ 3␣x␣= 4␣x␣$ 5␣x␣£ 6␣x␣¥ 7␣x␣¡ 8␣x␣¿ 9␣x␣« 10
sout | "x`" | 1 | "`x'" | 2 | "'x\"" | 3 | "\"x:" | 4 | ":x " | 5 | " x\t" | 6 | "\tx"; x` 1` x' 2' x" 3" x: 4: x␣ 5␣ x␣␣␣ 6␣␣␣ x
sout | "x (␣ " | 1 | "␣ ) x" | 2 | "␣ , x" | 3 | "␣ :x:␣ " | 4; x␣(␣ 1␣ )␣x␣2␣ ,␣x␣3␣ :x:␣ 4
The following manipulators control implicit output separation.
The effect of these manipulators is global for an output stream (except
sepSet( sout, ", $" ); // set separator from " " to ", \$" sout | 1 | 2 | 3 | " \"" |sepVal | "\""; 1,␣$ 2,␣$ 3␣",␣$" sepSet( sout, " " ); // reset separator to " " sout | 1 | 2 | 3 | " \"" |sepGet( sout ) | "\""; 1␣ 2␣ 3␣"␣"
char store[sepSize ]; // sepSize is the maximum separator size strcpy( store, sepGet( sout ) ); // copy current separator sepSet( sout, "_" ); // change separator to underscore sout | 1 | 2 | 3; 1_ 2_ 3 sepSet( sout, store ); // change separator back to original sout | 1 | 2 | 3; 1␣ 2␣ 3
[int, int, int] t1 = [1, 2, 3], t2 = [4, 5, 6]; sepSetTuple( sout, " " ); // set tuple separator from ", " to " " sout | t1 | t2 | " \"" |sepTupleVal | "\""; 1␣2␣3␣4␣5␣6␣"␣" sepSetTuple( sout, ", " ); // reset tuple separator to ", " sout | t1 | t2 | " \"" |sepGetTuple( sout ) | "\""; 1,␣2,␣3␣4,␣5,␣6␣",␣"
sout |sepOff | 1 | 2 | 3; // turn off implicit separator 123 sout |sepOn | 1 | 2 | 3; // turn on implicit separator 1␣2␣3
sout | 1 |The tuple separator also responses to being turned on and off.nosep | 2 | 3; // turn off implicit separator for the next item 12␣3 sout | sepOff | 1 |sep | 2 | 3; // turn on implicit separator for the next item 1␣23
sout | t1 |nosep | t2; // turn off implicit separator for the next item 1,␣2,␣34,␣5,␣6
sout |sep | 1 | 2 | 3 |sep ; // sep does nothing at start/end of line 1␣2␣3 sout |sepVal | 1 | 2 | 3 |sepVal ; // use sepVal to print separator at start/end of line␣ 1␣2␣3␣
The following manipulators control newline separation for input and output. For input:
For example, in:
sin | i |nl | j; 12 3
variable
sout |Note, a terminatingnl ; // only print newline sout | 2; // implicit newline sout | 3 |nl | 4 |nl ; // terminating nl merged with implicit newline sout | 5 |nl |nl ; // again terminating nl merged with implicit newline sout | 6; // implicit newline 2 3 4 5 6
The following manipulators control formatting of output values (printing), and only affect the format of the argument.
sout | bin( 0 ) | bin( 27HH ) | bin( 27H ) | bin( 27 ) | bin( 27L ); 0b0 0b11011 0b11011 0b11011 0b11011 sout | bin( -27HH ) | bin( -27H ) | bin( -27 ) | bin( -27L ); 0b11100101 0b1111111111100101 0b11111111111111111111111111100101 0b(58 1s) 100101
sout | oct( 0 ) | oct( 27HH ) | oct( 27H ) | oct( 27 ) | oct( 27L ); 0 033 033 033 033 sout | oct( -27HH ) | oct( -27H ) | oct( -27 ) | oct( -27L ); 0345 0177745 037777777745 01777777777777777777745Note, octal 0 is not preceded by
sout | hex( 0 ) | hex( 27HH ) | hex( 27H ) | hex( 27 ) | hex( 27L ); 0 0x1b 0x1b 0x1b 0x1b sout | hex( -27HH ) | hex( -27H ) | hex( -27 ) | hex( -27L ); 0xe5 0xffe5 0xffffffe5 0xffffffffffffffe5 sout | hex( 0.0 ) | hex( 27.5F ) | hex( 27.5 ) | hex( 27.5L ); 0x0.p+0 0x1.b8p+4 0x1.b8p+4 0xd.cp+1 sout | hex( -27.5F ) | hex( -27.5 ) | hex( -27.5L ); -0x1.b8p+4 -0x1.b8p+4 -0xd.cp+1
sout | sci( 0.0 ) | sci( 27.5 ) | sci( -27.5 ); 0.000000e+00 2.750000e+01 -2.750000e+01
sout | eng( 0.0 ) | eng( 27000.5 ) | eng( -27.5e7 ); 0e0 27.0005e3 -275e6
sout | unit(eng( 0.0 )) | unit(eng( 27000.5 )) | unit(eng( -27.5e7 )); 0 27.0005K -275M
sout | upcase( bin( 27 ) ) | upcase( hex( 27 ) ) | upcase( 27.5e-10 ) | upcase( hex( 27.5 ) ); 0B 11011 0X 1B 2.75E -09 0X 1.B 8P +4
sout | nobase( bin( 27 ) ) | nobase( oct( 27 ) ) | nobase( hex( 27 ) ); 11011 33 1b
sout | 0. | nodp( 0. ) | 27.0 | nodp( 27.0 ) | nodp( 27.5 ); 0.00 27.027 27.5
sout | sign( 27 ) | sign( -27 ) | sign( 27. ) | sign( -27. ) | sign( 27.5 ) | sign( -27.5 );+ 27 -27+ 27.0 -27.0+ 27.5 -27.5
sout | wd( 4, 34) | wd( 3, 34 ) | wd( 2, 34 ); sout | wd( 10, 4.) | wd( 9, 4. ) | wd( 8, 4. ); sout | wd( 4, "ab" ) | wd( 3, "ab" ) | wd( 2, "ab" );If the value is larger, it is printed without truncation, ignoring the minimum.␣␣ 34␣␣ 34␣34␣␣ 4.000000␣␣ 4.000000␣4.000000␣␣ ab␣␣ ab ab
sout | wd( 4, 34567 ) | wd( 3, 34567 ) | wd( 2, 34567 ); sout | wd( 4, 3456. ) | wd( 3, 3456. ) | wd( 2, 3456. ); sout | wd( 4, "abcde" ) | wd( 3, "abcde" ) | wd( 2,"abcde" ); 3456For integer types, precision is the minimum number of printed digits. If the value is shorter, it is padded on the left with leading zeros.7 ␣34567 ␣34567 3456. ␣3456. ␣3456. abcde ␣abcde ␣abcde
sout | wd( 4,3, 34 ) | wd( 8,4, 34 ) | wd( 10,10, 34 ); ␣If the value is larger, it is printed without truncation, ignoring the precision.0 34␣␣␣␣␣00 34␣00000000 34
sout | wd( 4,1, 3456 ) | wd( 8,2, 3456 ) | wd( 10,3, 3456 ); 3456␣␣␣␣␣3456␣␣␣␣␣␣␣3456If precision is 0, nothing is printed for zero. If precision is greater than the minimum, it becomes the minimum.
sout | wd( 4,0, 0 ) | wd( 3,10, 34 );For floating-point types, precision is the minimum number of digits after the decimal point.␣␣␣␣ ␣00000000 34
sout | wd( 6,3, 27.5 ) | wd( 8,1, 27.5 ) | wd( 8,0, 27.5 ) | wd( 3,8, 27.5 ); 27.For the C-string type, precision is the maximum number of printed characters, so the string is truncated if it exceeds the maximum.500 ␣␣␣␣␣27.5 ␣␣␣␣␣␣28.␣27.50000000
sout | wd( 6,8, "abcd" ) | wd( 6,8, "abcdefghijk" ) | wd( 6,3, "abcd" ) |Note, printing the null string with minimum width L pads with L spaces.wd( 10, "" ) | 'X'; ␣␣abcd␣abcdefgh␣␣␣␣abc␣␣␣␣␣␣␣␣␣␣ X
sout | ws(6,6, 234.567) | ws(6,5, 234.567) | ws(6,4, 234.567) | ws(6,3, 234.567); 234.567 234.5If a value's magnitude is greater than significant, the value is printed in scientific notation with the specified number of significant digits.7 234.6 235
sout | ws(6,6, 234567.) | ws(6,5, 234567.) | ws(6,4, 234567.) | ws(6,3, 234567.); 234567. 2.3457If significant is greater than minimum, it defines the number of printed characters.e+05 2.346e+05 2.35e+05
sout | ws(3,6, 234567.) | ws(4,6, 234567.) | ws(5,6, 234567.) | ws(6,6, 234567.); 234567. 234567. 234567. 234567.
sout | left(wd(4, 27)) | left(wd(10, 27.)) | left(wd(10, 27.5)) | left(wd(4,3, 27)) | left(wd(10,3, 27.5)); 2727.000000 27.500000 027 27.500
sout | pad0( wd( 4, 27 ) ) | pad0( wd( 4,3, 27 ) ) | pad0( wd( 8,3, 27.5 ) );00 270 2700 27.500
The format of numeric input values in the same as C constants without a trailing type suffix, as the input value-type is denoted by the input variable.
For
For floating-point types, any number of decimal digits, optionally preceded by a sign (
The following manipulators control formatting of input values (reading), and only affect the format of the argument.
char sk[] = "abc"; sin | "abc " | skip( sk ) | skip( 5 ); // match input sequenceabc␣␣␣ abc␣␣ xx
char s[10]; int i; double d; sin | wdi( 4, s ) | wdi( 3, i ) | wdi( 8, d ); // c == "abcd", i == 123, d == 3.456E+2Note, inputabcd1233.456E+2
double d; sin | ignore( d ); // d is unchanged␣␣-75.35e-4 ␣25
char s[10]; sin | incl( "abc", s );bca xyz
char s[10]; sin | excl( "abc", s );xyz bca
When a stream is shared by multiple threads, input or output characters can be intermixed or cause failure. For example, if two threads execute the following:
thread1 : sout | "abc " | "def "; thread2 : sout | "uvw " | "xyz ";
possible outputs are:
abc def uvw xyz |
abc uvw xyz def |
uvw abc xyz def |
abuvwc dexf yz |
uvw abc def xyz |
As a result, some form of mutual exclusion is required for concurrent stream access. C∀ streams contain a recursive lock and the stream has the lock trait so it can be used with the mutex statement.
The common usage is the short form of the mutex statement for expression statements, e.g.:
thread1 :mutex( sout ) sout | "abc " | "def "; thread2 :mutex( sout ) sout | "uvw " | "xyz ";
Now, the order of the thread execution is still non-deterministic, but the output is constrained to two possible lines in either order.
abc def uvw xyz |
uvw xyz abc def |
To lock a stream across multiple I/O operations, the long form of the mutex statement is used, e.g.:
mutex( sout ) { sout | 1;mutex( sout ) sout | 2 | 3; // unnecessary, but ok because of recursive lock sout | 4; } // implicitly release sout lock
Note, the unnecessary
The previous values written by threads 1 and 2 can be read in concurrently:
mutex( sin ) { int x, y, z, w; sin | x;mutex( sin ) sin | y | z; // unnecessary, but ok because of recursive lock sin | w; } // implicitly release sin lock
Again, the order of the reading threads is non-deterministic. Note, non-deterministic reading is rare.
WARNING: The general problem of nested locking can occur if routines are called in an I/O sequence that block, e.g.:
mutex( sout ) sout | "data:" | rtn( mon ); // mutex call on monitor
If the thread executing the I/O expression blocks in the monitor with the
intdata = rtn( mon ); mutex( sout ) sout | acquire | "data:" |data ;
Cultures use different syntax, called a locale, for printing numbers so they are easier to read, e.g.:
12, 345. 123 // comma separator, period decimal-point 12. 345, 123 // period separator, comma decimal-point 12␣ 345, 123. // space separator, comma decimal-point, period terminator
A locale is selected with function
#include <fstream.hfa> #include <locale.h> // setlocale #include <stdlib.h> // getenv int main() { void print() { sout | 12 | 123 | 1234 | 12345 | 123456 | 1234567; sout | 12. | 123.1 | 1234.12 | 12345.123 | 123456.1234 | 1234567.12345; sout | nl; } sout | "Default locale off"; print(); sout | "Locale on" |setlocale( LC_NUMERIC, getenv( "LANG" ) ) ; // enable local locale print(); sout | "German" |setlocale( LC_NUMERIC, "de_DE.UTF-8" ) ; // enable German locale print(); sout | "Ukraine" |setlocale( LC_NUMERIC, "uk_UA.utf8" ) ; // enable Ukraine locale print(); sout | "Default locale off" |setlocale( LC_NUMERIC, "C" ) ; // disable locale print(); } Default locale off 12 123 1234 12345 123456 1234567 12. 123.1 1234.12 12345.123 123456.1234 1234567.12345 Locale on en_US.UTF-8 12 123 1, 234 12, 345 123, 456 1, 234, 567 12. 123. 1 1, 234. 12 12, 345. 123 123, 456. 1234 1, 234, 567. 12345 German de_DE.UTF-8 12 123 1. 234 12. 345 123. 456 1. 234. 567 12. 123, 1. 1. 234, 12 12. 345, 123 123. 456, 1234 1. 234. 567, 12345 Ukraine uk_UA. utf8 12 123 1 234 12 345 123 456 1 234 567 12. 123, 1. 1␣ 234, 12. 12␣ 345, 123. 123␣ 456, 1234. 1␣ 234␣ 567, 12345. Default locale off C 12 123 1234 12345 123456 1234567 12. 123.1 1234.12 12345.123 123456.1234 1234567.12345