Hey guys, I am a new programmer just starting. The assignment my prof gave us has to deal with taking a file (the file is an equation, 5+23*2 for example) and calculating the result. The program also has to give appropriate errors when they arise. (missing operators, etc). I am a bit confused on how to do this, any help would be great thanks!
Gotovina7
 5 Contributors
 forum69 Replies
 83 Views
 10 Years Discussion Span
 comment Latest Post by ScholRLEA
Duoas 1,025
The best place to start is to get out a piece of paper and a pencil and figure out how you do it yourself. Once you know how to do it, step by step, you can tell the computer how to do it.
When you have thought it out enough to write some code, post it here and we'll be happy to help further.
Gotovina7
The best place to start is to get out a piece of paper and a pencil and figure out how you do it yourself. Once you know how to do it, step by step, you can tell the computer how to do it.
When you have thought it out enough to write some code, post it here and we'll be happy to help further.
Ok thanks. I looked at the other thread regarding the same type of program. Say i had the equation 1+2+3, I would want to look at the first number and save the value, then move to the next number and add it to the previous number. But I can't figure out how to write the code that moves from the first number, records it, then moves to the next number.
Duoas 1,025
I think that is the part your professor is interested in.
A string is an array of characters. So, no matter how you get the equation (reading it from file or from user input) you still have a string: var equation_string = '1+2+3';
What procedures and functions and techniques have you learned that can index and split a string? Turn a character digit into an integer?
Gotovina7
I think that is the part your professor is interested in.
A string is an array of characters. So, no matter how you get the equation (reading it from file or from user input) you still have a string:
var equation_string = '1+2+3';
What procedures and functions and techniques have you learned that can index and split a string? Turn a character digit into an integer?
Let me give some more information about this project. I need to read equations from an input file. For example, the file could look like this
5 + 3 * 5 2
51  14/5 + 1 *5
Operator precedence must be taken into account as well as the bracketing of expressions. The first equation will be completely evaluated and the final answer determined before the next equation is read and evaluated. "Every time an intermediate result is calculated the corresponding components of that calculation are removed from the array(s) and replaced with the correct answer". This is my first project using arrays, so I will have to get use to it
Gotovina7
Program Lesson9_Program(input, output);
Var file1 : Text;
eq1 : String;
eq2 : string;
Begin
Assign(file1,'input.txt');
Reset(file1);
If (IOResult <> 0) then
Begin
Writeln('The file required to be opened is not found!');
Readln;
End Else
Begin
readln(file1, eq1);
Writeln('The first line of the file reads: ',eq1);
readln(file1, eq2);
writeln('The second line of the file reads: ',eq2);
End;
End.
This is basically what I just have so far, it prints out both the equations that are in the file. Now, I need to somehow put those equations into an array I think.
Duoas 1,025
So, according to your assignment description, you account for operator precedence by evaluating the same expression over and over until there is only a number (or error):
I start with
5 + 3 * 5 2
The most precedent operator is *, so:5 + 3 * 5 2
5 + 15 2
The remaining operators have equal precedence, so I'll just take them left to right:5 + 15 2
20 2
and20 2
18
There are no more operators, so the answer is 18.
Now, you are supposed to store the expression in an array. So you could have an array of string, where each element is either a number or an operator: '5', '+', '3', '*', '5', '', '2'
Or you could have an array of some record type that tells you whether it is a number or an operator, say: type tType = (number, add, subtract, multiply, ...);
type tElement = record element_type: tType; number: integer end;
This is how I would do it (if forced to use an array), but if it is beyond you just stick to an array of strings. I assume the latter in what follows, but the concepts work either way.
So, even a bracketed expression is easily stuck in an array: 5 * (2 + (3 + 1))
becomes '5', '*', '(', '2', '+', '(', '3', '+', '1', ')', ')'
This makes it easy to find operators. The brackets are special, in that they work on a subarray. Hence:
5 * (2 + 3)
has the () operator, which means to evaluate a subexpression. We'll do that first:2 + 3
becomes5
Now we can stick it back into the original expression and remove the ():5 * 5
Evaluating further:25
Your professor wants you to use an array, alas. You can move stuff around every time, or you can just transform unused parts (which have been "removed") into, say, the empty string, which means just to ignore it. For example, taking: 1 + 2 + 3
and transforming it into 3 + 3
can have two affects on your array. Starting with: '1', '+', '2', '+', '3'
you can transform it to: '3', '+', '3'
(or '3', '+', '3', '', ''
)
or '3', '', '', '+', '3'
Both ways have caveats you must be aware of. The first means you must shift elements downward. If you are allowed to use dynamic arrays you can get rid of extra elements at the end, otherwise you must set them to ''. The second way requires your code to skip '' when finding elements adjacent to an operator.
Well, that's enough to think about. Consider how you want to make it work and get started. Remember, it is perfectly OK to use functions and procedures to do something. For example, you might have a function to search your array for the operator with the highest precedence and return its index. Another might modify take the array and an index to an operator and do the operation.
Oh yeah, almost forgot. Convert between numbers and strings with strToInt() and intToStr().
Hope this helps.
Gotovina7
Thanks for all the info! Should I keep the code I have so far? Or should I start all over?
Duoas 1,025
What do you think?
[EDIT] That is, use your own head.
Gotovina7
How do I put a record into an Array? Pretty lost for this.
Duoas 1,025
An array is just a list of things all having the same type. An array of integer is: var a: array[ 1..100 ] of integer;
(fixedsize array) var a: array of integer;
(dynamic array)
Likewise, an array of char is: var str: array[ 1..100 ] of char;
(fixedsize array)
So if your record's type is tElement
you create an array as: var equation: array of tElement;
(dynamic array)
You could have read this in your text book.
Good luck.
Gotovina7
Something still isn't right, this is what I have
Program Lesson9_Program(input, output);
Type
Str25 = String[25];
tEquation = Record
num : Str25;
add,subtract,multiply,divide : Str25;
end;
Var file1 : Text;
eq1 : String[255];
eq2 : string[255];
myEquation : tEquation;
myeqArray : array[1..50] of tEquation;
Begin
Assign(file1,'input.txt');
Reset(file1);
If (IOResult <> 0) then
Begin
Writeln('The file required to be opened is not found!');
Readln;
End Else
Begin
readln(file1, eq1);
Writeln('The first line of the file reads: ',eq1);
readln(file1, eq2);
writeln('The second line of the file reads: ',eq2);
End;
end.
Do I have an error somewhere in my record or Array? I can't seem to get my equation into an array. Sorry I am new to programming.
Duoas 1,025
You have no errors. However, I would be inclined to make a single enumeration type to tell me what the element is, as I suggested above.
Obviously, you can't just say readln( myEquation );
since the program has no idea how to read such a thing. You've already read a string that looks something like '1+20*3'
.
After reading it, all you have to do is convert it into your array.
The first character is a digit, and there is only one of them. So I take the first character and convert it into a number: 1. The first element of my array is a number = 1.
The second character is a plus sign. So it is an operator. The second element of my array is a plus operator.
The third and fourth characters are digits, so I convert them into a number: 20. The third element of my array is a number = 20.
The fifth character is an operator, so the fourth element of my array is the multiplication operator.
Etc.
If you can think out the process like this, then you can also draw it on a piece of paper. Think about the kinds of information you must have to do it: indices into your string, an index into your array, a way to tell numbers and various operators apart, etc. This is the reason I suggested a record type: because it can have a value that tells you what kind of thing it represents and another value to tell you what that thing is.
Also, you have no idea how many lines your file might have. It could be two, or twohundred. You can't possibly do all those equations at once. Instead, do them one at a time: Read a line, convert it to your equation array, solve, print the answer. Read the next line, convert, solve, print. Rinse and repeat.
Hope this helps.
Gotovina7
You have no errors. However, I would be inclined to make a single enumeration type to tell me what the element is, as I suggested above.
What do you mean? I dont really understand what you are doing here
type tType = (number, add, subtract, multiply, ...);
type tElement = record element_type: tType; number: integer end;
That second line confuses me. Records are a bit confusing. I read my textbook on them, but they are still confusing me. I am not really sure what my program is doing. Like, I can't understand the record part of it. Does my equation from the input file go into the record? How would I assign numbers from my file into "num" in the record, and operators from my file into the appropriate places in the record?
Duoas 1,025
If you haven't studied records yet (sigh, halfway through the semester and your teacher's asleep), then just use an array of strings.
Take a single string like 5+(12*3)
and convert it into an array of strings 5
, +
, (
, 12
, *
, 3
, )
The operator with highest precedence is (), so you find the subarray containing the bracketed expression (elements 3..5) and evaluate it in recursion. Replace elements 2..6 with the result of the last evaluation, so you would have 5
, +
, 36
.
The drawback is that you must check to see what kind of thing each element of the array is each time you look at it, and you must continually convert between numbers and strings.
I think you should go talk to your teacher and see if he can't give you a better idea of how he wants you to do this.
Your assignment got me interested so I did it myself in about 300 lines. About 100 of that is lots of error checking and extra functions I threw in (like a power function).
Gotovina7
I appreciate all the help. My prof is very confusing, and I don't think he is a good teacher at all. We did records last class but he didn't explain them very well.
Duoas 1,025
OK. A record is just a way to keep different kinds of data together.
Normally, you have simple types, like integer, char, real, etc.
You can have an array of things, but they are all the same kind (or type) of thing: array of integer, array of char, array of real.
Sometimes you need to store related things together. Say, a student. There's the student's name, current grade, etc.
type tStudent = record
last_name: shortstring;
first_name: shortstring;
grade: integer
end;
Now, if you want to store information about a student, you have all that stuff grouped together under one name:
var students: array[ 1..35 ] of tStudent;
You can access information about a particular student:
writeln(
'Student 12: ',
students[ 12 ].first_name,
' ',
students[ 12 ].last_name,
' has a numeric grade of ',
students[ 12 ].grade,
'.'
);
You can copy records just like simple data types.
var a_student, another_student: tStudent;
...
if a_student.grade <> another_student.grade
then writeln( 'very possible...' );
a_student := another_student;
if a_student.grade <> another_student.grade
then writeln( 'impossible!' );
You can use a with statement to get at all the elements of a record without having to repeat the record variable's name each time:
with a_student do
begin
first_name := 'Jenny';
last_name := 'O''Hara';
grade := 95
end;
{ Now a_student is Jenny O'Hara, who has an A+ }
An enumeration (which you should have learned already also) is just a bunch of names. It is stored as a number, but we don't usually care what those numbers are. The meaning is in the name. For example:
type
tCardSuite = (Spades, Hearts, Clubs, Diamonds);
tCardRank = 1..12;
tCard = record
suite: tCardSuite;
rank: tCardRank
end;
Now, you can create a function that creates a card with rank and suite.
function create_a_card( rank: tCardRank; suite: tCardSuite ): tCard;
var r: tCard;
begin
r.rank := rank;
r.suite := suite;
create_a_card := r
end;
And you can use it:
var card: tCard;
begin
card := create_a_card( 1, Spades );
end.

So, then, what I recommended is, since each type of thing in an equation is something different, you can't have an array of them. What you can have, though, is an array of the same thing, which stores different data depending on the type of thing it represents.
type
tEquationItemType = (
number, addition, subtraction, multiplication, division,
open_parentheses, close_parentheses
);
tEquationItem = record
itemType: tEquationItemType; // number? +? ? *? /?
value: real // if itemType = number, this is the number
end;
tEquation = array[ 1..100 ] of tEquationItem;
var
equation: tEquation;
Now, you can convert a string like 5*(12+3)
into an equation:
with equation[ 1 ] do begin itemType := number; value := 5.0 end;
equation[ 2 ].itemType := multiplication;
equation[ 3 ].itemType := open_parentheses;
with equation[ 4 ] do begin itemType := number; value := 12.0 end;
{ and so on }
Of course, you won't want to directly hardcode the equation like this, but you will read it from file and convert it in a similar manner. Use a loop to get lines from the file. In that loop, call a function to convert the line from the file into an equation. I named my version of this procedure string_to_equation: procedure string_to_equation( s: string; var equ: tEquation );
The function itself will use a loop to get characters out of the string. For each character, if it is a number, set the next element of equ to think of itself as a number and store a value. If it is a plus sign, set the next element of equ to think of itself as a multiplication. Etc.
You will want to write a few other functions or procedures that act on the equation to test it, evaluate it (or part of it), etc.
Hope this helps.
Gotovina7
Man, you are great at explaining. I wish you were my prof :D
Everything was clear until this part
procedure string_to_equation( s: string; var equ: tEquation );
Ok, I understand I need to get characters out of the string. This is the part that confused me a bit.
" For each character, if it is a number, set the next element of equ to think of itself as a number and store a value. If it is a plus sign, set the next element of equ to think of itself as a multiplication. Etc. "
Thanks for all the help!
Duoas 1,025
I'm sorry, but you'll need to think on that one yourself for a bit. I can help once you write some code... for a hint, how would you do something like the following:
Write a function that takes a string (an array of characters) composed of the digits '0'..'9', turns it into an integer, and returns that integer value.
For example:
var i: integer; begin i := str_to_int( '42' ); writeln( 'Converted the string "42" to the integer ', i ) end.
Once you have done that, modify your function to return real values:
var x: real; begin x := str_to_real( '3.141592' ); writeln( 'Converted the string "3.141592" to the floating point value ', x:0:6 ) end.
If you can break your code up into simple problems then all you have to do is solve a bunch of simple problems instead of one big problem. You'll have to do that to complete this assignment.
Once you have some code going, post here with specific problems for more help. Good luck. (And have fun!)
Gotovina7
I got some bad news. I talked to my prof today and he doesn't want us to use records for this assignment. The next assignment will involve records.
Gotovina7
So I started all over since I can't use records. What I wrote here wont compile.
program Assignment6(input, output);
Var
input : text;
temporary_result : real;
equation : string[255];
myArrayEquation : array[1..100] of string[255];
first_digit : char;
num : integer;
BEGIN
assign(input, 'input.txt');
reset(input);
read(input, equation);
end.
procedure ignore_space;
begin
while first_char := ' ' do
read(input, first_digit);
end;
procedure find_number;
begin
num := 0;
while (ord(first_digit) >= ord('0')) and (ord(first_digit) <= ord('9')) do
begin
num := num * 10 + (ord(first_digit)  ord('0'));
read(input, first_digit);
end;
end;
I get these errors
c6.p:23: warning: missing program header
c6.p:23: only one program declaration allowed
c6.p:23: syntax error before `Procedure'
Not sure where I should go from here.
Duoas 1,025
You are thinking in C. Don't put anything after the end. (that's "end" with a period after it). A program looks just like a giant procedure, with subroutines (procedures and functions) in it.
Did your professor tell you how he expects you to store your equation in an array? Or give any direction on how to solve it?
Gotovina7
You are thinking in C. Don't put anything after the end. (that's "end" with a period after it). A program looks just like a giant procedure, with subroutines (procedures and functions) in it.
Did your professor tell you how he expects you to store your equation in an array? Or give any direction on how to solve it?
Ooh I see now.
But yea, my prof didn't really say anything about how we store the equation in the array :(
Duoas 1,025
I think you ought to go sit down with your professor and ask for some more details about how he wants you to solve the problem. If you ask correctly (professors, as all people, generally love to talk about their subject) you might get a lot more information than otherwise, which will help you figure things out. Don't let him push you out. It is his job to help you understand, so if you are still confused about something in particular, just say: "I don't understand why ..." or "If I understand right, I need to ...".
Good luck.
Gotovina7
So basically I need to put the equations into an array, have a procedure that ignore spaces. Another procedure that will evaluate brackets first and so on.
Duoas 1,025
"Yes."
Gotovina7
Man I am just soo lost for this assignment. I keep trying different things but nothing works.
Duoas 1,025
That's because you keep thinking the computer can help you. Computers never help anyone. They're too stupid.
Turn the computer off. Get out some colored paper and some crayons and draw how you (that is, how you, personally) can solve equations like:
1+2+3
9+10
5*(2+3)
(2*(1+3))1
(These are ordered by increasing difficulty.) Be sure to nitpick. "First, my eyeball saw '1'. That's a number. Then my eyeball saw a '+'. That's good, because a number needs to be followed by an operator." Etc.
Once you can tell yourself how to solve the problem, then it is time to start thinking in terms of how to make the computer do it. Each step you made might be one or two or three steps the computer will make. Each one of those steps might be made up of even smaller steps.
For example, a big step might be "find the outermost matching parentheses." A smaller step would be something like "find the first '('", and "find the matching ')' [skipping intervening '(' and ')']".
Start thinking your way through this, then when you think you can explain how to do each collection of steps (both big steps and small steps), then post back and I'll help you more.
Gotovina7
Man I am just soo lost for this assignment. I keep trying different things but nothing works. This is what I got i guess.
program Assignment6(input, output);
Var
file1 : text;
c : char;
error : boolean;
num1 : integer;
function convert(c: char): integer;
begin
convert := ord(c)  ord('0');
end; { convert }
procedure find_digits(num : integer);
num := 0;
while (ord(c) >= ord('0')) and (ord(c) <= ord('9')) do
begin
num := num * 10 + (ord(c)  ord('0'));
read(file1, c);
end;
end; { find_digits }
procedure ignorespaces;
begin
while c = ' ' do
read(file1, c);
end; { ignore_spaces }
BEGIN
assign(file1, 'input.txt');
reset(file1);
read(file1, c);
error := false;
ignorespaces;
If ((ord(c) >= ord('0')) and (ord(c) <= ord('9'))) then
begin
find_digits;
num1 := num;
end;
end.
The problem is the "num1 := num;" part. I can't seem to get this to work. I get undeclared identifier.
Duoas 1,025
Your find_digits is good, but it never lets go of "num". find_digits;
{ What is num? }
I would make it a function: function find_digits( var c: char ): integer;
Then you can learn num: the_number := find_digits( c );
You also need that var c because c is always the next character read from the file. If you don't have that, then the last character read from file by find_digits will be lost. Make sense?
Hope this helps.