如何在Ada中检查字符串是否以另一个字符串结尾?

3
对于每种流行的编程语言,对于这个问题都有标准答案,尽管答案通常归结为:“使用标准库中的string.endsWith()函数”。就Ada而言,据我所查,在Fixed String包的文档中,并没有string.endswith函数。
因此,给定两个固定字符串A和B,如何检查A是否以B结尾?
declare
   A : constant String := "John Johnson";
   B : constant String := "son";
begin
   if A.Ends_With(B) then -- this doesn't compile
      Put_Line ("Yay!");
   end if;
end

我的目的是为Ada建立一个标准答案。


1
我认为如果没有更好的Ends_With规范,我们无法正确回答这个问题。虽然Ada.Strings.Fixed.Tail在预期情况下可以工作,但我们还需要知道在不太常见的情况下(A'Length < B'Length or B = "") Ends_With应该做什么。 - Jeffrey R. Carter
1
它应该回答得像你问了一个人一样。 "hi" 结尾是否比 "longer than hi" 更长?不是的。如果 A 比 B 短,A 不可能以 B 结尾。如果 B 是空的,答案应该始终为 Yes。 - TamaMcGlinn
哇,Ada,一个来自过去的炸弹。 - pm100
1
是的,太不可思议了。就像 C++ 中的 "++" 一样古老! - Zerte
在我看来,询问一个字符串是否以空字符串结尾是没有意义的,但是考虑到这个规范,我会选择Zerte的答案(由Simon Wright修改为表达式函数)。 - Jeffrey R. Carter
4个回答

6
Simon的回答稍加简化:
function Ends_With (Source, Pattern : String) return Boolean is
begin
   return Pattern'Length <= Source'Length 
     and then Source (Source'Last - Pattern'Length + 1 .. Source'Last) = Pattern;
end Ends_With;

4

好的,这里是一个可能的解决方案:

main.adb

with Ada.Text_IO;       use Ada.Text_IO;
with Ada.Strings.Fixed; use Ada.Strings.Fixed;

procedure Main is

   A : constant String := "John Johnson";
   B : constant String := "son";

begin

   if Tail (A, B'Length) = B then
      Put_Line ("Yay!");
   end if;

end Main;

输出

$ ./main
Yay!

更新(2)

另一个更新(感谢 @Brian Drummond 的评论;但该评论已经消失了),同样使用 Tail。现在它与 @Zerte 的答案几乎完全相同,除了依赖于 Ada.Strings.Fixed

main.adb

with Ada.Text_IO;       use Ada.Text_IO;
with Ada.Strings.Fixed; use Ada.Strings.Fixed;
with Ada.Assertions;    use Ada.Assertions;

procedure Main is

   function Ends_With (Source, Pattern : String) return Boolean is
   begin
      return Source'Length >= Pattern'Length and then
        Tail (Source, Pattern'Length) = Pattern;
   end Ends_With;   

begin

   Assert (Ends_With ("John Johnson", "son")  = True);
   Assert (Ends_With ("hi", "longer than hi") = False);

   Assert (Ends_With (""  , ""  ) = True);
   Assert (Ends_With (" " , ""  ) = True);
   Assert (Ends_With (""  , " " ) = False);
   Assert (Ends_With (" " , " " ) = True);

   Assert (Ends_With ("n ", "n ") = True);
   Assert (Ends_With (" n", "n" ) = True);
   Assert (Ends_With ("n" , " n") = False);
   Assert (Ends_With (" n", " n") = True);

   Put_Line ("All OK.");

end Main;

输出

$ ./main
All OK.

1
使用 Index 函数,可以实现查找第三个元素的功能。 - egilhh
1
请注意,此代码可以正确处理 A 比 B 短的情况;由于 Tail 使用前缀空格而不是引发错误,这些空格使得相等比较返回 False。 - TamaMcGlinn
1
除非您遇到像 A = "n"B = " n" 这样的情况。 - Zerte
1
评论消失了,因为我继续阅读后发现它重复了Zerte的答案(已赞)。 - user1818839

2

这是一个没有任何显式循环的示例。

with Ada.Assertions; use Ada.Assertions;
with Ada.Text_IO; use Ada.Text_IO;

procedure Main is
   function Ends_With(Source : String; Pattern : String) return Boolean is
      result : Boolean := False;
   begin
      if Pattern'Length <= Source'Length then
         if Pattern'Length > 0 then
            result := Source((Source'Last - Pattern'Length + 1)..Source'Last) = Pattern;
         else 
            result := True;
         end if;
      end if;
      return result;
   end Ends_With;

begin

   Assert (Ends_With ("John Johnson", "son") = True);


   Assert (Ends_With (""  , ""  ) = True);
   Assert (Ends_With (" " , ""  ) = True);
   Assert (Ends_With (""  , " " ) = False);
   Assert (Ends_With (" " , " " ) = True);   

   Assert (Ends_With (""  , "n" ) = False);
   Assert (Ends_With ("n"  , "" ) = True);

   Assert (Ends_With ("n ", "n ") = True);
   Assert (Ends_With (" n", "n" ) = True);
   Assert (Ends_With ("n" , " n") = False);
   Assert (Ends_With (" n", " n") = True);

   Put_Line("All OK");
end Main;

2

作为对Jim的回答的轻微简化,这也是有效的:

   function Ends_With (Source, Pattern : String) return Boolean is
   begin
      if Pattern'Length > Source'Length then
         return False;
      else
         return Source (Source'Last - Pattern'Length + 1 .. Source'Last)
           = Pattern;
      end if;
   end Ends_With;

但更好的是(感谢Zerte),
function Ends_With (Source, Pattern : String) return Boolean is
  (Pattern'Length <= Source'Length and then
     Source (Source'Last - Pattern'Length + 1 .. Source'Last) = Pattern);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接