Ada Tutorial (1): Ada basics - wordcount program

Ada commonly used libraries and methods

Ada.Text_IO:This library provides a set of functions for standard input and output, including functions for manipulating numbers. For example, Get and Put can be used to read and output integer or floating point numbers.
Ada.Integer_Text_IO:This library provides more specific input and output functions for working with integers.
Ada.Float_Text_IO:This library provides more specific input and output functions for working with floating point numbers.
Ada.Numerics:This library contains a series of functions and procedures for numerical calculations, including some mathematical functions such as square root, exponential, logarithm, etc.
Ada.Numerics.Float_Random:This library provides a pseudorandom number generator that can generate random numbers for floating point numbers.

Ada.Characters.Handling

insert image description here

character type functions

Character classification function:

Is_Control(Item : in Character) return Boolean:Determines whether the given character is a control character. The positions of the control characters are in the range 0...31 or 127...159.
Is_Graphic(Item : in Character) return Boolean:Determines whether the given character is a graphic character. The positions of the graphic characters are in the range 32...126 or 160...255.
Is_Letter(Item : in Character) return Boolean:Determines whether the given character is a letter. Alphabetic character positions in the range 'A'...'Z' or 'a'...'z', or in the range 192...214, 216...246, or 248...255.
Is_Lower(Item : in Character) return Boolean:Determines whether the given character is a lowercase letter. Lowercase alphabetic characters in the range 'a'...'z', or in the range 223...246 or 248...255.
Is_Upper(Item : in Character) return Boolean:Determines whether the given character is an uppercase letter. Uppercase alphabetic characters in the range 'A'...'Z', or in the range 192...214 or 216...222.
Is_Basic(Item : in Character) return Boolean:Determines whether the given character is a base letter. Basic alphabetic characters in the range 'A'…'Z' and 'a'…'z', or one of the following special characters: 'Æ', 'æ', 'Ð', 'ð', 'Þ', 'þ', or 'ß'.
Is_Digit(Item : in Character) return Boolean:Determines whether the given character is a decimal digit. Decimal digit characters in the range '0'...'9'.
Is_Decimal_Digit(Item : in Character) return Boolean:This function is an alias for Is_Digit.
Is_Hexadecimal_Digit(Item : in Character) return Boolean:Determines whether the given character is a hexadecimal digit. Hexadecimal digit characters in the range '0'...'9', 'A'...'F' or 'a'...'f'.
Is_Alphanumeric(Item : in Character) return Boolean:Determines whether the given character is a letter or a number.
Is_Special(Item : in Character) return Boolean:Determines whether the given character is a special graphic character. Special graphic characters are graphic characters that are not letters or numbers.

  • Is_space(Item: Character)Determine whether it is a space

conversion function

To_Lower(Item : in Character) return Characterand To_Lower(Item : in String) return String:Convert the given character or string to lowercase.
To_Upper(Item : in Character) return Characterand To_Upper(Item : in String) return String:Convert the given character or string to uppercase.
To_Basic(Item : in Character) return Characterand To_Basic(Item : in String) return String:if the given character or characters in the string are accented letters, convert them to unaccented letters;

An Overview of Ada's Basic Syntax

Datatypes and Subtypes

In Ada, type (Type) and subtype (Subtype) are the core concepts of its type system.

type

In Ada, a type defines a set of values ​​and some operations on those values. There are many built-in types, such as integer type Integer, real type Float, character type Character, Boolean type Boolean and so on . Additionally, you can define your own types. Type definitions can be scalar (such as numbers or enumeration values) or compound (such as arrays or records).

For example, here are some sample type definitions:

type My_Integer is range 1 .. 100;  -- 一个自定义的整数类型,值域是 1100
type Day is (Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday);  -- 一个枚举类型
type Matrix is array (1 .. 10, 1 .. 10) of Float;  -- 一个二维数组类型

Subtype (Subtype)

A subtype is a subset of a type that can be defined by constraints. Constraints can be range constraints, or discriminant constraints (for some advanced types). Each type has a corresponding anonymous subtype without any additional constraints.

**An important use of subtypes is to provide additional constraints to prevent values ​​from appearing in programs that should not be there. **For example:

subtype Positive is Integer range 1 .. Integer'Last;  -- 一个表示正整数的子类型

In this example, Positiveis Integera subtype of and must have a value between 1and Integer'Last. The compiler will generate an error if you try to Positiveassign a negative value or zero to .

Note that although subtyping provides additional constraints, it is not a new type. In other words, you can directly use the operations of the original type without explicit type conversion.

The difference between types and subtypes

The most important difference is that a type defines new data, whereas a subtype is just a part of the original type. When you define a new type, Ada provides default operations (such as assignment and comparison), but you cannot directly use the operations of the original type. On the other hand, a subtype can directly use all operations of the original type, but it provides additional constraints to limit the acceptable values.

Common Type Conversion Methods

In Ada, type conversion is usually achieved through "explicit type conversion" or through "type-related functions" . It's worth noting that Ada's type system is strongly typed , which means that the compiler usually won't automatically convert a value of one type to another, you have to do it explicitly.

Here are some common type conversion methods:

display type conversion

类型名(表达式)

For example:

declare
   A : Integer := 42;
   B : Float;
begin
   B := Float(A);
end;

type-dependent functions

Some types provide functions to perform type conversions. For example, you can use Integer'Valuethe function to convert a string to an integer:

declare
   S : String := "42";
   I : Integer;
begin
   I := Integer'Value(S);
end;

Likewise, you can use the Float'Value, , Boolean'Valueand other functions to convert strings to other types.

This is just the basic method of type conversion. More complex type conversions may require the use of other techniques, such as using subroutines or operator overloading.

loop statement

In the Ada programming language, there are several types of loop statements, below I will list and explain each one in Markdown format:

Unconditional loop (Loop)

An unconditional loop will repeatedly execute the loop body until an explicit exit condition is met. This is usually accomplished with an exit statement.

loop
   -- 循环体
   exit when 条件;
end loop;

for loop

The for loop is used to iterate over a range of values ​​or all elements of an iterator. In Ada, the loop variable of a for loop is immutable, which means you cannot modify its value within the loop body.

-- 数值范围
for I in 1 .. 10 loop
   -- 循环体
end loop;

-- 迭代器
for Element of Some_Array loop
   -- 循环体
end loop;

while loop

A while loop executes the body of the loop while certain conditions are met. If the condition is not met in the first place, the body of the loop may not execute even once.

while 条件 loop
   -- 循环体
end loop;

Other Control Structures in Loops

Ada also provides some other loop control structures:

exit:Used to exit the current loop.
exit when:Exit the current loop when certain conditions are met.
next:Skip the current loop iteration and go to the next iteration.
next when:Skip the current loop iteration and go to the next iteration when certain conditions are met.
return:Return from the procedure or function containing the current loop.

branch statement

if

if 条件 then
   -- 条件为真时执行的语句
end if;

An if statement can contain one or more elsif parts, and can also contain an else part:

if 条件1 then
   -- 条件1为真时执行的语句
elsif 条件2 then
   -- 条件1为假,但是条件2为真时执行的语句
else
   -- 所有条件都为假时执行的语句
end if;

case

case 表达式 is
   when1 =>
      -- 表达式的值为值1时执行的语句
   when2 =>
      -- 表达式的值为值2时执行的语句
   when others =>
      -- 表达式的值不是任何给定值时执行的语句
end case;
  • caseThe values ​​that the statement can handle must be 离散的, for example, integer or enumeration types.
  • when otherspart is optional, but without it the case statement must be able to handle all possible values ​​of the expression.
    In casea statement, whenthe value of a part cannot be repeated, that is, there cannot be two when parts dealing with the same value.

array

In Ada, an array is a composite data type used to store data items of the same type . Arrays consist of 元素and 索引. Elements are data items in the array, and each element has an associated index that uniquely identifies the element.

array definition

In Ada, you can define an array type with the following syntax:

type Array_Type is array (Index_Type range <>) of Element_Type;
  • To be more specific: For example, the following code defines an integer array whose index type is Integer:
-- 括号中的 Integer 的意思是索引类型, of Integer 代表数据类型是 integer
type Integer_Array is array (Integer range <>) of Integer;

Multidimensional arrays can also be defined. For example, the following code defines a two-dimensional array of integers:

type Matrix is array (Integer range <>, Integer range <>) of Integer;

declare array variable

Once you have defined the array type, you can declare array variables. For example:

declare
   A : Integer_Array(1 .. 10);
   M : Matrix(1 .. 10, 1 .. 10);
begin
   -- 这里可以使用数组 A 和 M
end;

In this example, A is a 10one-dimensional array containing elements, and M is a 100two-dimensional array containing elements.

access array elements

The elements of the array can be accessed by index. For example:

declare
   A : Integer_Array(1 .. 10);
begin
   A(1) := 42;  -- 设置数组的第一个元素
   Put(A(1));  -- 输出数组的第一个元素
end;

For multidimensional arrays, you need to provide multiple indices. For example:

declare
   M : Matrix(1 .. 10, 1 .. 10);
begin
   M(1, 1) := 42;  -- 设置数组的第一个元素
   Put(M(1, 1));  -- 输出数组的第一个元素
end;

Other properties of arrays

Ada also provides some other array features, such as array slicing, array assignment, array comparison , etc. Here are some examples:

  • Array slices: Array slices can be used to access a portion of an array. For example: A(1 .. 5)are the first five elements of array A.
  • Array assignment: You can assign to an entire array at once. For example: A := BAssign all elements of array B to A. Note that A and B must be the same type.
  • Array comparison: You can use the =and /=operator to compare two arrays for equality. For example: If A = B means that all elements of A and B are equal.

record

record definition

In the Ada programming language, recorda compound data type that allows combining data elements of different types into a single data structure. This is similar to a struct in C or C++, or a class in Python.
RecordA type is defined by a set of fields, each of which has a name and a type. RecordThe type definition syntax is as follows:

type Record_Type is record
   Field1 : Type1;
   Field2 : Type2;
   -- 更多的字段...
end record;

For example, the following code defines a Personrecord type named with three fields: Name、Ageand Is_Employed:

type Person is record
   Name        : String;
   Age         : Integer;
   Is_Employed : Boolean;
end record;

Create and use Record variables

Once the Record type is defined, you can create variables of this type and use .the operator to access its fields. For example:

declare
   P : Person;
begin
   P.Name := "Alice";
   P.Age := 30;
   P.Is_Employed := True;
   
   Put("Name: " & P.Name);
   Put("Age: " & Integer'Image(P.Age));
   Put("Is employed: " & Boolean'Image(P.Is_Employed));
end;

In this example, we create a Personvariable of type Pand set the values ​​of its fields.

Other Features of Record

Record also has some other features, such as variant recordand nested record.

Variant record

Variant record allows some fields in the record to have different types and numbers in different situations . This is similar to a union in C or C++.

Nested record

Nested record: A record can contain another record, which is called a nested record. This allows you to build more complex data structures.

subroutine

process procedure

A procedure is a subroutine that is used to perform some action but does not return a value. The syntax for defining a procedure is as follows:

procedure Procedure_Name (Parameter_List) is
begin
   -- 过程体
end Procedure_Name;

Among them, Procedure_Nameis the name of the procedure, Parameter_Listis the parameter list of the procedure, -- 过程体and is the body of the procedure, which contains the code to be executed.

For example, the following code defines a procedure named Print_Hello that prints a message:

procedure Print_Hello is
begin
   Put_Line("Hello, world!");
end Print_Hello;

function

A function is a subroutine that performs some action and returns a value. The function definition syntax is as follows:

function Function_Name (Parameter_List) return Return_Type is
begin
   -- 函数体
   return Result;
end Function_Name;

Among them, Function_Nameis the name of the function, Parameter_Listis the parameter list of the function, Return_Typeis the type of the return value of the function, -- function body is the main body of the function, which contains the code to be executed, and Resultis the result to be returned.

For example, the following code defines a Addfunction named that takes two integer arguments and returns their sum:

function Add (X, Y : Integer) return Integer is
begin
   return X + Y;
end Add;

Parameter passing

Parameter passing
Ada supports three types of parameter passing: in、outand in out.

  • In: This is the default parameter type, indicating that the parameter can only be read in the subroutine and cannot be modified.

  • Out: The parameters of this type do not need to be initialized before the subroutine is called, they are assigned in the subroutine and returned to the caller after the subroutine ends.

  • In Out: This type of parameter can be read or modified in the subroutine. After the subroutine ends, the modified value is returned to the caller.

The above is some basic knowledge of subroutines in Ada. Ada's subroutines have many other features and details not covered here, such as default parameters, subroutine overloading, subroutine pointers, and so on.

Tutorial 1

题目:Overview The WordCount program accepts a string from the standard input and delivers a count of words in the input string.
The following is a list of requirements:

  1. The program should accept a string characters on the standard input and count the number of words in the
    input.
  2. The input is terminated by a ‘#’ character.
  3. Words are separated by white spaces. To simplify the task, assume that white spaces are the space character (i.e. ignore tabs and new line characters).
  4. For the purposes of this workshop, a character that is not a whitespace character.
  5. The output is a single integer displaying the word count.
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Characters.Handling; use Ada.Characters.Handling;

procedure Word_Count is
   Input   : Character;
   Word_Cnt: Integer := 0;
   In_Word : Boolean := False;
   
begin
   loop
      Get(Item => Input);
      exit when Input = '#';

      if Is_Space(Input) then
         if In_Word then
            Word_Cnt := Word_Cnt + 1;
         end if;
         In_Word := False;
      else
         In_Word := True;
      end if;
   end loop;


   if In_Word then
      Word_Cnt := Word_Cnt + 1;
   end if;

   Put_Line("Word count: " & Integer'Image(Word_Cnt));
end Word_Count;

题目:Implement the word counting program specified in the Specification section, and run a few tests to convince yourself that the program works on most inputs.
Tip: it is of course a good idea to implement your program incrementally. Start by writing and running a small program that extends the program given.
Note the following in the skeleton provided. ProtectedStack is importaed by adding the following:insert image description here

  • This question is the answer given by the teacher, including the following operations:
    • defines a ProtectedStack package(including adb and ads files)
    • solutionBuilt the main logic in
  • This topic involves the use genericof data of the type, which needs to be instantiated before useis new
  • In fact, StringStackthe function we instantiated has the same function packageas the previous one ProtectedStack, but it is just an instance of it.
-- protectedStack.adb

package body ProtectedStack is
   
   protected body Stack is 
      
      entry Push(I: in Item)
      when True is
      begin
	 if Stk.Size < Max_Size then
	    Stk.Size := Stk.Size + 1;
	    Stk.Data(Stk.Size) := I;
	 else
	    raise Stack_Overflow;
	 end if;
      end Push;

      entry Pop(I: out Item) 
      when True is
      begin
	 if Stk.Size > 0 then
	    I := Stk.Data(Stk.Size);
	    Stk.Size := Stk.Size - 1;
	 else
	    raise Stack_Underflow;
	 end if;
      end Pop;

      entry Top(I: out Item)
      when True is
      begin
	 if Stk.Size > 0 then
	    I := Stk.Data(Stk.Size);
	 else
	    raise Stack_Underflow;
	 end if;
      end Top;

      entry Empty(EmptyStack: out Boolean) 
      when True is
      begin
	 EmptyStack := (Stk.Size = 0);
      end Empty;

      entry Full(FullStack: out Boolean) 
      when True is
      begin
	 FullStack := (Stk.Size = Max_Size);
      end Full;

      entry Clean
      when True is
      begin
	 Stk.Size := 0;
      end Clean;
      
   end Stack;
   
end ProtectedStack;
--protectedstack.ads

generic
   Max_Size: Positive;          -- The maximum size of the stack.
   type Item is private;        -- The type of items in the stack. The type must
                                -- be definite, and the private means that this
                                -- package may not examine its internals.
package ProtectedStack is
   
   type StackType is private;

   -- Exceptions.
   Stack_Underflow, Stack_Overflow: exception;
   
   -- The public interface to the stack consists of the following
   --  operations. The stack is "protected" which means that the tasks
   --  have muitually exclusive access to the stack operations. They
   --  are declared just like the "entry" points in a task type
   --  declaration and are implemented using "entry" keywords as
   --  well. Entry calls are the main means of communication between
   --  concurrent tasks in Ada so this is effectively an Abstract Data
   --  Type that protects the Stack by enforcing mutually exlcusive
   --  access.
   
   protected type Stack is
      entry Push(I: in Item); 
      entry Pop(I: out Item);
      entry Top(I: out Item); 
      entry Empty(EmptyStack: out Boolean); 
      entry Full(FullStack: out Boolean);
      entry Clean; 
   private 
      Stk : StackType;
   end Stack;
   
private
   
   type StackData is array(1.. Max_Size) of Item;
   type StackType is record
      Size: Integer range 0 .. Max_Size := 0;
      Data: StackData;
   end record;
      
end ProtectedStack;

-- solution
with Ada.Text_IO; 
use  Ada.Text_IO;

with Ada.Integer_Text_IO;
use  Ada.Integer_Text_IO;

with ProtectedStack;
with Ada.Strings.Unbounded;

with Ada.Characters.Latin_1;

-- The WordCount program counts the number of characters and words in
--  a string received from standard input. A word is any alphanum
--  character separated by a space or tab
procedure WordCount is
   
   package ASU renames Ada.Strings.Unbounded;
   use ASU;   
   package StringStack is new ProtectedStack(100, ASU.Unbounded_String);
   
   Ch        : Character;            -- the current character
   Word      : ASU.Unbounded_String; -- the current word
   
   -- The number of characters and words
   NumChars : Integer := 0;
   NumWords : Integer := 0;
   
   -- a stack for putting words into
   St : StringStack.Stack;
   
   -- for testing is the stack is empty
   IsEmpty : Boolean;
   
begin
   
   Get(Ch);
   
   Word := ASU.To_Unbounded_String("");
   
   while (Ch /= '#') loop
      
      NumChars := NumChars + 1;
      
      -- if a space or tab, we encounter a new word
      if Ch = ' ' or Ch = Ada.Characters.Latin_1.HT then	 
	 
	 -- consume remaining spaces and tabs
	 while Ch = ' ' or Ch = Ada.Characters.Latin_1.HT loop
	    Get(Ch);
	 end loop;
	 
	 NumWords := NumWords + 1;
	 St.Push(Word);
	 Word := ASU.To_Unbounded_String("");
	 
      else
	 Word := Word & Ch;
	 Get(Ch);
      end if;
      
   end loop;
   
   -- push the terminating word
   NumWords := NumWords + 1;
   St.Push(Word);

   Put(NumWords); New_Line;
   Put(NumChars); New_Line;
   
   -- print the words on the stack
   St.Empty(IsEmpty);
   while not IsEmpty loop
      St.Pop(Word);
      Put(ASU.To_String(Word) & " ");
      St.Empty(IsEmpty);
   end loop;
end WordCount;

  • Precautions:
    insert image description here

Guess you like

Origin blog.csdn.net/qq_42902997/article/details/131160770