presently learning how to code in pascal and vba. Assisting my daughter who is preparing for examinations next year. I am stuck on a problem concerning her present assignment. After running the code the following errors were received:
main.pas(1,2) Fatal: Syntax error, "BEGIN" expected but "identifier N" found
Fatal: Compilation aborted
Tried fixing the code, but as i said I have just started learning to code.
n: integer; (*n is ID number for each candidate*)
DV: integer; (*DV is the number of district votes available*)
VR: integer; (*VR is the number of votes received by the candidate in
the district*)
x: integer;
y: integer;
Divide: integer;
found: Boolean;
n: array[1..10] of integer; (*n is an array of 10 integers*)
Names: array[1…10] of string = (‘Richards’, ‘Gumbs’, ‘Carty’,
‘Fleming’, ‘Jones’, ‘Amorowat’, ‘De la cruz’, ‘Walker’,
‘Brooks’, ‘Baker’);
DV: array[1…10] of integer = (‘200’, ‘900’, ‘700’, ‘100’, ‘80’, ‘15’,
‘6, ‘20’, ‘50’, ‘1’);
VR: array[1…10] of integer = (‘50’, ‘700’, ‘600’, ‘20’, ‘30’, ‘2’,
‘6, ‘3’, ‘30’, ‘2’);
For x := 1 to 10 do
Begin
Repeat
Found:=false;
writeln('Enter Candidate ID Number: ’);
readln(n);
For y:= 1 to 10 do
if n = n[y] then
Found = true;
writeln(‘Name of Candidate is’ Names: array[1] ‘.’);
readln;
writeln(‘Number of votes available in the District is’
DV: array[1] ‘.’);
readln;
writeln(‘Number of votes received by the Candidate in the
District is’ VR: array[1] ‘.’);
readln;
Endif;
For y:= 1 to 10 do
if n = n[y] then
Divide:= (DV: array[1] DIV VR: array[1]);
Result:= Divide;
writeln(‘The percentage of votes received by’ Names:
array[1] ‘is’ Result ‘.’);
readln;
if Result:>= 0.20 then
writeln(‘The candidate,’ Names: array[1] ‘is to receive a
refund.’);
readln;
Elseif
writeln(‘The candidate,’ Names: array[1] ‘will not receive
a refund.’);
readln;
Endif;
Endif;
End;
The expected result is to choose a candidate by his ID number which would lead to his name, the number of vote available in a district and the number of votes the candidate obtained being displayed. it would then result in a calculation between the two vote counts (division) and if the percentage is greater than 20% he would receive a refund, if less than 20% he would not receive a refund. either result should be displayed.
I'm afraid that you q, as it currently stands, isn't really suited to SO
because SO is really about specific (single) programming problems, not
incrementally debugging source code (see Sertac's comment), nor providing
online tutorials, which I think you probably need at this point. And I feel
rather uncomfortable about posting this as an answer, because it isn't one
in the normal SO sense. However it seems to me that you could use a few pointers:
Unless you absolutely have to use the online compiler, download
and use a free online one like Free Pascal, which is well supported, uses
standard Pascal syntax, and I'm sure there are basic first-time tutorials
available. See here to download Lazarus, which is an excellent IDE for Free Pascal (which is included
in the install) and here for an introductory tutorial.
Secondly, there are structural and syntactic elements of your source-code
which are definitely not standard Pascal, in particular endif and elseif.
Another example is that in standard Pascal, you have to surround a string (like your
Richards, etc) with single-quotes ', not precede the string by a back-quote. This is very possibly the cause of your "illegal character" error
For a decent Free Pascal introductory
tutorial see here and this youtube tutorial, both found by googling
"free pascal" introductory tutorial.
Fourthly, your online compiler ought to be complaining about the endif abd elseifs, the incorrectly string formatting and the fact that several of your variables are duplicated (DV and VR used as the names of an integer variable and an array, for example as in Pascal, identifiers within the same 'scope' need to have unique names (the fact that I should explain what 'scope' means is a sign that what the q needs is a tutorial).
Related
PROGRAM approvedapplicants(input,output);
uses crt;
var
applcntname,housingcomm,clarendon_court,providence_gardens,
sangre_grande_villas:string;
slry,spcslry:integer;
c_qual_sal,s_qual_sal,p_qual_sal,qualifying_salary:integer;
BEGIN
writeln('enter applicant name, salary, spouce salary');
readln(applcntname,slry,spcslry);
writeln('enter housing community');
readln(housingcomm);
BEGIN
qualifying_salary:=0;
IF(housingcomm=clarendon_court)
then
qualifying_salary:=$12500;
writeln('you have selected clarendon court!');
readln(c_qual_sal) ;
end if ;
else if(housingcomm=sangre_grande_villas)then
qualifying_salary:=$9500;
writeln('you have selected sangre grande villas!');
readln(s_qual_sal);
end if ;
else(housingcomm=providence_gardens)then;
qualifying_salary:=$7500;
writeln('you have selected providence gardens!');
readln(p_qual_sal);
end if;
END.
Ordinarily, on SO, we don't post answers to homework/coursework, but your code is so far wide of the mark that I think it's ok to make an exception in this case.
Try compiling and running this program, which I think does pretty much what I think you are intending, then I'll explain a few things about it:
program approvedapplicants(input,output);
uses crt;
var
ApplicantName,
HousingCommunity,
ClarendonCourt,
ProvidenceGardens,
SangreGrandVillas :string;
Salary,
SpouseSalary,
QualifyingSalary : Integer;
CQualSal,
PQualSal,
SQualSal : Integer;
slry,spcslry:integer;
begin
ClarendonCourt := 'Clarendon Court';
ProvidenceGardens := 'Providence Gardens';
SangreGrandVillas := 'Sangre Grand Villas';
QualifyingSalary := 0;
writeln('enter applicant name');
readln(ApplicantName);
writeln('enter salary');
readln(Salary);
writeln('enter spouse salary');
readln(SpouseSalary);
writeln('enter housing community');
readln(HousingCommunity);
if (HousingCommunity = ClarendonCourt) then begin
QualifyingSalary := $12500;
writeln('you have selected clarendon court!');
readln(CQualSal);
end
else
if(HousingCommunity = SangreGrandVillas)then begin
QualifyingSalary := $9500;
writeln('you have selected sangre grande villas!');
readln(SQualSal);
end
else
if HousingCommunity = ProvidenceGardens then begin
QualifyingSalary :=$7500;
writeln('you have selected providence gardens!');
readln(CQualSal);
end;
end.
Firstly, notice how much easier it is to read and follow its logic. This is mainly
because of
The use of a layout (including indented blocks) which reflects the logical
structure of the code.
The use of consistent, lower case for keywords like program, begin, end, etc.
Keywords are usually the least interesting contents of source code, and it is distracting
to have them SHOUTing at you.
The avoidance of arbitrarily dropping characters from variable names (like the "i"
and second "a" of "applicant". In the days of interpreted code running on slow machines there was
argubably some justification for this, but not any more imo. Likewise, the avoidance
of underscores in variable names - admittedly this is more of a personal preference, but
why have you used them everywhere except the applicant's name?
Secondly, you still have quite a bit of work to do.
Having 3 different variables for the salary (?) numbers you prompt the user
for, one for each of the 3 communities, is probably a bad idea unless you will
subsequently want to work with all 3 figures at the same time. Also, you haven't provided text prompts to tell the user what information to enter for the readln(c_qual_sal) etc statements. It wasn't obvious to me what you intend, so I have not tried to guess.
The way you echo the user's choice of community is just creating you a maintenance
headache (what if you want to add more communities later?). It would be better
to have a variable which you set to whichever of the community names matches
what the user has entered.
You have 3 statements to execute for each community, which are duplicated for
each community. The only one you actually need is the QualifyingSalary one -
the others can execute regardless of the inputted community.
I developed the following sorting algorithm but there are some run time errors that I cant figure out. The program terminates when it comes to the part of filling the array. I'm still a beginner in ada so I couldn't figure out where the problem is...
With Ada.Text_IO;
With Ada.Integer_Text_IO;
Use Ada.Integer_Text_IO;
Use Ada.Text_IO;
Procedure sort is
n,i,x : Integer;
-- Max_Heapify Function...
Procedure Max_Heapify ( i, n : integer) is
j, Temp : Integer;
begin
Temp:=Int_Acc(i);
j:=2*i;
if Temp>Int_Acc(j) then
elsif Temp<=Int_Acc(j) then
Int_Acc(j/2):=Int_Acc(j);
j:=2*j;
end if;
end loop;
Int_Acc(j/2):=Temp;
end Max_Heapify;
begin
Get(n);
for i in MyArr'range loop
Put_Line("Enter Element " & Integer'Image(i));
Get(MyArr(i));
end loop;
end;
end sort;
Thanks in advance :)
Your Problem is that you are insisting on writing Ada code using c - Style programming paradigms.
Firstly:
The declarations:
Type Arr is array(1..20) of Integer;
Type int_access is access Arr;
MyArr : int_access;
Where you use Int_Acc : in out int_access as parameters to procedures are useless in Ada. You are trying to pass a pointer to an array in (which you are doing!), but you should just pass your Type Arr as in out - The Ada compiler knows to do this as a pointer!
Secondly:
I cannot see where you actually allocate any memory to MyArr. This is a possible source of your runtime error. (when you write to or index an array that does not exist, i would expect to have a problem!)
Thirdly:
You seem to be mixing fixed length arrays with variable length input. If N > 20, you will have a problem.
Fourthly:
Insulting the language is not the best way of getting help from those who like it.
NWS has nailed it : there is a pointer, but no array there.
But it's clear that you have learned C, which leaves you with a lot to learn about other languages including Ada. There really are better ways of doing many things, that aren't taught to C programmers because C doesn't allow them.
Allocating variable sized arrays without pointers, malloc and free for example...
Type Arr is array(positive range <>) of Integer; -- of any size
begin
Put_Line("Enter Number Of Elements Of Array");
Get(n);
declare -- now we know the size
My_Arr : Arr(1 .. n);
begin -- My_Arr is in scope until the end of this block
...
end;
end sort;
Using the type system better...
Bad programming :
for i in 1 .. n loop
Get(MyArr(i));
end loop;
HeapSort(MyArr,n);
for i in 1 .. n loop
Put_Line(Integer'Image(MyArr(i)));
end loop;
This is bad because it violates the DRY principle : loop bounds repeated, and something that hopefully represents the array size passed around as a separate parameter... a maintenance nightmare if you decide to rename n to something meaningful for example.
better programming : Use the type system. Recognise that merely declaring an array has declared a new subtype of integer, representing the index of the array. You can access it as My_Arr'range, and the high bound as My_Arr'last.
for i in My_Arr'range loop
Get(MyArr(i));
end loop;
HeapSort(MyArr);
for i in My_Arr'range loop
Put_Line(Integer'Image(MyArr(i)));
end loop;
And accidents such as redefining n after the array declaration can no longer generate buffer overflows.
NOTE: Heapsort now gets its range from the array. (Max_Heapify may still need a separate parameter to operate on subsets of the array)
Arguably best - if it makes the intent clearer - name the index datatype explicitly and use it...
declare -- now we know the size
subtype My_Range is positive range 1 .. n;
My_Arr : Arr(My_Range);
begin -- My_Arr is in scope until the end of this block
for i in My_Range loop ...
And lastly, which do you prefer; a Storage_Error exception immediately the bug occurs (writing to memory you forgot to allocate) or something odd happening much later because something scribbled across another variable?
EDIT
Having cleared up the major issues two more subtle ones remain...
If I compile the modified program (in Gnat 4.8) I get several warnings : one of them is important and tells you exactly what the problem is...
Most of the warnings stem from the fact that
for i in My_Arr'range loop
declares its own loop variable i which hides any existing in-scope declaration. So you can tidy up the code by removing the unnecessary declarations.
What remains is:
sort.adb:51:28: warning: loop range may be null
sort.adb:51:28: warning: bounds may be wrong way round
The for loop bounds are empty ranges, reversed...
1 .. 3 declares a subtype with 3 values
reverse 1 .. 3 declares the same subtype and iterates backwards over it.
But 3 .. 1 declares an EMPTY subtype (containing NO valid values) so iterating over it - either way round - does precisely nothing.
Hopefully that is the missing part of the puzzle. I'm not clear why one faulty loop gets this warning while the other (at line 38) doesn't...
if j<n **and then** Int_Acc(j+1)>Int_Acc(j) then
j:=j+1;
I think you want just 'and' instead of 'and then,' although I haven't looked at Ada code in years.
Did that compile?
I'm trying to make a (very) little code to determine whether a given variable x is a number or a letter. It has to be done by hand without things like type(x) -assuming there is such thing in Pascal-.
My plan was to verify that x is not a number one by one, then i wrote this:
(*let ischar be a boolean and let x be a letter or a number.*)
for i:=0 to 9 do
begin
if (x=i) then
ischar = false;
end;
if ischar then
write('x is a number!');
else
write('x is a letter');
I was hoping that the test "x=i" would return false if x is a letter, but here i don't even get to compile because of the following error: "Got char, expected long int". It seems that i can't compare x and i, i knew that but i tought that under that circumstances if would return false.
Is there another way to do this 'by hand'?
It's generally not possible to directly compare variables of different types. The compilation error suggests x is declared as a char, while i is a longint.
The available options may depend on what Pascal compiler you use.
My only experience is with the Borland (later CodeGear and Embarcadero) products "Turbo Pascal" and "Delphi".
Those compilers have the ord function which gives the numeric value of an ordinal type.
In the case of a char, the ord function should give you the ASCII code of the character, which you can test to see if it's in the code range of '0'..'9'.
You don't need the for loop. This should work:
if (ord(x)<48) or (ord(x)>57) then ischar:=true else ischar:=false;
Edit: Here's the Free Pascal documentation for the ord function:
http://www.freepascal.org/docs-html/rtl/system/ord.html
I'm having a problem when I use these 2 FOR to initialize a two dimensional vector/array:
I have these types defined:
type
Range9 = 0..8;
Digit = '0'..'9';
Board = array [Range9,Range9] of Digit;
and then the part of the code where there are problems with the FOR's is the following:
var
i : Range9;
j : Range9;
table : Board;
BEGIN
for i:=0 to 8 do begin
for j:=0 to 8 do begin
table[i,j] := '0'
end
end;
END.
Now the problem is that, when I debug this portion of code, for some reason, my i variable is modified when it's not supposed to.
For example, I have a watch on i and j and if I put a breakpoint in the line table[i,j] := 0
I see with the watches these values:
i j
0 0
256 1
512 2
768 3
1024 4
1280 5
1536 6
1792 7
2048 8
2049 8
1 0
257 1
513 2
769 3
and so on...
So, when the program enters in the second for (the one that increases the j) my i increases in intervals of 256... I really don't know why is this happening.
And another thing I discovered is that, the problem solves if I change the TYPE of the i variable.
If in the VAR section I put i : integer instead of i : Range9, i doesn't get modified when isn't supposed to.
I would really appreciate if someone explains me why is happening this.
I've found the answer to my own question... well, I didn't exactly found the answer, I've asked this same question in the forum board of the programming course I'm attending and one of the professors gave me this link:
(it's in spanish btw)
http://www.fing.edu.uy/inco/cursos/prog1/pm/field.php/FAQ/Laboratorio#toc17
A quick translation:
This happens with variables defined as subranges. The reason isn't sure; but without doubt is an implementation error of the debugger. There is a 'trick' that can work to solve this (although not always), to be able to see the correct values on the debugger:
Suppose that you have the following variable in your program:
var anything: 1 .. 10;
Add in your program a integer variable which won't be used in any part of the program:
var anything: 1..10;
aux: integer; { only for the debugger }
Then when you define the debugger watch, instead of adding the anything variable, you should add the following expression:
aux:= anything
The aux variable can be used to view different variables, so you only need to declare one aux variable.
In some cases, the previous may not work. Another solution is to change the type of all the variables defined with subranges to integer, char, string, etc (depending the case) only for debug and the change it back again.
end of the translation.
Hope this will be useful for someone else facing the same error.
BTW, this happens with the debugger of free pascal IDE 2.2.2 , maybe in another IDE/compiler/debugger of pascal it doesn't happen.
I haven't done Pascal in a while, so I might be a bit rusty. The only thing I can think of that is creating your problem is that you created a character range that was interpreted as a byte array, which was then converted to a Digits and then multiplied, which gave you those weird values. But, I could be wrong. I am unfamiliar with FreePascal.
Type
Range9 = 0..8
Board = Array[Range9,Range9] of Integer;
var
A : Board;
I,J : Integer;
begin
For I:=0 to 8 do
For J:=0 to 8 do
A[I,J]:=I*J;
end.
Reference: ftp://ftp.freepascal.org/pub/fpc/docs-pdf/ref.pdf
It was not me who wrote this code, it was the previous programmer. However, I noticed he didn't provide a decryption algorithm, rendering the encryption useless.
How can I decrypt this?
function Encrypt(jstr: String): String;
var
I: Integer;
A: Real;
begin
if Length(jstr) = 0 Then begin
Result := '';
Exit;
end;
A := 0;
for I := 0 To Length(jstr) do
A := A + (Ord(jstr[I]) * Pos(jstr[I],jstr)) / 33;
Result := FormatFloat('0000000000.0000000000',A);
if Pos(',',Result) > 0 then begin
Insert('.',Result,Pos(',',Result));
Delete(Result,Pos(',',Result),1);
end;
end;
Thanks!
It looks like a one way hash and hence is not reversible. For example, is the string is very big the result is still a string representation of a float.
That function cannot be reversed. Since it takes input of arbitrary length and returns output of finite length, simple information theory tells you the futility of attempting to write a general inverse. Even for shorter input strings it seems to me that different input strings can result in the same encrypted string.
Even as a hash this function seems very brittle to me due to the bizarre use of floating point code. If I were you I would replace this function with something more fit for purpose.
Finally, I recommend that you undertake a review of all code produced by this developer. The low quality of this code and algorithm suggests to me that everything that this developer touched is liable to have defects.