I remember the language had a for loop:
for i in [1..5]
Do things
End for
And also if statements involve keywords if, then, else, endif
My capitalization may be off
The Ada language makes extensive use of ranges. Those ranges are defined as low_value .. high_value. If the "low_value" is greater than the "high_value" then the range is interpreted as a null range.
Ada arrays are defined by providing a name, an index range, and an element type. The index range is allowed to be any range of values of a discrete type. Ada discrete types are integer types, modular types and enumeration types.
The Ada "for" loop iterates over the values of a specified range.
for I in 1..5 loop
do_something;
end loop;
Every Ada array has several attributes accessible during run time. One of those attributes is 'Range which evaluates to the index range for the array.
For example, the following program reads a text file and counts the occurrence of each lower case letter and each upper case letter.
with Ada.Text_IO; use Ada.Text_Io;
procedure Main is
subtype Upper is Character range 'A'..'Z';
subtype Lower is Character range 'a'..'z';
Upper_Count : array(Upper) of Natural := (Others => 0);
Lower_Count : array(Lower) of Natural := (Others => 0);
Filename : String(1..1024);
Length : Natural;
Input : String(1..1024);
The_File : File_Type;
begin
Put("Enter the name of the file to read: ");
Get_Line(Item => Filename, Last => Length);
Open(File => The_File,
Mode => In_File,
Name => Filename(1..Length));
-- Read each character from the file and tally the letters
while not End_Of_File(The_File) loop
Get_Line(File => The_File, Item => Input, Last => Length);
for I in 1..Length loop
if Input(I) in Upper then
Upper_Count(Input(I)) := Upper_Count(Input(I)) + 1;
elsif Input(I) in Lower then
Lower_Count(Input(I)) := Lower_Count(Input(I)) + 1;
end if;
end loop;
end loop;
close(The_File);
-- Print the tally for each upper case letter
for I in Upper_Count'Range loop
Put_Line(I'Image & " " & Upper_Count(I)'Image);
end loop;
-- Print the tally for each lower case letter
for I in Lower_Count'Range loop
Put_Line(I'Image & " " & Lower_Count(I)'Image);
end loop;
end Main;
The program reads the input file a line at a time then scans the input line for upper and lower case letters. The array Upper_Count is indexed by the upper case letters. The array Lower_Count is indexed by the lower case letters. The array elements in each array are of type Natural which is a pre-defined subtype of the type Standard.Integer. Natural has a valid range of 0 .. Integer'Last.
As each letter is identified in a scan that letter is used as the index value into its appropriate array and the corresponding element is incremented.
The two "for" loops at the bottom of the source code iterate through the arrays printing the index value (the upper or lower case letter) and its corresponding count.
Related
If I create a subprogram of type function that for instance orders you to type a string of a particular length and you type Overflow, it's supposed to type the last half of the string, so in this case it would be flow. But on the other end if I type an odd number of characters like Stack it's supposed to type the last half of the string + the middle letter, so in this case it would be "ack".
Let me make it clearer (text in bold is user input):
Type a string that's not longer than 7 characters: Candy
The other half of the string is: ndy
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
function Split_String (S : in String) return String is
begin
Mid := 1 + (S'Length / 2);
return S(Mid .. S'Last);
end Split_String;
S : String(1 .. 7);
I : Integer;
begin
Put("Type a string that's no longer than 7 characters: ");
Get_Line(S, I);
Put(Split_String(S));
end Split;
Let me tell you how I've been thinking. So I do a Get_Line to see how many characters the string contains. I then put I in my subprogram to determine if its evenly dividable by two or not. If it's dividable by two, the rest should be 0, thus it'll mean that typing out the other half of the string + THE MIDDLE CHARACTER is not needed. If in all the other cases, it's not dividable by two I have to type out the other half of the string + the middle character. But now I stumbled upon a big problem in my main program. I don't know how type out the other half of a string. If a string contains 4 words I can just type out Put(S(3 .. 4); but the thing is that I don't know a general formula for this. Help is appreciated! :) Have a good day!
You need a more general approach to your problem. Also, try to understand how Get_Line works for you.
For example, if you declare an input string with a large size such as
Input : String (1..1024);
You will have a string large enough to work with any likely input values.
Next, you need a variable to indicate how many characters were actually read by Get_Line.
Length : Natural;
The data returned by Get_Line will then be in the slice of the input string designated as
Input (1 .. Length);
Pass that slice to your function to return the second half of the string.
function last_half(S : string) return string;
last_half(Input(1..Length));
Now all you need is to calculate the last half of the string passed to the function last_half. The function will output a slice of the string passed to it. To find the first index of the last half of the input string you must perform the calculation
mid : Positive := 1 + (S'length / 2);
Then simply return the string S(mid .. S'Last).
It appears that the goal of this exercise is to learn how to use array slices. Concentrate on how slices work for you in the problem and the solution will be very simple.
One possible solution is
with Ada.Text_IO; use Ada.Text_IO;
procedure Main is
Input : String (1 .. 1_024);
Length : Natural;
function last_half (S : in String) return String is
Mid : Positive := 1 + (S'Length / 2);
begin
return S (Mid .. S'Last);
end last_half;
begin
Put ("Enter a string: ");
Get_Line (Input, Length);
Put_Line (Input (1 .. Length) & " : " & last_half (Input (1 .. Length)));
end Main;
Study how the solution uses array slices on the return value of Get_Line and on the parameter for the function last_half and on its return statement. It is also important to remember that the type String is defined as an unbounded array of character. This means that every slice of a string is also a string.
type String is array ( Positive range <> ) of Character;
Aside from being an untidy mess, your latest code edit (as of 20:11 GMT on 15 Nov 2021) doesn’t even compile. Please don’t show us code like this! (unless, of course, that’s the problem).
I’d like to strongly suggest this alternate way of inputting strings:
declare
S : constant String := Get_Line;
begin
-- do things with S, which is exactly as long as
-- the input you typed: no undefined characters at
-- the end to confuse the result, no need to worry
-- about overrunning an input buffer
end;
With this change, and obvious syntactic changes, your current code will do what you want.
I have a file that I wanted to read and apply the new values to an object. How do I use the string name to look for the desired object and update the value. Do note that content in file.txt can be over 1000 lines long and order will changes so I can't have if statement to check each condition.
file.txt
>A 1
>B 2
>D 5
.
desired result
Sample.A := 1;
Sample.B := 2;
Sample.D := 5;
One way is to declare your object to be an array indexed by an enumeration type whose values are the identifiers. For instance, if the identifiers are the symbols A through Z you might define the array as:
subtype Index is Character range 'A'..'Z';
type Collection is array(Index) of Integer;
Idx : Index;
Value : Integer;
The_Collection : Collection;
while not End_Of_File(Input_File) loop
Get(Idx);
Get(Value);
Skip_Line;
The_Collection(Idx) := Value;
end loop;
Of course you will need to "with" the appropriate I/O packages.
Hello I am confronted with the predicament of comparing two unbounded strings in Ada and arrange the set of data values in a sorted fashion using the names (strings) as keys. I am at an absolute loss to determine how to compare two strings in ada or more precisely to determine which one comes first in an ascending order.
with Ada.Text_IO;
with Ada.Integer_Text_IO;
with Ada.Unchecked_Deallocation;
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
with Ada.Text_IO.Unbounded_IO; use Ada.Text_IO.Unbounded_IO;
procedure Main is
package TIO renames Ada.Text_IO;
package IIO renames Ada.Integer_Text_IO;
Name_Main1, Name_Main2, Name_Main3 : Ada.Strings.Unbounded.Unbounded_String;
begin
TIO.Put_Line("Enter the Name of the student :");
Ada.Text_IO.Unbounded_IO.Get_Line(Name_Main1);
TIO.Put_Line("Enter the Name of the student :");
Ada.Text_IO.Unbounded_IO.Get_Line(Name_Main2);
TIO.Put_Line("Enter the Name of the student :");
Ada.Text_IO.Unbounded_IO.Get_Line(Name_Main3);
if Name_Main1 > Name_Main2 then
TIO.Put_Line("Some semblance");TIO.New_Line;
else
TIO.Put_Line("Cant be matched");
end if;
end Main;
More it does not help in any way that most of these strings are of varying length. I am of a C background so looking for a strcmp kind of a functionality.
Please help if you can. There is very less or no documentation regarding this important feature on the net for Ada.
Ada Reference Manual
For Unbounded_String:
http://www.adaic.org/resources/add_content/standards/12rm/html/RM-A-4-5.html
83
Each of the functions "=", "<", ">", "<=", and ">=" returns the same result as the corresponding String operation applied to the String values given or represented by Left and Right.
For String literals:
http://www.adaic.org/resources/add_content/standards/12rm/html/RM-3-6-3.html
5
54 String literals (see 2.6 and 4.2) are defined for all string types. The concatenation operator & is predefined for string types, as for all nonlimited one-dimensional array types. The ordering operators <, <=, >, and >= are predefined for string types, as for all one-dimensional discrete array types; these ordering operators correspond to lexicographic order (see 4.5.2).
For one-dimensional array types:
http://www.adaic.org/resources/add_content/standards/12rm/html/RM-4-5-2.html
26/3
For a discrete array type, the predefined ordering operators correspond to lexicographic order using the predefined order relation of the component type: A null array is lexicographically less than any array having at least one component. In the case of nonnull arrays, the left operand is lexicographically less than the right operand if the first component of the left operand is less than that of the right; otherwise, the left operand is lexicographically less than the right operand only if their first components are equal and the tail of the left operand is lexicographically less than that of the right (the tail consists of the remaining components beyond the first and can be null).
Examples:
37
"" < "A" and "A" < "Aa" -- True
"Aa" < "B" and "A" < "A " -- True
If you need to sort Unbounded_Strings, you can use Containers.Generic_Array_Sort:
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Text_IO.Unbounded_IO; use Ada.Text_IO.Unbounded_IO;
with Ada.Containers.Generic_Array_Sort;
procedure Main is
Name_Main1, Name_Main2, Name_Main3 : Unbounded_String :=
Null_Unbounded_String;
begin
Put_Line ("Enter the Name of the student :");
Get_Line (Name_Main1);
Put_Line ("Enter the Name of the student :");
Get_Line (Name_Main2);
Put_Line ("Enter the Name of the student :");
Get_Line (Name_Main3);
declare
-- Array of Unbounded_Strings
type Unbarr is array (Positive range <>) of Unbounded_String;
-- Sort procedure
procedure Unbsort is new Ada.Containers.Generic_Array_Sort
(Positive, Unbounded_String, Unbarr, "<");
-- Array of Unbounded_Strings
Z : Unbarr := Name_Main1 & Name_Main2 & Name_Main3;
begin
-- Sort array
Unbsort (Z);
-- Output sorted array
Put_Line ("Sorted:");
for X of Z loop
Put_Line (X);
end loop;
end;
end Main;.
(Translated from German to Englisch)
I need help in this exercise :
Thread: String processing The user can make simple changes to an input sentence.
conditions
The program displays a menu for the user to select the following action. This is also displayed again after the action has been completed until the user terminates the program (a loop is therefore required).
The menu contains the following items, which should be executed when the specified letter is entered:
A. Enter the sentence
B. Determine the number of words
C. Determine the number of characters that are less than their sequence character
D. Replace all the words in the sentence with their uppercase initials
X. end
If the user enters a different letter, nothing happens or the menu is output again.
If the menu item A is selected, a prompt is issued to enter a set which is read into a string variable. This variable can not be changed by the actions of menu items B, C and D! Possibly. A copy of the set has to be prepared beforehand in another string variable.
In menu point B the number of all words in the block is to be counted. For simplicity, you can assume that there is always one space between two words. At the beginning and end of the sentence there are no spaces. The number of words is output after the calculation (e.g., "The set is 4 words").
If the user executes menu item C, the set is traversed character-by-character, and for each character it is checked whether it is smaller than its trailing character. Here is a simple character comparison (you can also write directly something like '1' <'d'). The number of characters so found is then output (e.g., "13 characters found in the sentence less than the trailing character").
In menu item D, the sentence is traversed and every word contained in it is replaced by its upper-case initial character. The capitalization is of course only made if the first character is a letter, otherwise the character remains unchanged. You can assume that the sentence never starts or ends with a space. Between two words there is always exactly one space and so it should be between the initial letters. For example, from "123 good mood" becomes "1 G L".
It is not permissible here to build up a completely new string piece by piece! Instead, you should work in a loop on a copy of the original sentence with pos, copy, length, delete and insert! It is also forbidden to "gather" the initial characters all at the beginning or end of the string; These should be inserted directly into the string at the position of the corresponding word!
Furthermore, a string can not be accessed at menu point D, because the work with string routines is to be practised explicitly here. Menu items B, C and D may only be selectable if a record has already been entered. Otherwise nothing happens or a fault message is entered when entering B, C or D in the menu and the menu is output again.
Each call to the menu items B, C or D will always work on the original set entered by the user and not on a set that has already been altered by previously executed menu items!
By entering the menu item A again, the entered block can be overwritten by a new one.
With an 'X' the user can terminate the program.
Use wherever it is the predefined string functions and do not write it yourself with difficulty loops, etc.! However, the use of the strreplace or reverseString functions is forbidden!
Here's my work till now, I only have problems with part D:
program Project2;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils;
const
lz = ' ';
var
Satz: string;
Buchstabe: char;
i, p, j, zaehler2, index, count: integer;
writeln('A) Write Sentence');
readln(Satz);
'D':
begin
index := 2;
insert(lz, Satz, length(Satz)+1);
count := (pos(lz,Satz));
repeat
delete(Satz, index,(count - index));
index := index + 2;
count := pos(lz,copy(Satz,index,(length(Satz)-index)))+index-1;
until ;
writeln(uppercase(Satz));
end
I'm glad you've found your own solution, well done!
While you've been doing that, I've been writing the answer below and, as I
have finished it, I thought I'd post it here to show you another way
to go about the problem of extracting words from a string. There are
dozens of ways of doing that task, but I hope the one I've used is fairly
easy to follow.
Maybe the reason you were having a problem with this is that your string-indexing
expressions are a bit too complicated. I bet if you come back to your code in 6 months
it will take you a while to figure out what it is supposed to be doing and longer
to tell whether it is actually doing it. The key to avoiding problems like that
is to break your code up into chucks which are easier to follow and easier
to test. So instead of just telling you what your repeat condition should be,
I'll show you a way which is easier to follow.
The first thing to do is to extract a singe word from the input. So, first thing
I've written is a function, ExtractFirstWord which returns the first word in
the input string, whether or not the input includes spaces, and also returns
a Remainder string which is what is left or the input string after the first
word (and any spaces immediately following it have been removed). This is done
using some simple while loops which are coded to skip over the leading spaces
and then build a string from the non-space characters which follow.
Code
const
lz = ' ';
var
Satz: string;
FirstWord : String;
Remainder : String;
function ExtractFirstWord(const InputStr : String; var Remainder : String) : String;
var
P : Integer;
WordStart : Integer;
begin
Result := '';
P := 1;
// The following skips over any spaces at the start of InputStr
while (P <= Length(InputStr)) and (InputStr[P] = lz) do
Inc(P);
// Now we know where the first word starts
WordStart := P;
// Now we can get the first word, if there is one
while (P <= Length(InputStr)) and (InputStr[P] <> lz) do
Inc(P);
Result := Copy(InputStr, WordStart, P - WordStart);
Remainder := Copy(InputStr, P, Length(InputStr));
// the following is one way to remove spaces at the start of Remainder
while (Length(Remainder) > 0) and (Remainder[1] = lz) do
Delete(Remainder, 1, Length(lz));
// instead you could do something simlar to the first `while` loop above
end;
begin
Satz := ' cat dog ';
repeat
FirstWord := ExtractFirstWord(Satz, Remainder);
FirstWord := UpperCase(FirstWord);
Satz := Remainder;
writeln('First word: ', FirstWord, ' remainder: ', Remainder);
until Remainder = '';
readln;
end.
This particular way of doing it is not an ideal fit with the other requirements
specified in your task but should be easily adaptable to them. E.g, the upper-casing of words could be done "in place" on the input string by upper-casing the current character of it in the second While loop.
Btw, if you are using Delphi or Free Pascal/Lazarus, there is a much simpler
way of extracting the words from a string. It uses a TStringList. Try
looking it up in the online help and have a thing about how you might use it
to do the task.
I have these declared:
subtype Num_Char is Natural
range 1 .. Definitions.Page_Width + 1;
subtype Number_Of_Rows is Definitions.Number_Of_Rows;
type Chars is array (Number_Of_Rows, Num_Char) of Character;
The_Chars : Chars;
What is the best way to print this out to the screen using Ada.Text_IO.Put_Line()?
Assuming you want to use Ada.Text_IO and not just Put_Line specifically, and assuming that Number_Of_Rows is meant to be an integer range like Num_Char, that would be
for R in The_Chars'Range (1) loop
for C in The_Chars'Range (2) loop
Ada.Text_IO.Put (The_Chars (R, C));
end loop;
Ada.Text_IO.New_Line;
end loop;
A lot of problems in Ada actually go back to your initial choice of types. So personally, I'd suggest a slight rewrite to make your life easier:
subtype Row is String (1..Definitions.Tote_Page_Width + 1);
type Chars is array (Definitions.Number_Of_Rows) of Row;
Now you could write this out with the following:
for I in The_Chars'range loop
Ada.Text_IO.Put_Line (The_Chars (I));
end loop;
However, there is still a big problem here. Put_Line will print out all the characters in each row. Ada strings are not null-terminated, so if there unused data at the end of some of your lines, that will get printed too.
There are lots of ways to deal with this, but they are very different techniques than would be used to handle C strings. If you try to handle Ada strings like you'd handle C strings, you will drive yourself nuts.
For this reason, I would dearly like to see your code that actually fills The_Char with data (and the rationale behind it).