scanf(3)
๐ scanf(3) โ bestie edition ๐
okay so you're looking at the scanf(3) page from the Library Functions Manual, and tbh this is the iconic messy queen of stdio. she scans formatted input. she's also, and I cannot stress this enough, kind of a nightmare. let's get into it ๐ซถ
โจ NAME โจ
scanf, fscanf, vscanf, vfscanf โ input FILE format conversion ๐
๐ LIBRARY ๐
Standard C library (libc, -lc) โ she's built in, no extra drama required โจ
๐ธ SYNOPSIS ๐ธ
#include <stdio.h>
int scanf(const char *restrict format, ...);
int fscanf(FILE *restrict stream,
const char *restrict format, ...);
#include <stdarg.h>
int vscanf(const char *restrict format, va_list ap);
int vfscanf(FILE *restrict stream,
const char *restrict format, va_list ap);
๐ง Feature Test Macro Requirements for glibc (see feature_test_macros(7))
for vscanf(), vfscanf():
_ISOC99_SOURCE || _POSIX_C_SOURCE >= 200112L
๐ DESCRIPTION ๐
so the scanf() family scans formatted input, kinda like sscanf(3) does, except it reads from a FILE. and bestie. ngl. these functions are very difficult to use correctly ๐ญ the manpage itself says it's preferable to read whole lines with fgets(3) or getline(3) and then parse them later with sscanf(3), or with something more specialized like strtol(3). like, that's the author telling you to take a different route. periodt.
scanf() reads its input from the standard input stream, aka stdin, and fscanf() reads input from the stream pointer, aka stream. two sisters, one vibe ๐
vfscanf() is the analog of vfprintf(3) โ it reads input from the stream pointer stream using a variable argument list of pointers (peep stdarg(3)). and vscanf() is the analog of vprintf(3), and it reads from the standard input. so it's giving "same energy, but the args come in via va_list" ๐
๐ RETURN VALUE ๐
on success, these functions return the number of input items successfully matched and assigned. lowkey that can be fewer than you provided for, or even zero, if there's an early matching failure. zero items. nothing. we got nothing. ๐
the value EOF comes back if the end of input is reached before either the first successful conversion or a matching failure happens. EOF is also returned if a read error occurs โ in that case the error indicator for the stream gets set (see ferror(3)), and errno is set to indicate the error. so basically EOF is doing double duty and you have to check errno to know which one it is ๐
๐ฅ ERRORS ๐ฅ
EAGAINโ the file descriptor underlyingstreamis marked nonblocking, and the read operation would block. she's not waiting around, bestie.EBADFโ the file descriptor underlyingstreamis invalid, or it's not open for reading. wrong door, no entry ๐ซEILSEQโ the input byte sequence does not form a valid character.EINTRโ the read operation was interrupted by a signal; seesignal(7).EINVALโ not enough arguments; orformatisNULL. (she counted your args and she's disappointed.)ENOMEMโ out of memory.
๐ ATTRIBUTES ๐
for an explanation of the terms used in this section, see attributes(7).
- Interface:
scanf(),fscanf(),vscanf(),vfscanf()โ Attribute: Thread safety โ Value:MT-Safe locale
โญ STANDARDS โญ
C11, POSIX.1-2008. certified โจ
๐ฆ HISTORY ๐ฆ
C99, POSIX.1-2001. she's been around, she's seen things.
๐ CAVEATS ๐
these functions make it genuinely difficult to tell newlines apart from other white space. and that's especially problematic with line-buffered input, like the standard input stream. no cap, this will bite you.
also, these functions can't report errors after the last non-suppressed conversion specification. so errors happening at the very end? completely invisible. ๐ซฅ
๐ธ BUGS ๐ธ
it is impossible to accurately know how many characters these functions have consumed from the input stream, because they only report the number of successful conversions. like. literally impossible. let that sink in ๐ญ
for example, if the input is "123\n a", then
scanf("%d %d", &a, &b)
will consume the digits, the newline, and the space โ but not the letter a.
and that is exactly why it's so difficult to recover from invalid input. the stream is somewhere, you don't know where, and she's not telling you. ๐
๐ SEE ALSO ๐
fgets(3), getline(3), sscanf(3)
okay that's the whole page, bestie ๐ this was Linux man-pages 6.20, dated 2025-09-21, and remember: read the whole line first, parse it after, and keep your errno close ๐โจ๐ซถ
๐ฆ where this page comes from
- 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 6.20
- ๐ the page's license: Linux-man-pages-copyleft
- ๐ girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms