Formatted Strings
When you want to display information on the screen or write it to a file,
the easiest approach is usually the print statement.
name$ = 'Sally'
age = 26
print 'Hello '; name$; '. You are '; age; ' years old'
Sometimes, however, you do not want to print the information immediately.
You may need to build the complete text first so you can place it on a
webpage, store it in a database, save it as a note, or pass it to another
routine.
In that case, the formatted result needs to be placed into a string variable.
Sheerpower provides two major formatting functions for doing this. The
simplest is f$().
name$ = 'Sally'
age = 26
mytext$ = f$('Hello [[name$]]. You are [[age]] years old')
print mytext$
The result is:
Hello Sally. You are 26 years old
Inside an f$() format string, anything between
[[]] is evaluated and inserted into the
resulting string.
name$ = 'Sally'
years = 22
print f$('Her name was [[name$]], she was [[years]] years old.')
! Her name was Sally, she was 22 years old.
print f$('[[ucase$(name$)]] has [[len(name$)]] letters') ! SALLY has 5 letters
print f$('Total: [[sprintf$("%.2m",]]') ! Total: 1,234.50
Anything that can be used as an expression can appear between the brackets.
This includes variables, arithmetic expressions, function calls, string
slices, and other expressions whose values can be displayed.
print f$('Next year she will be [[years]].')
print f$('First three letters: [[left$(name$, 3)]]')
print f$('Uppercase name: [[ucase$(name$)]]')
Brackets used inside an expression are balanced normally, so an expression
such as [[name$[1:3]]] works as expected.
Arrays can also be inserted. They are formatted the same way that
print would display them. For example, if
scores contains 90, 85, 77:
print f$('Scores: [[scores]]') ! Scores: 90 85 77
When you need special formatting, such as a fixed number of decimal
places or thousands separators, use sprintf$() inside the
formatted segment.
amount = 1234.5
text$ = f$('Total: [[sprintf$("%.2m",]]')
print text$ ! Total: 1,234.50
The expressions are evaluated when f$() runs. This means a
format string stored in a variable can be reused, and each use will insert
the current values of its expressions.
Special Formatting using SPRINTF$()
string$ = sprintf$(string_format$, arg1, arg2, .. )
The name stands for "String Print-Formatted". The function name was chosen to match the name of similar
functions found in programming languages such as C, C++, Java, Javascript, PYTHON, etc.
sprintf$() is a managed, printf-inspired formatting function with
Sheerpower-specific extensions for grouping, dates, pluralization, title
capitalization, positional masks and English number words. Formatting errors
raise exceptions rather than corrupting runtime memory. Applications
must still use explicit monetary rounding where needed.
Given the formatting string and a list of optional arguments, returns the string result of the
arguments applied to the format. The arguments can be of any data type.
Simple Formatting Examples
Each
% within the formatting string marks where the content of the additional arguments are
substituted into the string. Each
% marks the beginning of a
format and is followed
by an optional letter and other specifications.
Simple Substitution
age = 33
print sprintf$('Age is %', age)
Age is 33
name$ = 'Sally Sue'
age = 22
note$ = sprintf$('% is %', name$, age)
print 'Here is my note: '; note$
Here is my note: Sally Sue is 22
Real and integer Formatting
In Sheerpower, the
r and
i formats are used for numeric values,
representing Real and Integer types, respectively. For compatibility with other
implementations of sprintf, the
f format can also be used for Real numbers,
and the
d format can also be used for Integer numbers.
print sprintf$('PI is about %r', pi)
print sprintf$('PI is about %i', pi)
PI is about 3.1415926535897932
PI is about 3
Using a
.n after the %, we can specify the number (.n) of decimal digits. This also rounds the number.
For example, we might want to show a REAL rounded to three decimal digits:
print sprintf$('PI is about %.3r', 3.14159265)
PI is about 3.142
Singulars and Plurals
One Sheerpower specific format is
%p, which produces a word in its plural form if needed.
The last numeric value that precedes the
%p format determines if the word is
produced as a singular or plural.
ox_counter = 56
print sprintf$('I have % %p.', ox_counter, 'ox')
I have 56 oxen.
ox_counter = 1
print sprintf$('I have % %p.', ox_counter, 'ox')
I have 1 ox.
print sprintf$('%p', 'foot')
feet
Dates and times
To format dates and times you use the
%t formatter followed by date/time item names.
Item names have a
@ prefix. The sprintf$() argument is the time in
seconds as calculated by the
seconds() function. If the seconds given is zero, then the
current date and time is used.
The date/time item names are:
- @yyyy -- Four digit year -- 2022
- @yy -- Two digit year -- 22
- @month -- Month name -- January
- @mon -- Short month name -- Jan
- @mm2 -- Two digit month -- 09
- @mm -- One or Two digit month -- 9 or 10
- @dd2 -- Two digit day -- 09
- @dd -- One or two digit day number -- 9 or 10
- @h2 -- Two digit hour -- 09
- @h -- One or two digit hour -- 9 or 10
- @mt -- Military time -- 14
- @m2 -- two digit minute -- 09
- @m -- One or two digit minute -- 9 or 10
- @s2 -- Two digit seconds -- 09
- @s -- one or Two digit seconds -- 9 or 10
- @ampm -- AM or PM indicator
- @day -- Day of the week -- Monday
- @tz -- The machine's UTC offset -- -07:00 (or Z when exactly at UTC)
- @ts -- The complete RFC 3339 timestamp in one item -- 2026-08-21T17:33:14-07:00 (equivalent to @yyyy-@mm2-@dd2T@mt:@m2:@s2@tz)
- @mil -- military datetime -- 15-Jun-2022 07:38:10
- @short -- short length datetime -- Jun09 13:54
If no prefixed item is given, the default of
@short is used.
If no sprintf$() argument is given, the
current datetime is used. The formatting of @short is highly optimized.
Over 10 million per second can be formatted.
This makes it ideal for inclusion into log files.
f$ = "%tThe party is @month (month# @mm) @dd, @yyyy @mt:@m2:@s2 - or @h2:@m2:@s2 @ampm on a @day"
now_secs = seconds('')
print sprintf$(f$, now_secs)
The party is June (month# 6) 10, 2022 05:32:28 - or 05:32:28 AM on a Friday
f$ = '%t@month @dd2-@mon-@yyyy'
now_secs = seconds('20221225 0000')
print sprintf$(f$, now_secs)
December 25-Dec-2022
print sprintf$('%t@mil Processing starting')
15-Jun-2022 08:26:47 Processing starting
print sprintf$('%t@short Processing starting')
Jun09 15:11 Processing starting
print sprintf$('%t Processing started')
Jun09 15:11 Processing started
Create Proper English Titles
Titles often follow special capitalization rules. Important words are
capitalized, while smaller connecting words such as
a, an, the,
of, and to may remain lowercase
when they are not the first word. In addition, hundreds of commom special
cases are supported.
The %T format specifier, using a capital
T, formats text using title capitalization.
In the example below, is is capitalized because it is a
verb. In title capitalization, verbs are treated as important words,
even when they are short.
my_text$ = 'this is a book title'
print sprintf$('%T', my_text$) // outputs: This Is a Book Title
Dealing With String Substitutions
Often strings need to be formatted in specific ways. The
%z format is used for this
purpose. It supports two methods --
each character in turn substitutions using the "@" and
segment substitutions using "[]":
ssn$ = '123456789'
print sprintf$('%z SSN: @@@-@@-@@@@', ssn$)
print sprintf$('%z SSN: [1:3]-[4:5]-[6:9]', ssn$)
Segments are the most versatile of the two methods. For each segment,
specify
[aaa:zzz] where
aaa
is the starting location in the string and
zzz is the ending location. Note that the first
location is one and the last location is the length of the string. The word "end" stands for the
end of the string.
Within the "[]" one can also
include the additional formatting options of "uc" or "lc" for uppercasing or lowercasing
the segment:
a$='abcdefGHI'
print sprintf$('%z[uc:1:3]-[4:5]-[lc:6:end]', a$)
ABC-de-fghi
Formatting Money and Large Numbers
Another Sheerpower specific format is
%m, which inserts commas into numbers as needed.
It is frequently used when formatting money or large numbers.
The
.2 in the example below says two decimal digits will be returned. The number will also
be rounded as needed.
cash = 1234567.887
print sprintf$('About $ %.2m', cash)
About $ 1,234,567.89
Writing Numbers in Words
Sheerpower supports the %w format for producing the written-in-words version
of a numeric value.
This is especially useful for checks, invoices, receipts, legal
documents, and other business output where an amount must appear both
numerically and in words.
Problem:
Business software often needs to print monetary amounts in words, such
as "One thousand two hundred thirty four and 56/100".
Solution:
Use the %w format in sprintf$() to convert
a numeric value into its written form.
English whole-number words are followed by a truncated two-digit hundredths fraction. The fractional
portion is produced in check
style as and nn/100.
Efficiency:
By making written-number formatting part of
sprintf$(), Sheerpower eliminates repetitive conversion
code and keeps business formatting fast, consistent, and easy to read.
For example:
a = 1234.56
print sprintf$('%r Written: %w', a, a)
Output: 1234.56 Written: One thousand two hundred thirty four and
56/100
Note: For financial output, the fractional portion is handled using
truncation to two decimal digits, not rounding. This follows
check-writing convention and ensures that the written value never
exceeds the numeric value.
amount = 1234.567
print sprintf$('%r Written: %w', amount, amount)
Output: 1234.567 Written: One thousand two hundred thirty four and 56/100
This behavior is intentional. A rounded result such as
57/100 would overstate the written amount. For check and
payment text, truncation is the safer and more conventional rule.
Some additional examples:
print sprintf$('%w', 0)
Zero and 00/100
print sprintf$('%w', 0.75)
Zero and 75/100
print sprintf$('%w', 1.01)
One and 01/100
print sprintf$('%w', -42.10)
Negative forty two and 10/100
Use %w when you want the number written in words. Use
other numeric formats such as %r or %m when
you want conventional numeric display.
Positioning with Horizontal Tabs
Sheerpower also supports a horizontal tab format using
%h. The argument
value is the tab position. Tab position one is the first position.
tab_pos = 15
age = 45
print sprintf$('The age was: %h%i',tab_pos, age)
The age was: 45
Column Alignment
Column alignment is accomplished by specifying the fixed width of a given number or string.
The width is specified by supplying a number directly after the %. For example,
to give a fixed width of 10 characters:
print sprintf$('Number: %10i and more.', 123)
Number: 123 and more.
By default, numbers are right-justified within columns. To left-justify a number, give
a negative column width:
print sprintf$('Number: %-10i and more.', 123)
Number: 123 and more.
Octal, Hexadecimal, and Binary
The %o, %x, and %b are used to format numbers into octal, hexadecimal, and binary.
print sprintf$('%i in Octal: %o Hex: %x Binary: %b', 123, 123, 123, 123)
123 in Octal: 173 Hex: 7b Binary: 1111011
Embedding Special Characters
Sometimes there is a need to embed special characters into the format. The "\" (back-slash) is
used for this purpose. For example, to insert a "new line" character into the format
use
\n. For example:
print sprintf$('Hello\nWorld')
Hello
World
Below is the full list of special characters:
| Combination | Result |
| \b | Backspace |
| \f | Form-feed |
| \n | New line |
| \r | Return |
| \t | Tab |
| \0nnn | Generate a character based
on the octal value
of nnn
For example \0102 >> B
|
| \\ | The "\" character |
print sprintf$('The letter (\0102)')
The letter (B)
All Conversion Formats
Below is the full set of
sprintf$() conversion formats. Formats
marked
SP are Sheerpower extensions (not part of C's printf).
Flags — a flag goes between the
% and the format letter,
and flags may be combined (for example
%-8.2f):
| Flag | Meaning | Example → Result |
N (a number) | Minimum field width, right-justified | sprintf$('%5i', 42) → 42 |
- | Left-justify within the width | sprintf$('%-5i|', 42) → 42 | |
0 | Pad a number with leading zeros | sprintf$('%05i', 42) → 00042 |
.N | Precision: number of decimal places | sprintf$('%.2f', 3.14159) → 3.14 |
+ | Force a leading + on positive reals (%r/%f/%m; integer formats ignore it) | sprintf$('%+.2f', 42) → +42.00 |
The conversion letters:
| Format | Meaning | Example → Result |
% | General substitution (any type) | sprintf$('%', 99) → 99 |
%s | String (a width justifies it: %-6s left, %6s right) | sprintf$('%s', 'hello') → hello |
%i %d | Integer | sprintf$('%i', 42) → 42 |
%r %f | Real number (.N decimals; + forces a sign) | sprintf$('%.2r', 3.14159) → 3.14 |
%e | Scientific notation | sprintf$('%e', 3.14159) → 3.141590e00 |
%g | Real, compact | sprintf$('%g', 3.14159) → 3.14159 |
%m (SP) | Number with comma grouping (.N decimals) | sprintf$('%.2m', 1234.5) → 1,234.50 |
%o %x %b | Octal, hexadecimal, binary | sprintf$('%x', 123) → 7b |
%c | The character with the given code (like C); given a string, its first character | sprintf$('%c', 66) → B |
%h (SP) | Horizontal tab to a column (argument = the position) | sprintf$('%h%i', 15, 45) → aligns 45 at column 15 |
%p (SP) | Pluralize the following word by the count | sprintf$('% %p', 2, 'item') → 2 items |
%t (SP) | Date/time with @-items (see the Date and Time page) | sprintf$('%t@yyyy', secs) → 2026 |
%T (SP) | Title Case | sprintf$('%T', 'hello world') → Hello World |
%w (SP) | Number written in words (check style) | sprintf$('%w', 1234) → One thousand two hundred thirty four and 00/100 |
%z (SP) | Lay the string into a template: @ takes the next character, [a:b] copies a range (a template must have at least one @ or [a:b]) | sprintf$('%z@@@-@@-@@@@', '123456789') → 123-45-6789 |
Literal %, @, [ and ]
To print a literal percent sign, double it:
%%. A single
% begins a conversion, so an undoubled
% with no matching
argument raises an error — always write
%%.
print sprintf$('50%% off, % left', 5)
50% off, 5 left
The characters
@,
[ and
] are ordinary
literals
everywhere except inside a
%t template (where
@ begins a date/time item) and a
%z template (where
@ is a placeholder and
[ begins a range). Outside those
two, type them directly:
print sprintf$('user@host has % msgs', 3)
user@host has 3 msgs
print sprintf$('arr[%] set', 7)
arr[7] set
There is no escape for a literal
@ or
[ inside a
%t or
%z template, so build any such text outside the
%t/
%z part (a separate
sprintf$(), or plain
string concatenation).
How %z handles string length
With the
@ mask, each
@ takes the next character of the
string in order:
- If the string has more characters than the mask has
@s, the extra trailing characters are dropped:
sprintf$('%z@@@', 'hello') → hel.
- If the string has fewer characters than the mask has
@s, it raises an error ("Not enough data for @ substitutions").
A
[a:b] range copies characters by absolute position and clamps to the
string's length, so a range past the end simply stops at the last character:
sprintf$('%z[1:10]', 'hi') →
hi.
Using %p with more than one count
Each
%p pluralizes its word using the
most recent
numeric
% before it, so several count/word pairs work in one format
string:
print sprintf$('% %p and % %p', 2, 'cat', 1, 'dog')
2 cats and 1 dog
If no number precedes a
%p, it defaults to the plural form
(
sprintf$('%p', 'foot') →
feet) — so always give
%p a count.
sprintf$() and Program Safety
Sheerpower's implementation of sprintf$() is completely safe. If a wrong data type is passed, Sheerpower
will attempt to convert it to the correct data type. If this cannot be done, an exception is
raised, explaining the problem. If too few or too many arguments are passed,
an exception is raised. In no case will the Sheerpower runtime environment crash or become polluted when processing
the sprintf$() function.
(Show/Hide Sheerpower SPRINTF and F$() Takeaways)
Sheerpower SPRINTF Takeaways
sprintf$() formats strings using placeholders (%)
and arguments of any data type.
- Supports standard formats (
%i, %r, %f,
%d) for integers and reals, including decimal rounding with
.n.
- Sheerpower adds unique formats:
%p (plurals),
%t (dates/times),
%T (titles),
%w (Numbers as written words),
%z (string substitutions),
%m (money/commas), and
%h (horizontal tabs).
- Column alignment is supported with positive widths (right-justify)
or negative widths (left-justify).
- Octal, hexadecimal, and binary are handled with
%o, %x, and %b.
- Special characters are embedded with backslashes
(e.g.,
\n, \t, \\, \0nnn).
- Optimized date/time formatting with
@short can process
10+ million operations per second, ideal for logging.
- Safe by design: type mismatches or wrong argument counts raise
clear exceptions without crashing the runtime.
-
f$() builds formatted strings — text with
expressions embedded right inside it:
f$("{lastname} is {age} years")