PVOID - Последовательности символов

Последовательности символов



Этот раздел является переводом туториала C++ Language


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

   Например, следующий массив:

char foo [20];

 это массив, который хранит до 20 элементов типа char. Он может быть представлен как:


 
   Следовательно, этот массив имеет емкость (capacity) для хранения последовательностей длиной до 20 символов. Но эта емкость не обязательно должна использоваться полностью: массив способен хранить более короткие последовательности. Например, в некоторой точке программы, foo может хранить последовательность «Hello» или последовательность «Merry Christmas», т.к. обе соответствуют последовательности длиной до 20 символов.

   По соглашению, конец строки, представленной в виде последовательности символов, обозначается специальным символом: нулевым символом (null character), фактическое значение которого может быть записано как ’\0′ (обратный слэш, ноль).

   В этом случае, массив из 20 элементов типа char с именем foo, хранящий последовательности символов «Hello» и «Merry Christmas», может быть представлен как:


 
   Обратите внимание, что после непосредственного содержимого строки добавлен нулевой символ (’\0′), чтобы обозначить конец последовательности. Панели серого цвета представляют элементы типа char с неопределенными значениями.

Инициализация нуль-терминированных последовательностей символов


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

char myword[] = { 'H', 'e', 'l', 'l', 'o', '\0' };

Это выражение объявляет массив из 6 элементов типа char, инициализированных символами, формирующими слово «Hello», плюс нулевой символ ’\0′ в конце.

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

   В выражениях, использованных в некоторых примерах в предыдущих главах, строковые литералы уже появлялись несколько раз. Они указываются в виде текста, заключенного в двойные кавычки ("). Например:

"the result is: "

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

   Последовательности символов, заключенные в двойные кавычки ("), являются литеральными константами. Их типом, фактически, является нуль-терминированный массив символов. Это означает, что строковые литералы всегда имеют нулевой символ (’\0′), автоматически добавляемый в конец.

   Следовательно, массив элементов типа char с именем myword может быть инициализирован нуль-терминированной последовательностью символов любым из следующих двух выражений:

char myword[] = { 'H', 'e', 'l', 'l', 'o', '\0' };
char myword[] = "Hello"; 

   В обоих случаях, массив символов myword объявлен с размером 6 элементов типа char: 5 символов составляют слово «Hello», плюс конечный нулевой символ (’\0′), который обозначает конец последовательности. Во втором случае, при использовании двойных кавычек ("), нулевой символ добавляется автоматически.

  Обратите внимание, что мы говорим об инициализации массива символов в момент объявления, а не о присваивании ему значения позже (когда он уже объявлен). Фактически, по той причине, что строковые литералы являются обычными массивами, они имеют такие же ограничения и им нельзя присваивать значения.

   Выражения (когда myword уже был объявлен, как указано выше), такие как:

myword = "Bye";
myword[] = "Bye";

 будут некорректными, как и:

myword = { 'B', 'y', 'e', '\0' };

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

myword[0] = 'B';
myword[1] = 'y';
myword[2] = 'e';
myword[3] = '\0';

 Строки и нуль-терминированные последовательности символов


   Простые массивы с нуль-терминированными последовательностями символов являются обычными типами, используемыми в языке Си для представления строк (поэтому они известны как Си-строки). В C++, хотя стандартная библиотека определяет конкретный тип для строк (класс string), тем не менее, простые массивы с нуль-терминированными последовательностями символов (Си-строки) являются естественным способом представления строк в языке; фактически, строковые литералы по-прежнему всегда создают нуль-терминированные последовательности символов, а не объеты string.

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

   Например, cin и cout поддерживают нуль-терминированные строки, позволяя непосредственно извлекать их из cin или помещать в cout, так же, как и строки типа string. Например:

#include <iostream>
#include <string>
using namespace std;

int main ()
{
  char question1[] = "What is your name? ";
  string question2 = "Where do you live? ";
  char answer1 [80];
  string answer2;
  cout << question1;
  cin >> answer1;
  cout << question2;
  cin >> answer2;
  cout << "Hello, " << answer1;
  cout << " from " << answer2 << "!\n";
  return 0;
}
What is your name? Homer
Where do you live? Greece
Hello, Homer from Greece!

   В этом примере используются как строки типа string, так и нуль-терминированные последовательности. Они вполне взаимозаменяемы при совместном использовании с cin и cout, но есть заметная разница в их объявлениях: массивы имеют фиксированный размер, который должен быть указан либо неявным, либо явным образом при объявлении; question1 имеет размер ровно 20 символов (включая завершающий нулевой символ), а answer1 имеет размер 80 символов; в то время как строки типа string не требуют указания размера. Это связано с тем, что строки типа string имеют динамический размер, определяемый во время выполнения, тогда как размер массивов определен во время компиляции, до запуска программы.

   В любом случае, нуль-терминированные последовательности и библиотечные строки легко трансформируются друг в друга:

   Нуль-терминированная последовательность символов может быть преобразована в string неявно, а объект string может быть преобразован в нуль-терминированную последовательность символов, используя методы класса string c_str или data:

char myntcs[] = "some text";
// преобразует си-строку в string
string mystring = myntcs;
// печатает как библиотечную строку
cout << mystring;
// печатает как си-строку
cout << mystring.c_str();


(обратите внимание: методы c_str и data являются эквивалентными)