Free Basic Calculator Issue - calculator

I have attempted to create a calculator with FreeBasic. What is the problem with line 9 in my code? Line 6 says that the dim choice is default and not allowed while line 9 tells me the variable isn't declared.
1 declare sub main
2 declare sub add
3 declare sub subtract
4 main
5 sub main
6 dim choice
7 print "1.Add"
8 print "2.subtract"
9 input "what is your choice" ; choice

Your source code is quite incomplete. For example, it misses the data types. In FreeBASIC you choose between several data types depending on what kind of data you want to store (Integer, Double, String, ...).
Moreover, you did not define how your sub programs actually should work. You didn't give any code what your procedure "subtract" should do.
Here's a working example of your small calculator:
' These two functions take 2 Integers (..., -1, 0, 1, 2, ...) and
' return 1 Integer as their result.
' Here we find the procedure declarations ("what inputs and outputs
' exist?"). The implementation ("how do these procedures actually
' work?") follows at the end of the program.
Declare Function Add (a As Integer, b As Integer) As Integer
Declare Function Subtract (a As Integer, b As Integer) As Integer
' == Begin of main program ==
Dim choice As Integer
Print "1. Add"
Print "2. Subtract"
Input "what is your choice? ", choice
' You could use "input" (see choice above) to get values from the user.
Dim As Integer x, y
x = 10
y = 6
If (choice = 1) Then
Print Add(x, y)
ElseIf (choice = 2) Then
Print Subtract(x, y)
Else
Print "Invalid input!"
End If
Print "Press any key to quit."
GetKey
End
' == End of main program ==
' == Sub programs (procedures = subs and functions) from here on ==
Function Add (a As Integer, b As Integer) As Integer
Return a + b
End Function
Function Subtract (a As Integer, b As Integer) As Integer
Return a - b
End Function

Related

Applying one Event to multiple Elements [duplicate]

I'm trying to create a dynamic function that's based off on what dropdown you interact with on a form. I need to pass the name of the dropdown to the function along with the form name when I call it.
Here's my current setup which only calls the funciton that passes the form name:
Private Sub KitchenMainCode_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
Call Populate([Form])
End Sub
Populate(frm As Form)
'do stuff
End Function
I have 8 dropdowns which means I have to copy paste 8 batches of the same code which isn't ideal, Ideally I would like something like this:
Private Sub KitchenMainCode_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
Call Populate([Form], [control.name OR "KitchenMainCode"])
End Sub
Populate(frm As Form AND dropdown name as name)
frm.name.value = xyz
End Function
Even at the least, if I can pass a string Its easier to make 8 Mousedown events than 8 unique functions, which is nearly 50 lines (x8).
Every time I google this, its bringing lots of Excel stuff & for some reason the code that's used isn't compatible with access (probably my issue) but they're both VBA scripts.
Kind regards,
You can do like this:
Private Sub KitchenMainCode_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
Call Populate(Me, Me.ActiveControl, Button, Shift, X, Y)
End Sub
Private Sub Populate(frm As Form, ctl As Control, Button As Integer, Shift As Integer, X As Single, Y As Single)
' do stuff
End Function
Or you could implement WithEvents. An example can be found in my project VBA.ModernTheme.
To call a function:
Private Sub KitchenMainCode_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
Dim Result As Long ' as the function returns.
Result = Populate(Me, Me.ActiveControl, Button, Shift, X, Y)
End Sub
Private Function Populate(frm As Form, ctl As Control, Button As Integer, Shift As Integer, X As Single, Y As Single) As Long
' do stuff
Populate = SomeResultValue
End Function

How to display an array of objects as will?

I have defined a class like
classdef Test
properties
a
b
end
methods
function this = Test(a, b)
this.a = a;
this.b = b;
end
function disp(this)
fprintf('a=%d b=%d\n', this.a, this.b);
end
end
end
But when I want to display a vector of Test, it seems not print each elements of array using the disp function just defined.
>> out = [Test(1,2),Test(3,4)]
out =
a=1 b=3
a=2 b=4
The questions is how to display an array of objects appropriately? Is there a way to overload the disp function and print as the following:
out=
a=1 b=2
a=3 b=4
(In my considering , the output will be same as calling disp function to element of array one by one.. But the output seems like firstly print all the a's value 1 3 and then b's value 2 4.)
You are getting this result because in your statement out = [Test(1,2),Test(3,4)], the variable out becomes an array of the same class Test, but of size [1x2].
If you try out.a in your console, you'll get:
>> out.a
ans =
1
ans =
3
This is a coma separated list of all the values of a in the out array. This is also the first parameter that your custom disp function sees. It then sees another column vector of all the values of b. To understand what the function fprintf is presented with you can also try in your console:
>> [out.a,out.b]
ans =
1 3 2 4
>> [out.a;out.b]
ans =
1 3
2 4
Since fprintf works in column major order, it will consume all the values column wise first. In that case we can see that the last option we tried seems better.
Indeed, if you change your disp function to:
function disp(this)
fprintf('a=%d b=%d\n', [this.a ; this.b]);
end
You get the desired output:
>> out = [Test(1,2),Test(3,4),Test(5,6)]
out =
a=1 b=2
a=3 b=4
a=5 b=6
Whichever size of object array you define. Just keep in mind that if you input an array of Test object they will be considered column wise:
>> out = [ Test(1,2),Test(3,4) ; Test(5,6),Test(7,8) ]
out =
a=1 b=2
a=5 b=6
a=3 b=4
a=7 b=8
Last option, if you want even more granularity over the display of your object array, you can customise it the way you like inside the disp function:
function disp(this)
nElem = numel(this) ;
if nElem==1
fprintf('a=%d b=%d\n', this.a , this.b );
else
for k=1:nElem
fprintf('a=%d b=%d\n', this(k).a , this(k).b);
end
end
end
This produces the same display than before, but since the elements are treated one by one, you could customise even further without having to consider the way arrays are treated by fprintf.
With the syntax you use, you should overload the display function instead of the disp function.
See the (not that simple to read) corresponding page in the documentation.

"operator symbol not allowed for generic subprogram" from Ada

I want to make subprogram for adding array's elements with Ada.
subprogram "Add_Data" have 3 parameters-
first parameter = generic type array (array of INTEGER or array of REAL)
second parameter = INTEGER (size of array)
third parameter = generic type sum (array of INTEGER -> sum will be INTEGER, array of REAL -> sum will be REAL)
I programmed it from ideone.com.
(I want to see just result by array of INTEGER. After that, I will test by array of REAL)
With Ada.Text_IO; Use Ada.Text_IO;
With Ada.Integer_Text_IO; Use Ada.Integer_Text_IO;
procedure test is
generic
type T is private;
type Tarr is array (INTEGER range <>) of T;
--function "+" (A,B : T) return T;
--function "+" (A, B : T) return T is
--begin
-- return (A+B);
--end "+";
procedure Add_Data(X : in Tarr; Y : in INTEGER; Z : in out T);
procedure Add_Data(X : in Tarr; Y : in INTEGER; Z : in out T) is
temp : T;
count : INTEGER;
begin
count := 1;
loop
temp :=temp+ X(count); //<-This is problem.
count := count + 1;
if count > Y then
exit;
end if;
end loop;
Z:=temp;
end Add_Data;
type intArray is array (INTEGER range <>) of INTEGER;
intArr : intArray := (1=>2, 2=>10, 3=>20, 4=>30, 5=>8);
sum : INTEGER;
procedure intAdd is new Add_Data(Tarr=>intArray, T=>INTEGER);
begin
sum := 0;
intAdd(intArr, 5, sum);
put (sum);
end test;
when I don't overload operator "+", It makes error.
"There is no applicable operator "+" for private type "T" defined."
What can I do for this?
If a generic’s formal type is private, then nothing in the generic can assume anything about the type except that it can be assigned (:=) and that it can be compared for equality (=) and inequality (/=). In particular, no other operators (e.g. +) are available in the generic unless you provide them.
The way to do that is
generic
type T is private;
with function "+" (L, R : T) return T is <>;
This tells the compiler that (a) there is a function "+" which takes two T’s and returns a T; and (b) if the actual T has an operator "+" which matches that profile, to allow it as the default.
So, you could say
procedure intAdd is new Add_Data (T => Integer, ...
or, if you didn’t feel like using the default,
procedure intAdd is new Add_Data (T => Integer, "+" => "+", ...
In addition to not knowing how to declare a generic formal subprogram (Wright has shown how to do this for functions), your code has a number of other issues that, if addressed, might help you move from someone who thinks in another language and translates it into Ada into someone who actually uses Ada. Presuming that you want to become such a person, I will point some of these out.
You declare your array types using Integer range <>. It's more common in Ada to use Positive range <>, because people usually refer to positions starting from 1: 1st, 2nd, 3rd, ...
Generics are used for code reuse, and in real life, such code is often used by people other than the original author. It is good practice not to make unstated assumptions about the values clients will pass to your operations. You assume that, for Y > 0, for all I in 1 .. Y => I in X'range and for Y < 1, 1 in X'range. While this is true for the values you use, it's unlikely to be true for all uses of the procedure. For example, when an array is used as a sequence, as it is here, the indices are immaterial, so it's more natural to write your array aggreate as (2, 10, 20, 30, 8). If I do that, Intarr'First = Integer'First and Intarr'Last = Integer'First + 4, both of which are negative. Attempting to index this with 1 will raise Constraint_Error.
Y is declared as Integer, which means that zero and negative values are acceptable. What does it mean to pass -12 to Y? Ada's subtypes help here; if you declare Y as Positive, trying to pass non-positive values to it will fail.
Z is declared mode in out, but the input value is not referenced. This would be better as mode out.
Y is not needed. Ada has real arrays; they carry their bounds around with them as X'First, X'Last, and X'Length. Trying to index an array outside its bounds is an error (no buffer overflow vulnerabilities are possible). The usual way to iterate over an array is with the 'range attribute:
for I in X'range loop
This ensures that I is always a valid index into X.
Temp is not initialized, so it will normally be initialized to "stack junk". You should expect to get different results for different calls with the same inputs.
Instead of
if count > Y then
exit;
end if;
it's more usual to write exit when Count > Y;
Since your procedure produces a single, scalar output, it would be more natural for it to be a function:
generic -- Sum
type T is private;
Zero : T;
type T_List is array (Positive range <>) of T;
with function "+" (Left : T; Right : T) return T is <>;
function Sum (X : T_List) return T;
function Sum (X : T_List) return T is
Result : T := Zero;
begin -- Sum
Add_All : for I in X'range loop
Result := Result + X (I);
end loop Add_All;
return Result;
end Sum;
HTH

Excel creating autofilling form

I'm trying to create a form which contains two entries:
-folder number
-list of toms which are in folders
This is for archiving purpose. Form is divided on 4 section which will be printed on labels for archive boxes.
Folders are numbered from 1 to 1500, some of them contain 1 tom of documents, some of them up to 10. For now I'm doing this manualy by just copying from the table which looks like this:
table
Only thing I need in form is TOM NUMBER from this table
form
I was trying to use VLOOKUP but it only returns first row which has searched folder number.
So bascially I want a function which will take folder number from label form and find all toms which are assigned to and write it below. first 3 digits in folder number aren't important, only last 4 digits are considered most important variable
Unfortunately vlookup will not work, you are going to have to use an array folder. I am making an assumption that you will have a table that is called [Folders]
and I am going to create a form form with some vba on how to do this.
1. Create a Table by selecting the folder dataset and push ctl+T.
Alt + F11 to enter Visual basic editor
At the top choose insert ==> UserForm
Push F4 and in the properties window name your form FileFinder
Your toolbox maynot appear if it doesn't choose view => toolbox to open
drag 2 labels, 2 listboxes, and 2 buttons, you can format it however you like.
7.Create a new Module same as adding userform only choose module
Copy paste this code
Public Function CreateWorksheet(Optional name As String = "") As Worksheet
Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets.Add
If name <> "" Then ws.name = name
Set Create = ws
End Function
Public Function LastRow() As Integer 'gets last row from column A
LastRow = ActiveSheet.Cells(Rows.count, 1).End(xlUp).Row
End Function
Public Function DistintFolders() As String()
Dim list() As String
Dim counter As Integer
For Each cell In ActiveSheet.Range("E2:E" & LastRow)
If Not IsInList(list, cell.Value, counter) Then
counter = counter + 1
ReDim Preserve list(1 To counter)
list(counter) = cell.Value
End If
Next cell
DistintFolders = list
End Function
Public Function TomNumberByFolder(folderName As Variant) As String()
Dim list() As String
Dim counter As Integer
Dim rowNumber As Integer
For Each cell In ActiveSheet.Range("B2:B" & LastRow)
rowNumber = rowNumber + 1
If IsCorrectFolder(folderName, rowNumber) Then
counter = counter + 1
ReDim Preserve list(1 To counter)
list(counter) = cell.Value
End If
Next cell
TomNumberByFolder = list
End Function
Public Function IsInList(ByRef list() As String, compare As String, count As Integer) As Boolean
Dim l As Variant
If compare = "" Then
IsInList = True
Exit Function
End If
If count = 0 Then
IsInList = False
Exit Function
End If
For Each l In list
If l = compare Then
IsInList = True
Exit Function
End If
Next l
IsInList = False
End Function
Public Function IsCorrectFolder(folderName As Variant, rowNumber As Integer) As Boolean
IsCorrectFolder = (ActiveSheet.Range("E" & rowNumber).Value = folderName)
End Function
double click your form and paste this code
`
Private Sub btnCancel_Click()
Unload Me
End Sub
Private Sub btnCreate_Click()
Dim ws As Worksheet
If lstTom.ListCount = 0 Then
MessageBox "Please select a folder"
End If
Set ws = ThisWorkbook.Sheets.Add
ws.Cells(1, 1).Value = "Tom Number"
ws.Cells(2, 1).Resize(Me.lstTom.ListCount, 1) = Me.lstTom.list
End Sub
Private Sub lstFolder_Click()
Dim folder As String
If ActiveSheet.name <> "Data" Then ThisWorkbook.Sheets("Data").Activate 'please name this whatever your datasheet is called
For i = 0 To lstFolder.ListCount - 1
If lstFolder.Selected(i) Then
Me.lstTom.Clear
For Each s In TomNumberByFolder(lstFolder.list(i))
With lstTom
.AddItem s
End With
Next s
End If
Next i
End Sub
Private Sub UserForm_Initialize()
For Each s In DistintFolders
With lstFolder
.AddItem s
End With
Next s
End Sub
`
please note that you may have to change sheet names if you would like I will send you this.
Download Here

How to return a value from subroutine

I don't want to use global value it is dangerous for a big program. Code is like this
subroutine has_key(id)
if (true) then
return 1
else
return 0
end if
end subroutine
subroutine main
if(has_key(id))
write(*,*) 'it works!'
end subroutine
how can I do something like this using subroutine. I was thinking of return a flag but I may use a global value. Anyone has idea?
Like this
subroutine test(input, flag)
integer, intent(in) :: input
logical, intent(out) :: flag
flag = input>=0
end subroutine
and
call test(3,myflag)
will set myflag to .true.
Note
that subroutines return values through their argument lists;
the use of the intent clause to tell the compiler what the subroutine can do with its arguments;
my example is very simple and you will probably want to adapt it to your needs.
You could also do it with a function. Say it returns true for even numbers
logical function has_key(id)
integer, intent(in):: id
has_key = mod(id,2) .eq. 0
end function has_key
program main
do ii = 1, 4
if(has_key(ii))
print *, ii, ' has key'
else
print *, ii, ' no key'
end if
end do
end program