Ch26.3: scan
1. The Function Surface
Input has two entry points. scan is the all-or-error form;
scan_some is the partial form.
| Function | Return | On end of input |
|---|---|---|
scan(in, args...) |
void |
Throws a herbception carrying parse_errc::end_of_file. |
scan_some(in, args...) |
scan_some_result_t |
Returns a result whose remained_args says how many arguments were
not scanned. The result is truthy only when every argument was scanned. |
Both forms take the input device first. There is no format string. Each argument is parsed according to its type, and a scan manipulator can change the syntax of one argument.
#include <fast_io.h>
int main()
{
using namespace ::fast_io::io;
::fast_io::ibuf_file in("numbers.txt");
int a{};
int b{};
scan(in, a, b);
println("a + b = ", a + b);
}
2. scan Requires a Buffered Input
Formatted input needs lookahead: it has to see the next character to know whether the
current token has ended, and it may need to leave that character for the next argument.
That is why scan requires an input device with a buffer. Use
ibuf_file or iobuf_file:
| Device | Can it be scanned? | Why |
|---|---|---|
::fast_io::ibuf_file |
Yes | Buffered input; provides the lookahead and refill path. |
::fast_io::iobuf_file |
Yes | Buffered bidirectional device; the input side works. |
::fast_io::native_file |
No | Unbuffered; it has no input buffer to look ahead in. Wrap it or use a buffered file type. |
::fast_io::iobuf_pipe |
Yes | Buffered pipe; useful when the producer is another process. |
This is the mirror image of output. print works on both buffered and
unbuffered output because it never needs to look ahead. scan cannot work
without an input buffer, and the type system rejects the attempt rather than letting it
read one byte at a time behind your back.
3. Failure: All-or-Nothing vs Partial
scan is for records that must be complete. If the input ends before all
arguments are read, it throws. That is the right default for a configuration line, a
command record or a fixed header.
scan_some is for streams where a partial final record is normal. Its result
carries the number of arguments that were not scanned:
#include <fast_io.h>
int main()
{
using namespace ::fast_io::io;
::fast_io::ibuf_file in("records.txt");
int a{};
int b{};
auto result{scan_some(in, a, b)};
if (!result)
{
println("stopped with ", result.remained_args, " argument(s) left");
}
}
A malformed token is still a parse error and still throws. scan_some only
changes the handling of “the stream ended before the record did”; it does not turn
invalid input into a success.
4. Whitespace, Bases and Token Boundaries
By default, formatted input skips leading whitespace and reads the longest token that forms a valid value. An integer stops at the first character that cannot continue it. A string reads a whitespace-delimited token unless it is wrapped in a whole-line or string-view manipulator.
int x{};
::fast_io::io::scan(in, x); // decimal by default
::fast_io::io::scan(in, ::fast_io::mnp::hex_get(x));
hex_get, base_get<N>, oct_get,
bin_get, dec_get, addrvw_get,
ch_get, strlike_get, strlike_line_get and
strlike_whole_get are the scan-side manipulators. They are header-side
helpers today; the module export list does not include them yet. If you are using the
module and need one, include the corresponding fast_io header or use the plain type.
Do not use a formatting manipulator such as mnp::hex as a scan target.
The output manipulator describes how to write a value; the scan manipulator describes
how to read one. The names differ for that reason.
5. What Can Be Scanned
The built-in path covers integers, floating-point values, characters, booleans,
strings and string-like types, IP addresses, timestamps and types that provide their own
scan_context_define / scan_contiguous_define customization.
A type with no scan support is a compile-time error.
Scanning into a fixed-size buffer is deliberately not silent. If the input token is longer than the destination, the operation fails rather than truncating. Use a string type that grows, or a length-prefixed/line-based manipulator when the size is part of the protocol.
6. scan and print Are Symmetric, Not Identical
| Property | print |
scan |
|---|---|---|
| Buffered device required | No | Yes, on input |
| Default stream | C stdout |
No default; the input device is explicit |
| Failure | Herbception from the device layer | Herbception from parsing or the device layer |
| Partial operation | Not applicable; each write is complete or fails | scan_some reports remaining arguments |
| Manipulator direction | hex, fixed, left, … |
hex_get, base_get<N>, ch_get, … |
Key Takeaways
scanis all-or-error;scan_somereports how many arguments remained.scanrequires a buffered input device;native_fileis not one.- Both forms take the input device as the first argument and have no format string.
scan_somehandles a short final record, not malformed input; parse errors still throw.- Use the
*_getfamily for scan syntax, not the output manipulators. - Fixed-size destinations reject overlong tokens instead of truncating.