Текст - еще один важный вид данных, с которым приходится работать компьютерным программам. В программировании мы называем любой сегмент текста строкой.

Строки как аргумент функций печати

Мы используем строку в качестве аргументов, передаваемых функциям печати: disp и fprintf.

Функция disp

Из документации Matlab по disp:

disp(X) отображает значение переменной X без печати имени переменной. Другой способ отобразить переменную — это напечатать ее имя, что добавляет перед значением префикс «X =».

Функция fprintf

Функция fprintf используется для вывода информации на экран.

fprintf('<message>', var1, var2);

Работу данной функции следует воспринимать как посимвольную печать строки, аналогично одноименной функции я.п. СИ. Функция fprintf отличается от disp тем, что позволяет вставлять значения переменных в последовательность символов массива используя параметр форматирования, начинающийся с символа % (здесь % не означает комментарий).

% в сообщении <message> является якорем на место которого будет вставлено значение из последующих перемененных var1, var2, ... в порядке следования.

Ниже приведены несколько примеров вывода переменных с помощью fprintf. Обратите внимание на использование %s для вывода строки, %d для вывода целого числа и %f для вывода вещественного числа.

fprintf('Имя преподавателя: %s\n', prof_name);
fprintf('Возраст: %d; Зарплата: %.2f\n', prof_age, prof_salary);

При использовании знаков % для вывода данных, хранящихся в переменных, мы должны использовать такое же количество знаков %, как и количество переменных.

Некоторые общие параметры форматирования:

  • %s - вывод строки
  • %c - вывод одного символа
  • %d - вывод целого числа
  • %f - вывод числа с плавающей запятой
  • \n - переход на новую строку
  • \t - вывод табуляции
  • \\ - вывод обратного слэша
  • %% - вывод знака процента

Пример %.2f показывает, что добавив точку и число в команду форматирования, можно ограничить вывод только двумя знаками после запятой. Это удобно в нашем случае для отображения денежной суммы, где тысячные доли рубля не важны.

Другим примером входного значения, представляющего собой строку, является intmax из предыдущей статьи. В то время как class является примером функции, возвращающей строку.

Кодирование символов

Интересно, что char - это числовой тип данных. За кулисами существует схема кодирования и декодирования, которая определяет, какое число обозначает какой символ.

Самая старая такая схема кодирования символов называется A-S-C-I-I. ASCII расшифровывается как American Standard Code for Information Interchange - американский стандартный код для обмена информацией, и была разработана в 1960-х годах. Код символа ASCII состоит из семи битов, поэтому в нем может быть закодирован набор из 128 символов.

ASCII table

Из специальных символов нам важен символ новой строки \n, сокращенно обозначенным LF (Line Feed) имеющий код 10. Важен и символ пробела обозначенном sp с кодом 32.

В Америке 1960-х годов 128 символов казалось много, но сейчас нам нужно значительно больше. Только подумайте обо всех символах во всех языках мира, а главное обо всех эмодзи. За прошедшие годы было разработано множество других схем с гораздо большим количеством символов. Хорошая новость для нас заключается в том, что старый добрый ASCII является подмножеством практически всех этих схем и сохраняет определенную актуальность.

Напечатаем все видимые символы таблицы ASCII:

for i = 33:126
    fprintf('%s', char(i));
end
fprintf('\n');
!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~

Вторым аргументом fprintf является значение индекса цикла, преобразованное в символ функцией преобразования char.

На самом деле нам не нужно использовать функцию преобразования char. Спецификатор формата %s воспримет число в виде символа:

for i = 33:126
    fprintf('%s', i);
end
fprintf('\n');
!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~

Работа со строкой как с массивом символов

Строка обозначенная в одинарных кавычках '' является на самом деле вектором (массивом) символов:

course_title = 'MATLAB COURSE';

Мы можем применить функцию, возвращающую количество элементов массива:

length(course_title)
ans =
    13

Или же извлечь какой то элемент по его позиции:

course_title(1)
ans =
    'M'

Или вернуть подмножество нашего массива:

course_title(1:6)
ans =
    'MATLAB'

Поскольку строки являются векторами символов, сравнить две строки не так просто, как два скаляра.

txt1 = 'colonel';
txt2 = 'kernel';
txt1 == txt2
Arrays have incompatible sizes for this operation.

Нельзя сравнивать два массива с помощью оператора ==, если они не одинакового размера.

И даже если длина двух массивов одинакова, результат сравнения, вероятно, окажется не тем, что нам нужно.

Рассмотрим пример:

a = course_title(1:6)
a =
    'MATLAB'
b = a(end:-1:1)
b =
    'BALTAM'

Поскольку 'MATLAB' и 'BALTAM' имеют одинаковую длину, мы можем использовать их в качестве операндов для оператора ==.

a == b
ans =
  1×6 logical array
   0   1   0   0   1   0

Мы получаем вектор логического типа (logical array), то есть то, что мы получим при любом поэлементном сравнении векторов. Вместо нужного нам ответа наподобие «эти строки не одинаковы». Мы получаем ответ для каждой пары символов в этих двух строках. А поскольку в нашем случае совпадают только A, то второй и пятый элементы - единственные истинные значения в результирующем векторе, остальные - ложные.

Давайте посмотрим на полезную функцию, которая даст нужный нам ответ:

strcmp(a, b)
ans =
  logical
   0

Функции для работы со строками

ФУНКЦИЯ ОПИСАНИЕ
char преобразует тип данных в символьный тип
findstr находит позиции подстроки в строке
ischar возвращает 1, если аргумент является символьным массивом, и 0 в противном случае
isletter находит буквы в строке
isspace находит пробелы, новые строки и табуляции в строке
isstrprop находит символы указанного типа в строке
num2str преобразует число в строку
length определяет количество символов в строке
lower преобразует строку в нижний регистр
sprintf записывает отформатированные данные в строку (аналогично fprintf, но сохраняет ,а не печатает)
strcmp сравнивает строки
strcmpi как strcmp, но без учета регистра
strmatch ищет строки в массиве, начинающиеся с указанной строки
strncmp как strcmp, но сравнивает только первые n символов
strncmpi как strncmp, но без учета регистра
str2num преобразует строку в число
upper преобразует строку в верхний регистр

Самые полезные:

  1. Поиск подстроки в строке становится простым с использованием findstr.
  2. Преобразование числа в строку и наоборот: num2str, str2num.
  3. Сравнение строк с помощью strcmp.
  4. Переключение между прописными и строчными буквами: lower, upper.
  5. sprintf: иногда нам нужно форматировать данные не в командное окно, а в переменную или файл.

Рассмотрим findstr более подробно:

findstr(course_title, 'LAB')
ans =
     4

Мы получили первое появление LAB в строке MATLAB Course.

findstr(course_title, 'lab')
ans =
     []

Строки чувствительны к регистру, поэтому если нет строчной 'lab', то нечего возвращать, и, следовательно, мы получаем пустой массив.

Теперь давайте найдем что-нибудь больше, чем один раз.

findstr(course_title, 'A')
ans =
     2     5

Рассмотрим sprintf более подробно:

Вычислим площадь круга определенного радиуса:

r = 12;
fprintf('The area of a circle with radius %.2f is %.2f\n', r, pi*r^2)
The area of a circle with radius 12.00 is 452.39

Теперь предположим, что мы хотим сохранить этот вывод в строке:

str = sprintf('The area of a circle with radius %.2f is %.2f\n', r, pi*r^2);
str
str =
    'The area of a circle with radius 12.00 is 452.39
     '

Тип «Строка» (введен в 2017a)

Строка обозначенная в двойных кавычках "" не является массивом символов. Типом таких данных является string.

Есть некоторые проблемы с использованием char для хранения строк, и MATLAB ввел новый тип с именем String, чтобы решить их.

Рассмотрим пример. Зададим строку в одинарных кавычках:

fruit = 'strawberries';
class(fruit)
size(fruit)
ans =
    'char'

ans =
     1    12

Чтобы создать строку нового типа, воспользуемся двойными кавычками:

berry = "watermelon"
berry = 
    "watermelon"
class(berry)
ans =
    'string'

Несмотря на то, что это разные типы, практически любая встроенная функция, предназначенная для обработки вектора char, будет работать и для string.

Например:

fprintf('The value of pi is %f\n', pi)
The value of pi is 3.141593
fprintf("The value of pi is %f\n", pi)
The value of pi is 3.141593

Можно преобразовать строку в старый формат:

char(new_fruit)
ans =
    'strawberries'

Экранирование кавычек:

string('There''s a place for us')
ans = 
    "There's a place for us"
Andy_Serkis = "The way he says, ""My precious"" makes my skin crawl!"
Andy_Serkis = 
    "The way he says, "My precious" makes my skin crawl!"


Важное отличие! Мы не можем обращаться к элементам string, так как будто они являются массивами.

course_title_new_string = "MATLAB Course";
course_title_new_string(1:6)
Index exceeds the number of array elements. Index must not exceed 1.
extractBetween(course_title_new_string, 1, 6)
ans = 
    "MATLAB"