Formatted data – C

For most of the programs it is necessary to communicate with the user by giving the user information about what is going on in the program and by asking its input on decisions. This can be achieved with various functions in C language, however in this post the main emphasis is on using printf and scanf functions and their variations. The reason for focusing mainly on these is simple – It is very useful to display data in a visually pleasing way. Meaning that user can more easily find necessary info and navigate within the program with ease.

Table of Contents

Printing formatted data

Printing functions write data on the screen or other I/O streams (files, stdout, stderr). In C if stream is not given as an argument it is written into stdout (on screen). C language has following printing functions (prototypes listed):

// From stdio.h
int printf(const char* format, ...);
int fprintf(FILE *stream, const char* format, ...);
int dprintf(int fd, const char* format, ...);
int sprintf(char *str, const char* format, ...);
int snprintf(char *str, size_t size, const char* format, ...);

// From stdarg.h
int vprintf(const char* format, va_list ap);
int vfprintf(FILE *stream, const char* format, va_list ap);
int vdprintf(int fd, const char* format, va_list ap);
int vsprintf(char *str, const char* format, va_list ap);
int vsnprintf(char *str, size_t size, const char* format, va_list ap);

Parameters and their meanings:

  • const char *format – Format string, present in every printf function which specifies the format, how data should be written
  • ... – Variable number of arguments, you need to pass as many arguments in addition to format as there are ‘%’ specifiers in the format string (NB! Order is important!).
  • va_list ap – Similar  to variable number of arguments see [ Link ] for different usages of vprintf and printf functions.
  • FILE *stream– Select stream to write to (file, stdout, stderr)
  • int fd – Instead of stream a file descriptor is used
  • char *str – Buffer where the formatted data will be written (NB! make sure buffer is big enough to store your data!)
  • size_t size – Sets the maximum amount of characters to write (safety feature to avoid buffer overflows)

Formatting data

Formatting data follows the following syntax:
%[flags][width][.precision][length]specifier

Table of specifiers:

Specifier Description Sample output
d or i Signed decimal integer -255
u Unsigned decimal integer 1024
o unsigned octal 777
x Unsigned hexadecimal integer f960
X Uppercase unsigned hexadecimal integer FA5B
f Floating point 0.46587
e Scientific notation for floats 4.246284e-02
E Uppercase scientific notation for floats 9.420000E+01
g Shortest representation of %e or %f 6.5e-09
G Shortest representation of %e or %f 5.32
a Hexadecimal floating point number 0x1.bead36p-28
A Uppercase hexadecimal floating point number 0X1.BEAD36P-28
c Character A
s String (array of characters) CodingMeta
p Memory address 0x7fffa538c020
n Stores number of characters printed in corresponding parameter
% Percentage symbol %

Sub-specifier tables will describe the additional formatting for the specifiers.

Flags:

# flag Description
1 Left-justify content, when width field is specified. Defaults to right justificaton.
2 + Forces a number to have a preceeding sign symbol (+ or -)
3 (space) Similar to +, however instead of positive sign a space is added ‘ ‘
4 # Used with o, x, X specifiers adds 0, 0x, 0X prefix. For floating point specifiers (a, A, e, E, f, F, g, G) output is guaranteed to have decimal point.
5 0 Fills additional space with zeroes preceeding the number

Some examples:

printf("1.1. |%8d|\n", 127);
printf("1.2. |%-8d|\n", 127);
printf("2. |%+d|\n", 127);
printf("3. |% d|\n", 127);
printf("4.1. |%#x|\n", 127);
printf("4.2. |%#o|\n", 127);
printf("4.3. |%f|\n", 24.00);
printf("4.4. |%#f|\n", 24.00);
printf("5. |%08d|\n", 127);
1.1. |     127|
1.2. |127     |
2. |+127|
3. | 127|
4.1. |0x7f|
4.2. |0177|
4.3. |24.000000|
4.4. |24.000000|
5. |00000127|

Width:

# width Description
1 (number) Minimum number of characters to be printed. If the printed characters is less than specified number, the value has preceeding spaces ‘ ‘ filling the space.
2 * Width will be specified by additional parameter preceeding the corresponding argument.

Precision:

# Precision Description
1 .(number) For integer specifiers (d, i, o, u, x, X) Minimum numbers of digits to be written. If value is shorter than specified width, value is preceeded with zeroes. Precision 0 means no character is written for value 0. For specifiers (a, A, e, E, f, F) this means number of digits AFTER the decimal point (Default is 6). For specifiers (g, G) this is the maximum number of significant digits to be printed. For specifier (s) this is maximum number of characters to be printed. By default all characters until null terminator (‘\0’) are printed.
2 .* Precision will be specified by additional parameter preceeding the corresponding argument.

Some examples:

printf("1.1. |%.5d|\n", 1214);
printf("1.2. |%.5x|\n", 1214);
printf("1.3. |%.5f|\n", 1214.8242);
printf("1.4. |%.5e|\n", 1214.8242);
printf("1.5. |%8s|\n", "CodingMeta");
printf("2.1. |%*d|\n", 16, 1214);
printf("2.2. |%*e|\n", 16, 1214.8242);
printf("2.3. |%*s|\n", 16, "CodingMeta");
1.1. |01214|
1.2. |004be|
1.3. |1214.82420|
1.4. |1.21482e+03|
1.5. |CodingMeta|
2.1. |            1214|
2.2. |    1.214824e+03|
2.3. |      CodingMeta|

Length specifiers:

length d i u o x X f F e E g G a A c s p n
(none) int unsigned int double int char* void* int*
hh char unsigned char char*
h short unsigned short short*
l long unsigned long wint_t wchar_t* long*
ll long long unsigned long long long long*
j intmax_t uintmax_t intmax_t*
z size_t size_t size_t*
t ptrdiff_t ptrdiff_t ptrdiff_t*
L long double

NB! Length specifiers hh, ll, j, z, t are introduced in C99.

Scanning formatted data

When outputting formatted data was done with printf and similar functions to (mainly) stdout then scanf and similar functions are used to read and store data (mainly) from stdin (from keyboard). For formatting with scanf functions some rules apply:

  • Whitespace characters – function will read and ignore any whitespace characters (space, newline, tab – see isspace function) encountered before the next non-whitespace character. Single whitespace in the format string validates any quantity of whitespace characters extracted from the stream (including none).
  • Non-whitespace characters (except format specifier – ‘%’) – Any non-whitespace characters which are part of format specifier will be read. When read character is whitespace it will be ignored, after which it will continue to read characters matching the format. When it does not match the format, rest of the characters will be left unread from the stream and the function will fail and return a value.
  • Format specifier – Percentage sign ‘%’ with following format specifier indicating the type and format of the data which will be retrieved from the stream and store into the locations pointed by additional arguments. Meaning that additional arguments will be memory addresses of corresponding types.

C language supports multiple functions similar to scanf, prototypes are listed below:

// From stdio.h
int scanf(const char *format, ...);
int fscanf(FILE *stream, const char *format, ...);
int sscanf(const char *str, const char *format, ...);

// From stdarg.h
int vscanf(const char *format, va_list ap);
int vfscanf(FILE *stream, const char *format, va_list ap);
int vsscanf(const char *str, const char *format, va_list ap);

Parameters and their meanings:

  • const char *format – Format string, present in every scanf function which specifies the format, how data should be read
  • ... – Variable number of arguments, you need to pass as many arguments in addition to format as there are ‘%’ specifiers in the format string (NB! Order is important! Takes addresses of variables – pointers!).
  • va_list ap – Similar  to variable number of arguments see [ Link ] for different usages of vprintf and printf functions. Same reasoning applies to vscanf functions.
  • FILE *stream– Select stream to read from (file, stdin)
  • char *str – Buffer where the formatted data will be read from

Formatting data

Format specifer for scanf follows the following syntax:

%[*][width][length]specifier
Table of specifiers:

# Specifier Characters extracted
1 i Any number of digits, optionally preceeded by sign (+ or -). Decimal digits (0-9), preceeding 0 will start reading octal digits (0-7) and 0x hexadecimal digits (0-f).
2 d or u any number of decimal digits (0-9), optionally preceeded by sign (+ or -). d for signed and u for unsigned arguments.
3 o Any number of octal digits (0-7), optionally preceeded by sign (+ or -). Unsigned argument
4 x any number of hexadecimal digits(0-9, a-f, A-F), optionally preceeded by 0x or 0X and sign (+ or -). Unsigned argument.
5 f, e, g, a Series of decimal digits, optionally containing a decimal point, opttionally preceeded by sign (+ or -)
6 c The next character. If a width other than 1 is specified, the function reads exactly width characters and stores them in the successive locations of the array passed as an argument. No null terminator is appended at the end.
7 s any number of non-whitespace characters, stopping at the first whitespace character found. Null terminator is automatically appended at the end.
8 p Sequence of characters representing a pointer. Works the same way as %p in fprintf.
9 n Stores number of characters read in corresponding parameter
10 [characters] Any number of the characters specified between the brackets. A dash (-) that is not the first character may produce non-portable behaviour in some library implementations.
11 [^characters] Any number of characters that are not between the brackets (excluding those characters).
12 % Matches a single percentage symbol ‘%’

Sub-specifiers:

# Sub-specifier Description
1 * An optional starting asterisc indicates that data is to be read from the stream but ignored (e.g. it is not stored in the location pointed by the argument).
2 width Specifies maximum number of characters to be read in the current reading operation (optional)
3 length This alters the expected type of the storage pointed by the corresponding argument (See table below). Applies to one of the following: hh, h, l, ll, j, z, t, L.

Length specifiers:

length d i u o x f e g a c s p n
(none) int* unsigned int* float* char* void** int*
hh char* unsigned char* char*
h short* unsigned short* short*
l long* unsigned long* double* wchar_t* long*
ll long long* unsigned long long* long long*
j intmax_t* uintmax_t* intmax_t*
z size_t* size_t* size_t*
t ptrdiff_t* ptrdiff_t* ptrdiff_t*
L long double*

NB! Length specifiers hh, ll, j, z, t are introduced in C99.

Some examples:

char numbuf[] = "13523.663";
char strbuf[] = "CodingMeta";
char sentence[] = "Lazy Red Fox Sat On The Floor";
char buf[32] = {0};
int ival = 0;
float fval = 0.0;

sscanf(numbuf, "%d", &ival); // ival : 13523
sscanf(numbuf, "%f", &fval); // fval : 13523.663086
sscanf(strbuf, "%[a-zA-Z]s", buf); // buf : CodingMeta
sscanf(strbuf, "%[^M]s", buf); // buf : Coding
sscanf(sentence, "%s", buf); // buf : Lazy
sscanf(sentence, "%[A-Za-z ]s", buf); // buf : Lazy Red Fox Sat On The Floor
sscanf(sentence, "%10[A-Za-z ]s", buf); // buf : Lazy Red F

Escape sequences

Escape sequences are used to print special characters. The most commonly used escape sequences used are \n and \a. The following table has a list of escape sequences available, hover over row to see some extra comments about them.

# Sequence Description
1 \” Doublequote
2 \\ Backslash
3 \a Alert (BEL)
4 \b Backspace
5 \e Escape sequence
6 \f Form feed
7 \n New line
8 \r Carriage return
9 \t Horizontal tab
10 \v Vertical tab
11 \NNN Byte with octal value NNN (1 to 3 digits)
12 \xHH Byte with hexadecimal value HH (1 to 2 digits)
13 \uHHHH Unicode (ISO/IEC 10646) character with hex value HHHH (4 digits)

Some examples:

printf("1. \" Doublequotes \"\n");
printf("2. \\ Backslashes \\\n");
printf("3. \aAlert\n");
printf("4. Backspace 2 times: string\b\b \n");
printf("5. \e[31mEscape sequence (red text)\e[37m\n");
printf("6. Form feed\fExample\n");
printf("7. New Line\nAnother line\n");
printf("8. Carriage Return\r8. New words\n");
printf("9. Horizontal tab\tMore text\n");
printf("10. Vertical tab\vLike form feed\n");
printf("11. Octal value '\055'\n");
printf("12. Hexadecimal value '\x54'\n");
printf("13. Unicode character \u03A3\n");

Output:

Resources

  1. printf – cplusplus [ Link ]
  2. scanf – cplusplus [ Link ]
  3. Data types [ Link ]
  4. Unicode characters [ Link ]

3 thoughts on “Formatted data – C

Comments are closed.