На этом шаге мы рассмотрим различия между строками и C-строками.
В стандарте C++ тип строковых литералов char* был заменен типом const char*. Впрочем, для сохранения совместимости поддерживается неявное, хотя и нежелательное преобразование к типу char*. Но так как строковые литералы все же не относятся к типу string, между "новыми" объектами строкового класса и традиционными С-строками существует тесная связь: С-строки могут использоваться практически в любых операциях вместе со строками (сравнение, присоединение, вставка и т. д.). В частности, поддерживается автоматическое преобразование типа const char* в строку. С другой стороны, не поддерживается автоматическое преобразование строковых объектов в С-строки. Возможность такого преобразования была исключена по соображениям безопасности - чтобы предотвратить непреднамеренные преобразования типов, приводящие к странным последствиям (а тип char* часто ведет себя довольно странно) и неоднозначности (например, в выражении, объединяющем строку string с С-строкой, можно было бы выполнять преобразование как string в char*, так и наоборот). Вместо этого в классе string были определены специальные функции для создания или записи/копирования С-строк. В частности, функция c_str() переводит содержимое строки в формат С-строки (то есть преобразует его в символьный массив с последним символом \0). Функция сору() позволяет копировать и записывать строковые значения в существующие С-строки и символьные массивы.
Следует помнить, что в строках не существует специальной интерпретации символа \0, который в традиционных С-строках является признаком конца строки. Символ \0 может входить в строки наравне с любым другим символом. Также учтите, что вместо параметра char* нельзя передавать NULL-указатель - это приводит к странным последствиям. Дело в том, что NULL относится к целочисленному типу и в перегруженных операциях интерпретируется как число 0 или символ со значением 0.
Преобразование содержимого строки в массив символов или С-строку осуществляется тремя функциями.
Функции data() и c_str() возвращают массив, принадлежащий строке, поэтому вызывающая сторона не должна модифицировать или освобождать память. Пример:
std::string s('12345"); atoi(s.c_str()); // Преобразование строки в целое число f(s.data(),s.length()); // Вызов функции для символьного массива // и количества символов char buffer[100]; s.copy(buffer,100); // Копировать не более 100 символов s в buffer s.copy(buffer,100,2); // Копировать не более 100 символов s в buffer, // начиная с третьего символа s
Обычно в программе следует работать со строками, а их преобразование в С-строки или символьные массивы должно производиться непосредственно перед тем, как вам потребуется содержимое строки в виде типа char*. Помните, что возвращаемые значения функций c_str() и data() остаются действительными только до следующего вызова неконстантной функции для той же строки:
std::string s; . . . . foo(s.c_str()); // Peзультат c_str() остается действительным // на время выполнения команды const char* p; р = s.c_str(); // p ссылается на содержимое s в формате С-строки foo(p); // OK (значение р остается действительным) s += "ext"; // Значение р становится недействительным foo(p); // ОШИБКА: недействительное значение аргумента р
На следующем шаге мы рассмотрим размер и емкость строк.