I tried everything : to change the data type, to initialize the variables before using them, but nothing worked, what is the problem?
Program Criptmat;
type Matrice = array[1..20,1..20] of char;
var x : Matrice;
s,s1 : string;
i,j,n,k,l : integer;
f,f1 : text;
begin
assign(f,'criptmat.in');
reset(f);
readln(f,n);
readln(f,s);
close(f);
k:=1;
l:=length(s) div n;
for i:=1 to l do
if i mod 2 = 1 then
for j:=1 to n do
begin
x[i,j]:=s[k];
k:=k+1;
end else
if i mod 2 = 0 then
for j:=n downto 1 do
begin
x[i,j]:=s[k];
k:=k+1;
end;
s1:='';
for j:=1 to n do
for i:=1 to l do
s1:=s1+x[i,j];
assign(f1,'criptmat.out');
rewrite(f1);
writeln(f1,s1);
close(f1);
end.
Please, help me to fix this error to avoid this kind of mistake in the future, thank you!
Error 216 in fpc is an access violation or segment fault, depending on your preferred terminology. This happens when you try to access a memory address that is not valid. Typically that happens when you attempt to access an array outside of its bounds, or access dynamically allocated memory that has already been deallocated.
In your case it is likely that you are accessing the array out of bounds. Use the debugger to locate the point of failure, and inspect the value of your indices at that point of execution. This will tell you which access is invalid, and then you can set about fixing the logic errors that lead to the out of bounds access.
A useful tool to help such debugging is to enable the range checking compilation option. This will inject runtime code to validate every array access. You will find it much easier to debug these faults with that enabled.
Related
How can I throw standard system exceptions (and if possible, create custom exceptions and throw them too).
The simplest thing that comes to mind, is to just divide a variable by zero, but that's just a hack at best.
I did find mentions of a function AppGenerateException in the CmpApp library, but I can't find any documentation for it, nor any examples. Can anybody point me to some documentation for this?
Out of curiosity I checked the AppGenerateException and got it working. Got some help from this Codesys help page.
I still think this is not the best way to achieve what you need, but it could work.
Unfortunately, I have 64 bit system and the TRY..CATCH is not yet working in other that 32 bit systems as far as I know, so I couldn't test catching.
Add the following libraries:
CmpApp
SysExcept
Then the following code seems to work. Set ThrowErr to true to get the system exception.
PROGRAM PRG_TestThrow
VAR CONSTANT
MY_PRIVATE_EXCEPTION : DWORD := 32001;
END_VAR
VAR
ThrowErr : BOOL; //Set this to TRUE to throw an error
//The next two are for getting App instance
_pApp : POINTER TO CmpApp.APPLICATION;
_Result : SysExcept.SysTypes.RTS_IEC_RESULT;
END_VAR
//Get App instance
_pApp := AppGetCurrent(pResult := ADR(_Result));
IF ThrowErr THEN
ThrowErr := FALSE;
IF _pApp <> 0 THEN
//Throw divide by zero exception
AppGenerateException(pApp:=_pApp, ulException:=RtsExceptions.RTSEXCPT_DIVIDEBYZERO);
//You could use probably any available number as your own custom exception.
//For example the following works BUT not sure if it's ok to this.
//AppGenerateException(pApp:=_pApp, ulException:=MY_PRIVATE_EXCEPTION);
//See RtsExceptions type for available exception codes.
//For my Codesys version, it has largest exception number of 0x2000 so all larger number are free (for now...)
END_IF
END_IF
It seems that it's possibly to use any custom exception code like:
AppGenerateException(pApp:=_pApp, ulException:=MY_PRIVATE_EXCEPTION);
But it's not documented so I would be careful.
So I'm just starting to learn Eiffel. One of the first exercises in the book I'm using says to make a function that does base^exp without using ^. I've copied my code below.
class
APPLICATION
inherit
ARGUMENTS
create
make
feature {NONE} -- Initialization
make
-- Run application.
do
create power(2;3)
printf("2 to the power of 3 is " + answer)
end
power(base : REAL; exp : INTEGER) : REAL
-- computers base raised to the bower of exp without using ^
local
remain : INTEGER
do
remain := exp
if remain = 0 then
result := 1
else
from
until
remain = 0
loop
result := result * result
remain := remain -1
end
end
end
end
How do I use this? Do I need it on the same level as feature{NONE}'s make? I know how I'm calling it is wrong, and I can't find anything in the chapter I just read, or online on how to pass parameters into it or how to use it's results.
There are several issues with the original code:
create is used to create an object, but you are not going to create anything, but to get a result of a computation of the function power by calling it. Therefore the keyword create is not needed.
You are using an entity answer to report the result of evaluation on a screen. However it is not declared anywhere. I believe the proper place would be a local variable declaration section.
The entity answer is not initialized to the result of the function power. This is usually done by an assignment instruction.
Feature arguments are separated by a comma, not by a semicolon.
From the original code it's unclear what is the type of the variable answer. Assuming it matches the type of the function power, before adding it to a string, it needs to be converted to a string. This is done by calling the feature out.
The standard feature for printing a string to a console is print, not printf.
Combining the critical points above, we get
make
-- Run application.
local
answer: REAL
do
answer := power(2, 3)
print ("2 to the power of 3 is " + answer.out)
end
After that the code can be compiled. Now less critical points:
It is a good style to put features to a dedicated feature clauses, so I would add a line like feature -- Basic operations before the feature power.
The implementation of the feature power has at least two problems. I'm not going to detail them here, but would give two hints instead:
by default numeric Result is initialized to 0, this needs to be taken into account for operations that use it without first assigning any other value
even though an argument base is passed to the function power it remains unused in the original version of the code
I am still learning from the DLL process and since no Delphi FTDI Libmpsse library exist, I must work my own way through with the DLL from scratch.
However, I'm far from perfect in Delphi!
I've been using it for few years without touching pointers.
This is the particular line I'm now stuck with (This is what I've tried to translate):
function I2C_DeviceWrite(
handle :dword;
deviceAddress :uint32;
sizeToTransfer :uint32;
out buffer :byte;
out sizeTransferred :uint32;
options :uint32
):FT_Result; cdecl; external 'libmpsse.dll';
From the API User guide it is describe the C way like this:
FT_STATUS I2C_DeviceWrite(
FT_HANDLE handle,
uint32 deviceAddress,
uint32 sizeToTransfer,
uint8 *buffer,
uint32 *sizeTransferred,
uint32 options )
Asterix means pointer in C from what I understand.
I don't know how to declare them properly yet.
Any hints?
NB: I'm still reading (XE2 Foundations) and searching about pointers and buffers the most I can!
Thank you!
BTW, API Guide is here for consulation:PDF from FTDI
EDIT:
var
Buffer: array of Byte;
written,towrite:cardinal;
begin
SetLength(Buffer,I2C_DEVICE_BUFFER_SIZE);
buffer[0] := $07;
towrite := 1;
i2c_openchannel(1,FT_HANDLE); //open channel 1
i2c_initchannel(FT_HANDLE,I2C_CLOCK_STANDARD_MODE and LATENCY_TIMER and 0);
i2c_devicewrite(FT_HANDLE,I2C_DEVICE_ADDRESS,towrite,buffer,written,I2C_TRANSFER_OPTIONS_START_BIT);
i2c_closechannel(FT_HANDLE); //close device
So far so good everything else work except the i2c_devicewrite line!It gives me E2033:unable to compile actual and formal var parameters must be identical
You've translated the byte array parameter incorrectly. You used
out buffer: byte
which is a single byte, passed out by reference. It should be
buffer: PByte
which here means a pointer to array of byte.
Then pass the address of the first element of the array. Like this:
#Buffer[0]
or like this
PByte(Buffer)
Note that I've not checked anything other than the byte array parameter.
FWIW, a constant length array may be simpler here than a dynamic array.
I'd also comment that you appear to be ignoring return values. Never do that. Always check return values for errors.
I'm just starting in Julia after a strong background in C++. I'm having an issue with my integer variables being reset to what I initialized them as in the beginning of my program.. even though I changed the variable value inside a function. Can anyone explain why this is?
num = 0
function getNum()
num = 1
end
getNum()
num #this returns 0, not 1
This is a problem because I will need to reference that variable in another function.
num is in global scope (note that the same behavior applies in e.g. Python)
If necessary, you could modify it by referencing as a global:
function getNum()
global num = 1
end
However, it is worth considering whether there is a more effective way to structure your code. Global variables can be useful in some situations, but they can also make code more difficult to reason about.
I'm new to Free Pascal and Lazarus. I'm testing out the new "advanced records" feature and getting what looks to be an unnecessary compiler warning.
The code is very simple, just a record with a single method to initialize the data fields. Something like:
{$mode delphi}
type TTest =
record
a,b: double;
procedure Init(x,y: double);
end
procedure TTest.Init(x,y: double);
begin
test.a := x;
test.b := y;
end;
var t: TTest;
begin
t.Init(0.1,0.2);
That last line shown, "t.Init()", always generates a compiler warning that 'variable "t" does not seem to have been initialized'.
Ok it's only warning, so obviously I can live with it, but I just want to make sure it's not due to some underlying misunderstanding on my part.
EDIT to add new information.
Re the Method verus Constructor point.
Looking into this some more I'm kind of glad that FPC doesn't allow constructors for records. Delphi has constructors but no destructors, and as far as I can tell constructors (for records) do absolutely nothing that a method couldn't do. I'm a minimalist, so to me there is no point to have extra syntax that does nothing more than some existing syntax does.
Particularly for a simple record like this, the very act of declaring it (var t: TTest) does all the "constructing" that this record needs. Anything else (like my Init) is just setting values, it's not constructing anything anyway. So as far as I can see constructors are not the answer, the compiler just needs to drop the warning.
Researching the issue I have come across one other technique that is often used, the so called "factory function". That is, a function outside of the record such as:
function InitTTest(x,y: double): TTest;
begin
Result.a := x;
Result.b := y;
end;
This technique does indeed work, and gets rid of the warning message. I don't like this method however and I wont use it. Advanced records don't have inheritance and other features of classes, encapsulation is all they've got going for them. So I really dislike having to make a "factory function" outside of the record like this.
Please bear in mind the the above is just the opinion of a "noob", after doing just a little research to answer my own question here. So if I'm wrong about anything above I'm quite happy to be corrected. :)
Yes, that is what constructors are for, the following compiles with FPC trunk and produces no warnings:
{$mode delphi}
type TTest =
record
a,b: double;
constructor Init(x,y: double);
end;
constructor TTest.Init(x,y: double);
begin
a := x;
b := y;
end;
var t: TTest;
begin
t.Init(0.1,0.2);
end.