FPRINTF(3P)
π FPRINTF(3P) π
okay bestie, welcome to the POSIX Programmer's Manual page for FPRINTF(3P) β the whole dprintf, fprintf, printf, snprintf, sprintf squad. No cap, this is the formatted-output moment.
β¨ PROLOG β¨
Real talk first: this manual page is part of the POSIX Programmer's Manual. The Linux implementation of this interface may differ β so go check the corresponding Linux manual page for the tea on Linux behavior β or the interface may not be implemented on Linux at all. iykyk.
πΈ NAME πΈ
dprintf, fprintf, printf, snprintf, sprintf β print formatted output π
π¦ SYNOPSIS π¦
#include <stdio.h>
int dprintf(int fildes, const char *restrict format, ...);
int fprintf(FILE *restrict stream, const char *restrict format, ...);
int printf(const char *restrict format, ...);
int snprintf(char *restrict s, size_t n,
const char *restrict format, ...);
int sprintf(char *restrict s, const char *restrict format, ...);
π DESCRIPTION π
Okay so, excluding dprintf() for a sec: the functionality described on this reference page is aligned with the ISO C standard. Any conflict between the requirements described here and the ISO C standard is unintentional. This volume of POSIX.1β2017 defers to the ISO C standard. Periodt.
fprintf() is the one that places output on the named output stream. printf() places output on the standard output stream stdout. sprintf() places output followed by the null byte, '\0', in consecutive bytes starting at *s β and it is the user's responsibility to ensure that enough space is available. Do not skip that part, bestie.
dprintf() is equivalent to fprintf(), except that dprintf() writes output to the file associated with the file descriptor specified by the fildes argument rather than placing output on a stream. Same energy, different destination.
snprintf() is equivalent to sprintf(), with the addition of the n argument which states the size of the buffer referred to by s. If n is zero, nothing shall be written and s may be a null pointer. Otherwise, output bytes beyond the nβ1st shall be discarded instead of being written to the array, and a null byte is written at the end of the bytes actually written into the array. She's giving buffer-aware, she's giving safe-ish.
If copying takes place between objects that overlap as a result of a call to sprintf() or snprintf(), the results are undefined. Not a vibe. Don't overlap.
Each of these functions converts, formats, and prints its arguments under control of the format. The format is a character string, beginning and ending in its initial shift state, if any. The format is composed of zero or more directives: ordinary characters, which are simply copied to the output stream, and conversion specifications, each of which shall result in the fetching of zero or more arguments. The results are undefined if there are insufficient arguments for the format. If the format is exhausted while arguments remain, the excess arguments shall be evaluated but are otherwise ignored. So they get looked at, then politely ignored. Iconic.
Conversions can be applied to the nth argument after the format in the argument list, rather than to the next unused argument. In this case, the conversion specifier character % (see below) is replaced by the sequence "%n$", where n is a decimal integer in the range [1,{NL_ARGMAX}], giving the position of the argument in the argument list. This feature provides for the definition of format strings that select arguments in an order appropriate to specific languages (see the EXAMPLES section). Multilingual slay.
The format can contain either numbered argument conversion specifications (that is, "%n$" and "*m$"), or unnumbered argument conversion specifications (that is, % and *), but not both. The only exception to this is that %% can be mixed with the "%n$" form. The results of mixing numbered and unnumbered argument specifications in a format string are undefined. When numbered argument specifications are used, specifying the Nth argument requires that all the leading arguments, from the first to the (N-1)th, are specified in the format string. No skipping ahead in line, babe.
In format strings containing the "%n$" form of conversion specification, numbered arguments in the argument list can be referenced from the format string as many times as required. Reuse, recycle, reference.
In format strings containing the % form of conversion specification, each conversion specification uses the first unused argument in the argument list. First come, first converted.
All forms of the fprintf() functions allow for the insertion of a language-dependent radix character in the output string. The radix character is defined in the current locale (category LC_NUMERIC). In the POSIX locale, or in a locale where the radix character is not defined, the radix character shall default to a <period> ('.'). So like, usually a dot, but your locale might have opinions.
π Each conversion specification, step by step π
Each conversion specification is introduced by the '%' character or by the character sequence "%n$", after which the following appear in sequence:
- Zero or more flags (in any order), which modify the meaning of the conversion specification. Flag parade.
- An optional minimum field width. If the converted value has fewer bytes than the field width, it shall be padded with
<space>characters by default on the left; it shall be padded on the right if the left-adjustment flag ('-'), described below, is given to the field width. The field width takes the form of an<asterisk>('*'), described below, or a decimal integer. Width is the vibe check for size. - An optional precision that gives the minimum number of digits to appear for the
d,i,o,u,x, andXconversion specifiers; the number of digits to appear after the radix character for thea,A,e,E,f, andFconversion specifiers; the maximum number of significant digits for thegandGconversion specifiers; or the maximum number of bytes to be printed from a string in thesandSconversion specifiers. The precision takes the form of a<period>('.') followed either by an<asterisk>('*'), described below, or an optional decimal digit string, where a null digit string is treated as zero. If a precision appears with any other conversion specifier, the behavior is undefined. Precision, but make it chaotic if you misuse it. - An optional length modifier that specifies the size of the argument. Size matters, technically.
- A conversion specifier character that indicates the type of conversion to be applied. The main character of the directive.
A field width, or precision, or both, may be indicated by an <asterisk> ('*'). In this case an argument of type int supplies the field width or precision. Applications shall ensure that arguments specifying field width, or precision, or both appear in that order before the argument, if any, to be converted. A negative field width is taken as a '-' flag followed by a positive field width. A negative precision is taken as if the precision were omitted. In format strings containing the "%n$" form of a conversion specification, a field width or precision may be indicated by the sequence "*m$", where m is a decimal integer in the range [1,{NL_ARGMAX}] giving the position in the argument list (after the format argument) of an integer argument containing the field width or precision, for example:
printf("%1$d:%2$.*3$d:%4$.*3$d\n", hour, min, precision, sec);
π Flag characters and their meanings π
'β (The<apostrophe>.) The integer portion of the result of a decimal conversion (%i,%d,%u,%f,%F,%g, or%G) shall be formatted with thousands' grouping characters. For other conversions the behavior is undefined. The non-monetary grouping character is used. Commas, but make it locale.-β The result of the conversion shall be left-justified within the field. The conversion is right-justified if this flag is not specified. Left is the moment.+β The result of a signed conversion shall always begin with a sign ('+'or'-'). The conversion shall begin with a sign only when a negative value is converted if this flag is not specified. Sign reveal.<space>β If the first character of a signed conversion is not a sign or if a signed conversion results in no characters, a<space>shall be prefixed to the result. This means that if the<space>and'+'flags both appear, the<space>flag shall be ignored. Space said "not today, plus sign."#β Specifies that the value is to be converted to an alternative form. Foroconversion, it shall increase the precision, if and only if necessary, to force the first digit of the result to be a zero (if the value and precision are both 0, a single0is printed). ForxorXconversion specifiers, a non-zero result shall have0x(or0X) prefixed to it. Fora,A,e,E,f,F,g, andGconversion specifiers, the result shall always contain a radix character, even if no digits follow the radix character. Without this flag, a radix character appears in the result of these conversions only if a digit follows it. ForgandGconversion specifiers, trailing zeros shall not be removed from the result as they normally are. For other conversion specifiers, the behavior is undefined. Alternative form: she's not like other flags.0β Ford,i,o,u,x,X,a,A,e,E,f,F,g, andGconversion specifiers, leading zeros (following any indication of sign or base) are used to pad to the field width rather than performing space padding, except when converting an infinity or NaN. If the'0'and'-'flags both appear, the'0'flag is ignored. Ford,i,o,u,x, andXconversion specifiers, if a precision is specified, the'0'flag shall be ignored. If the'0'and<apostrophe>flags both appear, the grouping characters are inserted before zero padding. For other conversions, the behavior is undefined. Zero padding with rules, okay?
π Length modifiers and their meanings π
hhβ Specifies that a followingd,i,o,u,x, orXconversion specifier applies to asigned charorunsigned charargument (the argument will have been promoted according to the integer promotions, but its value shall be converted tosigned charorunsigned charbefore printing); or that a followingnconversion specifier applies to a pointer to asigned charargument. Tiny types, big energy.hβ Specifies that a followingd,i,o,u,x, orXconversion specifier applies to ashortorunsigned shortargument (the argument will have been promoted according to the integer promotions, but its value shall be converted toshortorunsigned shortbefore printing); or that a followingnconversion specifier applies to a pointer to ashortargument. Short queen behavior.l(ell) β Specifies that a followingd,i,o,u,x, orXconversion specifier applies to alongorunsigned longargument; that a followingnconversion specifier applies to a pointer to alongargument; that a followingcconversion specifier applies to awint_targument; that a followingsconversion specifier applies to a pointer to awchar_targument; or has no effect on a followinga,A,e,E,f,F,g, orGconversion specifier. Long, wide, and unbothered.ll(ell-ell) β bestie this is the double L situation π it says: thed,i,o,u,xorXconversion specifier right after it applies to along longorunsigned long longargument. And if anncomes next? Then the argument is a pointer to along long. yes it's giving "big number energy" and we love that for us π«Άjβ this one says a followingd,i,o,u,xorXapplies to anintmax_toruintmax_targument. Or, if it's followed byn, the argument is a pointer to anintmax_t. maximum int, maximum slay β¨zβ followingd,i,o,u,xorX? Then it's asize_targument, or the corresponding signed integer type. Followingn? Then it's a pointer to a signed integer type corresponding to asize_targument. πtβ followingd,i,o,u,xorX? Then it's aptrdiff_tor the corresponding unsigned type argument. Followingn? Pointer to aptrdiff_targument, periodt.Lβ this one's only for the float girlies πΈ it says a followinga,A,e,E,f,F,gorGconversion specifier applies to along doubleargument.
π¨ If a length modifier shows up with any conversion specifier other than the exact combos listed above, the behavior is undefined. like, we don't know her. no cap. π
β¨ the conversion specifiers and what they actually mean β¨
d,iβ theintargument gets converted to a signed decimal in the style"[-]dddd". The precision sets the minimum number of digits that show up; if the value fits in fewer digits, it gets padded out with leading zeros. Default precision is1. And converting zero with an explicit precision of zero? That's no characters. nada. gone. π«₯oβ the unsigned argument gets converted to unsigned octal format, style"dddd". Precision = minimum digits; fewer digits than that means leading zeros get added. Default precision is1. Zero with an explicit precision of zero produces no characters. π§uβ the unsigned argument gets converted to unsigned decimal format, style"dddd". Same precision rules: minimum digits, padded with leading zeros if needed, default precision1, and zero with explicit precision zero is no characters. βxβ the unsigned argument gets converted to unsigned hexadecimal format, style"dddd", and the letters used are"abcdef". Precision specifies the minimum number of digits; pad with leading zeros if the value needs fewer. Default precision is1. Zero with explicit precision zero β no characters. π₯Xβ literally the same as thexconversion specifier, except the letters"ABCDEF"get used instead of"abcdef". same vibe, uppercase fit πf,Fβ thedoubleargument gets converted to decimal notation in the style"[-]ddd.ddd", where the number of digits after the radix character equals the precision specification. If the precision isn't there, it's taken as6. If the precision is explicitly zero and no'#'flag is present, no radix character appears. If a radix character does appear, at least one digit shows up before it. The low-order digit is rounded in an implementation-defined manner.
A double argument representing an infinity gets converted in one of the styles "[-]inf" or "[-]infinity" β which one is implementation-defined. A double argument representing a NaN gets converted in one of the styles "[-]nan(n-char-sequence)" or "[-]nan" β and which style, plus the meaning of any n-char-sequence, is implementation-defined. The F conversion specifier produces "INF", "INFINITY" or "NAN" instead of "inf", "infinity" or "nan", respectively. shouty infinity, iconic π£
e,Eβ thedoubleargument gets converted in the style"[-]d.dddeΒ±dd", where there's one digit before the radix character (and that digit is non-zero if the argument is non-zero) and the number of digits after it equals the precision. If the precision is missing, it's taken as6. If the precision is zero and no'#'flag is present, no radix character appears. The low-order digit is rounded in an implementation-defined manner. TheEconversion specifier produces a number with'E'instead of'e'introducing the exponent. The exponent always contains at least two digits. If the value is zero, the exponent is zero. π«
A double argument representing an infinity or NaN gets converted in the style of an f or F conversion specifier.
g,Gβ thedoubleargument representing a floating-point number gets converted in stylefore(or styleForEwhen it's aGconversion specifier), depending on the value converted and the precision. Let P equal the precision if it's non-zero,6if the precision is omitted, or1if the precision is zero. Then, if a conversion with styleEwould have an exponent of X:- If
P>Xβ₯-4, the conversion shall be with stylef(orF) and precisionP-(X+1). - Otherwise, the conversion shall be with style
e(orE) and precisionP-1.
- If
Finally, unless the '#' flag is used, any trailing zeros get removed from the fractional portion of the result, and the decimal-point character gets removed if there's no fractional portion left. cleanup era π§Ή
A double argument representing an infinity or NaN gets converted in the style of an f or F conversion specifier.
a,Aβ adoubleargument representing a floating-point number gets converted in the style"[-]0xh.hhhhpΒ±d", where there's one hexadecimal digit before the decimal-point character (and it's non-zero if the argument is a normalized floating-point number, otherwise unspecified) and the number of hexadecimal digits after it equals the precision. If the precision is missing andFLT_RADIXis a power of 2, then the precision shall be sufficient for an exact representation of the value. If the precision is missing andFLT_RADIXis not a power of 2, then the precision shall be sufficient to distinguish values of typedouble, except that trailing zeros may be omitted. If the precision is zero and the'#'flag is not specified, no decimal-point character appears. The letters"abcdef"get used for anaconversion and the letters"ABCDEF"for anAconversion. TheAconversion specifier produces a number with'X'and'P'instead of'x'and'p'. The exponent always contains at least one digit, and only as many more digits as necessary to represent the decimal exponent of 2. If the value is zero, the exponent is zero. π¦
A double argument representing an infinity or NaN gets converted in the style of an f or F conversion specifier.
cβ theintargument gets converted to anunsigned char, and the resulting byte gets written.
If an l (ell) qualifier is present, the wint_t argument gets converted as if by an ls conversion specification with no precision, and an argument that points to a two-element array of type wchar_t β the first element of which contains the wint_t argument to the ls conversion specification, and the second element contains a null wide character.
sβ the argument shall be a pointer to an array ofchar. Bytes from the array get written up to (but not including) any terminating null byte. If the precision is specified, no more than that many bytes get written. If the precision is not specified, or is greater than the size of the array, the application shall ensure that the array contains a null byte. πΈ
If an l (ell) qualifier is present, the argument shall be a pointer to an array of type wchar_t. Wide characters from the array get converted to characters (each as if by a call to the wcrtomb() function, with the conversion state described by an mbstate_t object initialized to zero before the first wide character is converted) up to and including a terminating null wide character. The resulting characters get written up to (but not including) the terminating null character (byte). If no precision is specified, the application shall ensure that the array contains a null wide character. If a precision is specified, no more than that many characters (bytes) get written (including shift sequences, if any), and the array shall contain a null wide character if, to equal the character sequence length given by the precision, the function would need to access a wide character one past the end of the array. In no case shall a partial character be written. no half-characters, we finish what we start π
pβ the argument shall be a pointer tovoid. The value of the pointer gets converted to a sequence of printable characters, in an implementation-defined manner.nβ the argument shall be a pointer to an integer, into which gets written the number of bytes written to the output so far by this call to one of thefprintf()functions. No argument gets converted. πCβ equivalent tolc.Sβ equivalent tols.%β prints a'%'character; no argument is converted. The complete conversion specification shall be%%. the double-percent, the moment, the icon π
π¨ If a conversion specification doesn't match one of the forms above, the behavior is undefined. And if any argument isn't the correct type for its corresponding conversion specification? Also undefined. be so fr, match your types bestie π
In no case shall a nonexistent or small field width cause truncation of a field; if the result of a conversion is wider than the field width, the field gets expanded to contain the conversion result. Characters generated by fprintf() and printf() are printed as if fputc() had been called. π
kay so for the a and A conversion specifiers</p> β if FLT_RADIX is a power of 2, the value shall be correctly rounded to a hexadecimal floating number with the given precision. β¨
For a and A conversions, if FLT_RADIX is not a power of 2 and the result isn't exactly representable in the given precision, the result should be one of the two adjacent numbers in hexadecimal floating style with the given precision β and the extra stipulation (iykyk) is that the error should have a correct sign for the current rounding direction. π
Now for the e, E, f, F, g, and G conversion specifiers, it's giving β¨ precision drama β¨:
- If the number of significant decimal digits is at most
DECIMAL_DIG, then the result should be correctly rounded. - If the number of significant decimal digits is more than
DECIMAL_DIGbut the source value is exactly representable withDECIMAL_DIGdigits, then the result should be an exact representation with trailing zeros. - Otherwise, the source value is bounded by two adjacent decimal strings
L < U, both havingDECIMAL_DIGsignificant digits. The value of the resultant decimal stringDshould satisfyL <= D <= U, with the extra stipulation that the error should have a correct sign for the current rounding direction.
okay and the timestamps, bestie, listen up π β the last data modification and last file status change timestamps of the file shall be marked for update:
- Between the call to a successful execution of
fprintf()orprintf()and the next successful completion of a call tofflush()orfclose()on the same stream or a call toexit()orabort() - Upon successful completion of a call to
dprintf()
π RETURN VALUE π
the moment of truth, the reveal, the main character moment:
Upon successful completion, the dprintf(), fprintf(), and printf() functions shall return the number of bytes transmitted. π
Upon successful completion, the sprintf() function shall return the number of bytes written to s, excluding the terminating null byte.
Upon successful completion, the snprintf() function shall return the number of bytes that would be written to s had n been sufficiently large, excluding the terminating null byte. (yes, even when it didn't actually write them β it's a tease, and honestly? iconic.)
If an output error was encountered, these functions shall return a negative value and set errno to indicate the error. π
And if the value of n is zero on a call to snprintf(), nothing shall be written, the number of bytes that would have been written had n been sufficiently large excluding the terminating null shall be returned, and s may be a null pointer. π«Ά
π ERRORS π
For the conditions under which dprintf(), fprintf(), and printf() fail and may fail, refer to fputc() or fputwc(). (go read those, they have the lore)
In addition, all forms of fprintf() shall fail if:
EILSEQβ A wide-character code that does not correspond to a valid character has been detected.EOVERFLOWβ The value to be returned is greater than{INT_MAX}.
The dprintf() function may fail if:
EBADFβ Thefildesargument is not a valid file descriptor.
The dprintf(), fprintf(), and printf() functions may fail if:
ENOMEMβ Insufficient storage space is available. (we ran out of room, tragic)
The snprintf() function shall fail if:
EOVERFLOWβ The value ofnis greater than{INT_MAX}.
The following sections are informative.
πΈ EXAMPLES πΈ
Bestie, this is the fun part. Buckle up, we're doing eight little mini-tutorials. π
β¨ Printing Language-Independent Date and Time β¨
Okay so the whole vibe here is: you want your date to print the same way no matter what locale your program is swimming in. This statement does that:
printf(format, weekday, month, day, hour, min);
For American usage, format could be a pointer to this string:
"%s, %s %d, %d:%.2d\n"
And that bad boy produces:
Sunday, July 3, 10:02
For German usage, format could be a pointer to this string instead:
"%1$s, %3$d. %2$s, %4$d:%5$.2d\n"
And this definition of format would produce:
Sonntag, 3. Juli, 10:02
Look at the positional arguments (%1$s, %3$d, β¦) doing all that reordering work. The way it just rearranges the pieces for a different language? Obsessed. π
β¨ Printing File Information β¨
This example prints info about the type, permissions, and number of links of a specific file in a directory. So like, ls -l but you built it yourself. Main character energy fr fr.
The first two calls to printf() use data decoded from a previous stat() call. The user-defined strperm() function shall return a string similar to the one at the beginning of the output for this command:
ls -l
The next call to printf() outputs the owner's name if it's found using getpwuid(); the getpwuid() function shall return a passwd structure from which the name of the user is extracted. If the user name is not found, the program instead prints out the numeric value of the user ID. No name? Fine, we'll take the number. π
The next call prints out the group name if it's found using getgrgid(); getgrgid() is very similar to getpwuid() except that it shall return group information based on the group number. Once again, if the group isn't found, the program prints the numeric value of the group for the entry.
The final call to printf() prints the size of the file.
#include <stdio.h>
#include <sys/types.h>
#include <pwd.h>
#include <grp.h>
char *strperm (mode_t);
...
struct stat statbuf;
struct passwd *pwd;
struct group *grp;
...
printf("%10.10s", strperm (statbuf.st_mode));
printf("%4d", statbuf.st_nlink);
if ((pwd = getpwuid(statbuf.st_uid)) != NULL)
printf(" %-8.8s", pwd->pw_name);
else
printf(" %-8ld", (long) statbuf.st_uid);
if ((grp = getgrgid(statbuf.st_gid)) != NULL)
printf(" %-8.8s", grp->gr_name);
else
printf(" %-8ld", (long) statbuf.st_gid);
printf("%9jd", (intmax_t) statbuf.st_size);
...
β¨ Printing a Localized Date String β¨
Here we're getting a localized date string. The nl_langinfo() function shall return the localized date string, which specifies the order and layout of the date. Then strftime() takes that info and, using the tm structure for values, places the date and time information into datestring. Then printf() outputs datestring and the name of the entry. Chain reaction, slay. β¨
#include <stdio.h>
#include <time.h>
#include <langinfo.h>
...
struct dirent *dp;
struct tm *tm;
char datestring[256];
...
strftime(datestring, sizeof(datestring), nl_langinfo (D_T_FMT), tm);
printf(" %s %s\n", datestring, dp->d_name);
...
β¨ Printing Error Information β¨
This one uses fprintf() to write error information to standard error. Classic.
In the first group of calls, the program tries to open the password lock file named LOCKFILE. If the file already exists, this is an error, as indicated by the O_EXCL flag on the open() function. If the call fails, the program assumes that someone else is updating the password file, and the program exits. Politely. πͺ
The next group of calls saves a new password file as the current password file by creating a link between LOCKFILE and the new password file PASSWDFILE.
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#define LOCKFILE "/etc/ptmp"
#define PASSWDFILE "/etc/passwd"
...
int pfd;
...
if ((pfd = open(LOCKFILE, O_WRONLY | O_CREAT | O_EXCL,
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) == -1)
{
fprintf(stderr, "Cannot open /etc/ptmp. Try again later.\n");
exit(1);
}
...
if (link(LOCKFILE,PASSWDFILE) == -1) {
fprintf(stderr, "Link error: %s\n", strerror(errno));
exit(1);
}
...
β¨ Printing Usage Information β¨
This example checks to make sure the program has the necessary arguments, and uses fprintf() to print usage information if the expected number of arguments isn't there. Be nice to your users, bestie. π«Ά
#include <stdio.h>
#include <stdlib.h>
...
char *Options = "hdbtl";
...
if (argc < 2) {
fprintf(stderr, "Usage: %s -%s <file\n", argv[0], Options); exit(1);
}
...
β¨ Formatting a Decimal String β¨
This one prints a key and data pair on stdout. Note use of the asterisk ('*') in the format string; this ensures the correct number of decimal places for the element based on the number of elements requested. That's the little star doing the most. β
#include <stdio.h>
...
long i;
char *keystr;
int elementlen, len;
...
while (len < elementlen) {
...
printf("%s Element%0*ld\n", keystr, elementlen, i);
...
}
β¨ Creating a Pathname β¨
This example creates a pathname using information from a previous getpwnam() function that returned the password database entry of the user.
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
...
char *pathname;
struct passwd *pw;
size_t len;
...
// digits required for pid_t is number of bits times
// log2(10) = approx 10/33
len = strlen(pw->pw_dir) + 1 + 1+(sizeof(pid_t)*80+32)/33 +
sizeof ".out";
pathname = malloc(len);
if (pathname != NULL)
{
snprintf(pathname, len, "%s/%jd.out", pw->pw_dir,
(intmax_t)getpid());
...
}
β¨ Reporting an Event β¨
This example loops until an event has timed out. The pause() function waits forever unless it receives a signal. The fprintf() statement should never occur due to the possible return values of pause().
Lowkey that's the whole point β if you ever see that message print, something has gone extremely wrong. π
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
...
while (!event_complete) {
...
if (pause() != -1 || errno != EINTR)
fprintf(stderr, "pause: unknown error: %s\n", strerror(errno));
...
}
β¨ Printing Monetary Information β¨
This example uses strfmon() to convert a number and store it as a formatted monetary string named convbuf. If it's the first number being printed, the program prints the format and the description; otherwise, it just prints the number. Money money money. πΈ
#include <monetary.h>
#include <stdio.h>
...
struct tblfmt {
char *format;
char *description;
};
struct tblfmt table[] = {
{ "%n", "default formatting" },
{ "%11n", "right align within an 11 character field" },
{ "%#5n", "aligned columns for values up to 99999" },
{ "%=*#5n", "specify a fill character" },
{ "%=0#5n", "fill characters do not use grouping" },
{ "%^#5n", "disable the grouping separator" },
{ "%^#5.0n", "round off to whole units" },
{ "%^#5.4n", "increase the precision" },
{ "%(#5n", "use an alternative pos/neg style" },
{ "%!(#5n", "disable the currency symbol" },
};
...
float input[3];
int i, j;
char convbuf[100];
...
strfmon(convbuf, sizeof(convbuf), table[i].format, input[j]);
if (j == 0) {
printf("%s%s%s\n", table[i].format,
convbuf, table[i].description);
}
else {
printf("%s\n", convbuf);
}
...
β¨ Printing Wide Characters β¨
Okay this one is the spicy one. This example prints a series of wide characters. Suppose that "L@" expands to three bytes:
wchar_t wz [3] = L"@@"; // Zero-terminated
wchar_t wn [3] = L"@@@"; // Unterminated
fprintf (stdout,"%ls", wz); // Outputs 6 bytes
fprintf (stdout,"%ls", wn); // Undefined because wn has no terminator
fprintf (stdout,"%4ls", wz); // Outputs 3 bytes
fprintf (stdout,"%4ls", wn); // Outputs 3 bytes; no terminator needed
fprintf (stdout,"%9ls", wz); // Outputs 6 bytes
fprintf (stdout,"%9ls", wn); // Outputs 9 bytes; no terminator needed
fprintf (stdout,"%10ls", wz); // Outputs 6 bytes
fprintf (stdout,"%10ls", wn); // Undefined because wn has no terminator
In the last line of the example, after processing three characters, nine bytes have been output. The fourth character must then be examined to determine whether it converts to one byte or more. If it converts to more than one byte, the output is only nine bytes. Since there is no fourth character in the array, the behavior is undefined.
π¨ Girl. wn has NO terminator. Two of those lines are literally undefined behavior. Do not do this at home. π¨
π APPLICATION USAGE π
If the application calling fprintf() has any objects of type wint_t or wchar_t, it must also include the <wchar.h> header to have these objects defined. Like, you must. No skipping. β¨
π¦ RATIONALE π¦
If an implementation detects that there are insufficient arguments for the format, it is recommended that the function should fail and report an [EINVAL] error. So like, if you forgot to pass the thing the format string is asking for β the recommendation is to fail loudly, not vibe silently. Periodt. π
π FUTURE DIRECTIONS π
None.
(Yeah. That's the whole section. Nothing coming. The future is, in fact, empty. π)
π SEE ALSO π
- Section 2.5, Standard I/O Streams,
fputc(),fscanf(),setlocale(),strfmon(),wcrtomb() - The Base Definitions volume of POSIX.1β2017, Chapter 7, Locale,
<inttypes.h>,<stdio.h>,<wchar.h>
π COPYRIGHT π
Portions of this text are reprinted and reproduced in electronic form from IEEE Std 1003.1-2017, Standard for Information Technology -- Portable Operating System Interface (POSIX), The Open Group Base Specifications Issue 7, 2018 Edition, Copyright (C) 2018 by the Institute of Electrical and Electronics Engineers, Inc and The Open Group. In the event of any discrepancy between this version and the original IEEE and The Open Group Standard, the original IEEE and The Open Group Standard is the referee document. The original Standard can be obtained online at http://www.opengroup.org/unix/online.html .
Any typographical or formatting errors that appear in this page are most likely to have been introduced during the conversion of the source files to man page format. To report such errors, see https://www.kernel.org/doc/man-pages/reporting_bugs.html .
And that's the whole page, bestie!! π This one came from the IEEE/The Open Group, dated 2017, and lives in the man page as FPRINTF(3P). You made it to the end of all four parts β that's genuinely iconic behavior. Go print something. π
β¨
π¦ where this page comes from
- alpine 3.22: man-pages-posix 2017a-r0 Β· custom
- alpine 3.23: man-pages-posix 2017a-r0 Β· custom
- alpine 3.24: man-pages-posix 2017a-r0 Β· custom
- arch rolling: man-pages 6.19-1
- arch rolling: man-pages 6.20-1 Β· BSD-2-Clause AND BSD-3-Clause AND BSD-4.3TAHOE AND BSD-4-Clause-UC AND GPL-1.0-or-later AND GPL-2.0-only AND GPL-2.0-or-later AND GPL-3.0-or-later AND LGPL-3.0-linking-exception AND LGPL-3.0-or-later AND LicenseRef-Public-Domain AND LicenseRef-UltraPermissive AND Linux-man-pages-1-para AND Linux-man-pages-copyleft AND Linux-man-pages-copyleft-2-para AND Linux-man-pages-copyleft-var AND MIT AND Spencer-94
- nixpkgs unstable: man-pages-posix 2017a
- opensuse-leap 16.0: man-pages-posix 2017a-160000.4.1 Β· SUSE-IEEE
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms