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.