Combobox value to code - combobox

I'm a Pascal newbie and I already read some stuff about it, but it is still pretty hard for me. I want to create a simple password generator, and adjust the number of characters.
I found a function that actually generates the random password for me, which is this:
function RandomPassword(PLen: Integer): string;
var
str: string;
begin
Randomize;
//string with all possible chars
str := 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890';
Result := '';
repeat
Result := Result + str[Random(Length(str)) + 1];
until (Length(Result) = PLen)
end;
This is the code that prints the string to the Memo:
procedure TForm1.Button2Click(Sender: TObject);
begin
Memo1.Caption := RandomPassword(10);
end;
I also got a TComboBox, and I want to use the value from the combobox to chose the number of characters (6-32). The number of characters is in this case 10 but I want to use the value from the Combobox instead of a predetermined number. Who can help me? I'd appreciate it!

You can select the combobox value like this:
RandomPassword(StrToInt(ComboBox.Items[ComboBox.ItemIndex]))
ComboBox.ItemIndex returns the index of select combobox item
ComboBox.Items[] is used to select a item in the combobox.
StrToInt() is used cause the combobox value is a string and you have to change it to integer

Related

Different results on printing the values of array

I am writing a stored procedure that accepts a string as an input and then converts that string to an array with comma as a delimiter, once I have that array I am appending a string '_1' to each element of the array as I need to further utilize that. However when I execute this stored proc to find the result the raise info command behaves differently on printing the value of array (the values will change obviously but the format in which they are displayed changes)
CREATE OR REPLACE FUNCTION Test1(inputlist text) RETURNS text AS $BODY$
DECLARE
a text;
acceptList text[];
counter integer;
length integer;
BEGIN
acceptList = string_to_array(inputList,',');
SELECT array_length(acceptList,1) into length;
RAISE INFO 'Length : %',length;
RAISE INFO 'AcceptList Print 1 : %',acceptList;
counter = 0;
FOREACH a in ARRAY acceptList LOOP
acceptList[counter] = a||'_1';
counter = counter + 1;
END LOOP;
RAISE INFO 'AcceptList Print 2 : %',acceptList;
END;
$BODY$
LANGUAGE plpgsql;
The output in messages tab would be :
INFO: Length : 4
INFO: AcceptList Print 1 : {INC000073535133,INC000073533828,INC000073535942,INC000073535857}
INFO: Acceptlist Print 2 : [0:4]={INC000073535133_1,INC000073533828_1,INC000073535942_1,INC000073535857_1,INC000073535857}
If you notice in the above output the values are appended correctly however, in the print 2 it is showing the size as well as an equal to symbol before printing the values of array
Want to understand why such behavior is seen
By default, arrays in Postgres are indexed from 1, while in the function body the first index of the modified array is 0. As a result, the original array has been extended by one element. The notation [0:4] = {...} means a five-element array with the non-standard first index of 0. Of course, this could be fixed in a simple way:
...
counter = 1;
FOREACH a in ARRAY acceptList LOOP
...
However, note the comment by horse_with_no_name that indicated how this should be done in Postgres with a single query:
select string_agg(concat(t.element, '_1'), ',' order by t.nr)
from unnest(string_to_array('one,two,three',',')) with ordinality as t(element, nr);
Read about arrays in the documentation.

Dynamic array of string skips the first index

I am doing a program in which the user inputs the wage, name and the number of working hours per month for a certain number of employees. This piece of code is supposed to recieve Nemp employees and then ask for Nemp names. The problem is, it always skips the first name, it displays 'Employee name:' twice and doesn't allow the user to insert the first one. I don't understand why this is happening, any help would be greatly appreciated!
program test;
uses crt;
var
i, Nemp : integer;
employee: array of string;
BEGIN
read(Nemp);
SetLength (employee, Nemp);
for i:=1 to Nemp do
Begin
writeln ('Employee name: ');
readln (employee[i]);
end;
END.
Dynamic arrays are zero based. You should loop from zero to Nemp-1. Or loop from zero to High(employee).
And as #Rudy and #trincot points out, to read the length of the employee array, use ReadLn(Nemp) to avoid unwanted input effects.
A tip:
Enable range and overflow check in the compiler when debugging. That would have detected the error at the high range.

Warning: function result variable of a managed type does not seem to be initialized

The task I have requires me to create two routines one of which reads in data from a terminal and the other outputs data to the terminal, and another two routines which utilize an array to loop through these two routines to perform them multiple times.
The issue I am having is that the terminal crashes after one run through of the ReadComputer function instead of looping multiple times. The compiler is also providing me the following warning:
"Warning: function result variable of a managed type does not seem to be initialized"
although after extensive research and due to the fact that no one uses pascal I cannot find a solution. Any help is much appreciated! :)
I have provided a copy of my code here for reference:
program CompupterProgram;
uses TerminalUserInput;
type
Computer = Record
id: integer;
manafacturer: String;
year: integer;
warranty: integer;
end;
type Computers = Array of Computer;
function ReadComputer(): Computer;
begin
ReadComputer.id := ReadInteger('PLease Enter Computer Id:');
ReadComputer.manafacturer := ReadString('PLease Enter Computer Manafacturer:');
ReadComputer.year := ReadInteger('PLease Enter Computer Year:');
ReadComputer.warranty := ReadInteger('PLease Enter Computer Warranty:');
result := ReadComputer;
end;
procedure WriteComputer(c: Computer);
begin
WriteLn('Computer ID: ', c.id);
WriteLn('Computer Manafacturer ', c.manafacturer);
WriteLn('Computer Year ', c.year);
WriteLn('Computer Warranty ', c.warranty);
ReadLn();
end;
function ReadAllComputers(count: Integer): Computers;
var i: Integer;
begin
for i := 0 to count do
begin
ReadAllComputers[i] := ReadComputer();
end;
result := ReadAllComputers;
end;
procedure WriteAllComputers(computerArray: Computers);
var i: Integer;
begin
for i:= 0 to (length(computerArray)) do
begin
WriteComputer(computerArray[i]);
end;
end;
procedure Main();
var computers: Array of Computer;
index: Integer;
begin
computers := ReadAllComputers(3);
WriteAllComputers(computers);
end;
begin
Main();
end.
Computers is a dynamic array, and you need to set its length before use in ReadAllComputers with SetLength().
All dynamic arrays are zero based, so you need to count from zero to Length(aDynArray)-1 in a couple of places. Or use the High(aDynArray) function to express the highest possible value of it's index.
Note: The Result use in ReadComputer is superfluous. Either use the function name or the Result variable to return the function result. The latter is to prefer, since code will be more clear.
In freepascal the Result variable is defined only in ObjFPC or Delphi mode.

Delphi TFloatField.DisplayFormat for numeric fields less than 1.0

This is my procedure.
procedure format_integer_field(Atable: TDataSet);
var i: integer;
begin
if Atable.Active then
if Atable.FieldCount > 0 then
with Atable do
begin
for i:= 0 to FieldCount-1 do
if (Fields[i] is TIntegerField) then
begin
(Fields[i] as TIntegerField).DisplayFormat := '###,###';
(Fields[i] as TIntegerField).EditFormat := '#';
end
else
if (Fields[i] is TFloatField) then
begin
(Fields[i] as TFloatField).DisplayFormat := '###,###.##';
(Fields[i] as TFloatField).EditFormat := '#.##';
end;
end;
end;
This is work fine until a number like "0.9" has been entered and result will be ".9".
How can I have thousand separator and zero before floating point that smaller than "1".
Try (Fields[i] as TFloatField).DisplayFormat := '##0,000.00';
As you did read in documentation at http://docwiki.embarcadero.com/RADStudio/XE3/en/Using_Default_Formatting_for_Numeric,_Date,_and_Time_Fields it says
Default formatting is performed by the following routines:
FormatFloat -- TFloatField, TCurrencyField
And how you did read in the following documentation pages
http://docwiki.embarcadero.com/Libraries/XE3/en/System.SysUtils.FormatFloat
http://docwiki.embarcadero.com/Libraries/XE3/en/Data.DB.TNumericField.DisplayFormat
the documentation quotes
0 -> Digit placeholder. If the value being formatted has a digit in the position where '0' appears in the format string, then
that digit is copied to the output string. Otherwise, a '0' is
stored in that position in the output string.
# -> Digit placeholder. If the value being formatted has a digit in the position where '#' appears in the format string, then
that digit is copied to the output string. Otherwise, nothing is
stored in that position in the output string.
So by using "#" in the formatting pattern you tell Delphi "i do not need any digits (and thousands separators with them) in this place, but you might put them if you want" - and since Delphi does not want to put leading zeros - you don't have any. However, if you really need those digits and the thousands separator with them, you put "0" instead of "#" and that way you tell Delphi "the digits just need to be here, whether you want to put them or not"
The format you need is ###,##0.0#

Free Pascal keep numbers in array

i don't know how to do this:
I want to do a program in pascal in which the user have to insert 90 numbers introduced by console and separated by a blank and keep them in a bidimensional array (10x9). Anyone knows how to implement this?
Thanks a lot.
var the_array:array[1..10] of array[1..9] of integer;
var i:integer; var j:integer;
...
i:=1; j:=1;
while i<=10 do begin
while j<=9 do begin
read(the_array[i,j]);
inc(j);
end;
j:=1;
inc(i);
end;
You just use two indices to iterate through an array while filling it from calling read().
You wrote that you use FreePascal, so you can make use of SScanF here.
This program lets you enter some lines of numbers that are separated by spaces.
After it's done, it prints the numbers.
I would not ever hand something like this over to end users though. Why not provide a graphical user interface instead?
program Project1;
uses
SysUtils;
const
Lines = 10;
type
TNumberArray = array[0..Lines-1,0..9] of integer;
procedure GetNumbers(var nums:TNumberArray);
var Line:Integer; s:String;
begin
for Line := Low(nums) to high(nums) do
begin
Write('Enter line ',Line, ': ');
ReadLn(S);
SScanf(s,'%d %d %d %d %d %d %d %d %d %d',
[
#nums[Line,0],
#nums[Line,1],
#nums[Line,2],
#nums[Line,3],
#nums[Line,4],
#nums[Line,5],
#nums[Line,6],
#nums[Line,7],
#nums[Line,8],
#nums[Line,9]
]
);
end;
end;
procedure ShowNumbers(nums:TNumberArray);
var Line,Col:Integer;
begin
for Line := Low(nums) to high(nums) do
begin
for Col:=Low(nums[Line]) to High(nums[Line]) do
Write(nums[Line,Col], ' ');
WriteLn;
end;
end;
var
Numbers: TNumberArray;
begin
WriteLn('Enter 10 numbers');
GetNumbers(Numbers);
ShowNumbers(Numbers);
WriteLn('Done. Press a key to continue.');
ReadLn;
end.
It's cleaner to parse the line using a TStringList, so that you don't have to hard-code the number of columns, but this should work.

Resources