简体   繁体   中英

Ada language - How to store a string value returned by a function?

I'm attempting to some basic command-line interaction in Ada 2012 and I can't find a way to capture the string returned from the Ada.Command_Line.Command_Name() function.

All the examples I can find online simply print the String using Put() without first storing it in a local variable. Here's the faulty code I've tried, which does compile but throws a CONSTRAINT_ERROR ... length check failed when I try to assign the return String value to the String variable...

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

procedure Command_Line_Test is
  ArgC : Natural := 0;
  InvocationName : String (1 .. 80);
begin
  ArgC := Argument_Count;
  Put ("Number of arguments provided: ");
  Put (ArgC'Image);
  New_Line;

  InvocationName := Command_Name;  --  CONSTRAINT_ERROR here
  Put ("Name that the executable was invoked by: ");
  Put (InvocationName);
  New_Line;

end Command_Line_Test;

I'm just using Command_Name as an example, but imagine it was any other function that could return a string (perhaps a string that would change multiple times during the program's life), how should we declare the local variable in order to store the returned string?

String handling in Ada is very different from other programming languages and when you declare a String(1..80) it expect that string returned by a function will actually have length 1..80 while your executable path (which is returned by Command_Name) may be a bit shorter (or longer).

You may always introduce new declare block and create a String variable inside of it like here

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

procedure Main is
   ArgC : Natural := 0;

begin
   ArgC := Argument_Count;
   Put ("Number of arguments provided: ");
   Put (ArgC'Image);
   New_Line;
   declare
      InvocationName: String := Command_Name;  --  no more CONSTRAINT_ERROR here
   begin
      Put ("Name that the executable was invoked by: ");
      Put (InvocationName);
      New_Line;
   end;

end Main;

Or you may use Ada.Strings.Unbounded package

with Ada.Command_Line; use Ada.Command_Line;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Strings; use Ada.Strings;
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;

procedure Main is
   ArgC : Natural := 0;
   InvocationName : Unbounded_String;
begin
   ArgC := Argument_Count;
   Put ("Number of arguments provided: ");
   Put (ArgC'Image);
   New_Line;

   InvocationName := To_Unbounded_String(Command_Name);  --  no more CONSTRAINT_ERROR here

   Put ("Name that the executable was invoked by: ");
   Put (To_String(InvocationName));
   New_Line;

end Main;

Agree with Timur except that there is no need to move the declaration of Invocation_Name into a nested declare block.

You could have just written;

   Invocation_Name : String := Command;

Where it was in the original code, in the declarations of procedure Main.

or better yet;

   Invocation_Name : constant String := Command;

or better yet, eliminate the declaration altogether and replace the last 3 lines of Main with;

   Put_Line ("Name that the executable was invoked by: " & Command);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM