Article Directory
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
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 Character
and To_Lower(Item : in String) return String:
Convert the given character or string to lowercase.
To_Upper(Item : in Character) return Character
and To_Upper(Item : in String) return String:
Convert the given character or string to uppercase.
To_Basic(Item : in Character) return Character
and 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
- You can refer to https://www.w3cschool.cn/ada/ada-shujuleixing.html
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; -- 一个自定义的整数类型,值域是 1 到 100
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, Positive
is Integer
a subtype of and must have a value between 1
and Integer'Last
. The compiler will generate an error if you try to Positive
assign 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'Value
the 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'Value
and 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
when 值1 =>
-- 表达式的值为值1时执行的语句
when 值2 =>
-- 表达式的值为值2时执行的语句
when others =>
-- 表达式的值不是任何给定值时执行的语句
end case;
case
The values that the statement can handle must be离散的
, for example, integer or enumeration types.when others
part is optional, but without it the case statement must be able to handle all possible values of the expression.
Incase
a statement,when
the 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 10
one-dimensional array containing elements, and M is a 100
two-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 := B
Assign 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, record
a 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.
Record
A type is defined by a set of fields, each of which has a name and a type. Record
The type definition syntax is as follows:
type Record_Type is record
Field1 : Type1;
Field2 : Type2;
-- 更多的字段...
end record;
For example, the following code defines a Person
record type named with three fields: Name、Age
and 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 Person
variable of type P
and set the values of its fields.
Other Features of Record
Record also has some other features, such as variant record
and 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_Name
is the name of the procedure, Parameter_List
is 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_Name
is the name of the function, Parameter_List
is the parameter list of the function, Return_Type
is 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 Result
is the result to be returned.
For example, the following code defines a Add
function 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、out
and 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:
- The program should accept a string characters on the standard input and count the number of words in the
input.- The input is terminated by a ‘#’ character.
- 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).
- For the purposes of this workshop, a character that is not a whitespace character.
- 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:
- This question is the answer given by the teacher, including the following operations:
- defines a
ProtectedStack
package
(including adb and ads files) solution
Built the main logic in
- defines a
- This topic involves the use
generic
of data of the type, which needs to be instantiated before useis new
- In fact,
StringStack
the function we instantiated has the same functionpackage
as the previous oneProtectedStack
, 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: