I wrote a function to clear the keyboard buffer, since I think I am having leftover input after a get, but it's just taking input forever.
here is the get(String(1..10)
--getString10--
procedure getString10(s : in out string10) is
Last: Integer;
begin
s := (others => ' ');
Get_Line(S, Last);
end getString10;
and here is the flush I made, pretty much copied from a wiki on clearing keyboard buffers
--flush--
procedure flush is
char : character;
more : boolean;
begin
loop
get_immediate(char, more);
exit when not more;
end loop;
end flush;
Whenever the flush is called, whatever I type is outputted on the screen until I exit the program.
Also, my getString10 function doesn't always wait on user input. For example, if I have
put("Enter a name: ");
getString10(name);
put("Enter a number: ");
getString10(number);
The output will be
Enter a name: Enter a number: exampleinput
I am using Ada 2005 on Gnat Programming Studio.
Updated with the entire main:
with Ada.Text_IO, Ada.Integer_Text_IO, BinarySearchTree;
use Ada.Text_IO, Ada.Integer_Text_IO;
procedure lab4 is
subtype String10 is String(1..10);
-- function "<"--
function "<"(TheKey: in String10; ARecord: in String10) return Boolean is
begin
for i in integer range 1..10 loop
if TheKey(i) <= ARecord(i) then
return true;
else
return false;
end if;
end loop;
return false;
end "<";
-- function ">"--
function ">"(TheKey: in String10; ARecord: in String10) return Boolean is
begin
for i in integer range 1..10 loop
if TheKey(i) >= ARecord(i) then
return true;
else
return false;
end if;
end loop;
return false;
end ">";
-- function "="--
function "="(TheKey: in String10; ARecord: in String10) return Boolean is
begin
for i in integer range 1..10 loop
if TheKey(i) /= ARecord(i) then
return false;
end if;
end loop;
return true;
end "=";
--getString10--
procedure getString10(s : in out string10) is
Last: Integer;
begin
s := (others => ' ');
Get_Line(S, Last);
end getString10;
--flush--
procedure flush is
char : character;
more : boolean;
begin
loop
get_immediate(char, more);
exit when not more;
end loop;
end flush;
package BST is new BinarySearchTree(String10, String10, "<", ">", "=");
Root, found : BST.BinarySearchTreePoint;
choice : integer;
nameTemp, phoneTemp : String10;
begin
BST.setRoot(Root);
loop
new_line;
put_line("Options:");
put_line("1 - Insert a record");
put_line("2 - Find a person iteratively and print their phone number");
put_line("3 - Find a person recursively and print their phone number");
put_line("4 - Traverse the tree from a person to a person");
put_line("0 - Quit program");
put("Choose an option: ");
get(choice); put(choice, 0); new_line;
case choice is
--case 1
when 1 =>
put("Enter the name: ");
get(nameTemp); put(nameTemp); new_line;
put("Enter the phone number : ");
get(phoneTemp); put(phoneTemp); new_line;
BST.InsertBinarySearchTree(root, nameTemp, phoneTemp);
--case 2
when 2 =>
put("Enter the name of the person to find: ");
get(nameTemp); put(nameTemp);
BST.FindCustomerIterative(root, nameTemp, found);
if BST.isNull(found) then
new_line;
put("Customer not found!");
else
new_line;
put("The phone number is: ");
put(BST.CustomerPhone(found));
end if;
--case 3
when 3 =>
put("Enter the name of the person to find: ");
get(nameTemp); put(nameTemp);
BST.FindCustomerRecursive(root, nameTemp, found);
if BST.isNull(found) then
new_line;
put_line("Customer not found!");
else
new_line;
put("The phone number is: ");
put(BST.CustomerPhone(found));
end if;
new_line;
--case 4
when 4 =>
put("Enter of the name of the person to start traversal at: ");
get(nameTemp); put(nameTemp);
BST.FindCustomerRecursive(root, nameTemp, found);
put("Enter then name of the person to stop traversal at: ");
get(phoneTemp); put(phoneTemp); --using phoneTemp for a name here
BST.FindCustomerRecursive(Root, nameTemp, found);
while BST.isNull(found) /= true loop
put_line("Name = " & BST.CustomerName(found));
BST.setNode(found, BST.InOrderSuccessor(found));
end loop;
--case 0
when 0 =>
exit;
--others
when others =>
put_line("Invalid choice!"); new_line;
end case;
end loop;
end lab4;
I switched out all of the getString10()s with get()s because I am trying to debug the threaded binary search tree. I am using an input file, so it's fine for now, I just can figure out why the other methods wouldn't work.
All of the get calls on nameTemp and phoneTemp should be getString10() calls.
You could use the get_line() function, which automatically clears the keyboard buffer.
with ADA.TEXT_IO; use ADA.TEXT_IO;
with ADA.TEXT_IO.UNBOUNDED_IO; use ADA.TEXT_IO.UNBOUNDED_IO;
with ADA.STRINGS.UNBOUNDED; use ADA.STRINGS.UNBOUNDED;
procedure MAIN is
type STRING_10 is new STRING(1..10);
procedure GET_STRING_10(S : in out STRING_10) is
BUF : UNBOUNDED_STRING;
begin
BUF := GET_LINE;
for I in STRING_10'range loop
if I <= LENGTH(BUF) then
S(I) := ELEMENT(BUF, I);
else
S(I) := ' ';
end if;
end loop;
end GET_STRING_10;
S : STRING_10;
begin
GET_STRING_10(S);
PUT_LINE(STRING(S));
end MAIN;
EDIT after reading the whole main:
You should insert a SKIP_LINE; after GET(CHOICE);. Then you can replace every GET by a GETSTRING10 in your different cases.
In general, a get must always be followed by a skip_line. There's no need to do this with a get_line, thus you don't have to modify you getstring10 procedure.
Related
Producer
Different Thread with its own SynchronizedBlockingQueue.
Each producer put there message into its own queue.
Consumer
Different Thread which will get message from either from any one of queue and start process.
Now for communicating producer and consumer, we need broker. which may be bottleneck. Is there any other way consumer get one message form any producer and start process.
Since you did not specify a language, I thought I would provide a general example using the Ada programming language. This example has the consumer simply print the messages from the producers, but it gives the producer-consumer architecture you described.
with Ada.Task_Identification; use Ada.Task_Identification;
package Multiple_Producer is
type Producer_Message is private;
protected type Buffer is
entry Set_Message (Item : in Producer_Message);
entry Get_Message (Item : out Producer_Message);
private
Msg : Producer_Message;
Is_New : Boolean := False;
end Buffer;
type Buf_Alias is access all Buffer;
type Buf_Array is array (Positive range <>) of aliased Buffer;
type Buf_Access is access all Buf_Array;
task type Producer is
entry Set_Buffer (Item : Buf_Alias);
entry Stop;
end Producer;
task Consumer is
entry Set_Buffers (Item : Buf_Access);
entry Stop;
end Consumer;
private
type Producer_Message is record
the_Task : Task_Id;
Value : Integer;
end record;
end Multiple_Producer;
with Ada.Text_IO; use Ada.Text_IO;
package body Multiple_Producer is
--------------
-- Producer --
--------------
task body Producer is
Message : Producer_Message := (Current_Task, 0);
The_Buf : Buf_Alias;
begin
accept Set_Buffer(Item : in Buf_Alias) do
The_Buf := Item;
end Set_Buffer;
loop
select
accept Stop;
exit;
else
delay 0.01;
The_Buf.Set_Message(Message);
Message.Value := Message.Value + 1;
end select;
end loop;
end Producer;
--------------
-- Consumer --
--------------
task body Consumer is
Message : Producer_Message;
Buffers : Buf_Access;
begin
accept Set_Buffers(Item : Buf_Access) do
Buffers := Item;
end Set_Buffers;
loop
select
accept Stop;
exit;
else
-- Poll the buffers
for I in Buffers'Range loop
select
Buffers(I).Get_Message(Message);
Put_Line(Image(Message.The_Task) & ": " &
Integer'Image(Message.Value));
or
delay 0.001;
end select;
end loop;
end select;
end loop;
end Consumer;
------------
-- Buffer --
------------
protected body Buffer is
-----------------
-- Set_Message --
-----------------
entry Set_Message (Item : in Producer_Message) when not Is_New is
begin
Msg := Item;
Is_New := True;
end Set_Message;
-----------------
-- Get_Message --
-----------------
entry Get_Message (Item : out Producer_Message) when Is_New is
begin
Item := Msg;
Is_New := False;
end Get_Message;
end Buffer;
end Multiple_Producer;
with Multiple_Producer; use Multiple_Producer;
procedure Main is
subtype Producer_Range is Positive range 1..5;
The_Producers : array(Producer_Range) of Producer;
The_Buffers : Buf_Access := new Buf_Array(Producer_Range);
begin
for I in Producer_Range loop
The_Producers(I).Set_Buffer(The_Buffers(I)'Access);
end loop;
Consumer.Set_Buffers(The_Buffers);
delay 4.0;
for P of The_Producers loop
P.Stop;
end loop;
Consumer.Stop;
end Main;
I'm just starting to learn Ada 95 and I'm having some problems with comparing strings.
Here's the code:
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
with Ada.Command_Line;
with Ada.Strings.Unbounded;
procedure Test1 is
vad : String(1..9);
Amount : Integer;
Main : Integer;
Second : Integer;
Third : Integer;
begin
Main := 1;
Second := 0;
Third := 0;
Put("What do you want to do?");
New_Line(1);
Get(vad);
New_Line(1);
if Vad = "fibonacci" then
Put("How long do you want the sequence to be");
New_Line(1);
Get(Amount);
New_Line(1);
Amount := Amount -1;
for I in 1 .. Amount loop
Put(Main);
New_Line(1);
--Put(" ");
Third := Second;
Second := Main;
Main := (Second + third);
end loop;
New_Line(2);
elsif Vad = "two" then
Put("How long do you want the sequence to be?");
New_Line(1);
Get(Amount);
New_Line(1);
for U in 1 .. Amount loop
Put(U * 2);
Put(", ");
end loop;
else
Put("ok");
end if;
end Test1;
As it is now, the if statement recognises when I type fibonacci, but when I type two it just goes to the 'else' part of the code.
Any ideas what might be wrong?
Thanks in advance.
What probably confuses you is that the type String is actually a fixed-length string.
This means that comparing Vad with any string, which isn't exactly 9 characters long will fail.
One option is to declare Vad and initialise it with the output from Ada.Text_IO.Get_Line in one go:
Vad : constant String := Ada.Text_IO.Get_Line;
This way you will read exactly what is written until (and not including) the next line-break entered into Vad.
Jacob's explanation is correct. Here's your code modified to use Ada.Text_IO.Get_Line
I removed the "with Ada.Strings.Unbounded" line because the package is not needed.
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
with Ada.Command_Line;
procedure Test1 is
Amount : Integer;
Main : Integer := 1;
Second : Integer := 0;
Third : Integer := 0;
begin
Put_Line("What do you want to do?");
declare
vad : constant string := Get_Line;
begin
if Vad = "fibonacci" then
Put_Line("How long do you want the sequence to be?");
Get(Amount);
Amount := Amount -1;
for I in 1 .. Amount loop
Put(Main);
New_Line;
--Put(" ");
Third := Second;
Second := Main;
Main := (Second + third);
end loop;
New_Line(2);
elsif Vad = "two" then
Put_Line("How long do you want the sequence to be?");
Get(Amount);
for U in 1 .. Amount loop
Put(integer'image(U * 2) & ", ");
end loop;
else
Put("ok");
end if;
end;
end Test1;
I have a problem regarding a testbench I am developing for an hardware butterfly algorithm for calculating the Fourier transform.
What I'm attempting to do is reading a series of input data files (32-bit vectors) and writing the output in some other output files.
The input files are Ar.txt, Ai.txt, Br.txt, Bi.txt, Wr.txt and Wi.txt.
The output files are Ar_OUT_TB.txt, Ai_OUT_TB.txt, Br_OUT_TB.txt, Bi_OUT_TB.txt.
But when I try to simulate with ModelSim, the program simply freezes: I can still do some stuff, like opening another project/file etc., but there's no waveform showing, and also the command line is missing. I also tried to simulate an older VHDL project of mine and it did simulate, so I guess the problem is within this code.
These are the main processes (EDIT: I'm also adding the rest of the code, for understanding):
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.NUMERIC_STD.ALL;
USE STD.TEXTIO.ALL;
ENTITY BUTTERFLY_TESTBENCH IS
END BUTTERFLY_TESTBENCH;
ARCHITECTURE DEVICE OF BUTTERFLY_TESTBENCH IS
COMPONENT progetto_butterfly
GENERIC(N_IN, N_OUT: INTEGER := 32;
N_BUSES: INTEGER := 63);
PORT(START, CLK, MAIN_RST_N: IN STD_LOGIC;
DATA_IN, Wr_IN, Wi_IN: IN SIGNED(N_IN-1 DOWNTO 0);
DATA_OUT: OUT SIGNED(N_IN-1 DOWNTO 0);
DONE: OUT STD_LOGIC);
END COMPONENT;
CONSTANT N_IN: INTEGER := 32;
CONSTANT N_OUT: INTEGER := 32;
SIGNAL TEST_DATA_IN, TEST_Wr_IN, TEST_Wi_IN: SIGNED(N_IN-1 DOWNTO 0);
SIGNAL TEST_OUTPUT: SIGNED(N_OUT-1 DOWNTO 0);
SIGNAL CLK: STD_LOGIC;
SIGNAL TEST_START, TEST_RST, TEST_DONE: STD_LOGIC;
FILE Ar_IN_FILE: TEXT OPEN READ_MODE IS "Ar.txt";
FILE Ai_IN_FILE: TEXT OPEN READ_MODE IS "Ai.txt";
FILE Br_IN_FILE: TEXT OPEN READ_MODE IS "Br.txt";
FILE Bi_IN_FILE: TEXT OPEN READ_MODE IS "Bi.txt";
FILE WR_FILE: TEXT OPEN READ_MODE IS "Wr.txt";
FILE WI_FILE: TEXT OPEN READ_MODE IS "Wi.txt";
FILE Ar_OUT: TEXT OPEN WRITE_MODE IS "Ar_OUT_TB.txt";
FILE Ai_OUT: TEXT OPEN WRITE_MODE IS "Ai_OUT_TB.txt";
FILE Br_OUT: TEXT OPEN WRITE_MODE IS "Br_OUT_TB.txt";
FILE Bi_OUT: TEXT OPEN WRITE_MODE IS "Bi_OUT_TB.txt";
BEGIN
BUTTERFLY_TEST_COMPONENT: progetto_butterfly PORT MAP(START => TEST_START, CLK => CLK, MAIN_RST_N => TEST_RST,
DATA_IN => TEST_DATA_IN, Wr_IN => TEST_Wr_IN, Wi_IN => TEST_Wi_IN,
DATA_OUT => TEST_OUTPUT, DONE => TEST_DONE);``
DATA_IN_PROCESS: PROCESS
VARIABLE DATA_BUFFER: LINE;
VARIABLE DATA_STIMULUS: BIT_VECTOR(N_IN-1 DOWNTO 0);
BEGIN
IF NOT (ENDFILE(Br_IN_FILE)) THEN
IF(TEST_START = '1' AND TEST_RST = '1') THEN
READLINE(Br_IN_FILE,DATA_BUFFER);
READ(DATA_BUFFER,DATA_STIMULUS);
TEST_DATA_IN <= SIGNED(TO_STDLOGICVECTOR(DATA_STIMULUS));
WAIT UNTIL CLK'EVENT AND CLK = '1';
READLINE(Bi_IN_FILE,DATA_BUFFER);
READ(DATA_BUFFER,DATA_STIMULUS);
TEST_DATA_IN <= SIGNED(TO_STDLOGICVECTOR(DATA_STIMULUS));
WAIT UNTIL RISING_EDGE(CLK);
READLINE(Ar_IN_FILE,DATA_BUFFER);
READ(DATA_BUFFER,DATA_STIMULUS);
TEST_DATA_IN <= SIGNED(TO_STDLOGICVECTOR(DATA_STIMULUS));
WAIT UNTIL RISING_EDGE(CLK);
READLINE(Ai_IN_FILE,DATA_BUFFER);
READ(DATA_BUFFER,DATA_STIMULUS);
TEST_DATA_IN <= SIGNED(TO_STDLOGICVECTOR(DATA_STIMULUS));
WAIT FOR 12 ns;
ELSE
TEST_DATA_IN <= (OTHERS => '0');
END IF;
END IF;
END PROCESS;
WR_PROCESS: PROCESS
VARIABLE wr_buf: LINE;
VARIABLE WR_STIMULUS: BIT_VECTOR(N_IN-1 DOWNTO 0);
BEGIN
WHILE NOT (ENDFILE(WR_FILE)) LOOP
IF(TEST_START = '1' AND TEST_RST = '1') THEN
READLINE(WR_FILE,wr_buf);
READ(wr_buf,WR_STIMULUS);
TEST_Wr_IN <= SIGNED(TO_STDLOGICVECTOR(WR_STIMULUS));
WAIT FOR 20 ns;
END IF;
END LOOP;
END PROCESS;
WRITING_PROCESS: PROCESS
VARIABLE STRING_LINE: STRING(N_OUT DOWNTO 1);
VARIABLE OUT_LINE: LINE;
VARIABLE I: INTEGER;
BEGIN
WAIT FOR 12 ns;
WHILE (TEST_START = '1' AND TEST_RST = '1') LOOP
FOR I IN N_OUT-1 DOWNTO 0 LOOP
IF(TEST_OUTPUT(I) = '0') THEN
STRING_LINE(I+1) := '0';
ELSE
STRING_LINE(I+1) := '1';
END IF;
END LOOP;
WRITE(OUT_LINE,STRING_LINE);
WRITELINE(Br_OUT,OUT_LINE);
WAIT UNTIL RISING_EDGE(CLK);
FOR I IN N_OUT-1 DOWNTO 0 LOOP
IF(TEST_OUTPUT(I) = '0') THEN
STRING_LINE(I+1) := '0';
ELSE
STRING_LINE(I+1) := '1';
END IF;
END LOOP;
WRITE(OUT_LINE,STRING_LINE);
WRITELINE(Bi_OUT,OUT_LINE);
WAIT UNTIL RISING_EDGE(CLK);
FOR I IN N_OUT-1 DOWNTO 0 LOOP
IF(TEST_OUTPUT(I) = '0') THEN
STRING_LINE(I+1) := '0';
ELSE
STRING_LINE(I+1) := '1';
END IF;
END LOOP;
WRITE(OUT_LINE,STRING_LINE);
WRITELINE(Ar_OUT,OUT_LINE);
WAIT UNTIL RISING_EDGE(CLK);
FOR I IN N_OUT-1 DOWNTO 0 LOOP
IF(TEST_OUTPUT(I) = '0') THEN
STRING_LINE(I+1) := '0';
ELSE
STRING_LINE(I+1) := '1';
END IF;
END LOOP;
WRITE(OUT_LINE,STRING_LINE);
WRITELINE(Ai_OUT,OUT_LINE);
END LOOP;
END PROCESS;
CLK_PROCESS: PROCESS
BEGIN
CLK <= '1';
WAIT FOR 2 ns;
CLK <= '0';
WAIT FOR 2 ns;
END PROCESS;
TEST_RST <= '0', '1' AFTER 2 ns;
TEST_START <= '0', '1' AFTER 3 ns;
END ARCHITECTURE;
Is something done wrong? I can't see what I'm missing.
Your DATA_IN_PROCESS process is an infinite loop. As long as as the condition TEST_START = '1' AND TEST_RST = '1' is not met, the process keeps on running, without incrementing simulated time. It eats up simulator time and simuated time does not increase.
Solve this by adding WAIT UNTIL RISING_EDGE(CLK); in the else clause.
Other problems with your code are listed here: http://www.sigasi.com/vhdl-code-check?ID=27869561
Your processes either need a sensitivity list or a WAIT statement.
After building an MVCe from your example I found that it appears an input file you're reading is too short, revealing faults in two of your processes (data_in_process and wr_process).
library ieee;
use std.textio.all;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity sometb is
end entity;
architecture foo of sometb is
constant n_in: integer := 8;
signal test_start: std_logic := '1';
signal test_rst: std_logic := '1';
file br_in_file: text open READ_MODE is "Br.txt";
signal test_data_in: signed(n_in - 1 downto 0);
signal clk: std_logic := '0';
file bi_in_file: text open READ_MODE is "Bi.txt";
file ar_in_file: text open READ_MODE is "Ar.txt";
file ai_in_file: text open READ_MODE is "Ai.txt";
file wr_file: text open READ_MODE is "Wr.txt";
signal test_wr_in: signed(n_in - 1 downto 0);
constant n_out: integer:= 8;
signal test_output: std_logic_vector(n_out - 1 downto 0);
file br_out: text open WRITE_MODE is "Br_OUT_TB.txt";
file bi_out: text open WRITE_MODE is "Bi_OUT_TB.txt";
file ar_out: text open WRITE_MODE is "Ar_OUT_TB.txt";
file ai_out: text open WRITE_MODE is "Bi_OUT_TB.txt";
begin
CLOCK:
process
begin
wait for 6 ns;
clk <= not clk;
end process;
data_in_process:
process
variable data_buffer: line;
variable data_stimulus: bit_vector(n_in-1 downto 0);
begin
if not endfile(br_in_file) then
if test_start = '1' and test_rst = '1' then
readline(br_in_file,data_buffer);
read(data_buffer,data_stimulus);
test_data_in <= signed(to_stdlogicvector(data_stimulus));
wait until clk'event and clk = '1';
readline(bi_in_file,data_buffer);
read(data_buffer,data_stimulus);
test_data_in <= signed(to_stdlogicvector(data_stimulus));
wait until rising_edge(clk);
readline(ar_in_file,data_buffer);
read(data_buffer,data_stimulus);
test_data_in <= signed(to_stdlogicvector(data_stimulus));
wait until rising_edge(clk);
readline(ai_in_file,data_buffer);
read(data_buffer,data_stimulus);
test_data_in <= signed(to_stdlogicvector(data_stimulus));
wait for 12 ns;
else
test_data_in <= (others => '0');
end if;
end if;
wait until rising_edge(clk); -- added for endfile
end process;
wr_process:
process
variable wr_buf: line;
variable wr_stimulus: bit_vector(n_in-1 downto 0);
begin
while not endfile(wr_file) loop
if test_start = '1' and test_rst = '1' then
readline(wr_file,wr_buf);
read(wr_buf,wr_stimulus);
test_wr_in <= signed(to_stdlogicvector(wr_stimulus));
wait for 20 ns;
end if;
end loop;
wait for 20 ns; -- added for when endfile(wr_file) is TRUE.
end process;
writing_process:
process
variable string_line: string(n_out downto 1);
variable out_line: line;
-- variable i: integer; -- the following are not my i
begin
wait for 12 ns;
while test_start = '1' and test_rst = '1' loop
for i in test_output'range loop -- n_out-1 downto 0 loop
if test_output(i) = '0' then
string_line(i + 1) := '0';
else
string_line(i + 1) := '1';
end if;
end loop;
write(out_line, string_line);
writeline(br_out, out_line);
wait until rising_edge(clk);
for i in test_output'range loop -- n_out-1 downto 0 loop
if test_output(i) = '0' then
string_line(i + 1) := '0';
else
string_line(i + 1) := '1';
end if;
end loop;
write(out_line,string_line);
writeline(bi_out,out_line);
wait until rising_edge(clk);
for i in test_output'range loop -- n_out-1 downto 0 loop
if test_output(i) = '0' then
string_line(i+1) := '0';
else
string_line(i+1) := '1';
end if;
end loop;
write(out_line,string_line);
writeline(ar_out,out_line);
wait until rising_edge(clk);
for i in test_output'range loop -- n_out-1 downto 0 loop
if test_output(i) = '0' then
string_line(i+1) := '0';
else
string_line(i+1) := '1';
end if;
end loop;
write(out_line,string_line);
writeline(ai_out,out_line);
end loop;
end process;
end architecture;
I added
wait until rising_edge(clk); -- added for endfile
before the end of the process in data_in_process, otherwise it would loop without suspending if END_FILE(br_in_file) is TRUE. (And you should really have a test or test that covers all your inputs).
I added
wait for 20 ns; -- added for when endfile(wr_file) is TRUE.
to wr_process for the same reason.
The changes to writing_process were used to discover a working range for the test_output signal. Note the the process declarative item for variable i can be removed, it's not used. (The i there is not the i in the loop constants).
I found the problems with the input files by in a UNIX environment (OS X) touching the input files which creates them with a zero length (after insuring my VHDL simulator would complain if they don't exist).
Please. help me determine how many small and big letters "s" and the sign "=" occurs in a given text. Print lines in which these characters are missing.
How do I implement validation text and how to recognize the line where there is no such marks
Help with the program. I would be very grateful!
my programm for now. what to do next,
program four;
var
i : integer;
MyString : string;
MyChar : char;
begin
read( MyString );
for i := 1 to MyString.Length do
begin
case ( MyString[i] ) of
'S' : writeln( i );
's' : writeln( i );
'=' : writeln( i );
end;
end;
end.
You need to implement counters to keep track of whether you've found any of the characters or not, so you'll know what to do.
Something like this should get you started:
program four;
var
i : integer;
LowerS, UpperS, Equals: Integer;
MyString : string;
begin
LowerS := 0;
UpperS := 0;
Equals := 0;
Write('Enter text to scan: ');
ReadLn( MyString );
for i := 1 to Length(MyString) do
begin
case ( MyString[i] ) of
'S' : Inc(UpperS);
's' : Inc(LowerS);
'=' : Inc(Equals);
end;
end;
if (UpperS + LowerS + Equals) = 0 then
WriteLn('No valid characters found')
else
WriteLn(Format('S: %d s: %d =: %d', [UpperS, LowerS, Equals]));
ReadLn;
end.
procedure Split(S: String; List: TStringList; Separator: Char);
var
P, C: PAnsiChar;
S, Buff: String;
begin
List.Clear;
if S = '' then
Exit;
List.BeginUpdate;
(* [Ajusting size - Slow *)
if S[1] = Separator then
Insert('', S, 1);
S := S + Separator;
(* Adjusting size] *)
//Get Pointer to data
P := PChar(S);
//initial position
C := P;
while P^ <> #0 do //check if reached the end of the string
begin
//when found a separator
if P^ = Separator then
begin
if P = C then //check if the slot is empty
Buff := ''
else //when it is not empty, make an string buffer
SetString(Buff, C, P-C);
List.Add(Buff); //add the string into the list
Inc(C, P-C+1); //moves the pointer C to the adress of the pointer P
end;
Inc(P); //go to next char in the string
end;
List.EndUpdate;
end;
This code is working fine but is moving the string 3 times in the memory:
In the Method Call (By copy)
In the Insert('', S, 1)
In the Concatenation: S := S + Separator;
I thought about adding const keyword in the S parameter, creating an internal string to copy the data more or less like this:
if S[1] = Separator then
begin
SetLength(Str, Length(S)+2);
//HERE!! how to copy the string
Str[1] := ' ';
end
else
begin
SetLength(Str, Length(S)+1);
//HERE!! how to copy the string
end;
//Add Separator in the last position
Str[Length(Str)] := Separator;
Thus:
if the S contains ';'
it will create an stringlist with 2 items ('','').
if the S contains ';A'
it will create an stringlist with 2 items ('','A').
if the S contains 'A;A'
it will create an stringlist with 2 items ('A','A').
if the S contains 'A;'
it will create an stringlist with 2 items ('A','').
Like this:
if S[1] = Separator then
begin
SetLength(Str, Length(S)+2);
Move(Pointer(S)^, Str[2], Length(S)*SizeOf(Char));
S[1] := ' '; // surely you mean Str[1] := ' '
end
else
begin
SetLength(Str, Length(S)+1);
Move(Pointer(S)^, Str[1], Length(S)*SizeOf(Char));
end;
//Add Separator in the last position
Str[Length(Str)] := Separator;
It would be easy enough to re-work this to avoid the duplication.
var
dest: PChar;
if S[1] = Separator then
begin
SetLength(Str, Length(S)+2);
dest := #Str[2];
S[1] := ' '; // surely you mean Str[1] := ' '
end
else
begin
SetLength(Str, Length(S)+1);
dest := #Str[1];
end;
Move(Pointer(S)^, dest^, Length(S)*SizeOf(Char));
//Add Separator in the last position
Str[Length(Str)] := Separator;
And so on. I'll leave it to you to polish it up.
The following routine is one I wrote (more accurately, adapted from SetDelimitedText and ExtractStrings) for Delphi 7 to handle the lack of the TStrings.StrictDelimiter property. Given the correct parameters, it'll return exactly the results you want.
{
SplitString will expand the delimited string S into its component parts and
store them in Strings. The primary difference between this routine and
Classes.ExtractStrings and TStrings.DelimitedText is that it does not treat
spaces, tabs, and CR/LF as delimiters whether you like it or not. If Quotes
is non-empty, then quoted strings will be handled correctly.
Leading and Trailing whitespace is significant if TrimStrings is False.
If you want to eliminate empty tokens, set SkipEmptyStrings to True.
If you want Strings to be cleared before parsing, set ClearStrings to True.
This procedure is especially useful for dealing with CSV files exported from
Excel, since Excel does not quote a string unless it contains a comma.
Using ExtractStrings or TStrings.CommaText will fail with such files.
In Delphi 2006+, TStrings has the StrictDelimiter property that renders this
routine largely useless.
}
procedure SplitString(const S: string; Separators, Quotes: TSysCharSet; const Strings: TStrings; ClearStrings, TrimStrings, SkipEmptyStrings: Boolean);
var
Head, Tail: PChar;
Item: string;
StringExists: Boolean;
{$IF NOT Declared(CharInSet)}
function CharInSet(C: Char; const CharSet: TSysCharSet): Boolean;
begin
Result := C in CharSet;
end;
{$IFEND}
begin
StringExists := False;
Strings.BeginUpdate;
try
if ClearStrings then
Strings.Clear;
if S = '' then
Exit;
Tail := PChar(S);
while Tail^ <> #0 do begin
if CharInSet(Tail^, Quotes) then
Item := AnsiExtractQuotedStr(Tail, Tail^)
else begin
// Mark beginning of token
Head := Tail;
// Look for end of token, delineated by end of string or separator
while (Tail^ <> #0) and not CharInSet(Tail^, Separators) do
Inc(Tail);
SetString(Item, Head, Tail - Head);
if TrimStrings then begin
Item := Trim(Item);
Head := PChar(Item);
if CharInSet(Head^, Quotes) then
Item := Trim(AnsiExtractQuotedStr(Head, Head^));
end;
if not (SkipEmptyStrings and (Item = '')) then
Strings.Append(Item);
end;
// If the last character in a string is a separator, then we need to mark
// that another string exists, otherwise the next Inc(Tail) call will
// place Tail^ at #0, we'll exit the while loop, and never know that there
// was an empty string there to add.
// --AAF
StringExists := Tail^ <> #0;
// Skip Separator
if StringExists then
Inc(Tail);
end;
// This can only happen if the very last character is a separator
if StringExists and not SkipEmptyStrings then
Strings.Append('');
finally
Strings.EndUpdate;
end;
end;