What is Free Pascal Error 3208 Illegal assignment to for-loop variable [closed] - freepascal

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
Tell me about Free Pascal compiler error 3208 "Illegal assignment to for-loop variable."

We cannot change the value of the indexer variable in a For-In loop.
For demonstration, copy this code into a new Project of type Simple Program, and compile it. Then, add the '$' character to the "Define symDemo" comment in the first line, to convert it to a compiler directive, and try to compile.
For discussion see https://forum.lazarus.freepascal.org/index.php?topic=17488.0
program ForIn; {$AppType Console} { Define symDemo}
var
strChrLst , // list of characters, without separators
idxChrOne : string ; // only one character; indexer in For-In loop
strChrUpr : string = ''; // uppercase version of the current character, init-ed to empty
begin
strChrLst := 'a[z' ; // initialize list of characters to work on
for idxChrOne in strChrLst do begin ; // scan all characters in the list
{$IfNDef symDemo} ; // when "symDemo" is not defined
strChrUpr := UpCase( idxChrOne ) ; // convert the current character to upcase
{$Else} ; // when "symDemo" is defined
idxChrOne := UpCase( idxChrOne ) ; // gives Error 3208 on "idxChrOne"
{$EndIf} ; // done with "symDemo"
if ( strChrUpr < 'A' ) // when the current character is
Or ( strChrUpr > 'Z' ) then begin ; // outside the range of alphabet letters
writeln(StdErr,'Not a letter: ',idxChrOne); // emit the non-letter character on StdErr
end ; // done with the non-letter character
end ; // done scanning characters in the list
end.

Related

Why is "result := char variable" getting me access violation? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
I created a function that has a Char represented by a variable named fsinal:
type
TCalculo = class(TObject)
private
fnumero1 : integer;
fnumero2 : integer;
fsinal : char;
public
I then created a method to get this Char:
function getSinal : char;
function TCalculo.getSinal: char;
begin
result := fsinal;
end;
Whenever I rum my program and press any button, I receive an error
access violation at address 005FD704, read of address 0000000C:
What am I doing wrong?
Whole code:
https://github.com/murillojndem/Calculadora/blob/master/Unit1.pas
An Access Violation error near address $00000000 usually means you are accessing memory via a nil pointer.
In this case, address $0000000C is 12 bytes from address $00000000. The TCalculo.getSinal() method is accessing the fsinal member, which is at an offset of 12 bytes from the start of the TCalculo class (offset 0 is a hidden pointer to TCalculo's vtable, offset 4 is the fnumero1 member, offset 8 is the fnumero2 member, and finally offset 12 is the fsinal member).
result := fsinal; is the same as result := Self.fsinal;, where the compiler adds the offset of fsinal (12) to the address that Self is pointing at, and then dereferences the resulting address to access the value of fsinal. In your case, you are calling TCalculo.getSinal() via a nil pointer to a TCalculo object, so the method's Self pointer is nil (0), thus dereferencing the address of fsinal (0+12) causes an AV error.
In your TForm code, all of your TButton.OnClick handlers are calling getSinal() on a global calculo variable that is never being initialized to point at a valid TCalculo object. Since the calculo variable is declared in global memory, it is default-initialized to nil at program startup.
type
TCalculo = class(TObject)
...
end;
var
Form1 : TForm1;
calculo: TCalculo; // <-- initialized to nil here!
...
procedure TForm1.Button0Click(Sender: TObject);
begin
if calculo.getSinal = 'a' then // <-- calculo is still nil here!
...
end;
... and so on...
You need to add a call to TCalculo.Create(), either in the TForm.OnCreate event (and conversely, Free the object in the TForm.OnDestroy event), eg:
procedure TForm1.FormCreate(Sender: TObject);
begin
calculo := TCalculo.Create;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
calculo.Free;
end;
Or, use the unit's initialization section instead (and conversely, the finalization section), eg:
implementation
...
initialization
calculo := TCalculo.Create;
finalization
calculo.Free;
end.

Why am I getting a "No matching subprogram was found." error?

I wrote a function inside a package file, and I'm calling it inside the main vhd file. It seems to me everything is correctly in place. But the Sigasi editor says "No matching subprogram was found." at the line where I called the function.
This is the package file content:
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.numeric_std.ALL;
PACKAGE pkg IS
TYPE t IS ARRAY (positive RANGE <>) OF std_logic_vector(7 DOWNTO 0);
FUNCTION char2byte (SIGNAL yazi_char: character) RETURN std_logic_vector;
END pkg;
PACKAGE BODY pkg IS
FUNCTION char2byte (SIGNAL yazi_char: character) RETURN std_logic_vector IS
VARIABLE yazi_byte: std_logic_vector;
BEGIN
case yazi_char is
when '0' => yazi_byte:=x"30";
when '1' => yazi_byte:=x"31";
when '2' => yazi_byte:=x"32";
....
when others =>
end case;
RETURN yazi_byte;
END char2byte;
END pkg;
And this is the main file content:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use WORK.pkg.ALL;
entity rs232 is
port(
clk:in std_logic;
tx_port:out std_logic
);
end rs232;
architecture Behavioral of rs232 is
signal yazi_byte: t;
begin
yazi_byte<=char2byte("y");
process(clk)
begin
....
end process;
end Behavioral;
Where is the fault? The funny thing is, ISE is giving another error, not a "No matching subprogram was found.".
It is:
ERROR:HDLParsers:522 - "D:/UME/FPGA/ise_projeleri/RS232_TEST/pkg.vhd" Line 16. Variable yazi_byte is not constrained.
ERROR:HDLParsers:3304 - "D:/UME/FPGA/ise_projeleri/RS232_TEST/pkg.vhd" Line 16. Can not determine the "others" values in aggregate. (LRM 7.3.2)
Thanks for helping.
You have lots of subtle errors. Some of them noted already, others not. Lets start with types. "y" is a single element string (string(1 to 1)). char2byte requires a character, such as 'y'. As #Brian pointed out, char2byte returns std_logic_vector and not type t (an array of std_logic_vector).
On char2byte you have declared the character input to be a signal. This would mean that you need to map a signal to it and not a literal, such as 'y'. You probably want to declare it as a constant instead (or just leave the class off). In the code below, note the fix to yazi_byte (also noted by #Andy).
FUNCTION char2byte (CONSTANT yazi_char: character) RETURN std_logic_vector IS
VARIABLE yazi_byte: std_logic_vector(7 downto 0) ;
BEGIN
case yazi_char is
when '0' => yazi_byte:=x"30";
when '1' => yazi_byte:=x"31";
when '2' => yazi_byte:=x"32";
....
when others =>
end case;
RETURN yazi_byte;
END char2byte;
Note a clever solution to Char2Byte may use an array of std_logic_vector(7 downto 0) that is indexed by type character (perhaps a project for another day). See #David's post here for an idea: Missing EOF at function. Indexing the array would work similar to a subprogram call.
If you only have char2byte, then your testbench needs to receive a std_logic_vector value (also see #Brian's fix):
architecture Behavioral of rs232 is
signal slv_byte: std_logic_vector(7 downoto 0) ;
begin
slv_byte<=char2byte('y');
If your testbench really needs to work with strings and type t, then a function that takes type string and returns type t, such as the following partially built function would be helpful:
FUNCTION string2slv (yazi_str : string) RETURN t is
variable result : t (yazi_str'range) ;
begin
. . .
end FUNCTION string2slv ;
The problem is that you are confusing a std_logic_vector with t, an array of std_logic_vector.
signal yazi_byte: t;
begin
yazi_byte<=char2byte("y");
...
Now t is an unconstrained array, which allows you to declare ts of different sizes when you use the package. There are two ways to do this :
declare a t and initialise it in the declaration : the initialiser (function call or array aggregate) defines its size. Works for signals but especially useful for constants
constrain it to the size you need in the declaration.
Thus the first example is constrained to be 4 bytes long:
constant deadbeef : t := (X"DE", X"AD", X"BE", X"EF");
And your second example is currently 1 byte long: however you still need to address that byte within it... This is actually why you get the obscure-looking error message.
signal yazi_byte: t(0 downto 0);
begin
yazi_byte(0) <= char2byte("y");
...
VHDL has operator and function overloading, so the compiler is looking for a "char2byte" function that returns an array of std_logic_vector because that's the type of the variable you are assigning to. It can't find one (hence "no matching subprogram") because the only "char2byte" you wrote returns a single std_logic_vector, not an array of them.
So addressing a single element of that array will let it find your char2byte - and now the error message makes perfect sense...
The variable yazi_byte needs to be constrained explicitly, as the error message says. It looks like it has a range of eight bit, so:
VARIABLE yazi_byte: std_logic_vector(7 downto 0);
would work.

Encoding a message with Vigenere cipher in Delphi?

I want to encrypt a message with a simple Vigenere cipher by assigning each letter in the alphabet a numeric value e.g. A= 1; B= 2;..Z= 26. The problem is I don't know which function to use to recognize a character in a string(as it is a message that has to be encoded, complete with spaces), and then giving it a specific, numeric value.
Next up, that numeric message has to be converted into binary, which is easy, but how do I convert that message that was a string into an integer(other that the StrToInt function)?
I just need to know which function to use for the Vigenere Cipher.
*I am still in High school so I apologize in advance for using the wrong terms.
You can use a case statement to perform the encoding.
function EncodedChar(C: Char): Byte;
begin
case C of
'A'..'Z':
Result := 1 + ord(C) - ord('A');
' ':
Result := ???;
',':
Result := ???;
... // more cases here
else
raise ECannotEncodeThisCharacter.Create(...);
end;
end;
Encode a string with a for loop:
function EncodedString(const S: string): TBytes;
var
i: Integer;
begin
SetLength(Result, Length(S));
for i := 1 to Length(S) do begin
// dynamic arrays are 0-based, strings are 1-based, go figure!
Result[i-1] := EncodedChar(S[i]);
end;
end;

Extract first character of each word in MySQL using a RegEx

In my MySQL database I have a column of strings in UTF-8 format for which I want to extract the first character using a RegEx, for example.
Assuming a RegEx which ONLY extracts the following characters:
ਹਮਜਰਣਚਕਨਖਲਨ
And given the following string:
ਹੁਕਮਿ ਰਜਾਈ ਚਲਣਾ ਨਾਨਕ ਲਿਖਿਆ ਨਾਲਿ ॥੧॥
The only characters extracted would be:
ਹਰਚਨਲਨ
I know the following steps would be required to solve this problem:
Break the string into individual words (substrings) by using space as the delimiter
For each word extract the first letter (substring of a substring) if it matches what is in the regex of valid characters
I have looked at all the similar questions/answers on SO and none have been able to solve my problem thus far.
I realy don't know MySql Regex Syntax and restrictions(never used), but you can add leading space before string, and match with something simple like this: " ([ਮਜਰਣਚਕਨਖਲਨ]{1})"
So, if you concatenate matched groups you will have this string "ਰਚਨਲਨ"(only "ਹ" not matched, because it's not exists in sample")
in C# it may look like this(working sample):
namespace TestRegex
{
using System.Linq;
using System.Text.RegularExpressions;
using System.Windows.Forms;
class Program
{
static void Main(string[] args)
{
// leading space(to match first word too)
// + sample string
var sample = " ";
sample += "ਹੁਕਮਿ ਰਜਾਈ ਚਲਣਾ ਨਾਨਕ ਲਿਖਿਆ ਨਾਲਿ ॥੧॥";
// Regex pattern that will math space, and
// if next character in set - add it to "match group 1"
var pattern = " ([ਮਜਰਣਚਕਨਖਲਨ]{1})";
// select every "match group 1" from matches as array
var result = from Match m in Regex.Matches(sample, pattern)
select m.Groups[1];
// concatenate array content into one string and
// show it in message box to user, for example..
MessageBox.Show(string.Concat(result));
}
}
}
in most non-query languages it will be look almost same. For example in php you need to do preg_match_all, and in foreach loop add "$match[i][1]"(every "match group 1") from every match to end of one single string.
well.. pretty simple. but not for mysql...
I finally achieved this with the help of a programmer friend of mine. I directly pasted the following piece of code into the SQL section of my database in PhpMyAdmin:
delimiter $$
drop function if exists `initials`$$
CREATE FUNCTION `initials`(str text, expr text) RETURNS text CHARSET utf8
begin
declare result text default '';
declare buffer text default '';
declare i int default 1;
if(str is null) then
return null;
end if;
set buffer = trim(str);
while i <= length(buffer) do
if substr(buffer, i, 1) regexp expr then
set result = concat( result, substr( buffer, i, 1 ));
set i = i + 1;
while i <= length( buffer ) and substr(buffer, i, 1) regexp expr do
set i = i + 1;
end while;
while i <= length( buffer ) and substr(buffer, i, 1) not regexp expr do
set i = i + 1;
end while;
else
set i = i + 1;
end if;
end while;
return result;
end$$
drop function if exists `acronym`$$
CREATE FUNCTION `acronym`(str text) RETURNS text CHARSET utf8
begin
declare result text default '';
set result = initials( str, '[ੴਓੳਅੲਸਹਕਖਗਘਙਚਛਜਝਞਟਠਡਢਣਤਥਦਧਨਪਫਬਭਮਯਰਲਵੜਸ਼ਖ਼ਗ਼ਜ਼ਫ਼ਲ਼]' );
return result;
end$$
delimiter ;
UPDATE scriptures SET search = acronym(scripture)
Just to explain the last line:
scriptures is the table I want to update
search is a new empty column I created inside the table to store the result
scripture is an existing column inside the scriptures table with all the strings I want to extract from
acronym is the function previously declared which is looking to match the first letter of each word with a character from the RegEx [ੴਓੳਅੲਸਹਕਖਗਘਙਚਛਜਝਞਟਠਡਢਣਤਥਦਧਨਪਫਬਭਮਯਰਲਵੜਸ਼ਖ਼ਗ਼ਜ਼ਫ਼ਲ਼]
So this final line of the code will go through each row of the column scripture, apply the function acronym to it and store the result in the new search column.
Perfect! Exactly what I was looking for :)

function return varray error

I keep getting a error when i run this code, What wrong with the code?
create or replace function f_vars(line varchar2,delimit varchar2 default ',')
return line_type is type line_type is varray(1000) of varchar2(3000);
sline varchar2 (3000);
line_var line_type;
pos number;
begin
sline := line;
for i in 1 .. lenght(sline)
loop
pos := instr(sline,delimit,1,1);
if pos =0 then
line_var(i):=sline;
exit;
endif;
string:=substr(sline,1,pos-1);
line_var(i):=string;
sline := substr(sline,pos+1,length(sline));
end loop;
return line_var;
end;
LINE/COL ERROR
20/5 PLS-00103: Encountered the symbol "LOOP" when expecting one of
the following:
if
22/4 PLS-00103: Encountered the symbol "end-of-file" when expecting
one of the following:
end not pragma final instantiable order overriding static
member constructor map
Stack Overflow isn't really a de-bugging service.
However, I'm feeling generous.
You have spelt length incorrectly; correcting this should fix your first error. Your second is caused by endif;, no space, which means that the if statement has no terminator.
This will not correct all your errors. For instance, you're assigning something to the undefined (and unnecessary) variable string.
I do have more to say though...
I cannot over-emphasise the importance of code-style and whitespace. Your code is fairly unreadable. While this may not matter to you now it will matter to someone else coming to the code in 6 months time. It will probably matter to you in 6 months time when you're trying to work out what you wrote.
Secondly, I cannot over-emphasise the importance of comments. For exactly the same reasons as whitespace, comments are a very important part of understanding how something works.
Thirdly, always explicitly name your function when ending it. It makes things a lot clearer in packages so it's a good habit to have and in functions it'll help with matching up the end problem that caused your second error.
Lastly, if you want to return the user-defined type line_type you need to declare this _outside your function. Something like the following:
create or replace object t_line_type as object ( a varchar2(3000));
create or replace type line_type as varray(1000) of t_line_type;
Adding whitespace your function might look something like the following. This is my coding style and I'm definitely not suggesting that you should slavishly follow it but it helps to have some standardisation.
create or replace function f_vars ( PLine in varchar2
, PDelimiter in varchar2 default ','
) return line_type is
/* This function takes in a line and a delimiter, splits
it on the delimiter and returns it in a varray.
*/
-- local variables are l_
l_line varchar2 (3000) := PLine;
l_pos number;
-- user defined types are t_
-- This is a varray.
t_line line_type;
begin
for i in 1 .. length(l_line) loop
-- Get the position of the first delimiter.
l_pos := instr(l_line, PDelimiter, 1, 1);
-- Exit when we have run out of delimiters.
if l_pos = 0 then
t_line_var(i) := l_line;
exit;
end if;
-- Fill in the varray and take the part of a string
-- between our previous delimiter and the next.
t_line_var(i) := substr(l_line, 1, l_pos - 1);
l_line := substr(l_line, l_pos + 1, length(l_line));
end loop;
return t_line;
end f_vars;
/