FORMAT(3)
π NAME π
Okay bestie, welcome to FORMAT(3) from SchilyΒ΄s LIBRARY FUNCTIONS, and yes it's giving β¨formatted outputβ¨. format() β generates formatted output as in printf, no cap. π
β¨ SYNOPSIS β¨
int format(cfun, farg, formatstr, formatargs)
int (*cfun)();
void *farg;
char *formatstr;
va_list formatargs;
π¦ DESCRIPTION π¦
format() generates ASCII data, based on a specified input string. It literally knows how to create ASCII representations of all C data types, which is kind of iconic ngl. π
This subroutine takes four arguments:
cfunβ is the address of a function declared in C as
int cfun(ch, farg)
char ch;
void *farg;
cfun is called with each character generated by format(). farg is an arbitrary value passed as the second argument to cfun.
formatstrβ is a format string that controls the output, as described below.formatargsβ points to a list of arguments that are to be formatted.
π Formatting Options π
The format string contains a string to be processed and places where other strings can be inserted. These places are denoted by a % followed by characters which specify how the next argument from formatargs is to be placed in the string. For example, %c inserts a character. The format string "I am printing the letter %c." with the character 'f' results in the string, "I am printing the letter f." β¨
The simplest formatting options are as follows:
%cβ outputs byte as a character%dβ outputs integer as a decimal number%iβ outputs integer as a decimal number%Dβ outputs long as a decimal number%oβ outputs integer as an octal number%Oβ outputs long as an octal number%uβ outputs unsigned integer as a decimal number%xβ outputs integer as a hexadecimal number%Xβ outputs long as a hexadecimal number%lβ outputs long decimal%ldβ outputs long decimal%liβ outputs long decimal%loβ outputs long octal%luβ outputs unsigned long as a decimal number%lxβ outputs long hexadecimal
For more specialized formatting, use the portable set. The syntax for the portable set is:
%<unsigned><intype><outtype>
<unsigned>, <intype>, and <outtype> are one character options, as follows:
<unsigned>β option, character, means:Uβ unsignednoneβ signed
<intype>β option, character, means:Cβ charIβ intSβ shortLβ long
<outtype>β option, character, means:Oβ octalXβ hexadecimalDβ decimal
<intype> indicates the type of argument, while <outtype> indicates the type of format you want <intype> printed in. π
For example, use %CO to output a character in octal or %US to output an unsigned short in decimal. π«Ά
Note that in The C Programming Language, Kernighan and Ritchie document %x and %d; in the portable set, %IX performs the same function as %x, while %ID performs the same function as %d.
Using U for the <unsigned> option is only useful when D is used as the <outtype> option because octal and hexadecimal numbers are never signed.
πΈ Specifying Field Width πΈ
Any type of formatting option can also have a number which further specifies the formatting. The number appears after the percent sign and before any characters. The number is of the form y.z and can be negative. π
y specifies the minimum number of characters that the formatted argument will fill. If the number is positive, the result will be right justified. If it is negative, the result will be left justified. This only specifies a minimum, so if there are more characters than can fit into y characters, the rest will be printed. Thus, "%6c" with the character 'f' results in the following:
"%6c" " f"
"%-6c" "f "
A leading 0 in the y specification causes zero filling for the right justification, so 3 printed in %06d yields "000003". The zero does not mean octal. π
z specifies a maximum number of characters or significant digits and is not used for the above types because they are all fixed length. The z is, however, used in %s, %b, %e, %f, and %g formats.
A field width or the significant digits or both may be indicated by an asterisk (*) instead of a digit string. In this case, an integer arg supplies the field width or the significant digits. The arg that is actually converted is not fetched until the conversion letter is seen, so the args specifying field width or the significant digits must appear before the arg (if any) to be converted. A negative field width argument is taken as a - flag followed by a positive field width. If the significant digits argument is negative, it will be changed to zero.
%sβ Inserts a string.
Useful for printing strings that have no null terminator. The minimum width of the string is y and the maximum width of the string is z.
NOTE: When string formatting reaches a null, the formatting stops. If the y field has specified more characters, the result is padded with blanks. Thus, formatting "test" results in the following:
"%6s" " test"
"%-6s" "test "
"%.2" "te"
"%6.2" " te"
%bβ Inserts a string bounded by a length.
This actually uses TWO arguments: the first is a string, and the second is a number. For instance:
"%b", x, 3 is the same as "%.3s", x
The number argument is used as the maximum number of characters in the string. %b is used when the number of characters used might change with different calls.
%eβ Inserts a floating number in 'e format'.
This is of the form "~.####e*&&":
~β either a minus sign or nothing#'sβ the digits of the mantissa*β either plus or minus&'sβ the digits of the exponent
Thus, 43.5 is formatted as .435e+02 and -.00435 is formatted as -.435e-02. There are always two digits of exponent. The y field gives a minimum width for the entire number, and the z field gives the maximum number of digits in the mantissa. z defaults to 6. Thus, formatting 43.5 results in the following:
"%10e" " .435e+02"
"%-10e" ".435e+02 "
"%5e" ".435e+02"
"%10.1e" " .4e+02"
%Eβ Inserts a floating number in 'E format'.
This is of the form "~.####E*&&", and identical to the %e format except that E is used instead of e in the exponent.
%fβ Inserts a floating number in 'f format'.
This is of the form "~####.&&":
~β either a minus sign or nothing#'sβ the digits before the decimal point&'sβ the digits after the decimal point
The number of #'s is always the number needed. Again, the y field gives a minimum on the size of the entire number, while the z field is the number of significant digits to keep after the decimal point. z defaults to 6. Thus, formatting 1.23456 results in the following:
"%10f" " 1.234560"
"%-10f" "1.234560 "
"%.2f" "1.23"
"%5.2f" " 1.23"
%Fβ Inserts a floating number in 'F format'.
This is mainly the same as the %f format.
%gβ Inserts a floating number in optional format.
Prints in either %e or %f format, whichever is shorter, with the minimum number of digits needed to the right of the decimal. Whole numbers will have no digits to the right of the decimal because trailing zeroes are suppressed. z gives the maximum number of significant digits including digits before the decimal point. z defaults to 6. For example, the format string "%10.4g" results in the following:
435.0 " 435."
4.35 " 4.35"
.0435 " .435e-01"
.000435 " .435e-03"
%Gβ Inserts a floating number in 'G format'.
This outputs the form "~.####E*&&" in case that the exponent variant is used.
%rβ Recursive or remote format.
This takes two arguments: the first is a format string, and the second is a pointer to the argument list. The new format string is formatted and put out in place of the %r.
The field width and significant digit specification is ignored within the %r format. The recursive format makes it possible to write variable arg printing routines without using format(3) directly.
%%β Inserts%.
A double percent sign in the format string becomes a single percent sign in the output. This does not use an argument.
%<SP>β Inserts spaces.
A space character as a format control causes a field of y spaces to be output. This does not use an argument. Note that an actual space should appear where <SP> appears above.
β RETURNS β
the number of characters transmitted excluding the trailing null byte. π
β¨ EXAMPLES β¨
Okay bestie, this is the part where it gets real β two whole worked examples, so you can see how format() actually gets wired into stuff you already use every day. Iconic behaviour only. π
fprintf()(formatted print to a file) could be implemented this way:
#include <stdio.h>
#include <varargs.h>
/* VARARGS2 */
fprintf(f, fmt, va_alist)
FILE *f;
char *fmt;
va_dcl
{
va_list args;
extern int fputc();
va_start(args);
format(&fputc, (long)f, fmt, args);
va_end(args);
}
See how that works? You grab the args with va_start, shove &fputc in as the putc function, pass (long)f as the data it'll hand back to your function, and let format() do the actual glamorous part. Then va_end(args) to clean up after yourself like a responsible main character. πΈ
comerr()could be implemented this way:
#include <stdio.h>
#include <varargs.h>
/* VARARGS1 */
comerr(fmt, va_alist)
char *fmt;
va_dcl
{
va_list args;
int err;
char errbuf[20];
char *errnam;
extern int errno;
extern int sys_nerr;
extern char *sys_errlist[];
err = errno;
va_start(args);
if (err < 0) {
fprintf(stderr, "Progname: %r", fmt, args);
} else {
if (err >= sys_nerr) {
sprintf(errbuf, "Error %d", err);
errnam = errbuf;
} else {
errnam = sys_errlist[err];
}
fprintf(stderr, "Progname: %s. %r",
errnam, fmt, args);
}
va_end(args);
exit(err);
}
Right?? It grabs errno first (saving it in err, because you know something's gonna stomp on it), then branches: if err < 0 you just print "Progname: %r" with the fmt and args. Otherwise it looks up the name β sys_errlist[err] if err is a real boy (i.e. less than sys_nerr), or it formats "Error %d" into errbuf if it's out of range β and prints "Progname: %s. %r". Then exit(err). Chef's kiss. π
π« SEE ALSO π«
Go read these next, they're lowkey the whole friend group:
π NOTES π
Listen up, this part actually matters, don't scroll past it π
- If there are no floating point operations anywhere in the program, the floating point package is not loaded, and therefore floating point printing commands will possibly not work correctly. Like... the linker just won't drag that stuff in if nothing needs it. So if your floats are acting weird for no reason, this might be why. π
- To just print a plain string with zero formatting drama, use the
%sformat β that makes sure the string gets interpreted correctly. This is especially important if the string itself contains%characters, becauseformat()will straight up try to interpret them, which causes unwanted additions in the output string. Not the vibe. π - The number of characters inserted for either
%sor%bshould be less than 512.
So basically: plain string?%sit. Got%signs in your text? Especially%sit. And keep an eye on that 512 limit, bestie. π«Ά
That's the whole page, bestie β you made it to the end and I'm so proud of you π₯Ήβ¨ Big thank you to the legend Joerg Schilling, who wrote this back on 2022/09/09, and this is the FORMAT(3) manual page, in case you forgot where you were (no judgement π). Now go print something pretty. π¦
π¦ where this page comes from
- opensuse-leap 16.0: libschily-devel-doc 2022.10.16-160000.2.2 Β· CDDL-1.0
- Copyright 1985-2020 J. Schilling
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms