Ada String Concatenation

时间:2011-02-14 02:49:41

标签: ada

我有一个函数返回特定项的字符串,我需要多次调用该函数并将这些字符串合并为一个。组合的字符串是有界的。当空格字符初始化时我确保填充它但我不断收到“长度检查失败”错误。我有什么基本的错误吗?

FOR I IN 1..Collection.Size LOOP  
    Combined_String :=  combined_string & Tostring(Collection.Book(I));  
END LOOP;

5 个答案:

答案 0 :(得分:5)

Unbounded_String可能是最简单的方法:

with Ada.Strings.Unbounded;
use Ada.Strings.unbounded;

   ...

Temp_Unbounded_String : Unbounded_String;  -- Is empty by default.

   ...

for I in 1 .. Collection.Size loop
   Append(Temp_Unbounded_String, ToString(Collection.Book(I));
end loop;

如果您需要将结果放在固定长度的标准字符串中:

declare
   Temp_String : constant String := To_String(Temp_Unbounded_String);
begin
   -- Beware! If the length of the Temp_String is greater than that of the
   -- fixed-length string, a Constraint_Error will be raised.  Some verification
   -- of source and target string lengths must be performed!
   Combined_String(Temp_String'Range) := Temp_String;
end;

或者,您可以使用Ada.Strings.Fixed Move()过程将Unbounded_String引入目标固定长度字符串:

Ada.Strings.Fixed.Move(To_String(Temp_Unbounded_String), Combined_String);

在这种情况下,如果源字符串“太长”,则默认情况下会引发Length_Error异常。 Move()还有其他参数可以修改该情况下的行为,有关更多详细信息,请参阅Move上提供的链接。

答案 1 :(得分:3)

要分配Combined_String,您必须立即指定完整的正确长度。你不能“建立”一个字符串并在Ada中以那种方式分配。

如果没有看到你的其余代码,我认为Ada.Strings.Unbounded可能是你应该使用的。

答案 2 :(得分:2)

我知道这是一个古老的问题,但现在Ada 2012已经出局了,我以为我会分享一个我一直在发现自己使用的习语......

declare
  function Concatenate(i: Collection'index)
  is
    (tostring(Collection(i) &
      if (i = Collection'last) then
        ("")
      else
        (Concatenate(i+1))
    );

  s: string := Concatenate(Collection'first);
begin
  Put_Line(s);
end;

键入我的头顶,所以它会充满错别字;如果你想让它在空集合上工作,你需要调整逻辑(应该很明显)。

Ada 2012的表达功能非常棒!

答案 3 :(得分:1)

当您可以使用尺寸合适的数组和字符串时,Ada效果最佳。这非常适用于99%的字符串使用,但是在您需要逐步从其他地方逐步构建字符串时会导致问题。

鉴于此,我真的很想知道为什么你需要这个组合字符串。

如果你真的需要它,那么我知道有两种很好的方法可以做到这一点。第一种是使用Ada.Strings.Unbounded中的“无界”(动态大小)字符串,正如Dave和Marc C建议的那样。

另一种是使用一些函数式编程(在本例中为递归)来创建固定字符串。例如:

function Combined_String (String_Collection : in String_Collection_Type) return String is
begin
    if String_Collection'length = 1 then 
        return String_Collection(String_Collection'first);
    end if;    
    return String_Collection(String_Collection'first) & 
           Combined_String (String_Collection'first + 1 .. String_Collection'last);
end Combined_String;

我不知道你使用什么类型的Collection,所以我正在做一些猜测。特别是,我假设它是一个无约束的固定字符串数组。如果不是,您将需要用容器用于返回其边界,访问元素和执行切片的任何内容替换上面的一些代码。

答案 4 :(得分:1)

来自AdaPower.com

function Next_Line(File : in Ada.Text_IO.File_Type :=
   Ada.Text_Io.Standard_Input) return String is
   Answer : String(1..256);
   Last   : Natural;
begin
   Ada.Text_IO.Get_Line(File => File,
      Item => Answer,
      Last => Last);
   if Last = Answer'Last then
      return Answer & Next_Line(File);
   else
      return Answer(1..Last);
   end if;
end Next_Line;

正如您所看到的,此方法从它正在读取的文件构建一个无限长*的字符串(使用Get_Line)。所以你需要做的是,为了保持你拥有的东西,大概是这样的:

function Combined_String (String_Collection : in String_Collection_Type)
                   Return String is      
begin
    if String_Collection'length = 1 then 
        Return String_Collection(String_Collection'First).All;
    end if;

      Recursion:
      Declare
         Data : String:= String_Collection(String_Collection'First).All;
         SubType Constraint is Positive Range
           Positive'Succ(String_Collection'First)..String_Collection'Last;
      Begin
         Return Data & Combined_String( String_Collection(Constraint'Range) );
      End Recursion;
end Combined_String;

假设String_Collection定义为:

 Type String_Collection is Array (Positive Range <>) of Access String;

*实际上受Integer'Range,IIRC的限制