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

Compose String — Control Systems/Strings

"%d" "42"

Control_Systems/Strings/Compose_String · 2 input / 1 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.

Compose String

Control Systems / Strings

Builds text from a format and its inputs, as C's and MATLAB's sprintf do: y = sprintf(Format, u1, u2, …). With the Format "x=%d, v=%.2f" and the inputs 7 and 3.14159, the output is x=7, v=3.14.

Ports

  • Input 1 (i32, ICoreInt32, for the default Format's %d) – the value for the first conversion, one value [1,1].
  • Input 2 – the value for the default Format's %f, one number [1,1].
  • Output – the text (str, ICoreString), one value, cut at 255 bytes.

There is one input per conversion, in order; the number of inputs is yours to set and must equal the number of conversions in the Format. What each input carries is decided by its conversion, exactly as in Simulink: %d and %i take a signed integer of at most 32 bits (i8, i16, i32) or a bool; %u, %x, %X and %o an unsigned one (u8, u16, u32) or a bool; %f, %e, %E, %g and %G a floating-point number (f64, f32); %s text (str, ICoreString). Anything else is refused at the port. A double does not go into %d: convert it with Data Type Conversion first, as in Simulink.

Parameters

  • Format – the format, written with its quotes as in Simulink: "%d %f" (the default). A doubled quote inside is one quote. Text is copied as it is; %% is a percent sign; the escapes \n, \t, \r, \a, \b, \f, \v and \\ are the control characters they name. A conversion is %, then optional flags (- left-justify, + always show the sign,   a space for a positive sign, 0 pad with zeros), an optional width, an optional .precision, and one of d i u x X o f e E g G s. Between 1 and 128 conversions.
  • Sampling Time (s) – zero or less inherits the solver's rate; a positive value runs the block at that period.

What is not offered

Each of these stops the run with a message naming it: %c, %a, %p, %n and a * width or precision (Simulink refuses them too); length modifiers such as %ld and %hd, which Simulink accepts; the # flag; 0 together with -, with text, or with an integer precision; + or a space on an unsigned or text conversion; an integer precision of 0; and the escapes \x.. and octal \... These are left out because the six target languages do not agree on what they mean, and a block whose exported code disagreed with it would be worse than one that says no.

Not-a-number and infinity

A floating-point conversion writes NaN, Inf or -Inf – +Inf under the + flag – and applies no width, precision or zero padding to them. That is Simulink's own rule, measured; C's own printf would write nan and pad it.

Code export

C, C++, Python, MATLAB, Java and Rust all write the same text. The first four use their own printf for each conversion; Java and Rust have no equivalent that agrees with C on floating point, so their generated code rounds each value exactly and lays it out by the same rules. 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/Compose String. "Format" crosses unchanged, quotes and all; on import the number of inputs and what each one carries are read off it, since Simulink derives both from the Format as well. The output data type is always string and is written as a fixed setting. 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 output depends only on the current inputs.
  • Width and precision on %s count bytes of UTF-8 here and in C, and characters in Simulink and in Java, Python and MATLAB – the same number for plain English text.

Code facts#

FactValue
registered typeControl_Systems/Strings/Compose_String
familyControl_Systems/Strings
solver environment classICoreBlock_0_Control_Systems_1_Strings_2_Compose_String
sourcesrc/ICoreBlocks/ICoreBlockLibrary/Blocks/Control_Systems/Strings/Compose_String/ICoreBlock_0_Control_Systems_1_Strings_2_Compose_String.cpp
headersrc/ICoreBlocks/ICoreBlockLibrary/Blocks/Control_Systems/Strings/Compose_String/ICoreBlock_0_Control_Systems_1_Strings_2_Compose_String.h
default size on canvas100 × 70 px
ports at insert2 in, 1 out
code generators implementedPython, MATLAB, Java, Rust, C, C++

Ports#

#DirectionSignal typeDescription label
1inICoreInt32—
2inICoreDouble—
3outICoreString—

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/Compose String
port-count rulePortsParam::ComposeStringFormat
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).

Compose String -- sprintf(Format, u1, u2, ...), one input per conversion The Format is parsed ONCE per use into literal pieces and conversions (parseFormat below), and everything else is driven by that parse: the input count verify checks, each input's type and accepted set, the live answer, and every generator -- which walks the pieces at EXPORT time and emits straight-line code, so no target has to interpret a format at run time. The measured Simulink rules the parse enforces are in the header.

The output is a String signal, so the value leaves through the PORT (D2), and it is cut at 255 bytes, what the exported C buffer holds beside its terminator.

Sample results#

Compose String — Repeating Sequence Stair: [-2 -1 -0.5 0 0.5 1 2 3], one entry per sampleCompose String — Repeating Sequence Stair: [-2 -1 -0.5 0 0.5 1 2 3], one entry per sample-202012345t (s)

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 ICoreDouble-Out-0out ICoreString-Out-0
0-20 -2.000000
0.40.50 0.500000
0.8-20 -2.000000
1.20.50 0.500000
1.6-20 -2.000000
20.50 0.500000
2.4-20 -2.000000
2.80.50 0.500000
3.2-20 -2.000000
3.60.50 0.500000
4-20 -2.000000
4.40.50 0.500000
4.8-20 -2.000000
5.20.50 0.500000

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)—
rampRamp: slope 1 from t = 0—
sineSine Wave: amplitude 1, 2 rad/s, no phase, no bias—
stepStep: 0 -> 1 at t = 1 s—

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__Compose_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).