【问题标题】:How to use refs to constant Strings in arrays and records?如何在数组和记录中使用 refs 到常量字符串?
【发布时间】:2017-01-26 23:48:41
【问题描述】:

我打算将一些用 C/C++ 编写的程序转换为 Ada。 这些大量使用常量 char 字面量,通常作为参差不齐的数组,例如:

const char * stringsA = { "Up", "Down", "Shutdown" };

或记录中的字符串引用,例如:

typedef struct
   {
   int something;
   const char * regexp;
   const char * errormsg
   } ERRORDESCR;
ERRORDESCR edscrs [ ] =
   {
    { 1, "regexpression1", "Invalid char in person name" },
    { 2, "regexp2", "bad bad" }
   };

预设是由 C/C++ 编译器计算的,我希望 Ada 编译器是 也能做到。

我用谷歌搜索了参差不齐的数组,但只能找到两种方法 预设琴弦。约翰·巴恩斯 (John Barnes) 的 Ada 95 的基本原理和另一个 在http://computer-programming-forum.com/44-ada/d4767ad6125feac7.htm。 这些在下面显示为 stringsA 和 stringsB。 StringsA是分两个阶段定义的,如果有几百个就有点繁琐了 要设置的字符串。 StringsB 仅使用一步,但取决于编译器。

问题1:还有其他方法吗? 问题 2:第二个 stringsB 可以与 GNAT Ada 一起使用吗?

我还没有开始转换。以下软件包仅用于实验 并自学...

package ragged is
   type String_ptr is access constant String;
   procedure mydummy;
end ragged;

package body ragged is
   s1: aliased constant String := "Up";
   s2: aliased constant String := "Down";
   s3: aliased constant String := "Shutdown";

   stringsA: array (1 .. 3) of String_ptr :=
     (s1'Access, s2'Access, s3'Access); -- works

   stringsB: array (1 .. 3) of String_ptr :=
      (new String'("Up"), new String'("Down"),
      new String'("Shutdown"));  -- may work, compiler-dependent

   --   this would be convenient and clear...
   --stringsC: array (1 .. 3) of String_ptr :=
   -- ("Up", "Down", "Shutdown");  -- BUT Error, expected String_ptr values

   --stringsD: array (1 .. 3) of String_ptr :=
   --("Up"'Access, "Down"'Access, "Shutdown"'Access);  --Error - bad Access use

   --stringsE: array (1 .. 3) of String_ptr :=
   --(String_ptr("Up"), String_ptr("Down"),
   -- String_ptr("Shutdown"));  -- Error, invalid conversion

   procedure mydummy is
   begin
   null;
   end;
end ragged;

【问题讨论】:

  • 我用谷歌搜索,但错过了类似的帖子。我做了一个测试程序,发现 stringsA 和 stringsB 适用于 GNAT Ada。但是,与 C 版本 const char * strings[] = { "Up", "Down", "Shutdown" }; 相比,这两种方法都显得冗长而杂乱。具有 C、Java、JS 和 C# 等现代语言背景的 Ada 新手可能会感到失望。
  • 为什么您的 B 示例应该依赖于编译器?很丑,是的,但我看不到编译器依赖。
  • Jacob:我在“参差不齐的数组”上搜索了一下,得到了匹配项。一个匹配,coding.derkeiler.com/Archive/Ada/comp.lang.ada/2004-09/… 包含对 Tucker Taft 的引用,他说示例 B 中的方法是依赖于实现的。我还没有做出这种声明的知识。
  • 我认为 Tucker 的观点是优化(不进行任何实际分配,也不发出任何运行时代码)依赖于编译器。 GNAT GPL 2016 进行了优化。

标签: ada


【解决方案1】:

稍微明智的运算符重载可以以不那么混乱的方式做到这一点:

(在包体内)

   function New_String(S : String) return String_Ptr is
   begin
      return new String'(S);
   end New_String;

   function "+" (S : String) return String_Ptr renames New_String;

现在你可以这样做了:

   stringsC: array (1 .. 3) of String_ptr := (+"Up", +"Down", +"Shutdown");

【讨论】:

  • 真是太好了!本质上与类 C 语言相同。将尝试并报告。
  • 我为stringsC写了一个小测试程序。这些值是正确的,但是是在运行时而不是在编译时生成的。我在 return new String'(S) 和 stringsC 数组声明处设置断点,两者都被触发。我还在主程序开始时使用了 Debug/Data/Display 来查看 stringsC(1)... 并且全部显示为 NULL。当我在开始时显示 stringsA 和 stringsB 时,它们正确显示。我以前没有用过 Ada,所以我可能错了。测试程序在下一个答案框中。
  • GNAT 似乎有电路来识别new String’("Up") 可以根据我们的需要进行优化,但+"Up" 不能。有趣的是,使用-gnatG 表明StringsB 在内部表示就像StringsA
  • 函数 "+" 可以从头开始定义而无需重命名
【解决方案2】:

评论空间不足 测试程序

package raggedtest is
   type String_ptr is access constant String;
   procedure mytest;
end raggedtest;

with ada.text_IO; use Ada.Text_IO;
package body raggedtest is
   s1: aliased constant String := "Up";
   s2: aliased constant String := "Down";
   s3: aliased constant String := "Shutdown";
   stringsA: array (1 .. 3) of String_ptr :=
     (s1'Access, s2'Access, s3'Access);

   stringsB: array (1 .. 3) of String_ptr :=
      (new String'("UpB"), new String'("DownB"),
       new String'("ShutdownB"));

   function New_String(S : String) return String_Ptr is
   begin
      return new String'(S);
   end New_String;
   function "+" (S : String) return String_Ptr renames New_String;
   stringsC: array (1 .. 3) of String_ptr := (+"UpC", +"DownC", +"ShutdownC");


   procedure mytest is
   begin
      put ( "s1A: " ); put( stringsA(1).all ); New_line;
      put ( "s2A " ); put( stringsA(2).all ); New_line;
      put ( "s3A: " ); put( stringsA(3).all ); New_line;

      put ( "s1B: " ); put( stringsB(1).all ); New_line;
      put ( "s2B " ); put( stringsB(2).all ); New_line;
      put ( "s3B: " ); put( stringsB(3).all ); New_line;

      put ( "s1C: " ); put( stringsC(1).all ); New_line;
      put ( "s2C " ); put( stringsC(2).all ); New_line;
     put ( "s3C: " ); put( stringsC(3).all ); New_line;
   end;
end raggedtest;

with raggedtest; use raggedtest;
procedure main is
begin
   mytest;
end main;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-07-29
    • 2012-06-27
    • 2010-12-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-17
    • 2015-05-21
    相关资源
    最近更新 更多