\section{Строки}
Получив в предыдущих разделах представление об указателях и массивах, и вскользь несколько раз упомянув строки, пришла пора изучить их подробнее.

Итак, что же такое \textbf{строка}. В повседневной жизни строка \textit{это набор или последовательность символов}. Так вот в языке С строка - это тоже последовательность символов. А последовательности значений, в том числе символьных, в языке С представлены, как вы, уже знаете, массивами и указателями. Никакого примитива \code{string} в языке С нет. Как бы нам этого не хотелось - его нет. Но есть и хорошая новость, примитива \code{string} не существует и в других языках (здесь имеются ввиду, конечно, си-подобные языки, то есть примерно треть вообще всех языков программирования, известных сегодня). Раз строка - это массив или указатель, это всегда ссылочный тип данных. Например, строку можно объявить двумя способами:

\begin{figure}[h!]
  \begin{lstlisting}[language=C,style=CCodeStyle]
// строка
char str[50] =
    {'h','e','l','l','o',' ','w','o','r','l','d','\0'}; 

// литерал
    char* str = "Hello world"; 
  \end{lstlisting}
\end{figure}
Раз строка - это набор символов, давайте немного вспомним что такое сиволы и как с ними работать. Как вам уже известно, символьная переменная это переменная типа \code{char}. В отличие от строки это примитивный, числовой, тип данных, и к нему применимы все операции допустимые для примитивов, такие как присваивание, сложение, вычитание, умножение, деление, хотя не все имеют смысл, так автор, например с трудом может представить ситуацию в которой необходимо умножать или делить коды символов, кроме, пожалуй, криптографии. Обратим внимание на следующую запись:
\begin{figure}[h!]
  \begin{lstlisting}[language=C,style=CCodeStyle]
    char c0 = 75;
    сhar с1 = ‘К’;
  \end{lstlisting}
\end{figure}
Здесь значением \code{c0} является \code{75}, что абсолютно эквивалентно значению переменной \code{c1}, равной символу \code{K}. То есть можно сказать, что преобразование чисел в символы и наоборот согласно таблицы, наподобие ASCII, частично приведённой на стр.  \hyperref[table:ascii]{\pageref{table:ascii}}, встроена в работу компилятора языка С. Однако для улучшения читаемости кода лучше использовать вариант \code{sym = 'K'}.

\begin{figure}[h!]
  \begin{tabular}{||c|c|c||c|c|c||c|c|c||c|c|c||}
    \hline
    dec & hex  & val   & dec & hex  & val               & dec & hex  & val      & dec & hex  & val \\
    \hline
    000 & 0x00 & (nul) & 032 & 0x20 & \textvisiblespace & 064 & 0x40 & @        & 096 & 0x60 & \textquoteleft \\
    001 & 0x01 & (soh) & 033 & 0x21 & !                 & 065 & 0x41 & A        & 097 & 0x61 & a \\ 
    002 & 0x02 & (stx) & 034 & 0x22 & "                 & 066 & 0x42 & B        & 098 & 0x62 & b \\ 
    003 & 0x03 & (etx) & 035 & 0x23 & \#                & 067 & 0x43 & C        & 099 & 0x63 & c \\ 
    004 & 0x04 & (eot) & 036 & 0x24 & \$                & 068 & 0x44 & D        & 100 & 0x64 & d \\ 
    005 & 0x05 & (enq) & 037 & 0x25 & \%                & 069 & 0x45 & E        & 101 & 0x65 & e \\ 
    006 & 0x06 & (ack) & 038 & 0x26 & \&                & 070 & 0x46 & F        & 102 & 0x66 & f \\ 
    007 & 0x07 & (bel) & 039 & 0x27 & \textquotesingle  & 071 & 0x47 & G        & 103 & 0x67 & g \\ 
    008 & 0x08 & (bs)  & 040 & 0x28 & (                 & 072 & 0x48 & H        & 104 & 0x68 & h \\ 
    009 & 0x09 & (tab) & 041 & 0x29 & )                 & 073 & 0x49 & I        & 105 & 0x69 & i \\ 
    010 & 0x0A & (lf)  & 042 & 0x2A & *                 & 074 & 0x4A & J        & 106 & 0x6A & j \\ 
    011 & 0x0B & (vt)  & 043 & 0x2B & +                 & 075 & 0x4B & K        & 107 & 0x6B & k \\ 
    012 & 0x0C & (np)  & 044 & 0x2C & \textquoteright   & 076 & 0x4C & L        & 108 & 0x6C & l \\ 
    013 & 0x0D & (cr)  & 045 & 0x2D & -                 & 077 & 0x4D & M        & 109 & 0x6D & m \\ 
    014 & 0x0E & (so)  & 046 & 0x2E & .                 & 078 & 0x4E & N        & 110 & 0x6E & n \\ 
    015 & 0x0F & (si)  & 047 & 0x2F & /                 & 079 & 0x4F & O        & 111 & 0x6F & o \\ 
    016 & 0x10 & (dle) & 048 & 0x30 & 0                 & 080 & 0x50 & P        & 112 & 0x70 & p \\ 
    017 & 0x11 & (dc1) & 049 & 0x31 & 1                 & 081 & 0x51 & Q        & 113 & 0x71 & q \\ 
    018 & 0x12 & (dc2) & 050 & 0x32 & 2                 & 082 & 0x52 & R        & 114 & 0x72 & r \\ 
    019 & 0x13 & (dc3) & 051 & 0x33 & 3                 & 083 & 0x53 & S        & 115 & 0x73 & s \\ 
    020 & 0x14 & (dc4) & 052 & 0x34 & 4                 & 084 & 0x54 & T        & 116 & 0x74 & t \\ 
    021 & 0x15 & (nak) & 053 & 0x35 & 5                 & 085 & 0x55 & U        & 117 & 0x75 & u \\ 
    022 & 0x16 & (syn) & 054 & 0x36 & 6                 & 086 & 0x56 & V        & 118 & 0x76 & v \\ 
    023 & 0x17 & (etb) & 055 & 0x37 & 7                 & 087 & 0x57 & W        & 119 & 0x77 & w \\ 
    024 & 0x18 & (can) & 056 & 0x38 & 8                 & 088 & 0x58 & X        & 120 & 0x78 & x \\ 
    025 & 0x19 & (em)  & 057 & 0x39 & 9                 & 089 & 0x59 & Y        & 121 & 0x79 & y \\ 
    026 & 0x1A & (eof) & 058 & 0x3A & :                 & 090 & 0x5A & Z        & 122 & 0x7A & z \\ 
    027 & 0x1B & (esc) & 059 & 0x3B & ;                 & 091 & 0x5B & [        & 123 & 0x7B & \char`\{ \\ 
    028 & 0x1C & (fs)  & 060 & 0x3C & <                 & 092 & 0x5C & \char`\\ & 124 & 0x7C & | \\ 
    029 & 0x1D & (gs)  & 061 & 0x3D & =                 & 093 & 0x5D & ]        & 125 & 0x7D & \char`\} \\ 
    030 & 0x1E & (rs)  & 062 & 0x3E & >                 & 094 & 0x5E & \^{}     & 126 & 0x7E & \~{} \\ 
    031 & 0x1F & (us)  & 063 & 0x3F & ?                 & 095 & 0x5F & \char`\_ & 127 & 0x7F & \DEL \\ 
    \hline
  \end{tabular}
  \caption{Фрагмент таблицы ASCII}
  \label{table:ascii}
\end{figure}

Таких таблиц кодировок несколько, а может, даже и несколько десятков. Разные операционные системы и разные приложения используют разные кодировки, например, в русскоязычной версии ОС Windows по-умолчанию используется cp1251, в то время как в командной строке этой же ОС используется cp866. Файлы можно сохранить в Unicode или ANSI. UNIX-подобные ОС, такие как Linux и Mac OS X обычно используют UTF-8 или UTF-16, а более ранние операционные системы и интернет пространства в русскоязычном сегменте использовали KOI8-R.

Немного вспомнив, что такое символы, переходим к строкам. Строками мы пользуемся с самых первых страниц этого документа: написав в двойных кавычках <<Привет, Мир>>, мы использовали строку, а если точнее, строковый литерал. Строки иногда называют типом данных, но в языке С строка это указатель на последовательно записанный набор символов, поэтому работать с ним можно, как с массивами. Строки в языке С можно описать двумя способами: как указатель и как массив из переменных типа char.
\frm{Объявление строки как указателя на символы в языке С++ полностью заменили на указатель на константный набор символов, чтобы подчеркнуть неизменяемость литерала. То есть, если в языке С считается нормальной запись \code{char* s = "Hello";} то в С++ это можно записать \textbf{только} как \code{const char* s = "Hello";} при этом в обоих языках поведение такого указателя будет обинаковым.}
Давайте создадим строку в виде массива из \code{char} назовем ее \code{string1} и запишем внутрь литерал \code{This is a string!} - это строка. Также создадим указатель, назовем его \code{string2} и запишем в него литерал \code{This is also a string!} – это тоже строка. Выведем наши строки в консоль и убедимся, что автор не ошибся и их действительно можно так объявлять.

\begin{figure}[h!]
  \begin{lstlisting}[language=C,style=CCodeStyle]
char string1[256] = "This is a string!";
char* string2 = "This is also a string!";
printf("%s \n", string1);
printf("%s \n", string2);
  \end{lstlisting}
\end{figure}

У каждого из способов есть свои особенности. Так, например в \textit{массиве} из переменных типа \code{char} мы можем изменять символы. Всё работает. Попробовав изменить какой-нибудь символ в \code{string1}, например, пятый, на символ \code{X} можно будет убедиться, что объявленная таким образом строка изменяемая, в отличие от строкового литерала, попытка изменить который приведёт к ошибке во время исполнения программы. Указатель на \code{char} нам не даёт возможности частично менять содержимое внутри строки, и, получается, представляет собой \textbf{immutable string} – неизменяемую строку. 

\begin{figure}[h!]
  \begin{lstlisting}[language=C,style=CCodeStyle]
string1[5] = 'X';
printf("%s\n", string1);

string2[5] = 'X';
printf("%s\n", string2);
  \end{lstlisting}
\end{figure}

Обратите внимание, что компилятор не считает такую запись неверной и ошибка проявляет себя только во время исполнения программы. Таким образом, становится очевидно, что программисту недостаточно просто убедиться в том, что его код компилируется, но необходимо и проверить его работу во время исполнения. Часто в этом помогают Unit-тесты. Среди нерадивых программистов бытует мнение, что вообще все тесты должны писать специалисты в тестировании, но на примере выше, когда код компилируется, а программа всё равно не работает должным образом, мы видим, что некоторая более тщательная проверка своей работы должна быть выполнена именно программистом, а тестирование - это лишь инструмент, помогающий автоматизировать такие проверки.
\begin{verbatim}
$ ./program
Hello, world!
Hello, world!
HelloX world!
zsh: bus error  ./program
$
\end{verbatim}

Но довольно об ограничениях. Указатели на строки не такие уж бесполезные, мы можем, например, возвращать их из функций. То есть, мы можем объявить тип возвращаемого из функции значения как указатель \code{char*}, вернуть из нее строку и, например, вывести в консоль. Это открывает перед нами широчайшие возможности по работе с текстами. 

\begin{figure}[h!]
  \begin{lstlisting}[language=C,style=CCodeStyle]
char* helloFunction() {
    return "Hello!";
}

int main() {
    printf("%s \n",* helloFunction ());
}
  \end{lstlisting}
\end{figure}

Этот код выведет в консоль ожидаемое приветствие. Параллельно с написанием функции, приветствующей мир, предлагаю изучить некоторые стандартные возможности языка С для работы со строками. Например, специальную функцию, которая призвана выводить строки в консоль: \code{puts();} работает она очень похожим на \code{printf();} образом, но может выводить только строки, без каких-то других параметров, и всегда добавляет символ конца строки. Также изучим специальную функцию \code{gets();} которая призвана считывать строки из консоли и записывать их в переменные.
\frm{Функция \code{gets();} некоторыми компиляторами признана небезопасной, её использование рекомендуется заменить на \code{gets\_s();} В С11 и позднее небезопасная функция была вовсе удалена из стандартной библиотеки языка и перестала поддерживаться всеми производителями компиляторов.}
Создадим изменяемую строку типа \code{char[]}, назовём её \code{name}, передадим эту строку в функцию \code{gets();} и выведем на экран результат, полученный из консоли. Это будет очень полезная заготовка для дальнейшего общения с пользователем.

\begin{figure}[h!]
  \begin{lstlisting}[language=C,style=CCodeStyle]
    char name[255];
    gets(name);
    puts(name);
  \end{lstlisting}
\end{figure}

Теперь, мы можем поприветствовать пользователя нашей программы как следует, по имени. В нашей существовавшей функции приветствия внесём небольшие изменения. Создадим строку, в которой будем хранить приветственное слово, и в которую будет дописываться имя пользователя. Применим функцию склеивания строк. Поскольку склеивание - ненаучный термин, будем использовать слово \textbf{конкатенация}. И именно это слово подсказывает нам название функции, которую мы будем использовать: \code{strcat();}
\frm{Для использования функции \code{strcat();} необходимо подключить в программу заголовочный файл, содержащий функции, работающие со строками \code{\#include <string.h>}}
Функция принимает на вход два параметра - строку, \textit{к которой} нужно что-то прибавить, и строку, \textit{которую} нужно прибавить. Логично предположить, что первая строка должна быть изменяемой (то есть являться массивом символов, а не литералом). Функция прибавит все символы второй строки в первую (если в массиве хватит места) и вернёт указатель на изменённую строку. Очень удобно. Запустим наш проект, введем имя и убедимся что всё \textbf{сломалось}.

\begin{lstlisting}[language=C,style=CCodeStyle]
char* helloFunction(char* name) {
    char welcome[255] = "Hello, ";
    return strcat(welcome, name);
}

int main(int argc, const char* argv[]) {
    char name[256];
    gets(name);

    puts(helloFunction(name));
    return 0;
}
\end{lstlisting}
Что же случилось? Мы можем возвращать из функции только фиксированные строки, как в предыдущем примере. То есть, получается, нужно писать кейс, в котором содержатся все возможные имена, и оператором вроде \code{switch()} перебирать все возможные варианты ввода, и описывать все возможные приветствия пользователей, иначе мы устраиваем утечку памяти, создавая болтающийся в воздухе указатель, который никак не удалим? Нет, нас это, естественно, не устраивает. Что делать? Какой бы мы ни создали указатель в функции - он перестанет существовать, как только мы выйдем из области видимости этой функции.
\frm{В некоторых случаях может показаться, что никакой проблемы нет, поскольку написанная таким образом программа благополучно поприветствует пользователя, но такое поведение не гарантируется ни одним компилятором и ни одной операционной системой, поскольку возвращаемый таким образом указатель может быть переписан абсолютно любой следующей инструкцией кода. Такое \textit{исчезающее} значение называется \textbf{xvalue}.}
Выход очень простой: раз указатель не идёт в \code{int main (int argc, char *argv[])}, надо чтобы \code{int main (int argc, char *argv[])} дал нам указатель. Добавим в параметры функции указатель на выходную строку, и напишем что для начала сложить строки и положить в локальный массив \code{strcat(welcome, name)}. Добавим в основную функцию массив \code{char result[]}, который будет хранить результат и передадим в функцию \code{helloFunction} аргументы \code{name} и \code{result}. А раз функция больше ничего не возвращает, вполне легально сделать её \code{void}.

\begin{lstlisting}[language=C,style=CCodeStyle]
void helloFunction(char* name, char* out) {
    char welcome[255] = "Hello, ";
    strcat(welcome, name);
    out = welcome;
}

int main(int argc, const char* argv[]) {
    char name[256];
    char result[256];
    gets(name);

    helloFunction(name, result);
    puts(result);
    return 0;
}
\end{lstlisting}

Запускаем, и \textbf{снова не работает}, да ещё и как интересно, смотрите! Предупреждение, ладно, понятно, мы о нём говорили, но дальше, когда мы вводим имя на выходе получается какая-то совсем уж непонятная строчка, совсем не похожая на приветствие.
\begin{verbatim}
$ ./program 
warning: this program uses gets(), which is unsafe.
Ivan
??:

$
\end{verbatim}
А все дело в том, что строк в языке С за время повествования не появилось, и все манипуляции со строками - это довольно сложные алгоритмы работы с памятью и массивами символов. Поэтому, работая со строками, мы должны использовать библиотечные функции, например, есть функция \code{strcpy()}, которая не просто перекладывает указатель в определенную переменную, а копирует строку.

\begin{figure}[h!]
\begin{lstlisting}[language=C,style=CCodeStyle]
void helloFunction (char* name, char* out) {
    char welcome[255] = “Hello, ”;
    strcat(welcome, name);
    strcpy(out, welcome);
}
int main(int argc, const char* argv[]) {
    char name[256];
    char result[256];
    gets(name);
    helloFunction(name, result);
    puts(result);
    return 0;
}
\end{lstlisting}
\end{figure}
Если присмотреться, то можно заметить, что все функции работающие со строками, именно так и делают - запрашивают источник данных и конечную точку, куда данные нужно положить. А кто мы такие, чтобы спорить со стандартными библиотечными функциями? Обратите внимание на то, что функции \code{strcat();} и \code{strcpy();} возвращают указатель на получившуюся строку. Мы перестали возвращать указатель на получившуюся строку, поскольку никто не гарантирует, что он просуществует достаточно долго, и тут встаёт вопрос о вызывающем функцию контексте, нужен ли этот указатель вызывающему. В случае необходимости, конечно, его можно вернуть. Работа со строками в С до сих пор является очень и очень актуальной темой на программистских форумах, можете удостовериться в этом самостоятельно.

Раз уж заговорили о стандартной библиотеке, рассмотрим ещё пару-тройку функций. Например, сравнение строк: функция \code{strcmp();} допустим, я хочу, чтобы именно меня программа приветствовала как-то иначе. Функция возвращает отрицательные значения, если первая строка меньше второй, положительные, если первая больше второй, и ноль, если строки равны. Это функция, которую удобно применять в условиях. Если строки будут действительно равны, мы скопируем в строку с именем слово \code{Creator}.

\begin{figure}[h!]
\begin{lstlisting}[language=C,style=CCodeStyle]
void helloFunction (char* name, char* out) {
    char welcome[255] = “Hello, ”;
    if (strcmp("Ivan", name) == 0)
        strcpy(name, "Creator");
    strcat(welcome, name);
    strcpy(out, welcome);
}
\end{lstlisting}
\end{figure}

Из всех функций для работы со строками чрезвычайно часто используются \code{atoi();} и \code{atof();} переводящие написанные в строке цифры в численные переменные внутри программы. \code{atoi();} переводит в \code{int}, а \code{atof();} во \code{float}, соответственно. Для примера объявим переменную \code{num}, предложим пользователю ввести цифру, естественно в виде строки. Будем принимать ее при помощи небезопасной функции \code{gets();}, хотя как мы помним, могли бы и \code{scanf();} который сразу бы преобразовал строку согласно использованного заполнителя. Заведем переменную \code{int number} для хранения результата работы функции преобразования. Затем, давайте умножим результат сам на себя, чтобы убедиться, что это и правда число, причём именно то, которое мы ввели, и выведем окончательное число в консоль.

\begin{figure}[h!]
\begin{lstlisting}[language=C,style=CCodeStyle]
char num[64];
puts("Enter a number: ");
gets(num);
int number = atoi(num);
number *= number;
printf("We powered your number to %d", number);
\end{lstlisting}
\end{figure}
Полный список функций для работы со строками можно посмотреть в заголовочном файле \code{string.h}. Описание и механика их работы легко гуглится, документации по языку очень много.

В завершение беседы о строках и манипуляциях с ними, скажем ещё пару слов об обработке символов. Функции для работы с символами содержатся в заголовочном файле \code{stdlib.h}. Естественно, наша программа может получить от пользователя какие-то значения в виде строк. Не всегда же есть возможность использовать \code{scanf();} например, считывание из графических полей ввода или потоковый ввод данных из сети даёт нашей программе значения в виде строк. Стандартная библиотека языка С предоставляет нам функции для работы с каждым символом строки, например:
\begin{itemize}
\item \code{isalpha();} – возвращает истину, если символ в аргументе является символом из алфавита;
\item \code{isdigit();} – возвращает истину, если символ в аргументе является цифрой;
\item \code{isspace();} – проверяет, является ли переданный в аргументе символ пробельным;
\item \code{isupper();} \code{islower();} – находится ли переданный в аргументе символ в верхнем или нижнем регистре;
\item \code{toupper();} \code{tolower();} – переводят символ в верхний или нижний регистр, соответственно.
\end{itemize}
Можем использовать одну из них соответственно нашей задаче, допустим, пользователь может вводить своё имя как с заглавной буквы, так и всеми строчными. Уравняем оба варианта для нашей проверки одной строкой \code{name[0] = tolower(name[0]);} а после проверки вернём заглавную букву на место \code{name[0] = toupper(name[0]);} и удостоверимся что даже если мы напишем своё имя с маленькой буквы - программа напишет его с большой.

\begin{figure}[h!]
\begin{lstlisting}[language=C,style=CCodeStyle]
void helloFunction (char* name, char* out) {
    char welcome[255] = “Hello, ”;
    name[0] = tolower(name[0]); 
    if (strcmp("ivan", name) == 0)
        strcpy(name, "Creator");
    name[0] = toupper(name[0]); 
    strcat(welcome, name);
    strcpy(out, welcome);
}
\end{lstlisting}
\end{figure}
