前段时间我在玩这个,除了类似于 Tom 的解决方案外,我还想出了两个变体。
我遇到的一个问题是并非所有单词都用空格分隔,例如 Run-Time 和 Read/Write,所以我编写了这个版本以使用任何非字母字符作为分隔符。
我还想把变音符号和重音字符算作字母,所以它变得有点复杂。为了解决这个问题,我创建了两个版本的标题,一个大写和一个小写。两个字符串相同的地方是非字母字符,它们不同的地方是字母字符。标题通常很短,因此这种方法并不像最初看起来那样低效。
FUNCTION TitleCase2 RETURNS CHARACTER
( pcText AS CHARACTER ) :
/*------------------------------------------------------------------------------
Purpose: Converts a string to Title Case.
Notes: This version takes all non-alphabetic characters as word seperators
at the expense of a little speed. This affects things like
D'Arby vs D'arby or Week-End vs Week-end.
------------------------------------------------------------------------------*/
DEFINE VARIABLE cUText AS CHARACTER NO-UNDO CASE-SENSITIVE.
DEFINE VARIABLE cLText AS CHARACTER NO-UNDO CASE-SENSITIVE.
DEFINE VARIABLE i AS INTEGER NO-UNDO.
DEFINE VARIABLE lFound AS LOGICAL NO-UNDO INITIAL TRUE.
cUText = CAPS(pcText).
cLText = LC(pcText).
DO i = 1 TO LENGTH(pcText):
IF (SUBSTRING(cUText, i, 1)) <> (SUBSTRING(cLText, i, 1)) THEN
DO:
IF lFound THEN
DO:
SUBSTRING(cLText, i, 1) = (SUBSTRING(cUText, i, 1)).
lFound = FALSE.
END.
END.
ELSE lFound = TRUE.
END.
RETURN cLText.
END FUNCTION.
另一个问题是标题格应该是特定于语言的,即动词和名词与介词和连词的处理方式不同。这些是标题大小写的一些可能规则:
- 第一个和最后一个单词总是大写
- 将所有名词、动词(包括“is”和其他形式的“to
be")、副词(包括“than”和“when”)、形容词(包括
“this”和“that”)和代词(包括“its”)。
- 将属于动词短语的介词大写。
- 小写冠词(a、an、the)。
- 小写并列连词(and、but、for、nor 或 or)。
- 四个或更少字母的小写介词。
- 不定式短语中的小写“to”。
- 如果复合词中的第二个词是名词或
适当的形容词或单词具有相同的权重(交叉引用,
Pre-Microsoft 软件、读/写访问、运行时)。小写
第二个词,如果它是另一个词性或分词
修改第一个单词(How-to、Take-off)。
如果不教计算机英语,我当然不能编写所有这些代码,所以我创建了这个版本作为一个简单但粗略的折衷方案;它在大多数情况下都有效,但也有例外。
FUNCTION TitleCaseE RETURNS CHARACTER
( pcText AS CHARACTER ) :
/*------------------------------------------------------------------------------
Purpose: Converts an English string to Title Case.
Notes:
------------------------------------------------------------------------------*/
DEFINE VARIABLE i AS INTEGER NO-UNDO.
DEFINE VARIABLE cWord AS CHARACTER NO-UNDO.
DEFINE VARIABLE lFound AS LOGICAL NO-UNDO INITIAL TRUE.
DEFINE VARIABLE iLast AS INTEGER NO-UNDO.
DEFINE VARIABLE cSmallWords AS CHARACTER NO-UNDO
INITIAL "and,but,or,for,nor,the,a,an,to,amid,anti,as,at,but,by,down,from,in" +
",into,like,near,of,off,on,onto,over,per,than,to,up,upon,via,with".
pcText = REPLACE(REPLACE(LC(pcText),"-"," - "),"/"," / ").
iLast = NUM-ENTRIES(pcText, " ").
DO i = 1 TO iLast:
cWord = ENTRY(i, pcText, " ").
IF LENGTH(cWord) > 0 THEN
IF i = 1 OR i = iLast OR LOOKUP(cWord, cSmallWords) = 0 THEN
ENTRY(i, pcText, " ") = CAPS(SUBSTRING(cWord, 1, 1)) + LC(SUBSTRING(cWord, 2)).
END.
RETURN REPLACE(REPLACE(pcText," - ","-")," / ","/").
END FUNCTION.
我不得不提到,汤姆的解决方案比我的两个都快得多。根据您的需要,您可能会发现速度并不那么重要,因为您不太可能在大型数据处理过程或长字符串中使用它,但我不会忽略它。确保您的需求证明性能损失是合理的。