I'm writing assembler for imaginary processor of my design (kinda like DCPU-16) and I want to include all major number bases. I've got hex,bin and dec, but I cannot get oct, because there seem to be no OctToInt function. Any help?
function OctToInt(Value: string): Longint;
var
i, int: Integer;
begin
int := 0;
for i := 1 to Length(Value) do
int := int * 8 + StrToInt(Copy(Value, i, 1));
Result := int;
end;
Related
When creating a procedural data type, Free Pascal throws a strange error. But I'm passing one parameter, why is the number of parameters incorrect?
Type
Func = Function (x:Real):Real;
Function middlfunc(a, b:Real; n:Integer; f:Func): Real;
Var
x,s,d: Real; k:Integer;
Begin
d:=(b-a)/n;
s:=0;
For k:=0 To n Do
Begin
x:=a+k*d;
s:=s+f(x);
End;
middlfunc:=s/(n+1);
End;
Function f1(x:Real):Real; {There is the error}
Begin
f1:=x*x;
End;
Var
mf1:Real;
a, b: real;
n: integer;
Begin
a := 0;
b := 3.1415;
n := 100;
mf1 := middlfunc(a,b,n,f1); {ERROR :((((((((}
WriteLn(mf1)
End.
USE PASCAL PROCEDURE INSTEAD OF FUNCTION for suitability
If you want to use a Function as a parameter to another function, then you have to do it like this:
Type
TFunctionParameter = function(x: Real): Real;
Function middlfunc(a, b:Real; n:Integer; f:TFunctionParameter): Real;
Var
x,s,d: Real; k:Integer;
Begin
d:=(b-a)/n;
s:=0;
For k:=0 To n Do
Begin
x:=a+k*d;
s:=s+f(x);
End;
middlfunc:=s/(n+1);
End;
function RaiseToSecondPower(x: Real): Real;
begin
result := x*x;
end;
Var
mf1:Real;
a, b: real;
n: integer;
Begin
a := 0;
b := 3.1415;
n := 100;
mf1 := middlfunc(a,b,n,RaiseToSecondPower);
WriteLn(mf1)
End.
Huge amount of numeric data (from a database) is stored in a Tstringlist variable. the Data may look like:
4
4 1/2
12.006
13 3/8
1.05
13.25
5 1/2
2.25
13 5/8
By setting the sort property of the Tstringlist to true, they are sorted as texts and as a result, 13.25 shows up before 4.
How can these data be sorted numerically (and efficiently)?
(Delphi, Rad Studio 10.4)
Here is a solution:
// Conversion accepting input like '4', '4.003', '4 1/2' or '1/4'
// No leading or trailing space allowed (use trim if required).
function MyStrToFloat(const S : String) : Double;
var
I, J : Integer;
FS : TFormatSettings;
begin
I := Pos('/', S);
if I > 0 then begin
// We have a fractional part
J := Pos(' ', S);
if J > 0 then
// Both integer and fractional parts
Result := StrToInt(Trim(Copy(S, 1, J - 1)))
else
Result := 0;
Result := Result + StrToInt(Trim(Copy(S, J + 1, I - J - 1))) /
StrToInt(Trim(Copy(S, I + 1)));
end
else begin
FS.DecimalSeparator := '.';
Result := StrToFloat(S, FS);
end;
end;
function StringListSortProc(
List : TStringList;
Index1 : Integer;
Index2 : Integer): Integer;
var
N1, N2: Double;
begin
N1 := MyStrToFloat(List[Index1]);
N2 := MyStrToFloat(List[Index2]);
if N1 > N2 then
Result := 1
else if N1 < N2 then
Result := -1
else
Result := 0;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
SL : TStringList;
S : String;
begin
SL := TStringList.Create;
try
SL.Add('4');
SL.Add('1/2');
SL.Add('4 1/2');
SL.Add('12.006');
SL.Add('13 3/8');
SL.Add('1.05');
SL.Add('13.25');
SL.Add('5 1/2');
SL.Add('2.25');
SL.Add('13 5/8');
Memo1.Lines.Add('Raw:');
for S in SL do
Memo1.Lines.Add(S);
SL.CustomSort(StringListSortProc);
Memo1.Lines.Add('Sorted:');
for S in SL do
Memo1.Lines.Add(S);
finally
SL.Free;
end;
end;
The conversion is done in the sorting which is not very efficient. It is probably better to create a new list with converted values and then sort it. Or convert when loading the list from database. You've got the idea...
Two components solve your problem:
StrCmpLogical is your friend. It uses Natural sorting - Digits in the strings are considered as numerical content rather than text.
And this SO post How do I enter fractions in Delphi?
I put it together below:
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;
type
TForm1 = class(TForm)
Memo1: TMemo;
ButtonSort: TButton;
Memo2: TMemo;
procedure ButtonSortClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
//Natural sorting - Digits in the strings are considered as numerical content rather than text. This test is not case-sensitive.
function StrCmpLogicalW(P1, P2: PWideChar): Integer; stdcall; external 'Shlwapi.dll';
function StrCmpLogical(const S1, S2: string): Integer;
var
Form1: TForm1;
implementation
{$R *.dfm}
function StrCmpLogical(const S1, S2: string): Integer;
begin
result := StrCmpLogicalW(PChar(S1), PChar(S2));
end;
function CustomNbrSort(List: TStringList; Index1, Index2: Integer): Integer;
begin
result := StrCmpLogical(List[index1], List[index2]);
end;
procedure DoCustomSort(const List : TStringList);
begin
List.CustomSort(CustomNbrSort);
end;
// https://stackoverflow.com/questions/18082644/how-do-i-enter-fractions-in-delphi
function FractionToFloat(const S: string): real;
var
BarPos: integer;
numStr, denomStr: string;
num, denom: real;
begin
BarPos := Pos('/', S);
if BarPos = 0 then
Exit(StrToFloat(S));
numStr := Trim(Copy(S, 1, BarPos - 1));
denomStr := Trim(Copy(S, BarPos + 1, Length(S)));
num := StrToFloat(numStr);
denom := StrToFloat(denomStr);
result := num/denom;
end;
function FullFractionToFloat(S: string): real;
var
SpPos: integer;
intStr: string;
frStr: string;
int: real;
fr: real;
begin
S := Trim(S);
SpPos := Pos(' ', S);
if SpPos = 0 then
Exit(FractionToFloat(S));
intStr := Trim(Copy(S, 1, SpPos - 1));
frStr := Trim(Copy(S, SpPos + 1, Length(S)));
int := StrToFloat(intStr);
fr := FractionToFloat(frStr);
result := int + fr;
end;
procedure TForm1.ButtonSortClick(Sender: TObject);
begin
var MyList : TStrings := TStringList.Create;
try
//MyList.Assign(Memo1.Lines);
var MyFormatSettings : TFormatSettings := FormatSettings; //Make a copy of the global variable;
MyFormatSettings.DecimalSeparator := '.'; //The system's seporator may be a comma ','
for var i : integer := 0 to Memo1.Lines.Count - 1 do begin
var s : string := Memo1.Lines[i];
if not s.Contains('.') then
s := FloatToStr(FullFractionToFloat(s), MyFormatSettings);
MyList.AddObject(s, TObject(i));
end;
TStringList(MyList).CustomSort(CustomNbrSort);
Memo2.Lines.Clear;
for var i : integer := 0 to Memo1.Lines.Count - 1 do
Memo2.Lines.Add(Memo1.Lines[Integer(MyList.Objects[i])]);
finally
MyList.Free;
end;
end;
end.
Following is a program in lazarus to perform RC4 encryption and decryption when given a string. When the compiler directive {$mode fpc} is used and the string 123 is entered it crashes with External: SIGSEGV. However there is no crash when inputting the same string in {$mode objfpc}. Another inconsistency is that in {$mode objfpc} the program raises the exception External: SIGSEGV again with the input of hellow.
//{$mode fpc}
{$mode objfpc}
program project1;
uses
sysutils, strutils;
type
myArray = array[0..255] of integer;
dynamicArray = array of integer;
dynamicArrayString = array of string;
const
key = 'qwertyui';
var
plaintext : string;
function KSA(const key: string): myArray;
var
i, j, key_length, temp: integer;
S : myArray;
begin
key_length := length(key);
j := 0;
for i := Low(S) to High(S) do
S[i] := i;
for i := Low(S) to High(S) do
begin
j := ((j + S[i] + ord(key[i mod key_length + 1])) mod 256);
temp := S[i];
S[i] := S[j];
S[j] := temp;
end;
KSA := S;
end;
function PRGA(S : myArray; n : integer) : dynamicArray;
var
i, j, K, temp, sizeOfArray : integer;
key : dynamicArray;
begin
i := 0;
j := 0;
K := 0;
temp := 0;
sizeOfArray := n - 1;
SetLength(key, sizeOfArray);
while n > 0 do
begin
n := n - 1;
i := (i + 1) mod 256;
j := (j + S[i]) mod 256;
temp := S[i];
S[i] := S[j];
S[j] := temp;
K := S[(S[i] + S[j]) mod 256];
key[i-1] := K;
end;
PRGA := key;
end;
procedure getPlaintext;
begin
readln(plaintext);
end;
function encrypt : string;
var
sizeOfArray, i : integer;
cipherString : string;
cipher, keystream: dynamicArray;
S : myArray;
begin
S := KSA(key);
keystream := PRGA(S, length(plaintext));
sizeOfArray := 0;
for i := 0 to (length(plaintext) - 1) do
begin
sizeOfArray := sizeOfArray + 1;
SetLength(cipher, sizeOfArray);
cipher[i] := (keystream[i]) xor (ord(plaintext[i + 1]));
end;
cipherString := '';
for i := 0 to High(cipher) do
cipherString := cipherString + IntToHex(cipher[I], 2);
encrypt := cipherString;
end;
function stringToHex(cipherString : string) : dynamicArrayString;
var
sizeOfArray, i: integer;
DecryptArrayString : dynamicArrayString;
begin
sizeOfArray := 0;
i := 0;
// Turn the string into an array of hex
while length(cipherString) > 0 do
begin
sizeOfArray := sizeOfArray + 1;
SetLength(DecryptArrayString, sizeOfArray);
DecryptArrayString[i] := cipherString[1] + cipherString[2];
i := i + 1;
cipherString := rightstr(cipherString, length(cipherString) - 2);
end;
stringToHex := DecryptArrayString;
end;
function hexToDecimal(DecryptArrayString : dynamicArrayString) : dynamicArray;
var
sizeOfDecryptArrayInt, i : integer;
DecryptArrayInt : dynamicArray;
begin
sizeOfDecryptArrayInt := 0;
// Hex to decimal
for i := 0 to high(DecryptArrayString) do
begin
sizeOfDecryptArrayInt := sizeOfDecryptArrayInt + 1;
SetLength(DecryptArrayInt, sizeOfDecryptArrayInt);
DecryptArrayInt[i] := Hex2Dec(DecryptArrayString[i]);
end;
hexToDecimal := DecryptArrayInt;
end;
function decrypt(DecryptArrayInt : dynamicArray) : string;
var
DecryptedString : string;
S : myArray;
keystream, Decrypted : dynamicArray;
sizeOfArray, i : integer;
begin
sizeOfArray := 0;
for i := 0 to high(DecryptArrayInt) do
begin
sizeOfArray := sizeOfArray + 1;
SetLength(Decrypted, sizeOfArray);
S := KSA(key);
keystream := PRGA(S, length(plaintext));
Decrypted[i] := (keystream[i] xor DecryptArrayInt[i]);
end;
decryptedString := '';
// Turn array to string
for i := 0 to high(Decrypted) do
decryptedString := decryptedString + chr(Decrypted[i]);
decrypt := decryptedString;
end;
procedure encryptDecrypt;
var
cipherString, DecryptedString : string;
DecryptArrayString : dynamicArrayString;
DecryptArrayInt : dynamicArray;
begin
cipherString := encrypt;
writeln(cipherString);
DecryptArrayString := stringToHex(cipherString);
DecryptArrayInt := hexToDecimal(DecryptArrayString);
DecryptedString := decrypt(DecryptArrayInt);
writeln(DecryptedString);
end;
begin
getPlaintext;
encryptDecrypt;
readln;
end.
I've not been able to find the many specific cases that makes the program crash apart from a string of any three characters will always crash in {$mode fpc} but not in {$mode objfpc}
You should debug (and watch) your code so any error can be traced more easily. Use the FP IDE, it helps a lot.
Meanwhile, watch this line:
keystream := PRGA(S, length(plaintext));
And inside the PRGA function watch these lines:
sizeOfArray := n - 1;
SetLength(key, sizeOfArray);
What's wrong here? Well, suppose "plaintext" has only 1 character. So, "Length(plaintext)"=1, right? In PRGA you do "sizeOfArray:= n-1;", so sizeOfArray = 0. When you do SetLength, "Key" will be NIL because you're indicating a zero indexes length. Later, on loop, you have:
key[i-1] := K;
the program will fail because you are accessing at index 0 and the Key variable is NIL.
Careful: On "SetLength(key, sizeOfArray);" valid indexes for key are in range [0..sizeOfArray-1], but sizeOfArray must be at least 1 to be valid (sizeOfArray >= 1).
So, you should check your PRGA function. It's up to you to find the definitive solution. Don't give up. Good luck!
I know Delphi for almost a month,
I have found a function code that change the color of the gray-scale by changing the color weights, I would like to ask, is there a faster way than this code for changing color or weighting the color?
function tform1.changecolorweighting(coloredbmp:tbitmap):tbitmap;
Var
X, Y: Integer;
P : TColor;
r,g,b: byte;
RP,GP,BP:single;
changegray:tbitmap;
changecolor:tbitmap;
begin
x:=RedWeight.value+GreenWeight.value+BlueWeight.value;
RP:=RedWeight.value/x;
GP:=Greenweight.value/x;
BP:=BlueWeight.value/x;
changegray := tbitmap.Create;
changegray.Width := coloredbmp.Width;
changegray.Height := coloredbmp.Height;
changecolor.Assign(coloredbmp);
For X := 0 to changecolor.Width do
begin
For y := 0 to changecolor.Height do
begin
P := changecolor.Canvas.Pixels[X, Y];
r := (P and $00000FF);
g := (P and $00FF00) shr 8;
b := (P and $FF0000) shr 16;
changegray.Canvas.Pixels[X, Y] := round(r * RP + g * GP + b*BP) * $010101;
end;
end;
result := changegray;
end;
if there is someone of you has a faster way of changing the color weights, please correct the code that I have found in the internet, or if you have something to offer faster than that code, please help.
The code above, it takes 1 second before the gray-scale applied with the color weighting.
thank you
This is the answer that I'm looking for, it's from Embarcadero:
https://community.embarcadero.com/blogs/entry/converting-to-grayscale-with-tbitmapscanline-property-39051
procedure ToGray(aBitmap: Graphics.TBitmap; redweightvalue,greenweightvalue,blueweightvalue:integer);
var w, h: integer; CurrRow, OffSet: integer;
x: byte; pRed, pGreen, pBlue: PByte;
function RGBToGray(R, G, B: byte): byte;
var x:integer;
RP,GP,BP:single;
begin
x:=redweightvalue+greenweightvalue+blueweightvalue;
RP:=redweightvalue/x;
GP:=greenweightvalue/x;
BP:=blueweightvalue/x;
//Result := round(0.2989*R + 0.5870*G + 0.1141*B); // coeffs from Matlab
Result := round(rp*R + gp*G + bp*B);
end;
begin
if aBitmap.PixelFormat <> pf24bit then exit;
CurrRow := Integer(aBitmap.ScanLine[0]);
OffSet := Integer(aBitmap.ScanLine[1]) - CurrRow;
for h := 0 to aBitmap.Height - 1 do
begin
for w := 0 to aBitmap.Width - 1 do
begin
pBlue := pByte(CurrRow + w*3);
pGreen := pByte(CurrRow + w*3 + 1);
pRed := pByte(CurrRow + w*3 + 2);
x := RGBToGray(pRed^, pGreen^, pBlue^);
pBlue^ := x;
pGreen^ := x;
pRed^ := x;
end;
inc(CurrRow, OffSet);
end;
end;
this is my simple code to generate
all possible combinations of a set for
example
1,2,3:
Display:
123
132
213
231
312
321
i want to create variable number of for loops to let the user determine the length of given string...
does anyone have an idea...
thank's in advance.
type
TNumber = '0'..'9';
procedure TForm1.Button1Click(Sender: TObject);
var
Numbers: array[0..3] of TNumber;
a, b, c, d: Integer;
s: string;
begin
Numbers[0] := '1';
Numbers[1] := '8';
Numbers[2] := '7';
Numbers[3] := '2';
for a := low(Numbers) to High(Numbers) do
for b := low(Numbers) to High(Numbers) do
for c := low(Numbers) to High(Numbers) do
for d := low(Numbers) to High(Numbers) do
begin
s := Numbers[a] + Numbers[b] + Numbers[c] + Numbers[d];
if
(Occurrences('1', s) > 1 ) or
(Occurrences('8', s) > 1 ) or
(Occurrences('7', s) > 1 ) or
(Occurrences('2', s) > 1 )
then
Continue
else
Memo1.Lines.Add(s);
end;
end;
function TForm1.Occurrences(const Substring, Text: string): Integer;
var
Offset: Integer;
begin
Result := 0;
Offset := PosEx(Substring, Text, 1);
while Offset <> 0 do
begin
Inc(Result);
Offset := PosEx(Substring, Text, offset + length(Substring));
end;
end;
end.
Here is some code that produces the output you desire. You'd need to work it around a bit for your needs, but the concept expressed in this recursive solution is the important thing:
program Permuatations;
{$APPTYPE CONSOLE}
type
TElements = '1'..'3';
procedure EnumerateCombinations(const Stem: string; Len: Integer);
var
i: Integer;
el: TElements;
Used: set of TElements;
begin
if Len=0 then
exit;
Used := [];
for i := 1 to Length(Stem) do
Include(Used, Stem[i]);
for el := low(el) to high(el) do
begin
if el in Used then
continue;
if Len=1 then
Writeln(Stem+el)
else
EnumerateCombinations(Stem+el, Len-1)
end;
end;
procedure Main;
begin
EnumerateCombinations('', 1+ord(high(TElements))-ord(low(TElements)));
end;
begin
Main;
Readln;
end.
Output:
123
132
213
231
312
321
If you change the definition of TElements, for example to '1'..'4' then you will see the 24 possible permutations.