Polyglot
Languages MATLAB strings
MATLAB § strings

Strings and char arrays

MATLAB carries two distinct text classes: the older char — a one-dimensional matrix of UTF-16 code units, written with single quotes — and the newer string — a boxed scalar string, written with double quotes and introduced in R2016b. The two are not interchangeable and they observe different rules under concatenation, indexing, and comparison; understanding which is which is the substance of MATLAB text processing. New code is encouraged to use string; the standard library accepts both, often through the conversion convertCharsToStrings performed in argument-validation blocks.

char arrays

A character array is a matrix whose class is char. A single-quoted literal produces a 1×N character array:

s = 'hello';
class(s)           % 'char'
size(s)            % [1 5]
s(1)               % 'h'      (a 1×1 char)

Character arrays are real arrays in MATLAB’s sense: they have a size, they are indexed with parentheses, and they obey the column-major layout. Two strings concatenated with [] form a longer character array:

['hello', ' ', 'world']
% 'hello world'      (1×11 char)

A 2×5 character array is a list of strings of equal length; the rows are separate “strings” but stored as a single matrix:

names = ['Ada  '
         'Grace'
         'Knuth']
size(names)        % [3 5]
names(1, :)        % 'Ada  '

The padding is the substance of the limitation: a char array cannot contain strings of unequal length without padding (or being stored in a cell array). Equality == on character arrays returns an element-wise logical array; it tests characters, not strings as a whole.

'cat' == 'cab'
% 1×3 logical: [1 1 0]

A character literal admits two escapes — doubled single-quote to embed a quote and the newer (R2024a) extended escape syntax in compose/sprintf strings. In a string literal proper there are no \n-style escapes; the function sprintf provides them when constructing text.

s = 'It''s a test';        % an apostrophe by doubling
fprintf('line one\nline two\n')   % \n interpreted by fprintf, not the literal

string scalars and arrays

A string scalar is a single boxed string. The double-quoted literal produces a 1×1 string:

s = "hello";
class(s)           % 'string'
size(s)            % [1 1]
strlength(s)       % 5

The class is array-shaped: ["a", "b", "c"] is a 1×3 string and indexes like any other array. Equality == between strings tests string equality and returns a scalar logical (or, broadcasting, a logical array):

"cat" == "cab"
% logical 0
["cat", "cab"] == "cat"
% 1×2 logical: [1 0]

Concatenation uses + for strings — a deliberate departure from [] — and [] concatenates them into a longer string array (not a longer string):

"hello" + " " + "world"     % "hello world"      (a single string)
["hello"; "world"]           % 2×1 string array

The + overload is the most-cited “this is the new API” feature.

Conversion

The classes convert through named functions:

char("hello")              % 'hello'   (char)
string('hello')            % "hello"   (string)

convertCharsToStrings('a')   % "a"   (recommended in argument blocks)
convertStringsToChars("a")   % 'a'

A common pattern in user-facing functions is to accept either form and convert at the door:

function out = greet(name)
    arguments
        name (1,1) string
    end
    out = "Hello, " + name + "!";
end

greet('Ada')                   % accepts char, converted to string
greet("Ada")                   % accepts string

The argument-validation block converts as part of validation.

Building strings

The two principal builders are sprintf (returns a formatted string) and compose (vectorised over an input array):

sprintf('%d squared is %d', 5, 25)
% '5 squared is 25'           (returns char by default)

sprintf("%d squared is %d", 5, 25)
% "5 squared is 25"           (returns string when given a string template)

compose("%d squared is %d", (1:3)', (1:3)'.^2)
% 3×1 string:
%   "1 squared is 1"
%   "2 squared is 4"
%   "3 squared is 9"

The conversion specifiers are essentially the C printf family: %d, %f, %e, %g, %s, with the %*.*f width-and-precision form and the MATLAB-specific %i (integer with sign) and %n (count). The full reference is at mathworks.com/help/matlab/ref/sprintf.html.

The + operator and the function strcat perform plain concatenation; for joining a string array with a delimiter, the function join is the clearest choice:

join(["red", "green", "blue"], ", ")
% "red, green, blue"

Searching, replacing, splitting

The string class supports a substantial library of methods. Selected highlights:

s = "the quick brown fox";

contains(s, "quick")           % true
startsWith(s, "the")           % true
endsWith(s, "fox")             % true
strlength(s)                   % 19

replace(s, "brown", "red")     % "the quick red fox"
split(s)                       % 4×1 string: ["the"; "quick"; "brown"; "fox"]
split(s, " ")                  % same; explicit delimiter
extract(s, "quick" + (" " + alphanumericsPattern)) % "quick brown"

reverse(s)                     % "xof nworb kciuq eht"
upper(s)                       % "THE QUICK BROWN FOX"
lower("MIXED Case")            % "mixed case"
strip("  hello  ")             % "hello"

A pattern — produced by pattern, digitsPattern, alphanumericsPattern, lookAheadBoundary, and so on — is a structured object representing a piece of text to match, an alternative to regular expressions for many cases. Regular expressions are also fully supported through the regexp, regexprep, and regexpi functions; the dialect is roughly Perl-compatible.

regexp("phone: 555-1234", '(\d{3})-(\d{4})', 'tokens')
% 1×1 cell: { {'555', '1234'} }

Numeric ↔ text

Conversion from text to a number uses str2double (for scalar text) or str2num (which eval-s the text and is best avoided in production code for security reasons):

str2double("3.14")                     % 3.14
str2double(["1", "2", "3"])            % [1 2 3]

The inverse direction uses num2str for arbitrary numeric formatting and string for the default representation:

num2str(pi, "%.4f")                    % '3.1416'
string(pi)                             % "3.141592653589793"

The string constructor is the cleanest default; the num2str family is preferable when a specific format string is wanted.

Unicode and code units

Both char and string are UTF-16 internally — a code unit is 16 bits. A character outside the Basic Multilingual Plane (such as most emoji) occupies two code units. The strlength function returns the number of code units, not the number of grapheme clusters; for true grapheme counting use count(s, characterListPattern(...)) or one of the locale-aware functions in the Text Analytics Toolbox. For practical purposes most engineering text is ASCII or BMP-only and the distinction does not arise.

A recommendation

In new code: use string (“double quoted”) as the default text type; use the arguments block to convert char inputs to string at the boundary; reach for char only when writing legacy-compatible code or when working with the C MEX API, which exposes characters as UTF-16 code units in a char matrix.