Generated reference › Scan String — Control Systems/Strings
kind: generated#block#control-systems-strings

Scan String — Control Systems/Strings

"42" %d

Control_Systems/Strings/Scan_String · 1 input / 2 output port(s) at insert · exports to Python, MATLAB, Java, Rust, C, C++

Description#

The block's own DESCRIPTION_HTML, rendered verbatim — the same text the config dialog's info panel and the library navigator show. Fix a wrong sentence in the block's .cpp (R-D9), never here.

Scan String

Control Systems / Strings

Reads values out of text by a format, one output per conversion, as Simulink's Scan String does. With the Format "%d %f" (the default) and the text 42 3.5, output 1 is 42 and output 2 is 3.5. It is not C's sscanf: every rule below was measured on Simulink, and several of them differ from C.

Ports

  • Input (str, ICoreString) – the text, one value.
  • Output 1 (i32, ICoreInt32, for the default Format's %d) – one value [1,1].
  • Output 2 (f32, ICoreSingle, for the default Format's %f) – one value [1,1].

There is one output per conversion, in order; the number of outputs is yours to set and must equal the number of conversions in the Format. What each output carries is decided by its conversion, exactly as in Simulink: %d and %ld a 32-bit integer (i32), %hd a 16-bit one (i16), %u and %lu an unsigned 32-bit integer (u32), %hu an unsigned 16-bit one (u16), %f, %e and %g a single (f32), %lf, %le and %lg a double (f64), %s and %c text (str, ICoreString).

Parameters

  • Format – the format, written with its quotes as in Simulink: "%d %f" (the default). A doubled quote inside is one quote. A conversion is %, an optional width, an optional h or l, and one of d u f e g s c; any other character must be matched exactly by the text; %% matches a percent sign; the escapes \n, \t, \r, \a, \b, \f, \v and \\ match the control characters they name. Between 1 and 128 conversions, Simulink's own limits.
  • Sampling Time (s) – zero or less inherits the solver's rate; a positive value runs the block at that period.

How the text is read

  • Each character of the Format that is not a conversion – a space included – must match exactly one identical character of the text: "%d %d" does not read 1<tab>2, and " %d" does not read 5. The first character that does not match STOPS the scan, and every later output is 0 or empty text.
  • A number skips white space first (space, tab, newline, vertical tab, form feed, return), then reads an optional +, an optional -, and then Inf (a capital I, then n and f in either case), NaN (any case), or decimal digits – with a fraction for %f, %e and %g and without one for %d and %u, whose exponent is still read: %d of 1e3 is 1000 and of 3.9 is 3. An exponent is read only when digits follow it. Hexadecimal is not read.
  • A number that is not there is not a stop: the output is 0 and the scan goes on from the same place ("%d%s" of abc is 0 and abc).
  • An integer conversion cuts the number toward zero into a 64-bit integer that saturates (NaN is 0) and keeps its low 32 or 16 bits: %d of 1e10 is 1410065408, of Inf is -1; %u of -5 is 4294967291. Digits beyond what a double holds are kept exactly.
  • A single is the double nearest the text, rounded again to single.
  • %s skips white space and takes the characters up to the next white space; %c skips nothing and takes one character, or as many as its width. A width limits what a conversion may take after the white space it skipped, signs included – except a leading +, which is skipped with the white space and costs nothing: "%2d" of -123 is -1 and of +123 is 12.

What is not offered

Each of these stops the run with a message naming it: %i, %x, %o, %X, %E, %G, %n, a *, a flag such as %-d or %0d, a precision (%5.2f), hh, ll and L – all refused by Simulink too – and scansets such as %[abc], which Simulink accepts and this block does not.

Code export

C, C++, Python, MATLAB, Java and Rust all read the same values: each carries the same small scanner, written out in the language, and turns digits into numbers with the language's own correctly rounded parser. The Format is read when the code is generated, not when it runs.

VHDL, Verilog and SystemVerilog do not carry text, and PLC Structured Text is not supported either: the language has a string type, but the check that runs an exported core cannot read one back. An export to any of these four stops and names this block and the reason.

Simulink bridge

Import and export, mapped to simulink/String/Scan String. "Format" crosses unchanged, quotes and all; on import the number of outputs and what each one carries are read off it, since Simulink derives both from the Format as well. simulink/String/String to Double and String to Single are this same block with the Format preset to "%lf" and "%f" (measured: the same block type, the same one-parameter dialog), and they import as this block with that Format; they export back as Scan String. The Simulink block has no sampling-time setting of its own, so a positive Sampling Time (s) stays on this side and is reported rather than written.

Notes

  • Algebraic, with no state: the outputs depend only on the current input.
  • Widths, %s and %c count bytes of UTF-8 here – the same count as Simulink's for plain ASCII text.
  • One measured corner is not reproduced: Simulink saturated an in-range value written as an 18-digit mantissa with an exponent – the value eight below 263, so still inside the 64-bit range – where this block keeps it. Integer text of 18 digits or fewer is not affected.

Code facts#

FactValue
registered typeControl_Systems/Strings/Scan_String
familyControl_Systems/Strings
solver environment classICoreBlock_0_Control_Systems_1_Strings_2_Scan_String
sourcesrc/ICoreBlocks/ICoreBlockLibrary/Blocks/Control_Systems/Strings/Scan_String/ICoreBlock_0_Control_Systems_1_Strings_2_Scan_String.cpp
headersrc/ICoreBlocks/ICoreBlockLibrary/Blocks/Control_Systems/Strings/Scan_String/ICoreBlock_0_Control_Systems_1_Strings_2_Scan_String.h
default size on canvas100 × 70 px
ports at insert1 in, 2 out
code generators implementedPython, MATLAB, Java, Rust, C, C++

Ports#

#DirectionSignal typeDescription label
1inICoreString—
2outICoreInt32—
3outICoreSingle—

Ports the constructor creates. A block whose port list changes with its configuration adds or removes ports at load time; the count above is the one a freshly inserted block has.

Configuration variables#

Config variableDefaultSimulink parameter
Format"%d %f"Format

Every block also carries Sampling Time (s) from ICoreBlockSolverEnvironment: zero or less inherits the solver's rate, a positive value runs the block at that period.

supportSupport::Both
Simulink pathsimulink/String/Scan String
port-count rulePortsParam::ScanStringFormat
SampleTime parameterno — the counterpart defines none; the rate stays on the ICore side
ICore configSimulink parameterValue translation
FormatFormatpasses through

Caveat (shown to the user): "Format crosses verbatim, quotes included

Catalog contract: src/ICoreBlocks/ICoreCoder/ICoreCommandSystem/SimulinkBridge/ICoreSimulinkBlockCatalog.h

Description vs code#

The lists agree. check_block_descriptions.py finds no disagreement between the description's Ports, Parameters, Code export and Simulink bridge lists and the code's.

The verdict above is tools/docs/check_block_descriptions.py (P7.1), which compares LISTS. It cannot read a sentence: "stateless" on a block with a state, an initial-value semantic the recursion does not implement, a "not synthesizable" caveat the HDL banner contradicts. That is the agent audit (P7.3) on BLOCK_DESCRIPTION_AUDIT.md, and this tool's green is not a substitute for one.

File banner (developer view)#

The top comment of the block's .cpp — the maths, the realization and the export strategy, addressed to whoever changes it. It must not contradict the description above (P7.5).

Scan String -- read values out of text by a Format, one output per conversion The Format is parsed ONCE per use into literal runs and conversions (parseFormat below), and everything else is driven by that parse: the output count verify checks, each output's type, the live answer, and every generator -- which walks the items at EXPORT time and emits straight-line calls into a small scanner written out in the target language, so no target interprets a format at run time.

The scanner is Simulink's, measured on R2026a, and the rules are in the header. Two of them shape every implementation below and are worth restating here:

  • A NUMBER is read as text first -- signs, digits, a fraction for the float conversions,

an exponent only when digits follow it -- and turned into a value from that text: a float by a correctly rounded parse (a single is that double, rounded again: measured, "1.0000000596046448" reads as 1, not as the single above it); an integer by the same parse, cut toward zero, when that double is below 2^53 in magnitude, and EXACTLY from the digits above it ("9007199254740993" reads as ...993, which no double holds).

  • The integer is a SATURATING 64-bit value whose low 16 or 32 bits are the output, so a

"%d" of 1e10 is 1410065408 and a "%u" of -5 is 4294967291.

Sample results#

Scan String — Repeating Sequence Stair: [-2 -1 -0.5 0 0.5 1 2 3], one entry per sampleScan String — Repeating Sequence Stair: [-2 -1 -0.5 0 0.5 1 2 3], one entry per sample-1-0.500.51012345t (s)out ICoreInt32-Out-0out ICoreSingle-Out-1

This block carries a ICoreString signal, whose value is text rather than a number and is not something a plot has an axis for. The samples are in the table below, exactly as the run recorded them.

tin ICoreString-Out-0out ICoreInt32-Out-0out ICoreSingle-Out-1
0u000
0.4u000
0.8u000
1.2u000
1.6u000
2u000
2.4u000
2.8u000
3.2u000
3.6u000
4u000
4.4u000
4.8u000
5.2u000

Every 4th of 60 samples, from the table stimulus.

The same rig also ran:

StimulusWhat it isOutput range
impulseImpulse: one sample of 1 at k = 5, 0 elsewhere (Repeating Sequence Stair)0 … 0
rampRamp: slope 1 from t = 00 … 0
sineSine Wave: amplitude 1, 2 rad/s, no phase, no bias0 … 0
stepStep: 0 -> 1 at t = 1 s0 … 0

Plotted: table — Repeating Sequence Stair: [-2 -1 -0.5 0 0.5 1 2 3], one entry per sample

Category static · sample time 0.1 · 60 steps · commit 93133d604 · produced by docsSample --out <folder> --blocks Gain_Scheduled_Lead_Lag Controller_1D Controller_Blend_1D Controller_2D Controller_3D Observer_Form_1D Self_Conditioned_1D Line_Of_Sight_Access Orbit_Propagator_Kepler Attitude_Dynamics Attitude_Profile_Nadir_Pointing Attitude_Profile_Geographic_Pointing Multitaper_PSD Cross_Power_Spectral_Density Transfer_Function_Estimate Envelope_Spectrum Compose_String Scan_String --steps 60 · data docs/generated/samples/Control_Systems__Strings__Scan_String.json · the SVG is generated from those numbers by tools/docs/plot_svg.py, so it is a run and not a drawing (R-D10).