Как сделать массив символов

Добавил пользователь Валентин П.
Обновлено: 04.10.2024

This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters

Lerbytech commented Nov 26, 2017

Объяснение на пальцах того, как работать с массивом строк.

  1. Числовые матрицы
  2. Массивы строк
  3. Ввод и вывод (пример)

Чтобы понять массивы строк вспомним второй блок задач задач про числовые матрицы. Обычно мы считали их квадратными, но я буду предполагать что они могут быть прямоугольными.
ТВ показывала различные варианты объявления матрицы. Рассмотрим их ещё раз.

Проще всего объявить через индексы:
0> int Mat[10][10];

Такой вариант объявления матрицы даёт нам фиксированную матрицу размером 10 на 10. Изменить его в ходе работы нельзя. В памяти будет выделено W*H*sizeof(int) байт. Отметим что матрице блок памяти выделяется последовательно. Очевидно что для большой матрицы вы можете столкнуться с некоторыми проблемами - она может в целом влезать в память, но вот однородного свободного блока для неё не будет .
Зато обращение к элементу производится легко и просто (за что все индексы и любят):
1> int N = Mat[0][1]; // 0 строка, 1 столбец

Другой вариант объявления матрицы который вы проходили заключался в объявлении массива указателей вот такого вида:
2> int *Arr[10]; // массив из 10 указателей типа integer

Объявляется массив указателей из 10 элементов. Каждый элемент - указатель, который будет дальше указывать на какую-либо строку матрицы.
Сразу заметим, что у вас не может быть больше 10 строк, так как на 11 физически нет места в массиве в виде свободного указателя. С другой стороны, в памяти пока что занято место только под эти 10 указателей (уже меньше, чем в прошлом примере, верно?).
Как же выделить место под каждую строчку матрицы шириной в W столбцов? Да легко, каждому указателю из массива Arr можно выделить память через malloc.
3>

В чём преимущество данного подхода?
В первую очередь, это не фиксированный размер матрицы. Можно выделить сколько угодно места под каждую строчку, то есть матрицу можно легко сделать неквадратной и даже определить кол-во столбцов в ходе работы программы.
Во-вторых, вы можете даже не использовать все 10 указателей под каждую строчку. В общем, по памяти это оптимальнее.

С другой стороны, простота данного подхода является мнимой. Если вам понадобится больше 10 строк, то ваш массив Arr не подойдет по размеру. Можно выделить и больший размер, но где потолок? 20? 100? 1000? Всегда у вас либо не хватает, либо вы берёте с избытком.
Откровенно говоря, эта проблема немного надуманная. Когда вы реально с ней столкнетесь, то будете знать много больше чем сейчас и заботить вас будут другие вещи. С другой стороны, из спортивного интереса и чувства вселенской справедливости, было бы неплохо научиться делать всё в виде чистой динамики.
Так что нет места полумерам! Мы можем объявить полностью динамически определяемую матрицу! Для этого введем двойной указатель.

4>

Код выше - абсолютная динамика. Размеры матрицы задаются в любом месте программы. Да, двойной указатель может казаться страшным. Но он точно выглядит менее уродским, чем конструкции массивов указателей. С другой стороны, массивы указателей достаточно часто используются в программах Жуковой и, вероятно, она будет ожидать увидеть именно их.
Важно понимать, что и двойной указатель, и массив указателей взаимозаменяемы.

int **Mat;
int *Arr[4];
// пропустим код где внесли значения в Mar и Arr

Обратимся к элементу в второй строчке и втором столбце. Для этого через двойной указатель *( (*Mat + 1) + 2) , а через массив - *(*(Arr[1]) + 2). Как видно, разницы при работе между ними почти нет.

Пытливый читатель может задаться вопросом - как это связано с строками? Ответ: самым очевидным образом.
Строка представляется как массив символов. С ней удобно работать через указатели.
Пусть вы вводите массив строк. Заранее количество вводимых строк скорее всего вам неизвестно. Каждая строка имеет различное число элементов. Работать через двойной указатель в этих условиях проще всего. Но сегодня здесь будет описана только работа через массив строк.
Просмотрите ещё раз код программы на самом верху страницы прежде чем начать читать следующий раздел.

image

Обычная строка в памяти представляется как массив символов. Все элементы лежат последовательно.

image

Если вы объявляете указатель, то под него тоже выделяется ячейка памяти.
Когда вы "выделяете ему память" и вносите в эту память значения, то на заранее неизвестном свободном участке памяти будет "огорожен" участок, в которой будут внесены значения массива.
Блок памяти и участок необязательно расположены рядышком.

image

Когда же вы выделяете массив указателей, то в памяти это выглядит примерно так:

То есть, заданный в программе массив указателей даёт нам кучку указателей, для каждого из которых можно выделить память, заполнить её значениями и работать с ними. Для простоты, можно считать, что в каждой ячейке массива хранится строка.

Рассмотрим подробнее что происходит в нашей программе-примере.
Программа выполняет следующее: пользователь вводит строку, то есть последовательность символов и жмет enter. Эта последовательность записывается в память. Если пользователь ввёл пустую строку (просто нажал enter), то ввод считается законченным. После чего на экран выводятся записанные в память строки.

Теперь построчно:
char *STR[10]; - массив указателей. Каждому указателю будет выделена память, куда будет записана введенная строка.
char **s; - указатель на строку из массива. С его помощью в цикле будем обращаться к нужной строке. Обязательно двойной: первый уровень позволяет обратиться к элементу массива, а второй уровень должен совпадать с типом строки _char*_
char buf[80]; - массив фиксированной длины, в который заносится введенная с клавиатуры строка. Можете использовать и char*, но проще через массив ( по не до конца понятным мне причинам если использовать строку возникают непонятные глюки. С массивом такой байды нету + Жукова обычно пишет массив она что-то знает ). Обратите внимание - в массиве 80 элементов, то есть строка большей длины записана не будет. Функция gets() передаст всю введенную строку в этот массив, но поместятся только первые 80.
int n = 0; - счетчик числа введенных строк.
int max_number_of_strings = 10; - указываете сколько максимум строк хотите ввести. Счетчик количества строк не превысит это значение.

Для того, чтобы работать с строкой мы будем пользоваться переменной **s - она имеет такой же тип данных, как и наш массив указателей (для людей это разное, для компьютера одно и то же).
Перед началом работы укажем: s = STR
В дальнейшем после каждой итерации цикла ввода (то есть, после каждой успешно введенной строки) будем увеличивать эту переменную: s++

Так как ввод строк осуществляется в цикле, то обсудим условия выхода из него. Их ровно два:

  1. Массив указателей заполнен
  2. Введена пустая строка

С первым условие проблем нет: у нас есть счётчик n и условие n подойдет под наши задачи.
С вторым условием немножко сложнее.
Строка считывается функцией gets(char*) . Аргумент функции - это переменная в которую мы хотим записать пользовательский ввод. Будем записывать в наш массив buf (то есть buffer // буфер):
gets(buf)
Если пользователь ввёл пустую строку, то в строке будет записан только '\0' . В случае нашего буфера мы говорим о ячейке buf[0] .
Второе условие можно записать следующим образом: buf[0] != '\0'

Теперь когда мы считали строку с клавиатуры и убедились, что её следует записать в память, запишем. Я объясню этот момент чуть позже, пока закончим с циклом.
Если руководствоваться нашими соображениями, то нам нужен вот такой цикл:

Язык Си очень хитёр. Формально, к каждой функции можно обратиться по указателю и тип void - не исключение. Есть хитрая возможность повыё******ся оптимизировать работу цикла и сделать его ещё более непонятным .
Мы можем обратиться к функции gets(buf) через разыменовывание и, тем самым, получим доступ к считанной ей строке. Этот доступ указывает сразу на начало строки, которое совпадает с первым элементом. Сравниваем его с символом конца строки и дело в шляпе. Наш счётчик n тоже можно вынести в цикл.
Из таких соображений мы получаем цикл:
for (s = STR, n = 0; n

Теперь рассмотрим как записать в память нашу считанную строку. Сейчас (после выполнения gets(buf) ) она хранится в buf
Нам необходимо нужному(!) указателю из нашего массива указателей STR выделить память подходящего размера и в эту память записать значения buf .
Для выделения памяти воспользуемся malloc :
*s= (char*)malloc( strlen(buf) * sizeof(char) + 1)
В первую очередь, обратите внимание что вы выделяем память не s, а хранимому в ней значению. То есть, мы берем наш указатель из массива STR на который сейчас указывает s и ему(!) выделяем память. Соответственно в скобочках перед malloc пишем одну звездочку, а не две (так как строка - это char* , а не char** )
Для выделения памяти нам нужно знать сколько её выделять, то есть - нужно найти длину строки buf воспользовавшись strlen . Эта функция вернем нам количество символов, но не учтёт нуль-символ. Его придется добавить вручную - просто увеличим +1 объем памяти. Обратите внимание на эту деталь, так убережёте себя от кучи убитых часов на отладку.

Теперь остается скопировать нашу строчку из временного места хранения в постоянное. Вызываем strcpy :
strcpy(STR[i], buf).

И на этом всё! В полном виде наш цикл устроен так:

Обсудим вывод строки. Он полностью аналогичен работе с массивами (ну или работе с строками, кому как угодно). Мы знаем сколько строк введено. Берем указатель S , связываем его с массивом и выводим на экран все первые n элементов.
Один нюанс: наш s формально указывает на указатель в массиве, а не на строчку. Строка же - это то, что хранится в том блоке памяти, на который указывает указатель. Поэтому воспользуемся разыменованием чтобы получить нашу строчку.
( Компилятор вам сразу выдаст подсказку: функция puts принимает на вход char* , а тип s - char** .

В программе строки могут определяться следующим образом:

  • как строковые константы;
  • как массивы символов;
  • через указатель на символьный тип;
  • как массивы строк.

Кроме того, должно быть предусмотрено выделение памяти для хранения строки.

Для корректного вывода любая строка должна заканчиваться нуль-символом '\0' , целочисленное значение которого равно 0. При объявлении строковой константы нуль-символ добавляется к ней автоматически. Так, последовательность символов, представляющая собой строковую константу, будет размещена в оперативной памяти компьютера, включая нулевой байт.

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

Строковые константы размещаются в статической памяти. Начальный адрес последовательности символов в двойных кавычках трактуется как адрес строки. Строковые константы часто используются для осуществления диалога с пользователем в таких функциях, как printf() .

При определении массива символов необходимо сообщить компилятору требуемый размер памяти.

Компилятор также может самостоятельно определить размер массива символов, если инициализация массива задана при объявлении строковой константой:

В этом случае имена m2 и m3 являются указателями на первые элементы массивов:

  • m2 эквивалентно &m2[0]
  • m2[0] эквивалентно ‘Г’
  • m2[1] эквивалентно ‘o’
  • m3 эквивалентно &m3[0]
  • m3[2] эквивалентно ‘x’


При объявлении массива символов и инициализации его строковой константой можно явно указать размер массива, но указанный размер массива должен быть больше, чем размер инициализирующей строковой константы:

Для задания строки можно использовать указатель на символьный тип .

В этом случае объявление массива переменной m4 может быть присвоен адрес массива:

Здесь m3 является константой-указателем. Нельзя изменить m3 , так как это означало бы изменение положения (адреса) массива в памяти, в отличие от m4 .

Для указателя можно использовать операцию увеличения (перемещения на следующий символ):

Массивы символьных строк

Иногда в программах возникает необходимость описание массива символьных строк . В этом случае можно использовать индекс строки для доступа к нескольким разным строкам.

В этом случае poet является массивом, состоящим из четырех указателей на символьные строки. Каждая строка символов представляет собой символьный массив, поэтому имеется четыре указателя на массивы. Указатель poet[0] ссылается на первую строку:
*poet[0] эквивалентно 'П',
*poet[l] эквивалентно '-'.

Инициализация выполняется по правилам, определенным для массивов.
Тексты в кавычках эквивалентны инициализации каждой строки в массиве. Запятая разделяет соседние
последовательности.
Кроме того, можно явно задавать размер строк символов, используя описание, подобное такому:

Массив строк

Свободный массив


определяет свободный массив, где длина каждой строки определяется тем указателем, который эту строку инициализирует. Свободный массив не тратит память напрасно.

Операции со строками

Большинство операций языка Си, имеющих дело со строками, работает с указателями. Для размещения в оперативной памяти строки символов необходимо:

  • выделить блок оперативной памяти под массив;
  • проинициализировать строку.

Для выделения памяти под хранение строки могут использоваться функции динамического выделения памяти. При этом необходимо учитывать требуемый размер строки:

Для ввода строки использована функция scanf() , причем введенная строка не может превышать 9 символов. Последний символ будет содержать '\0' .

Функции ввода строк

Для ввода строки может использоваться функция scanf() . Однако функция scanf() предназначена скорее для получения слова, а не строки. Если применять формат "%s" для ввода, строка вводится до (но не включая) следующего пустого символа, которым может быть пробел, табуляция или перевод строки.

Для ввода строки, включая пробелы, используется функция

В качестве аргумента функции передается указатель на строку, в которую осуществляется ввод. Функция просит пользователя ввести строку, которую она помещает в массив, пока пользователь не нажмет Enter.

Функции вывода строк

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

или в сокращенном формате

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

которая печатает строку s и переводит курсор на новую строку (в отличие от printf() ). Функция puts() также может использоваться для вывода строковых констант, заключенных в кавычки.

Функция ввода символов

Для ввода символов может использоваться функция

которая возвращает значение символа, введенного с клавиатуры. Указанная функция использовалась в рассмотренных ранее примерах для задержки окна консоли после выполнения программы до нажатия клавиши.

Функция вывода символов

Для вывода символов может использоваться функция

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

Пример Посчитать количество введенных символов во введенной строке.

Количество введенных символов в строке

Результат выполнения

Основные функции стандартной библиотеки string.h

Основные функции стандартной библиотеки string.h приведены в таблице.

Пример использования функций

Использование функций

Результат выполнения

А как в известной строке найти только цифры? Я знаю такой метод: создать строку "0123456789" и по одному символу проверять, находится ли он в этой строке. Как это осуществить в си?

Неформатированные ввод из стандартного потока и вывод в стандартный поток

С помощью функции printf() можно легко вывести на экран строку, содержащую пробелы:

С другой стороны, ввести строку произвольной длины, содержащую пробелы в неизвестных местах, исключительно с помощью функции scanf() невозможно. Для scanf() любой символ пустого пространства является сигналом завершения ввода очередных данных, если только не производится считывание символа.

На помощь может прийти функция getchar() , осуществляющая посимвольный ввод данных:

В заголовке цикла getchar() возвращает символ, далее записываемый в очередную ячейку массива. После этого элемент массива сравнивается с символом '\n'. Если они равны, то цикл завершается. После цикла символ '\n' в массиве "затирается" символом '\0'. В условии цикла должна быть также предусмотрена проверка на выход за пределы массива; чтобы не усложнять пример, опущена.

Однако в языке программирования C работать со строками можно проще. С помощью функций стандартной библиотеки gets() и puts() получают строку из стандартного потока и выводят в стандартный поток. Буква s в конце слов gets и puts является сокращением от слова string (строка).

В качестве параметров обе функции принимают указатель на массив символов (либо имя массива, либо указатель).

Функция gets() помещает полученные с ввода символы в указанный в качестве аргумента массив. При этом символ перехода на новую строку, который завершает ее работу, игнорируется.
Функция puts() выводит строку на экран и при этом сама добавляет символ перехода на новую строку. Простейший пример использования этих функций выглядит так:

Итак, если вы работаете со строками, а не другими типами данных, при этом нет необходимости выполнять их посимвольную обработку, то удобнее пользоваться функциями puts() и gets() . (Однако функция gets() считается опасной и была выпилена из версии языка C11.)

Массив символов и указатель на строку

Как мы знаем, строка представляет собой массив символов, последний элемент которого является нулевым символом по таблице ASCII, обозначаемым '\0'. При работе со строками также как с численными массивами можно использовать указатели. Мы можем объявить в программе массив символов, записать туда строку, потом присвоить указателю адрес на первый или любой другой элемент этого массива и работать со строкой через указатель:

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

Иногда в программах можно видеть такое объявление и определение переменной-указателя:

Строку, которая была присвоена не массиву, а указателю, также можно получить, обратившись по указателю:

Но давайте посмотрим, что же все-таки происходит, и чем такая строка, присвоенная указателю, отличается от строки, присвоенной массиву.

Когда в программе определяются данные и объявляются переменные, то под них отводится память. При этом данные, которые не были присвоены переменным, поменять в процессе выполнения программы уже нельзя.

Что происходит в примере? В программе вводится строковый объект, который по сути является строковой константой (литералом). Ссылка на первый элемент этой строки присваивается указателю. Мы можем менять значение указателя сколько угодно, переходить к любому из элементов константного массива символов или даже начать ссылаться на совершенно другую строку. Но вот поменять значение элементов строки не можем. Это можно доказать таким кодом:

В последней строке кода возникнет ошибка, т.к. совершается попытка изменить строку-константу.

Тем более нельзя делать так:

В данном случае память не была выделена под массив символов, который мы пытаемся считать функцией scanf() ; память была выделена только под указатель. Поэтому записать строку просто некуда. Другое дело, если память была выделена с помощью объявления массива, после чего указателю был присвоен адрес на этот массив:

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

Передача строки в функцию

Передача строки в функцию ничем не отличается от передачи туда массива чисел:

В этом примере функция change() принимает в качестве параметра указатель на символ. В теле функции значение указателя инкрементируется, указывая на следующий символ массива. В теле цикла инкрементируется значение, которое находится по адресу, который содержит указатель.

Объявите в программе три массива символов. Данные для двух из них получите с помощью вызовов функции gets() . Третий массив должен содержать результат конкатенации (соединения) двух введенных строк. Напишите функцию, которая выполняет конкатенацию строк.

Массив строк и массив указателей

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

Набор строк можно представить как двумерный массив, т.е. массив, состоящий из одномерных массивов, где каждый одномерный массив — это строка символов:

Представьте себе, что значит выполнить сортировку строк. Это значит, надо поменять местами содержимое множества ячеек памяти. Это достаточно трудоемкая для компьютера работа, особенно если строк очень много. Однако можно поступить по-иному. Достаточно создать массив указателей, каждый элемент которого будет указывать на соответствующую ему строку первого массива. Далее выполнить сортировку указателей, что несомненно быстрее. Конечно, сам массив строк отсортирован не будет, однако благодаря указателям у нас будет хранится отсортированный "срез" массива:

Примечания к программе:

  • На самом деле параметром функции sortlen() является указатель на указатель. Хотя для понимания проще сказать, что параметром является массив указателей на символы. Мы передаем в функцию указатель на первый элемент массива strP, который сам является указателем. Если бы в функции мы инкрементировали переменную s, то переходили бы к следующему элементу-указателю массива strP.
  • Сортировка выполняется методом пузырька: если длина строки, на которую ссылается следующий указатель массива strP, меньше длины строки под текущим указателем, то значения указателей меняются.
  • Выражение strP[i] = &strings[i][0] означает, что элементу массива указателей присваивается ссылка на первый символ каждой строки.

Напишите программу, которая сортирует строки по алфавиту. Для упрощения задачи пусть сортировка выполняется только по первым буквам строк (если первые буквы слов одинаковы, то вторые и последующие символы проверять не надо).

При использовании простых переменных каждой области памяти для хранения данных соответствует свое имя. Если с группой величин одинакового типа требуется выполнять однообразные действия, им дают одно имя, а различают по порядковому номеру. Это позволяет компактно записывать множество операций с помощью циклов. Конечная именованная последовательность однотипных величин называется массивом.

Описание массива в программе отличается от описания простой переменной наличием после имени квадратных скобок, в которых задается количество элементов массива (размерность):

float а [10]; // описание массива из 10 вещественных чисел

Элементы массива нумеруются с нуля. При описании массива используются те же модификаторы (класс памяти, const и инициализатор), что и для простых переменных. Инициализирующие значения для массивов записываются в фигурных скобках. Значения элементам присваиваются по порядку. Если элементов в массиве больше, чем инициализаторов, элементы, для которых значения не указаны, обнуляются:

Размерность массива вместе с типом его элементов определяет объем памяти, необходимый для размещения массива, которое выполняется на этапе компиляции, поэтому размерность может быть задана только целой положительной константой или константным выражением. Если при описании массива не указана размерность, должен присутствовать инициализатор, в этом случае компилятор выделит память по количеству инициализирующих значений. В дальнейшем мы увидим, что размерность может быть опущена также в списке формальных параметров.

Массивы в C++

ВниманиеПри описании массивов квадратные скобки являются элементом синтаксиса, а не указанием на необязательность конструкции.

Для доступа к элементу массива после его имени указывается номер элемента (индекс) в квадратных скобках. В следующем примере подсчитывается сумма элементов массива.

Динамические массивы

Динамические массивы создают с помощью операции new, при этом необходимо указать тип и размерность, например:

int п = 100:
float *р = new float [n];

В этой строке создается переменная-указатель на float, в динамической памяти отводится непрерывная область, достаточная для размещения 100 элементов вещественного типа, и адрес ее начала записывается в указатель р. Динамические массивы нельзя при создании инициализировать, и они не обнуляются.

Преимущество динамических массивов состоит в том, что размерность может быть переменной, то есть объем памяти, выделяемой под массив, определяется на этапе выполнения программы. Доступ к элементам динамического массива осуществляется точно так же, как к статическим, например, к элементу номер 5 приведенного выше массива можно обратиться как р[5] или *(р+5).

Альтернативный способ создания динамического массива — использование функции mallос библиотеки С:

int n = 100;
float *q = (float *) malloc(n * sizeof(float));

Операция преобразования типа, записанная перед обращением к функции mallос, требуется потому, что функция возвращает значение указателя тина void*, а инициализируется указатель на float.

Память, зарезервированная под динамический массив с помощью new [], должна освобождаться оператором delete [], а память, выделенная функцией mallос — посредством функции free, например:

delete [] р; free (q);

При несоответствии способов выделения и освобождения памяти результат не определен. Размерность массива в операции delete не указывается, но квадратные скобки обязательны.

Многомерные массивы

Многомерные массивы задаются указанием каждого измерения в квадратных скобках, например, оператор

задает описание двумерного массива из 6 строк и 8 столбцов. В памяти такой массив располагается в последовательных ячейках построчно. Многомерные массивы размещаются так, что при переходе к следующему элементу быстрее всего изменяется последний индекс. Для доступа к элементу многомерного массива указываются все его индексы, например, matr[i][j], или более экзотическим способом: *(matr[i]+j) или *(*(matr+i)+j). Это возможно, поскольку matr[i] является адресом начала i-й строки массива.

При инициализации многомерного массива он представляется либо как массив из массивов, при этом каждый массив заключается в свои фигурные скобки (в этом случае левую размерность при описании можно не указывать), либо задается общий список элементов в том порядке, в котором элементы располагаются в памяти:

Пример. Программа определяет в целочисленной матрице номер строки, которая содержит наибольшее количество элементов, равных нулю.

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

Строка представляет собой массив символов, заканчивающийся нуль-символом. Нуль-символ — это символ с кодом, равным О, что записывается в виде управляющей последовательности ‘’. По положению нуль-символа определяется фактическая длина строки. Строку можно инициализировать строковым литералом.

char str[10] = "Vasia";
// выделено 10 элементов с номерами от 0 до 9
// первые элементы — ‘V’, ‘а’, ‘s’, ‘i’, ‘а’, ‘’

В этом примере под строку выделяется 10 байт, 5 из которых занято под символы строки, а шестой — под нуль-символ. Если строка при определении инициализируется, ее размерность можно опускать (компилятор сам выделит соответствующее количество байт):

char str [] = "Vasia"; // выделено и заполнено 6 байт

char *str = "Vasia"

создает не строковую переменную, а указатель на строковую константу, изменить которую невозможно (к примеру, оператор str[l]=’o’ не допускается). Знак равенства перед строковым литералом означает инициализацию, а не присваивание. Операция присваивания одной строки другой не определена (поскольку строка является массивом) и может выполняться с помощью цикла или функций стандартной библиотеки. Библиотека предоставляет возможности копирования, сравнения, объединения строк, поиска подстроки, определения длины строки и т. д., а также содержит специальные функции ввода строк и отдельных символов с клавиатуры и из файла.

При работе со строками часто используются указатели.

Массивы в C++

ВниманиеРаспространенные ошибки при работе со строками — отсутствие пуль-символа и выход указателя при просмотре строки за ее пределы.

Существует несколько способов работы со строками (через массивы или указатели) и они имеют свои плюсы и минусы, но в общем случае лучше не изобретать велосипед, а пользоваться функциями библиотеки или определенным в стандартной библиотеке C++ классом string, который обеспечивает индексацию, присваивание, сравнение, добавление, объединение строк и поиск подстрок, а также преобразование из С-строк, то есть массивов типа char, в string, и наоборот.

Читайте также: