1

我不一定想这样做,但我很好奇。在 C/C++ 中,除了 null 终止符之外,还有其他方法可以定义字符串终止符吗?例如,是否可以这样写,

char* str = "123456|ABCDEF";

char* foo = str;
char* bar = strstr(str, "|") + 1;

// do something here to define '|' as a terminator

std::cout << foo << std::endl;
std::cout << bar << std::endl;

// undo pipe-as-terminator definition

并获得输出,

123456
ABCDEF

?

如果不可能,那么有没有办法获得指向缓冲区部分的指针,而无需分配/复制内存,也无需修改缓冲区,即将s覆盖|\0s?

4

2 回答 2

6

您可以编写一个字符串引用包装器,其中包含指向子字符串和大小的指针,然后使用write而不是operator<<

// Sketch
struct StringRef {
    const char* start;
    std::size_t length;
    // add code to initialize the object out of the substring
};
std::ostream& operator<<(std::ostream& o, const StringRef& s) {
   return o.write(s.start,s.length);
}
于 2013-01-16T19:31:18.757 回答
0

我不认为你可以,因为这条规则是在编译器内部硬构建的。事实上,编译器在您声明的每个字符串常量的末尾都包含了 null-trminator,方法是使用程序集 '.asciz' 指令。所以除非你修改gcc的源代码,我认为你不能。我真的不知道其他编译器,例如 MSVC。对于 Clang,我不知道是否有办法这样做,这需要调查。作为替代方案,您可以通过艰难的方式将每个字符串输入为 const char message[] = { 'H','e','l','l','o',' ', '!','|' };

但我想指出,如果编译器施加这种限制,那是有充分理由的。例如,想象一个您从用户那里获取输入文本的程序。如果用户输入'|'怎么办 在他的文字中?选择空字符的原因是用户无法输入此字符(因为它不是可打印字符集的一部分,而且我不知道任何键盘包括“空”键. 至少,你应该取另一个字符作为空终止符,但不要取一个容易输入的字符。

否则,我对操作系统开发感兴趣,人们喜欢重新发明轮子,而且我已经看到有人尝试使用另一种技术:为每个字符串加上长度,允许在字符串中嵌入空字符,以及提供恒定时间的 strlen() 操作。此外,C#/.NET 字符串是以长度为前缀和以空值结尾的,尽管我并不真正看到它的兴趣......

在我更精确之前,我想知道您正在使用哪个编译器,以及您在编程中的“水平”(只是不要告诉您您不会理解的事情)x)

干杯,摘要

于 2013-01-16T19:44:23.243 回答