Каковы различные способы в C/С++ для определения строки без нулевого завершения char (\ 0) в конце?
EDIT: Меня интересуют только массивы символов, а не строки STL.
Каковы различные способы в C/С++ для определения строки без нулевого завершения char (\ 0) в конце?
EDIT: Меня интересуют только массивы символов, а не строки STL.
Обычно, как писал другой плакат:
char s[6] = {'s', 't', 'r', 'i', 'n', 'g'};
или если ваша текущая C-кодировка - ASCII, которая обычно верна (не так много EBCDIC сегодня)
char s[6] = {115, 116, 114, 105, 110, 107};
Существует также сильно игнорируемый способ, который работает только в C (не С++)
char s[6] = "string";
Если размер массива слишком мал, чтобы удерживать конечный 0 (но достаточно большой, чтобы удерживать все остальные символы константной строки), конечный ноль не будет скопирован, но он все еще действителен C (но недействителен С++).
Очевидно, вы также можете сделать это во время выполнения:
char s[6];
s[0] = 's';
s[1] = 't';
s[2] = 'r';
s[3] = 'i';
s[4] = 'n';
s[5] = 'g';
или (то же замечание в кодировке ASCII, как указано выше)
char s[6];
s[0] = 115;
s[1] = 116;
s[2] = 114;
s[3] = 105;
s[4] = 110;
s[5] = 103;
Или используя memcopy (или memmove или bcopy, но в этом случае нет никакой пользы для этого).
memcpy(c, "string", 6);
или strncpy
strncpy(c, "string", 6);
Что следует понимать, так это то, что в C нет строки типа C (в С++ есть объекты строк, но это совсем другая история). Так называемые строки - это просто char массивы. И даже имя char вводит в заблуждение, это не char, а просто своего рода числовой тип. Вероятно, мы могли бы назвать его байтом, но в прежние времена существовало странное аппаратное обеспечение, использующее 9-битные регистры или такие, а байты - 8 бит.
Поскольку char будет очень часто использоваться для хранения символьного кода, дизайнеры C подумали о более простом способе, чем хранить номер в char. Вы можете поместить письмо между простыми кавычками, и компилятор поймет, что он должен хранить этот код символа в char.
Что я имею в виду (например), что вам не нужно делать
char c = '\0';
Чтобы сохранить код 0 в char, просто выполните:
char c = 0;
Поскольку нам очень часто приходится работать с кучей символов переменной длины, дизайнеры C также выбрали соглашение для "строк". Просто поместите код 0, где текст должен заканчиваться. Кстати, есть имя для такого рода строкового представления "строка с нулевым завершением", и если вы видите две буквы sz в начале имени переменной, это обычно означает, что это содержимое является строкой с нулевым завершением.
"C sz strings" не является типом вообще, просто массив символов, как обычно, как, скажем, массив int, но функции манипуляции с строкой (strcmp, strcpy, strcat, printf и многие другие) понимают и используйте соглашение о завершении 0. Это также означает, что если у вас есть массив char, который не завершен нулем, вы не должны вызывать какие-либо из этих функций, поскольку он, вероятно, сделает что-то неправильно (или вы должны быть осторожны и использовать функции с буквой от их имени как strncpy).
Самая большая проблема с этим соглашением заключается в том, что существует много случаев, когда он неэффективен. Один типичный пример: вы хотите поместить что-то в конец строки с завершающим 0. Если вы сохранили размер, вы можете просто прыгать в конце строки, используя соглашение sz, вы должны проверить его char на char. Другие проблемы возникают при работе с кодированным юникодом или таковым. Но в то время, когда C был создан, это соглашение было очень простым и отлично справилось с работой.
В настоящее время буквы между двойными кавычками, такими как "строка", не являются обычными массивами char, как в прошлом, но const char *
. Это означает, что указатель указывает на константу, которая не должна быть изменена (если вы хотите ее изменить, вы должны сначала ее скопировать), и это хорошо, потому что она помогает обнаруживать многие ошибки программирования во время компиляции.
С++ std::string
не завершены NUL.
P.S: NULL
- макрос 1. NUL
- \0
. Не смешивайте их.
1: C.2.2.3 Макро NULL
Макрос NULL, определенный в любом из <clocale>
, <cstddef>
, <cstdio>
, <cstdlib>
, <cstring>
,
<ctime>
, или <cwchar>
, представляет собой константу нулевого указателя С++, определенную реализацией в этом Интернационале
Стандарт (18.1).
Конечный нуль должен прекратить строку. Без этого вам понадобится другой метод для определения его длины.
Вы можете использовать предопределенную длину:
char s[6] = {'s','t','r','i','n','g'};
Вы можете эмулировать строки в стиле pascal:
unsigned char s[7] = {6, 's','t','r','i','n','g'};
Вы можете использовать (поскольку вас не интересует std::string).std::string
(на С++).
Предпочтительно использовать некоторую ранее существовавшую технологию, которая обрабатывает unicode или, по крайней мере, понимает строковое кодирование (т.е. wchar.h
).
И комментарий: если вы помещаете это в программу, предназначенную для запуска на реальном компьютере, вы можете подумать о том, чтобы ввести свою собственную "строку". Это подтолкнет ваш компилятор к barf, если вы случайно попытаетесь передать его функции, ожидающей строки в стиле C.
typedef struct {
char[10] characters;
} ThisIsNotACString;
В С++ вы можете использовать класс string и вообще не иметь дело с нулевым char.
Используйте std::string.
Существуют десятки других способов хранения строк, но использование библиотеки часто лучше, чем создание собственных. Я уверен, что мы могли бы придумать множество дурацких способов делать строки без нулевых терминаторов:).
В C вообще не будет более легкого решения. Вы могли бы сделать то, что сделал pascal, и поместить длину строки в первый символ, но это немного больно и ограничит вашу длину строки размером целого числа, которое может поместиться в пространство первого char. В С++ я бы определенно использовал класс std::string, к которому можно получить доступ
#include <string>
Являясь широко используемой библиотекой, это почти наверняка будет более надежным, чем перенос собственного класса строк.
Причина завершения NULL заключается в том, что обработчик строки может определить ее длину. Если вы не используете завершение NULL, вам нужно передать длину строк либо через отдельный параметр/переменную, либо как часть строки. В противном случае вы можете использовать другой разделитель, если он не используется внутри самой строки.
Честно говоря, я не совсем понимаю ваш вопрос, или если на самом деле это вопрос.
Даже класс string
сохранит его с нулевым значением. Если по какой-то причине вам абсолютно не нужен нулевой символ в конце вашей строки в памяти, вам придется вручную создать блок символов и заполнить его самостоятельно.
Я не могу лично думать о каком-либо реалистичном сценарии, почему вы хотите это сделать, поскольку нулевой символ является сигналом конца строки. Если вы также сохраняете длину строки, я думаю, вы сохранили один байт за счет того, что размер вашей переменной (вероятно, 4 байта), и получил более быстрый доступ к длине указанной строки.
Просто для полноты и гвоздя это полностью.
vector<char>