是否可以编写适用于所有本地化和字符串类型的通用字符串反向函数?


16

我只是在看Dev-DaysJon Skeet(与Tony the Pony)一起演讲。

尽管“编写字符串反向函数”正在对采访101进行编码-我不确定实际上是否可以编写一种通用的字符串反向函数,但肯定不是在所有本地化和所有字符串类型中都有效的函数。

除了检测输入字符串是否为ascii,UTF8,UTF16(固定长度和可变长度)等之外
,Jon还突出显示了“对下一个字符应用重音符号”(U + 0301)代码。然后有可能显示或不显示或连字编码为双字符的连字。

似乎“反向字符串”实际上是较难的计算机科学任务之一!


不,尝试将暂停问题的难度提高一些,但更容易向人们解释。
JB金

作为一个非主观的技术性问题,我敢说这在StackOverflow上更合适(不过请不要在此处重新发布,如果有足够的人投票将其关闭,它将自动迁移)。
彼得Török

1
取决于编程语言。例如,在Ruby中,它很容易做到"stressed".reverse:p
Marcelo

伟大的哲学问题。FWIW,Java的StringBuilder获得了正确的替代方法,但没有组合器
kdgregory

2
“使用Java在适当位置反转此字符串”是一个很好的技巧问题。:)
Scott C Wilson

Answers:


5

是。如果我们得到一个字符串,我们可以确定地反转每个字符。

乔恩(Jon)指出,问题在于反转是​​否有意义,并符合语言和文化规则,字符和编码。水越深,水越暗。

如果您在C#中执行任何类型的字符串操作,在读写时都使用Invariant文化,这样您就可以安全地操作它们。否则,为土耳其支持电话失败做好准备。

ToUpper()看起来很天真,但是这是史诗般的失败等待发生。


2
另一个问题是-除采访Q之外,有人会使用反向字符串吗?用绳子甚则几乎从未实际-我只是以往任何时候都需要它的I / O端口低水平缓冲区操作
马丁贝克特

@马丁-同意。也许是通过英语程序来查找回文症?除了解决测验问题外,我认为我没有使用过它。
乔恩·雷诺

@马丁是真的。我认为这只是讽刺的。:)
Scott C Wilson

2

通常,当询问此问题时,它采用的是US-ASCII。重点不是测试用户对Unicode的了解(尽管这将是一个有趣的后续步骤),而不是看他们是否了解指针的工作原理。数量惊人的人无法执行这种指针运算。


2
“使用unicode怎么会失败?” 是一个很好的后续问题
Martin Beckett

很好,但也许有点先进-毕竟,“将字符串反转”是一个入门级面试问题。您可能不会问一个经验丰富的人这么简单的事情,除非他们很害羞并且您想给他们热身。
Scott C Wilson

1

作为一个采访问题,通常只询问有关就地交换8位项目以颠倒其顺序的技术位(无论这些位实际上可能代表什么字符)。

同时,特别是如果您正在采访相对资深的人士,您至少可以希望听到一些有关规格和输入形式的问题。即使您将它们引回只是交换8位项目的简单情况,也要知道它们是否比这更广泛地考虑可能是有价值的。

如果您确实需要处理各种各样的输入,则只需考虑“堆栈”(有点像网络堆栈)。您必须将软件构建为多个层次,每个层次均以特定顺序应用一组相当特定的转换。这使您可以使转换的每个部分足够简单,以使您可以控制它,并有合理的机会使其符合要求。

我将概述至少已发现可行的一种可能性。我是第一个承认也许会有其他人有更好想法的人。至少在我看来,这有点像蛮力工程,几乎没有真正的优雅。

通常,您首先需要将任何其他表示形式转换为UCS-4(又名UTF-32)。为此,您通常宁愿依赖用户的输入,也不愿自己尝试输入。在某些情况下,您可以确保特定的八位位组序列遵循特定编码方案的规则,但是很少(如果有的话)可以确保它确实遵循特定的编码方案。

下一步是可选的。您可以将输入标准化为四种Unicode标准化形式之一。在这种情况下,您可能要应用“ NFKC”转换:兼容性分解后再进行规范合成。这将(在可能的情况下)将组合的变音形式(例如Jon提到的U + 301)转换为单个代码点(例如,带有“ U + 301”的“ A”将被转换为“带有急性的拉丁大写字母A”) ,U + 00C1)。

然后,您从头到尾遍历所有字符,将字符串分解为实际字符-如果(仍然)结合了变音符号,则将它们与修改后的字符保持在一起。其结果通常是字符串中实际字符的索引,例如每个字符的位置和长度。

您通常通过使用在上一步中创建的索引来反转这些完整字符的顺序。

然后(再次,可选地)应用另一个Unicode标准化过程,例如NFD(规范分解)。这将使前面提到的“带有急性的拉丁A”变成两个代码点-“拉丁大写A”和“合并急性”。但是,如果您的输入恰好包含一个U + 00C1,它也会将转换为两个代码点。

然后,您可以将UCS-4代码点的序列编码为所需的编码(UTF-8,UTF-16等)

请注意,Unicode规范化步骤可以/将更改存储字符串所需的代码点数量,因此,如果包括这些代码点,则无法再计划适合原始存储的结果字符串。显然,所得代码点也可能不直接对应于输入代码点。


在乔恩提出U + 301之前,我还没有遇到过。我不明白为什么它需要以Unicode与字形所有重音字符-我想象它的向后兼容性
马丁贝克特

@马丁:实际上有很多变音符号组合(从U + 0300到U + 036F的整个范围,尽管从U + 0363到U + 036F充其量是过时的)。提供了一些最常见的可能的预组合字符,并结合了变音符号来满足其他任何需要。
杰里·科芬,

过多的额外存储,规范化和转换。只需迭代字符,并就地反转组成代码单元的顺序。然后就地颠倒所有代码单元的顺序。
Deduplicator
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.