Перейти к содержимому
Теория · Строки · урок 1 из 10

Строки и символы

Чему вы научитесь

Чему вы научитесь:

  • читать символы строки по индексу и записывать в литерал кавычки, обратную косую черту и перевод строки;
  • собирать текст интерполяцией и обрабатывать его методами строки;
  • объяснять, почему методы не меняют строку, и сравнивать строки с учётом регистра и без него;
  • собирать длинный текст в цикле через StringBuilder.
Чек из кассового аппарата со строкой receipt по клеточкам, первая клеточка с биркой word[0] отмечена как char

Представьте чек из магазина. На нём в одну ленту напечатаны символы: буквы, цифры, пробелы, точки. У каждого символа своё место, поэтому чек можно прочитать целиком или найти на нём пятый символ. Исправить напечатанное нельзя: если в чеке ошибка, кассир печатает новый.

Строка в C# устроена так же. Тип string вы уже встречали: это текст в двойных кавычках. Внутри строка — ряд символов типа char, и к каждому можно обратиться по номеру:

C#
string word = "receipt";
Console.WriteLine(word.Length);  // 7
Console.WriteLine(word[0]);      // r
Console.WriteLine(word[6]);      // t
char first = word[0];
Console.WriteLine(first == 'r'); // True

Давайте разберём пример по строкам:

  1. word.Length — длина строки, то есть число символов в ней: 7.
  2. word[0] — символ с индексом 0, первый в строке: r. Индексы строки, как и у массива, начинаются с нуля.
  3. word[6] — последний символ t: его индекс на единицу меньше длины.
  4. char first = word[0]; кладёт символ в переменную типа char. Индекс в квадратных скобках даёт именно char, а не строку из одной буквы.
  5. first == 'r' сравнивает два символа и печатает True.

Строка — ряд символов char

С символами строки работают так же, как с элементами массива:

  • word[^1] — последний символ;
  • word[2..5] — новая строка из символов с индексами 2, 3 и 4, то есть "cei";
  • foreach (char c in word) перебирает символы по порядку, от первого до последнего;
  • у пустой строки "" длина 0, и символов в ней нет;
  • индекс за пределами строки, например word[7], останавливает программу с исключением IndexOutOfRangeException.

Length считает значения char, а не знаки, которые видит человек. Буквы латиницы и кириллицы, цифры и знаки препинания занимают по одному char, а эмодзи 😀 — два, поэтому "😀".Length равно 2.

Здесь чек и строка расходятся. На чеке видно каждый символ, а в строке бывают символы, которые не печатаются как знак: перевод строки и табуляция. Для них и для кавычки внутри строки в C# есть особые обозначения.

Управляющие последовательности

Двойная кавычка заканчивает литерал, поэтому поставить её внутрь строки как есть нельзя. Перевод строки в литерал тоже не вставить: обычный литерал должен закончиться на той же строке файла. Такие символы записывают через обратную косую черту \.

Управляющая последовательность — обратная косая черта и знак после неё, которые вместе означают один символ строки. Чаще всего нужны четыре:

  • \" — двойная кавычка;
  • \\ — сама обратная косая черта;
  • \n — перевод строки;
  • \t — табуляция, отступ до следующей колонки.
C#
Console.WriteLine("He said \"hi\""); // He said "hi"
Console.WriteLine("C:\\temp");       // C:\temp
Console.WriteLine("Milk\nBread");    // Milk
                                     // Bread
Console.WriteLine("a\nb".Length);    // 3

Посмотрим, что получилось:

  1. В первом литерале две пары \", и программа печатает кавычки вокруг hi.
  2. \\ печатается как одна черта.
  3. \n переносит Bread на следующую строку вывода.
  4. В строке "a\nb" три символа: a, перевод строки и b. Два знака \n в коде дают один символ в строке.

Текст как есть

Когда в тексте много обратных черт или кавычек, удвоенные \\ и \" мешают его читать. Для таких случаев в C# есть ещё две формы литерала.

Буквальная строка @"…"

Буквальная строка начинается с @ перед кавычкой. В ней обратная косая черта — обычный символ, и путь к папке Windows пишут как есть: @"C:\temp\new". Кавычку внутри такой строки удваивают: @"She said ""yes""" печатает She said "yes". Буквальная строка может занимать несколько строк файла.

Необработанная строка """…"""

Необработанная строка открывается и закрывается тремя двойными кавычками. Внутри неё не обрабатывается ничего: кавычки и обратные черты остаются как есть. Такие строки появились в C# 11. Чаще всего её пишут на нескольких строках:

  • текст начинается со строки после открывающих """;
  • закрывающие """ стоят на отдельной строке;
  • отступ перед закрывающими кавычками компилятор убирает из каждой строки текста, поэтому ни одна строка текста не может начинаться левее них.
C#
string path = @"C:\temp\new";
string note = """
    "Milk" 2
    C:\temp
    """;
Console.WriteLine(path); // C:\temp\new
Console.WriteLine(note); // "Milk" 2
                         // C:\temp

Перед закрывающими кавычками в note стоят четыре пробела. Компилятор срезал их у обеих строк текста, поэтому "Milk" 2 печатается с начала строки вывода.

Частая ошибка

Путь к папке записали в обычной строке:

C#
string path = "C:\docs\files"; // ✗
Console.WriteLine(path);
TEXT
error CS1009: Unrecognized escape sequence

Программа не компилируется: компилятор прочитал \d как управляющую последовательность, а такой в C# нет. С путём "C:\temp\new" ошибки не будет, и это хуже. \t и \n превратятся в табуляцию и перевод строки, и программа молча напечатает испорченный путь. Пишите такие строки с @ или удваивайте черту: @"C:\docs\files" или "C:\\docs\\files".

Главное

  • Строка — ряд символов char: s[i] даёт символ по индексу с нуля, s.Length — их число.
  • Кавычку, обратную черту и перевод строки в обычном литерале записывают как \", \\ и \n.
  • В буквальной строке @"…" обратная черта — обычный символ, а кавычку удваивают.
  • Необработанная строка """…""" хранит текст как есть и может занимать несколько строк файла.