我需要存储一个字符串,用一些字符替换它的空格。当我取回它时,我需要再次用空格替换字符。我在存储时想到了这个策略,我将替换(用_a 的空格)和(用_aa 的_a),在检索时将替换(用空格的_a)和(用_a 的_aa)。即,即使用户在字符串中输入_a,它也会被处理。但我不认为这是一个好的策略。请让我知道是否有人有更好的?
7 回答
当字符串中已经存在某些内容时,用某些内容替换空格是一个问题。为什么不简单地对字符串进行编码 - 有很多方法可以做到这一点,一种是将所有字符转换为十六进制。
例如
Hello world!
被编码为
48656c6c6f20776f726c6421
空间为 0x20。然后,您只需将字符串解码回(十六进制到 ascii)。
这样编码的字符串中就没有空格。
--编辑- 优化--
您将字符串中的所有空格替换为%
字符的十六进制代码。%xx
xx
例如
Wine having 12% alcohol
变成
Wine%20having%2012%25%20alcohol
- %20 是空格
- %25 是 % 字符
这样, (空间)%
都不再是问题 - 解码很容易。
编码算法
- replace all `%` with `%25`
- replace all ` ` with `%20`
解码算法
- replace all `%xx` with the character having `xx` as hex code
(您甚至可以进行更多优化,因为您只需要编码两个字符:使用%1
for%
和%2
for ,但我推荐该
%xx
解决方案,因为它更便携 - 如果您需要编码更多字符,以后可以使用)
我不确定您的解决方案是否有效。阅读时,您将如何区分最初的" a"
字符串和最初的字符串"_a"
:如果我理解正确,两者都会结束
"_aa"
。
一般来说,给定的情况是一组特定的字符不能这样出现,但必须进行编码,解决方案是选择一个允许的字符作为“转义”字符,将其从允许的字符集中删除,然后对所有字符进行编码禁止字符(包括转义字符)作为以转义字符开头的两个(或更多)字符序列。例如,在 C++ 中,字符串或字符文字中不允许有新行。转义字符是
\
; 因此,它也必须编码为转义序列。所以我们有"\n"
一个新行(的选择n
是任意的)和
"\\"
一个\
. (选择\
因为第二个字符也是任意的,但通常使用转义字符来表示自己。)在你的情况下,如果你想_
用作转义字符并"_a"
表示一个空格,逻辑选择是是"__"
代表 a _
(但我会建议一些更具视觉暗示性的东西 - 也许^
作为逃生,"^_"
for a space 和"^^"
for a ^
)。阅读时,只要您看到转义字符,就必须映射以下字符(如果它不是预定义的映射之一,则输入文本有误)。这实现起来很简单,而且非常可靠;唯一的缺点是,在极端情况下,它可以使字符串的大小加倍。
I'm guessing that there is more to this question than appears; for example, that you the strings you are storing must not only be free of spaces, but they must also look like words or some such. You should be clear about your requirements (and you might consider satisfying the curiosity of the spectators by explaining why you need to do such things.)
Edit: As JamesKanze points out in a comment, the following won't work in the case where you can have more than one consecutive space. But I'll leave it here anyway, for historical reference. (I modified it to compress consecutive spaces, so it at least produces unambiguous output.)
std::string out;
char prev = 0;
for (char ch : in) {
if (ch == ' ') {
if (prev != ' ') out.push_back('_');
} else {
if (prev == '_' && ch != '_') out.push_back('_');
out.push_back(ch);
}
prev = ch;
}
if (prev == '_') out.push_back('_');
对于使用 X 字符的普通字符串,您不能仅使用 1 个字符/输入字符来编写或编码带有 x-1 的字符串。您可以使用 2 个字符的组合来替换给定的字符(这正是您在示例中尝试的)。
为此,请遍历您的字符串以计算空格的出现及其长度,创建一个新的字符数组并用“//”替换这些空格,但这只是一个示例。这种方法的问题是您的输入字符串中不能有“//”。
另一种方法是使用很少使用的字符,例如“^”来替换空格。
最后一种方法,流行于这两种方法的组合中。它在 unix 和 php 中用于将语法字符作为字符串中的文字。如果你想要一个 " " ",你只需把它写成 \" 等等。
我认为只编码为 ascii 十六进制是一个好主意,但当然需要双倍的存储量。
如果您想使用更少的内存来执行此操作,那么您将需要两个字母的序列,并且必须小心您可以轻松返回。
例如,您可以将空白替换为_a
,但您还需要注意转义字符_
。为此,请将 every 替换_
为__
(两个下划线)。您需要扫描一次字符串并同时进行两次替换。
这样,在生成的文本中,所有原始下划线都将加倍,并且唯一出现的下划线将出现在组合中_a
。您可以安全地将其翻译回来。每当你看到一个下划线时,你需要一个 1 的lookahed,然后看看下面的内容。如果一个a
跟随,那么这之前是一个空白。如果_
跟随,那么它之前是一个下划线。
请注意,重点是替换_
原始字符串中的转义字符 ( ),而不是您将空白映射到的字符序列。你的想法是更换_a
休息时间。因为您不知道_aa
最初是_a
或a
(空白后跟a)。
您想使用 C/C++ 来实现它吗?我认为你应该将你的字符串分成多个部分,用空格分隔。
如果您的字符串是这样的:“a__b”(多个空格连续),它将被拆分为:
sub[0] = "a";
sub[1] = "";
sub[2] = "b";
希望这会有所帮助!
为什么不使用替换功能
String* stringWithoutSpace= stringWithSpace->Replace(S" ", S"replacementCharOrText");
所以现在 stringWithoutSpace 不包含空格。当你想把这些空间放回去时,
String* stringWithSpacesBack= stringWithoutSpace ->Replace(S"replacementCharOrText", S" ");