定义一个字符串,在结尾处没有空终止char(\ 0)

时间:2010-09-30 06:32:09

标签: c++ c

C / C ++中有哪些方法可以定义一个字符串,在末尾没有空终止char(\ 0)?

编辑:我只对字符数组感兴趣,而不是STL字符串。

9 个答案:

答案 0 :(得分:32)

通常另一张海报写道:

char s[6] = {'s', 't', 'r', 'i', 'n', 'g'};

或者如果您当前的C字符集是ASCII,这通常是正确的(今天的EBCDIC不多)

char s[6] = {115, 116, 114, 105, 110, 107};

还有一种基本上被忽略的方式只适用于C(不是C ++)

char s[6] = "string";

如果数组大小太小而不能保持最后的0(但足够大以容纳常量字符串的所有其他字符),则不会复制最终的零,但它仍然是有效的C(但是无效的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都是误导性的,它不是一个字符,而只是一种数字类型。我们可能已经将它称为字节,但在过去,使用9位寄存器或类似的字节意味着8位,有奇怪的硬件。

由于char通常用于存储字符代码,因此C设计者想到了一种比在char中存储数字更简单的方法。你可以在简单的引号之间放一个字母,编译器会理解它必须将这个字符代码存储在char中。

我的意思是(例如)您不必做

char c = '\0';

要在char中存储代码0,只需执行:

char c = 0;

由于我们经常需要处理一堆可变长度的字符,因此C设计师也选择了“字符串”的约定。只需将代码0放在文本应该结束的位置。顺便说一句,这种字符串表示有一个名称“零终止字符串”,如果你在变量名的开头看到两个字母sz,通常意味着它的内容是一个零终止的字符串。

“C sz strings”根本不是一个类型,只是一个正常的字符数组,比如一个int数组,但字符串操作函数(strcmp,strcpy,strcat,printf和许多其他函数)都明白并使用0结束约定。这也意味着如果你有一个非零终止的char数组,你不应该调用任何这些函数,因为它可能会出错(或者你必须格外小心并使用带有 n的函数他们名字中的字母,如 strncpy )。

这个惯例的最大问题是很多情况下效率低下。一个典型的例子:你想把一些东西放在一个0终止的字符串的末尾。如果你保持大小你可以跳到字符串的末尾,使用sz约定,你必须通过char检查它的char。处理编码的unicode等时会出现其他类型的问题。但是在创建C的时候,这个约定非常简单并完美地完成了工作。

如今,像“string”这样的双引号之间的字母不像过去那样是普通的char数组,而是const char *。这意味着指针指向的是一个不应修改的常量(如果你想修改它必须先复制它),这是一件好事,因为它有助于在编译时检测到许多编程错误。

答案 1 :(得分:6)

C ++ std::string未终止NUL。

P.S:NULL是宏 1 NUL\0。不要混淆它们。

1:C.2.2.3宏NULL

在任何<clocale><cstddef><cstdio><cstdlib><cstring>中定义的宏NULL, <ctime><cwchar>是本国际实现定义的C ++空指针常量 标准(18.1)。

答案 2 :(得分:6)

终止null用于终止字符串。没有它,你需要一些其他的方法来确定它的长度。

您可以使用预定义的长度:

char s[6] = {'s','t','r','i','n','g'};

您可以模拟pascal风格的字符串:

unsigned char s[7] = {6, 's','t','r','i','n','g'};

您可以使用std::string(在C ++中)。(因为您对std :: string不感兴趣)。

最好使用一些处理unicode的预先存在的技术,或者至少理解字符串编码(即wchar.h)。

评论:如果你把它放在一个打算在实际计算机上运行的程序中,你可以考虑输入你自己的“字符串”。如果您不小心尝试将其传递给期望C风格字符串的函数,这将鼓励您的编译器进行barf。

typedef struct {
    char[10] characters;
} ThisIsNotACString;

答案 3 :(得分:1)

在C ++中,您可以使用string类,而不是处理null char。

答案 4 :(得分:1)

只是为了完整起见并完全确定下来。

vector<char>

答案 5 :(得分:0)

使用std :: string。

有许多其他方法可以存储字符串,但使用库通常比制作自己的更好。我相信我们都可以提出大量古怪的方法来做无字符串的字符串:)。

答案 6 :(得分:0)

在C中通常不会有更简单的解决方案。您可以执行pascal所做的操作并将字符串的长度放在第一个字符中,但这有点痛苦,并且会将字符串长度限制为可以适合第一个字符空间的整数的大小。 在C ++中,我肯定使用可以通过

访问的std :: string类
#include <string>

作为一个常用的库,这几乎肯定比滚动你自己的字符串类更可靠。

答案 7 :(得分:0)

NULL终止的原因是字符串的处理程序可以确定它的长度。如果不使用NULL终止,则需要通过单独的参数/变量或作为字符串的一部分传递字符串长度。否则,你可以使用另一个分隔符,只要它不在字符串本身中使用。

说实话,我不太明白你的问题,或者它实际上是一个问题。

答案 8 :(得分:0)

即使string类也会将其存储为null。如果由于某种原因你绝对不希望在内存中你的字符串末尾有一个空字符,你必须手动创建一个字符块,并自己填写。

我个人无法想到为什么要这样做的任何现实场景,因为空字符表示字符串结尾的信号。如果你也存储字符串的长度,那么我猜你已经节省了一个字节,代价是变量的大小(可能是4个字节),并且可以更快地访问所述字符串的长度。< / p>