【问题标题】:Ada - Commando- line reader and processerAda - 命令行阅读器和处理器
【发布时间】:2021-11-13 23:23:22
【问题描述】:

应该创建一个加载和处理命令行参数的程序。

这里有几个例子说明你运行它时的外观(粗体文本是用户将要输入的文本):

Terminal prompt % **./my_program**

No arguments given.

Terminal prompt % **./my_program 123**

Wrong amounts of arguments given.

Terminal prompt % **./my_program 10 XYZ 999 Greetings!**


Wrong amounts of arguments given.

Terminal prompt % **./my_program 3 HELLO**

Message: HELLOHELLOHELLO

The program "./my program" is ending.

Terminal prompt % **./my_program 0 Bye**

Message:

The program "./my program" is ending.

这是我目前的代码:

with Ada.Text_IO;         use Ada.text_IO;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
with Ada.Command_Line;    use Ada.Command_Line;

procedure my_program is 
   
    type String is array (Positive) of Character;
 
    N : Integer;
    Text : String;
   
begin
   
    N := Argument_Count;

    if N = 0 then
        Put_Line("No arguments given.");
    elsif N /= 2 then 
        Put_Line("Wrong number of arguments given.");
    elsif N = 2 then
        Put("Message: ");

        for I in 1 .. N loop
            Put(Text);
            New_Line;
        end loop;
      
        Put("The program """);
        Put(""" is ending. ");
    end if;
   
 end my_program;

我的程序处理前 3 三个案例,但是当我继续处理第 4 和第 5(最后一个)案例时,我在 Put(Text) 行显示错误代码

在调用“Put”时缺少参数“Item”的参数

我不知道我是否正确声明了我的字符串,因为我不想要一个特定长度的字符串。谁能想出一些可以帮助我解决案例 4 和 5 的方法?这将是很好和高度赞赏

【问题讨论】:

  • 请注意,当您调用Put(Text) 时,Text 尚未初始化。你的意思是使用Put(Argument(I));
  • 嗯,我真的不明白你的意思。所以我有N个整数,所以当一个例子输入“5 Hi”时,它应该输入“Hi”五次(HiHiHiHiHi)。这就是我试图用我的循环做的事情。还是我应该做 Get_Line?我真的不知道
  • 那么你需要获取第一个参数的整数值,然后多次打印第二个参数。您现有的代码甚至不会尝试做这些事情。
  • 另一个直接的问题是您的声明 type String is array (Positive) of Character; 创建了一个新的 String 类型,因此 Text 是新类型,它实际上没有“Put”方法。将其注释掉并改为With / Use Ada.Strings;Ada.Text_IO 已经为此提供了 I/O 方法。

标签: command ada


【解决方案1】:

这似乎是一个家庭作业或考试问题,所以我通常不会提供完整的答案。但是克里斯已经给出了(有一些缺陷),所以这是我的建议。与 Chris 的解决方案相比,我尽量避免使用不必要的变量,并且我更喜欢 case 语句而不是 if-then-else 级联,并且我尝试减少异常处理程序的范围。我更喜欢将 use 子句放在子程序中,以便 context-clause 部分只包含 with 子句。我使用来自 Ada.Strings.Fixed 的字符串乘法“*”运算符,但这可能是不必要的改进。

with Ada.Command_Line;
with Ada.Strings.Fixed;
with Ada.Text_IO;

procedure My_Program
is
   use Ada.Strings.Fixed;
   use Ada.Text_IO;
begin

   case Ada.Command_Line.Argument_Count is

   when 0 =>
      Put_Line ("No arguments given.");

   when 2 =>
      begin
         Put_Line (
              Natural'Value (Ada.Command_Line.Argument(1))
            * Ada.Command_Line.Argument(2));
      exception
         when Constraint_Error =>
            Put_Line ("Invalid input for argument 1.");
      end;

   when others =>
      Put_Line ("Wrong amount of arguments given.");

   end case;

   Put_Line (
        "The program """
      & Ada.Command_Line.Command_Name
      & """ is ending.");

end My_Program;

注意我的版本:

  • 拒绝否定的第一个参数(如“-3”)。
  • 按照给定示例的要求,在一行中输出重复的字符串。
  • 在最后的消息中包含程序的名称,这也是必需的。

【讨论】:

    【解决方案2】:

    鉴于 cmets 中对程序目的的说明,要打印消息 n 次,其中 n 是第一个参数,消息是第二个参数,您需要将第一个参数解析为整数。这可以通过Integer'Value 完成。

    现在,这增加了用户不使用整数运行程序的可能性。所以我们必须处理可能的Constraint_Error 异常。

    with Ada.Text_IO;         use Ada.text_IO;
    with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
    with Ada.Command_Line;    use Ada.Command_Line;
    
    procedure my_program is
    
        argc : Integer;
        N : Integer;
    
    begin
    
        argc := Argument_Count;
    
        if argc = 0 then
            Put_Line("No arguments given.");
        elsif argc /= 2 then
            Put_Line("Wrong number of arguments given.");
        else
            n := Integer'Value(Argument(1));
    
            Put("Message: ");
    
            for I in 1 .. N loop
                Put_Line(Argument(2));
            end loop;
    
            Put("The program """);
            Put(""" is ending. ");
        end if;
    
    exception
    
        when Constraint_Error =>
            Put_Line("Invalid input for argument 1.");
    
    end my_program;
    

    顺便说一句,当我们检查条件如果argc 为零且不等于二时,我们不必使用elsif。唯一的其他可能性是它 2

    【讨论】:

      【解决方案3】:

      你说

      我的程序处理前 3 种情况,但是当我继续处理第 4 种和第 5 种(最后一种)情况时,我在 Put(Text) 行收到一个错误代码,其中显示“调用中的参数“Item”缺少参数到“放”。”

      这没有意义,因为您的程序如图所示无法编译。我猜你的意思是“当我尝试添加代码来处理案例 4 和案例 5 时,它无法编译”。

      无法编译的原因隐藏在实际的错误信息中:

      leun.adb:24:10: no candidate interpretations match the actuals:
      leun.adb:24:10: missing argument for parameter "Item" in call to "put" declared at a-tiinio.ads:97, instance at a-inteio.ads:18
      ...
      leun.adb:24:14: expected type "Standard.Integer"
      leun.adb:24:14: found type "String" defined at line 7
      leun.adb:24:14:   ==> in call to "Put" at a-tiinio.ads:80, instance at a-inteio.
      

      你在第 7 行有

         type String is array (Positive) of Character;
      

      这既具有误导性,又不是您的意思。

      这不是你的意思,因为 array (Positive) 表示从 1 到 Positive’Last 的固定长度数组,它不适合你的计算机内存。你的意思是array (Positive range <>)

      即使有这个更正,它也是“误导”的,因为尽管它与标准 StringARM 3.6.3(4) 中的声明文本相同,但在 Ada 中,两个不同的类型声明声明了两个不同的类型。因此,当您编写Put(Text); 时,您打算调用的PutARM A.10.7(16) 中的第二个)不匹配,因为它需要Standard.String 类型的参数,但Text 的类型是my_program.String


      解决这个问题:不要声明自己的 String 类型。

      【讨论】:

      • Nitpick:对于某些 Ada 编译器,字符数组 (Positive) 可能适合计算机的内存,因为 Positive'Last 可能小到 32767(当编译器具有 16 位整数类型时) )。
      • @NiklasHolsti:是的,但考虑到 OP 的起点,这不太可能!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-30
      • 1970-01-01
      • 1970-01-01
      • 2013-07-09
      • 1970-01-01
      • 2018-04-15
      相关资源
      最近更新 更多