2010-12-02 3 views
0

Мне нравится «изобретать колесо» для учебных целей, поэтому я работаю над классом контейнеров для строк. Будет ли использовать символ NULL в качестве терминатора массива (т. Е. Последнее значение в массиве будет NULL) вызывать помехи для строк с нулевым символом?Использование NULL в качестве терминатора в массивах?

Я думаю, что это будет проблемой, если будет добавлена ​​пустая строка, но я могу что-то упустить.

EDIT: Это на C++.

+0

Что вы подразумеваете под «вмешательством». Можете ли вы опубликовать любой код, чтобы показать, что вы описываете? – SpeksETC 2010-12-02 18:26:17

+0

Это C или C++? Какой тип строк вы сохраняете? – 2010-12-02 18:26:18

+0

@Sht C++. Извините, я не прояснил это. @SpeksETC Я имею в виду, что, поскольку строки имеют нуль-конец (я думаю?), Пустая строка будет иметь то же значение, что и значение «конец массива». – Maxpm 2010-12-02 18:27:52

ответ

2

"" - пустая строка в C и C++, а не NULL. Обратите внимание: "" имеет ровно один элемент (вместо нуля), то есть он эквивалентен {'\0'} как массив из char.

char const *notastring = NULL; 
char const *emptystring = ""; 

emptystring[0] == '\0'; // true 
notastring[0] == '\0'; // crashes 
0

Почему вы не следовать шаблону, используемому vector - хранить число элементов в классе контейнера, то вы всегда будете знать, сколько значений есть в нем:

vector<string> myVector; 

size_t elements(myVector.size()); 

инстанцировании строка с x, где const char* x = 0; может быть проблематичным. Смотрите этот код в STL Visual C++, которая вызывается, когда вы это делаете:

_Myt& assign(const _Elem *_Ptr) 
    { // assign [_Ptr, <null>) 
    _DEBUG_POINTER(_Ptr); 
    return (assign(_Ptr, _Traits::length(_Ptr))); 
    } 

static size_t __CLRCALL_OR_CDECL length(const _Elem *_First) 
    { // find length of null-terminated string 
    return (_CSTD strlen(_First)); 
    } 
1

При копировании из std::string, итераторы begin(), end() и вам не придется беспокоиться о NULL - в действительности, NULL присутствует только в том случае, если вы вызываете c_str() (в этом случае блок памяти, на который это указывает, будет иметь NULL для завершения строки.) Если вы хотите, чтобы memcpy использовали метод data().

2

Нет, это не так, потому что вы не будете хранить в массиве символов, вы будете хранить в массиве char *.

char const* strings[] = { 
    "WTF" 
, "Am" 
, "I" 
, "Using" 
, "Char" 
, "Arrays?!" 
, 0 
}; 
2

Это зависит от того, какую строку вы храните.

Если вы храните строки в стиле C, которые в основном являются указателями на массивы символов (char*), существует разница между значением указателя NULL и пустой строкой. Первое означает, что указатель «пуст», последний означает, что указатель указывает на массив, содержащий один элемент с символьным значением 0 ('\0'). Таким образом, указатель все еще имеет значение, и его тестирование (if (foo[3])) будет работать так, как ожидалось.

Если то, что вы храните, является стандартными библиотечными строками C++ типа string, тогда значение NULL отсутствует. Это потому, что нет указателя, а тип string рассматривается как одно значение. (. В то время как указатель технически нет, но может рассматриваться в качестве ссылки)

0
#include "Maxmp_crafts_fine_wheels.h" 
MaxpmContaner maxpm; 
maxpm.add("Hello"); 
maxpm.add(""); // uh oh, adding an empty string; should I worry? 
maxpm.add(0); 

На данный момент, как пользователь MaxpmContainer, кто не читал документацию, я бы ожидать следующее:

strcmp(maxpm[0],"Hello") == 0; 
*maxpm[1] == 0; 
maxpm[2] == 0; 

Интерференция между нулевым терминатором в позиции 2 и пустой строкой в ​​позиции 1 исключается с помощью оператора «интерпретировать это как адрес памяти» *. Позиция одна не будет равна нулю; это будет целое число, которое, если вы интерпретируете его как адрес памяти, окажется равным нулю.Позиция two будет равна нулю, что, если вы интерпретируете ее как адрес памяти, окажется резким беспорядочным выходом из вашей программы.

2

Я думаю, вы смущены. В то время как C-строки имеют «нулевое завершение», символ «NULL» отсутствует. NULL - это имя для нулевого указатель. Терминатор для C-строки является нулевым символом , то есть байтом со значением нуля. В ASCII этот байт (несколько смутно) называется NUL.

Предположим, что ваш класс содержит массив char, который используется для хранения строковых данных. Вам не нужно «отмечать конец массива»; массив имеет определенный размер, который устанавливается во время компиляции. Вам нужно знать, какая часть этого пространства используется; нуль-терминатор на строковых данных выполняет это для вас, но вы можете получить лучшую производительность, фактически сохраняя длину. Кроме того, класс «строка» со статическим буфером символов не очень полезен, потому что этот размер буфера является верхним пределом длины строк, которые вы можете иметь.

Таким образом, лучший класс строк будет содержать указатель типа char*, который указывает на динамически распределенный массив (new[]) char. Опять же, нет смысла «отмечать конец массива», но вам нужно будет запомнить как длину строки (т. Е. Объем используемого пространства), так и размер выделения (т. Е. Объем пространства, могут быть использованы до того, как вам придется перераспределить).

Смежные вопросы