Как работает c_str() в c++?
Меня интересует как выглядит массив на который стоит указатель. Я так понимаю что функция берет строку например string str = «12345» и превращает в массив чаров <'1' ,'2' ,'3' ,'4' ,'5' , \0 >а потом возвращает указатель на этот массив Или так ? И еще такой момент , если возвращает указатель то почему работает вот это :'1'>
cout
Отслеживать
задан 1 мар 2020 в 23:07
655 2 2 золотых знака 8 8 серебряных знаков 20 20 бронзовых знаков
"12345" и есть массив чаров
– user176262
1 мар 2020 в 23:10
Связанный вопрос: Хранится ли в конце string терминальный символ?.
2 мар 2020 в 12:28
3 мар 2020 в 8:07
1 ответ 1
Сортировка: Сброс на вариант по умолчанию
Насколько я понимаю, string::c_str возвращает указатель на область памяти, где хранит саму строку. То есть, при возвращении не создает никаких дополнительных массивов, ничто никуда не преобразовывает и не копирует.
Отслеживать
28.8k 12 12 золотых знаков 59 59 серебряных знаков 118 118 бронзовых знаков
ответ дан 2 мар 2020 в 0:46
Dr. Andrey Belkin Dr. Andrey Belkin
226 1 1 золотой знак 2 2 серебряных знака 11 11 бронзовых знаков
Строки в языке C
Строка -- это последовательность ASCII или UNICODE символов.
Строки в C, как и в большинстве языков программирования высокого уровня рассматриваются как отдельный тип, входящий в систему базовых типов языка. Так как язык C по своему происхождению является языком системного программирования, то строковый тип данных в C как таковой отсутствует, а в качестве строк в С используются обычные массивы символов.
Исторически сложилось два представления формата строк:
- формат ANSI;
- cтроки с завершающим нулем (используется в C).
Формат ANSI устанавливает, что значением первой позиции в строке является ее длина, а затем следуют сами символы строки. Например, представление строки "Моя строка!" будет следующим:
11 'М' 'о' 'я' ' ' 'с' 'т' 'р' 'о' 'к' 'а' '!'
В строках с завершающим нулем, значащие символы строки указываются с первой позиции, а признаком завершения строки является значение ноль. Представление рассмотренной ранее строки в этом формате имеет вид:
'М' 'о' 'я' ' ' 'с' 'т' 'р' 'о' 'к' 'а' '!' 0
Объявление строк в C
Строки реализуются посредством массивов символов. Поэтому объявление ASCII строки имеет следующий синтаксис:
char имя[длина];
Объявление строки в С имеет тот же синтаксис, что и объявление одномерного символьного массива. Длина строки должна представлять собой целочисленное значение (в стандарте C89 – константа, в стандарте C99 может быть выражением). Длина строки указывается с учетом одного символа на хранение завершающего нуля, поэтому максимальное количество значащих символов в строке на единицу меньше ее длины. Например, строка может содержать максимально двадцать символов, если объявлена следующим образом:
char str[21]; Инициализация строки в С осуществляется при ее объявлении, используя следующий синтаксис:
char str[длина] = строковый литерал;
Строковый литерал – строка ASCII символов заключенных в двойные кавычки. Примеры объявления строк с инициализацией:
char str1[20] = "Введите значение: ", str2[20] = "";
const char message[] = "Сообщение об ошибке!";
Работа со строками в С
Так как строки на языке С являются массивами символов, то к любому символу строки можно обратиться по его индексу. Для этого используется синтаксис обращения к элементу массива, поэтому первый символ в строке имеет индекс ноль. Например, в следующем фрагменте программы в строке str осуществляется замена всех символов 'a' на символы 'A' и наоборот.
for(int i = 0; str[i] != 0; i++)
if (str[i] == 'a') str[i] = 'A';
else if (str[i] == 'A') str[i] = 'a';
>
Массивы строк в С
Объявление массивов строк в языке С также возможно. Для этого используются двумерные массивы символов, что имеет следующий синтаксис:
char имя[количество][длина];
Первым размером матрицы указывается количество строк в массиве, а вторым – максимальная (с учетом завершающего нуля) длина каждой строки. Например, объявление массива из пяти строк максимальной длиной 30 значащих символов будет иметь вид:
При объявлении массивов строк можно производить инициализацию:
char имя[количество][длина] = ;
Число строковых литералов должно быть меньше или равно количеству строк в массиве. Если число строковых литералов меньше размера массива, то все остальные элементы инициализируются пустыми строками. Длина каждого строкового литерала должна быть строго меньше значения длины строки (для записи завершающего нуля).
char days[12][10] = <
"Январь", "Февраль", "Март", ”Апрель", "Май",
"Июнь", "Июль", "Август", "Сентябрь","Октябрь",
"Ноябрь", "Декабрь"
>;
При объявлении массивов строк с инициализацией допускается не указывать количество строк в квадратных скобках. В таком случае, количество строк в массиве будет определено автоматически по числу инициализирующих строковых литералов.
Например, массив из семи строк:
char days[][12] = <
"Понедельник", "Вторник", "Среда", "Четверг",
"Пятница", "Суббота", "Воскресенье"
>;
Функции для работы со строками в С
Все библиотечные функции, предназначенные для работы со строками, можно разделить на три группы:
- ввод и вывод строк;
- преобразование строк;
- обработка строк.
Ввод и вывод строк в С
Для ввода и вывода строковой информации можно использовать функции форматированного ввода и вывода (printf и scanf). Для этого в строке формата при вводе или выводе строковой переменной необходимо указать спецификатор типа %s. Например, ввод и последующий вывод строковой переменной будет иметь вид:
char str[31] = "";
printf("Введите строку: ");
scanf("%30s”,str);
printf("Вы ввели: %s”,str);
Недостатком функции scanf при вводе строковых данных является то, что символами разделителями данной функции являются:
- перевод строки,
- табуляция;
- пробел.
Поэтому, используя данную функцию невозможно ввести строку, содержащую несколько слов, разделенных пробелами или табуляциями. Например, если в предыдущей программе пользователь введет строку: "Сообщение из нескольких слов", то на экране будет выведено только "Сообщение".
Для ввода и вывода строк в библиотеке stdio.h содержатся специализированные функции gets и puts.
Функция gets предназначена для ввода строк и имеет следующий заголовок:
char * gets(char *buffer);
Между тем использовать функцию gets категорически не рекомендуется, ввиду того, что она не контролирует выход за границу строки, что может произвести к ошибкам. Вместо нее используется функция fgets с тремя параметрами:
char * fgets(char * buffer, int size, FILE * stream);
где buffer - строка для записи результата, size - максимальное количество байт, которое запишет функция fgets, stream - файловый объект для чтения данных, для чтения с клавиатуры нужно указать stdin. Эта функция читает символы со стандартного ввода, пока не считает n - 1 символ или символ конца строки, потом запишет считанные символы в строку и добавит нулевой символ. При этом функция fgets записывает в том символ конца строки в данную строку, что нужно учитывать.
Функция puts предназначена для вывода строк и имеет следующий заголовок:
int puts(const char *string);
Простейшая программа: ввод и вывод строки с использованием функций fgets и puts будет иметь вид:
char str[102] = "";
printf("Введите строку: ");
fgets(str, 102, stdin);
printf("Вы ввели: ");
puts(str);
Для считывания одного символа можно использовать функцию fgetc(FILE * stream) . Она считывает один символ и возвращает значение этого символа, преобразованное к типу int, если же считывание не удалось, то возвращается специальная константа EOF, равная -1. Функция возвращает значение -1 для того, чтобы можно было обрабатывать ситуацию конца файла, посимвольное чтение до конца файла можно реализовать следующим образом:
int c;
while ((c = fgetc(stdin)) != EOF) // Обработка символа
>
Для вывода одного символа можно использовать функцию int fputc(int c, FILE *stream); .
Помимо функций ввода и вывода в потоки в библиотеке stdio.h присутствуют функции форматированного ввода и вывода в строки. Функция форматированного ввода из строки имеет следующий заголовок:
int sscanf(const char * restrict buffer, const char * restrict string, [address] . );
Функции форматированного вывода в строку имеют следующие заголовки:
int sprintf(char * restrict buffer,
const char * restrict format, [argument] . );
int snprintf(char * restrict buffer, size_t maxsize,
const char * restrict format, [argument] . );
Преобразование строк
В С для преобразования строк, содержащих числа, в численные значения в библиотеке stdlib.h
предусмотрен следующий набор функций:
double atof(const char *string); // преобразование строки в число типа double
int atoi(const char *string); // преобразование строки в число типа int
long int atol(const char *string); // преобразование строки в число типа long int
long long int atoll(const char *string); // преобразование строки в число типа long long int
Корректное представление вещественного числа в текстовой строке должно удовлетворять формату:
После символов E, e указывается порядок числа. Корректное представление целого числа в текстовой строке должно удовлетворять формату:
Помимо приведенных выше функций в библиотеке stdlib.h доступны также следующие функции преобразования строк в вещественные числа:
float strtof(const char * restrict string, char ** restrict endptr);
double strtod(const char * restrict string, char ** restrict endptr);
long double strtold(const char * restrict string,char ** restrict endptr);
Аналогичные функции присутствуют и для преобразования строк в целочисленные значения:
long int strtol(const char * restrict string, char ** restrict endptr, int base);
unsigned long strtoul(const char * restrict string,
char ** restrict endptr, int base);
long long int strtoll(const char * restrict string,
char ** restrict endptr, int base);
unsigned long long strtoull(const char * restrict string,char ** restrict endptr, int base);
Функции обратного преобразования (численные значения в строки) в библиотеке stdlib.h присутствуют, но они не регламентированы стандартом, и рассматриваться не будут. Для преобразования численных значений в строковые наиболее удобно использовать функции sprintf и snprintf.
Обработка строк
В библиотеке string.h содержаться функции для различных действий над строками.
Функция вычисления длины строки:
size_t strlen(const char *string);
char str[] = "1234";
int n = strlen(str); //n == 4
Функции копирования строк:
char * strcpy(char * restrict dst, const char * restrict src);
char * strncpy(char * restrict dst, const char * restrict src, size_t num);
Функции сравнения строк:
int strcmp(const char *string1, const char *string2);
int strncmp(const char *string1, const char *string2,size_t num);
Функции осуществляют сравнение строк по алфавиту и возвращают:
положительное значение – если string1 больше string2;
отрицательное значение – если string1 меньше string2;
нулевое значение – если string1 совпадает с string2;
Функции объединения (конкатенации) строк:
char * strcat(char * restrict dst, const char * restrict src);
char * strncat(char * restrict dst, const char * restrict src, size_t num);
Функции поиска символа в строке:
char * strchr(const char *string, int c);
char * strrchr(const char *string, int c);
Функция поиска строки в строке:
char * strstr(const char *str, const char *substr);
char str[] = "Строка для поиска";
char *str1 = strstr(str,"для"); //str1 == "для поиска"
Функция поиска первого символа в строке из заданного набора символов:
size_t strcspn(const char *str, const char *charset);
Функции поиска первого символа в строке не принадлежащему заданному набору символов:
size_t strspn(const char *str, const char *charset);
Функции поиска первого символа в строке из заданного набора символов:
char * strpbrk(const char *str, const char *charset);
Функция поиска следующего литерала в строке:
char * strtok(char * restrict string, const char * restrict charset);
CString Операции, связанные со строками в стиле C
Объект CString содержит символьные строковые данные. CString наследует набор методов и операторов, определенных в шаблоне CStringT класса для работы со строковыми данными. ( CString является тем typedef , который специализируется CStringT на работе с типом символьных данных, которые CString поддерживают.)
CString не обеспечивает внутреннее хранение символьных данных как строка с завершающим нулевым байтом в стиле C. Вместо этого CString отслеживает длину символьных данных, чтобы безопаснее контролировать эти данные и требуемое им место.
CString принимает строки в стиле C и предоставляет способы для доступа к символьным данным как строке в стиле C. В этом разделе содержатся следующие подразделы, в которых описано использование объекта CString , как если бы он являлся строкой с завершающим нулевым байтом в стиле C.
- Преобразование в строки, завершаемые значением NULL в стиле C
- Работа со стандартными функциями строк библиотеки времени выполнения
- Изменение содержимого CString напрямую
- Использование CString объектов с функциями аргументов переменной
- CString Указание формальных параметров
Использование CString в качестве строки, завершаемой значением NULL в стиле C
Чтобы использовать CString объект в качестве строки в стиле C, приведение объекта к объекту LPCTSTR . В следующем примере CString возвращает указатель на строку с завершающим нулевым байтом в стиле C, доступную только для чтения. Функция strcpy помещает копию строки в стиле C в переменную myString .
CString aCString = "A string"; char myString[256]; strcpy(myString, (LPCTSTR)aCString);
Вы можете использовать методы CString , например SetAt , для изменения отдельных символов в объекте строки. LPCTSTR Однако указатель является временным и становится недействительным при изменении CString . CString также может выйти за пределы области, после чего выполняется его автоматическое удаление. Рекомендуется получать свежий LPCTSTR указатель CString объекта при каждом использовании.
Иногда вам может потребоваться копия данных CString для непосредственного внесения изменений. Используйте более защищенную функцию strcpy_s (или переносимую между Юникодом и многобайтовой кодировкой _tcscpy_s ) для копирования объекта CString в отдельный буфер. Именно здесь можно безопасно изменить символы, как показано в следующем примере.
CString theString(_T("This is a test")); int sizeOfString = (theString.GetLength() + 1); LPTSTR lpsz = new TCHAR[sizeOfString]; _tcscpy_s(lpsz, sizeOfString, theString); //. modify lpsz as much as you want
Третий аргумент strcpy_s (или Юникод/МБ CS-переносимое _tcscpy_s ) — это либо const wchar_t* (Юникод) или const char* an (ANSI). Приведенный выше пример передает CString для этого аргумента. Компилятор C++ автоматически применяет функцию преобразования, определенную для класса CString , который преобразует CString в LPCTSTR . Возможность определения операций приведения от одного типа к другому — это одна из самых полезных особенностей C++.
Работа со стандартными функциями строк библиотеки времени выполнения
Вы должны иметь возможность найти метод CString для выполнения строковой операции, для которой может потребоваться использование стандартных строковых функций библиотеки времени выполнения, таких как strcmp (или переносимой между Юникодом и многобайтовой кодировкой _tcscmp ).
Если необходимо использовать строковые функции времени выполнения C, можно использовать методы, описанные в статье Using CString as a C-style null-terminated string. Вы можете скопировать объект CString в эквивалентный строковый буфер в стиле C, выполнить операции в этом буфере, а затем снова назначить полученную строку в стиле C объекту CString .
Изменение содержимого CString напрямую
В большинстве ситуаций для изменения содержимого объекта CString или для преобразования CString в символьную строку в стиле C следует использовать функции-члены CString .
В некоторых ситуациях имеет смысл напрямую изменить содержимое CString , например, при работе с функциями операционной системы, требующими символьный буфер.
Методы GetBuffer и ReleaseBuffer предоставляют доступ к внутреннему символьному буферу объекта CString и позволяют изменять его напрямую. Приведенные ниже действия показывают, как использовать такие функции в этих целях.
GetBuffer Использование и ReleaseBuffer доступ к внутреннему буферу символов CString объекта
- Вызовите GetBuffer для объекта CString и укажите требуемую длину буфера.
- Используйте указатель, возвращенный GetBuffer , для записи символов напрямую в объект CString .
- Вызовите ReleaseBuffer для объекта CString , чтобы обновить все внутренние сведения о состоянии CString , например длину строки. После непосредственного изменения содержимого объекта CString необходимо вызвать ReleaseBuffer до вызова любых других функций-членов CString .
Использование CString объектов с функциями аргументов переменной
Некоторые функции C принимают переменное число аргументов. Ярким примером этого является printf_s . Из-за способа объявления этого вида функции компилятор не может быть уверен в типе аргументов и не может определить, какую операцию преобразования требуется выполнить для каждого аргумента. Таким образом, вам важно использовать явное приведение типа при передаче объекта CString в функцию, которая принимает переменное число аргументов.
Чтобы использовать CString объект в функции аргумента переменной, явно приведение CString к LPCTSTR строке, как показано в следующем примере.
CString kindOfFruit = _T("bananas"); int howmany = 25; _tprintf_s(_T("You have %d %s\n"), howmany, (LPCTSTR)kindOfFruit);
Указание формальных CString параметров
Для большинства функций, которым требуется строковый аргумент, в прототипе функции в качестве указателя const на символ ( LPCTSTR ) вместо CString лучше всего указать формальный параметр. Если формальный параметр указан в качестве const указателя на символ, можно передать указатель TCHAR на массив, литеральную строку [ "hi there" ], или CString объект. CString Объект будет автоматически преобразован в объект LPCTSTR . Любое место, где можно использовать LPCTSTR объект, можно также использовать CString объект.
Можно также указать формальный параметр в виде ссылки на константную строку (т const CString& . е. ), если аргумент не будет изменен. Удалите модификатор, const если строка будет изменена функцией. Если требуется использовать по умолчанию значение NULL, инициализируйте его с нулевой строкой [ "" ], как показано ниже:
void AddCustomer(const CString& name, const CString& address, const CString& comment = _T(""));
Для большинства результатов функции вы можете просто возвратить объект CString по значению.
C str c что это
Формирует массив строк в стиле си. И возвращает указатель на него.
Допустим, некоторая функция в качестве параметра принимает указатель на массив чаров:
void Foo(const char* content);
То есть, в неё можно передать строку только в виде c-ctyle указателя
А у тебя есть строка записанная в стринге:
std::string str="привет мир";
И тебе нужно передать эту строку в твою функцию:
Foo(str); //нельзя. функция не умеет работать со стрингами
но так как функция не умеет работать со стрингами, а только с указателями, то единственный способ сделать это - функция c_str()
Функция c_str() присутствует только для совместимости с с-style кодом.
И в собственном c++ style коде, её лучше избегать настолько, насколько это возможно, дабы не плодить "суржик" (смесь двух стилей в одном исходном коде)