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