String Operations
Every string function MEX provides — concatenation, slicing, searching, padding, case conversion, and tokenizing
Strings are everywhere in BBS scripting. You’re building prompts, formatting profile cards, parsing filenames, tokenizing user input, padding columns for neat display. MEX gives you dynamic strings that handle their own memory and a solid set of functions to work with them.
This page covers every string operation available in MEX — from the basics
(concatenation, length) to the functions you’ll reach for when you need to
slice, search, pad, or recase. If you’re looking for the numeric-to-string
conversion functions (itostr, ltostr, etc.), those live on the
Variables & Types
page since they’re about type conversion rather than string manipulation.
On This Page
- Quick Reference
- Concatenation
- Length
- Substrings
- Searching
- Tokenizing
- Padding & Alignment
- Case Conversion
- Trimming
- Character Access
Quick Reference
| Function | Signature | What It Does |
|---|---|---|
strlen |
unsigned int strlen(string: s) |
Returns the length of s |
substr |
string substr(string: s, int: pos, int: length) |
Extracts a substring (1-based) |
strfind |
int strfind(string: str, string: substring) |
Finds first occurrence, returns position or 0 |
stridx |
int stridx(string: str, int: startpos, int: ch) |
Finds character forward from position |
strridx |
int strridx(string: str, int: startpos, int: ch) |
Finds character backward from position |
strtok |
string strtok(string: src, string: toks, ref int: pos) |
Extracts next token |
strpad |
string strpad(string: str, int: length, char: pad) |
Right-pads to length |
strpadleft |
string strpadleft(string: str, int: length, char: pad) |
Left-pads to length |
strupper |
string strupper(string: s) |
Converts to uppercase |
strlower |
string strlower(string: s) |
Converts to lowercase |
strtrim |
string strtrim(string: s, string: x) |
Trims characters from both ends |
Concatenation
The + operator joins strings together. It’s the same + used for
arithmetic on numbers — the compiler knows which one you mean based on the
types:
string: greeting;
greeting := "Hello, " + usr.name + "! Welcome to " + prm_string(0) + ".\n";
print(greeting);
You can chain as many + operations as you like. Each one produces a new
string — MEX handles all the memory automatically.
To concatenate a number with a string, convert it first:
print("You have " + uitostr(usr.times) + " calls on record.\n");
Length
unsigned int strlen(string: s);
Returns the number of characters in s. An empty string has length 0.
if (strlen(usr.city) = 0)
print("You haven't set your city yet.\n");
// Truncate a string to fit a column
string: display_name;
display_name := usr.name;
if (strlen(display_name) > 20)
display_name := substr(display_name, 1, 20);
Substrings
string substr(string: s, int: pos, int: length);
Extracts length characters from s, starting at position pos.
Positions are 1-based — the first character is position 1.
string: s;
s := "Hello, World!";
substr(s, 1, 5) // "Hello"
substr(s, 8, 5) // "World"
substr(s, 1, 1) // "H"
If pos + length exceeds the string, you get whatever characters are
available — no error, no crash.
Common pattern — strip a prefix:
// Remove "Re: " from a subject line
string: subject;
subject := "Re: Testing 1 2 3";
if (strlen(subject) > 4)
{
if (substr(subject, 1, 4) = "Re: ")
subject := substr(subject, 5, strlen(subject) - 4);
}
Searching
strfind — Find a Substring
int strfind(string: str, string: substring);
Returns the 1-based position of the first occurrence of substring in
str, or 0 if not found.
int: pos;
pos := strfind(usr.city, "TX");
if (pos > 0)
print("Howdy, fellow Texan!\n");
stridx — Find a Character (Forward)
int stridx(string: str, int: startpos, int: ch);
Searches forward from startpos for character ch. Returns the 1-based
position, or 0 if not found. startpos is 1-based.
// Find the first space in a string
int: space_pos;
space_pos := stridx(usr.name, 1, ' ');
if (space_pos > 0)
print("First name: " + substr(usr.name, 1, space_pos - 1) + "\n");
strridx — Find a Character (Backward)
int strridx(string: str, int: startpos, int: ch);
Searches backward from startpos for character ch. If startpos is 0,
the search begins from the end of the string.
// Find the last dot in a filename
string: filename;
int: dot_pos;
filename := "archive.tar.gz";
dot_pos := strridx(filename, 0, '.');
if (dot_pos > 0)
print("Extension: " + substr(filename, dot_pos + 1, strlen(filename) - dot_pos) + "\n");
Tokenizing
strtok — Split on Delimiters
string strtok(string: src, string: toks, ref int: pos);
Extracts the next token from src, splitting on any character in toks.
The pos variable tracks the current position — initialize it to 0
before the first call. Returns an empty string when there are no more
tokens.
string: line, token;
int: pos;
line := "one,two,three,four";
pos := 0;
token := strtok(line, ",", pos);
while (strlen(token) > 0)
{
print("Token: " + token + "\n");
token := strtok(line, ",", pos);
}
Output:
Token: one
Token: two
Token: three
Token: four
You can split on multiple delimiter characters:
// Split on comma, space, or semicolon
token := strtok(input, ", ;", pos);
Padding & Alignment
strpad — Right-Pad
string strpad(string: str, int: length, char: pad);
Returns str padded on the right with pad characters until it reaches
length. If str is already at least length characters, it’s returned
unchanged.
// Right-pad a label to 20 characters
print(strpad("Name:", 20, '.') + " " + usr.name + "\n");
print(strpad("City:", 20, '.') + " " + usr.city + "\n");
Output:
Name:............... Kevin
City:............... Austin, TX
strpadleft — Left-Pad
string strpadleft(string: str, int: length, char: pad);
Pads on the left. Great for right-aligning numbers:
// Right-align a number in a 6-character column
print(strpadleft(uitostr(usr.times), 6, ' ') + " calls\n");
Utility Headers: intpad.mh
The intpad.mh header provides convenience wrappers that combine conversion
and padding in one call:
#include <intpad.mh>
// intpad(int, width) — right-pad an int with spaces
// uintpad(uint, width) — right-pad an unsigned int
// intpadleft(int, width, ch) — left-pad an int with a character
// uintpadleft(uint, width, ch) — left-pad an unsigned int
print(intpadleft(42, 5, '0')); // "00042"
print(intpad(42, 8)); // "42 "
Case Conversion
strupper — To Uppercase
string strupper(string: s);
Returns a copy of s with all lowercase letters converted to uppercase.
Non-letter characters are unchanged.
string: answer;
input_str(answer, INPUT_NLB_LINE, 0, 1, "Continue? [Y/N] ");
if (strupper(answer) = "Y")
print("Continuing...\n");
strlower — To Lowercase
string strlower(string: s);
Returns a copy of s with all uppercase letters converted to lowercase.
// Case-insensitive comparison
if (strlower(usr.city) = "austin, tx")
print("Local caller!\n");
Trimming
strtrim — Trim Characters
string strtrim(string: s, string: x);
Removes all characters in x from both the beginning and end of s.
Characters in the middle are not affected.
string: padded;
padded := " Hello ";
print("[" + strtrim(padded, " ") + "]"); // "[Hello]"
You can trim multiple character types at once:
// Strip leading/trailing whitespace and dots
string: clean;
clean := strtrim(raw_input, " .\t");
Character Access
Individual characters in a string are accessed with [] using 1-based
indexing:
string: s;
char: ch;
s := "Hello";
ch := s[1]; // 'H'
ch := s[5]; // 'o'
You can also assign to individual positions:
s[1] := 'h'; // s is now "hello"
Building strings character by character:
string: result;
int: i;
result := "";
for (i := 1; i <= strlen(source); i := i + 1)
{
if (source[i] <> ' ')
result := result + source[i];
}
Note that s[i] returns a char, and concatenating a char to a string
with + works — the char is promoted to a single-character string
automatically.
See Also
- Variables & Types — type system, including numeric-to-string conversions
- Display & I/O Intrinsics —
print(),input_str(), and other I/O functions - Control Flow — loops and conditionals for string processing