230 likes | 488 Views
Programming Errors. Lexical errors – occur whenever Karel reads a word that is not in his vocabulary. Example in English: We are asking directions and instead of saying “How do I get to Portland?” we say “fadt jdhpy hqngrps ggssi sgr ghhgh grmplhms?” In English these are spelling errors.
E N D
Programming Errors • Lexical errors – occur whenever Karel reads a word that is not in his vocabulary. Example in English: We are asking directions and instead of saying “How do I get to Portland?” we say “fadt jdhpy hqngrps ggssi sgr ghhgh grmplhms?” In English these are spelling errors. Example for Karel: We are wanting Karel to turn left and we write TurnToTheLeft();
Syntactic error – when we use incorrect grammar or inaccurate punctuation. Example in English: Suppose we are giving instructions to a lost motorist and we say “for keep hundred just miles going eight.” These errors are grammatical errors in English. Example in Karel: Suppose we wish Karel to turn left and we write ()TurnLeft;
Execution errors – This is caused in a Karel program when Karel is unable to execute an instruction successfully and is forced to perform an error shutoff. For example, we ask Karel to move and he is facing a wall.
Intent (or Logic errors) – This happens when Karel performs a different task than his assigned task. This means that the program is incorrect for the task, but not so incorrect that Karel can discover the error. For example, we wish for Karel to go get his newspaper and come back to bed. However, we forget to issue a PickBeeper() command so when he gets back to bed, he has not completed his assigned task.
All types of errors are known as bugs. Debugging is the name that programmers give to the activity of removing errors from a program.
Good Programming Style • A program that works perfectly is not considered a good program; it is simply a working program. To write a good robot program you must follow these • Guidelines: • a program must be easy to read and understand • a program must be easy to debug • a program must be easy to modify to solve a variation of the original task
Harvesting Problem • The problem: During the summer Karel works as a field laborer. His task is to harvest the field of beepers. He can relax and TurnOff as soon as he has harvested all beepers.
Programming by Stepwise Refinement helps us write “good” programs • Stepwise refinement tells us to first write the program using any instruction names we desire • then write the definitions of the new instruction names used in the program. • Finally assemble all of the definitions into a complete program.
We might solve the harvest problem as follows: #include “karel.h” int main() { TurnOn(); Move(); Harvest2Rows(); PositionForNextHarvest(); Harvest2Rows(); PositionForNextHarvest(); Harvest2Rows(); Move(); TurnOff(); }
The commands Harvest2Rows() and PositionForNextHarvest() are new commands so the next step is to write these commands. We might write the first new command as: void Harvest2Rows() { HarvestARow(); GoToNextRow(); HarvestARow(); } What is our next step to finish this command?
We must now define the commands HarvestARow() and GoToNextRow(). void GoToNextRow() { TurnLeft(); Move(); TurnLeft(); } void HarvestARow() { PickBeeper(); Move(); PickBeeper(); Move(); PickBeeper(); Move(); PickBeeper(); Move(); PickBeeper(); }
All we lack to finish this program is to define the instruction PositionForNextHarvest(); void PositionForNextHarvest() { TurnRight(); Move(); TurnRight(); } The final step is to combine all of the definitions (plus a definition of TurnRight()) into a complete program. Now let’s look at why this is a “good” program by examining two versions of programs that solve this problem.
//First version #include "karel.h“ ... int main() { TurnOn(); Move(); Harvest2Rows(); PositionForNextHarvest(); Harvest2Rows(); PositionForNextHarvest(); Harvest2Rows(); Move(); TurnOff(); } //Second version #include "karel.h" int main() { TurnOn(); Move(); PickBeeper(); Move(); PickBeeper(); ... TurnLeft(); Move(); TurnLeft(); PickBeeper(); Move(); ... TurnLeft(); TurnLeft(); TurnLeft(); Move(); TurnLeft(); TurnLeft(); TurnLeft(); PickBeeper(); Move(); ... TurnOff(); }
Critique of version 1 • After filling in the definitions for the new words, this program will not necessarily be shorter than program 1. However, it seems easy to see what is going on, even if you are not an expert in robot programming. It is easy to read. • If one of the instructions does not work, we can concentrate on fixing it. Once it is fixed, it will continue to work correctly at every point where it is used.Therefore, the program is easy to debug. • If, say, another pair of rows (or columns) of beepers grows overnight, this program could very easily be modified. Just add a couple of lines and those rows will be harvested as well. It is easy to extend.
Critique of Version 2 • This program is correct and works (after the dots are filled in, of course). However, it is very difficult to take a quick look at the program and decide what it is doing. It is unreadable. • It is easy to forget one of the instructions, in which case the whole program would either lead to an error shutoff or to an intent error. However, it would be difficult to find the missing (or superfluous) instruction. It is hard to debug. • If, say, another row (or column) of beepers grows overnight, this program would need a whole slew of new instructions. It is difficult to extend.
Karel’s Sensory Equipment • Karel has three video cameras, a microphone, a compass, and tactile sensors to help him stay out of trouble. He can request information from his sensory equipment: frontIsClear, frontIsBlocked, nextToABeeper, etc. • Each request will result in a true or false answer. We call such requests that are either true or false predicates.
Decision statements • Karel can check predicates by using what is called an IF construct. These constructs can be used wherever instructions are used in a program. In the C/C++ language, there are two variations of the IF statement • The simple IF • The compound IF-THEN-ELSE
if (predicate) { <then-clause statement(s)> } If the predicate is true the statements in the then clause are executed and then the instruction immediately after the then clause. If the predicate is false, then the statements in the then clause are not executed and we jump to the instruction immediately following the then clause. Simple If
if(predicate) { <then-clause statement(s)> } else { <else-clause statement(s)> } If the predicate is true, the instructions in the then clause are executed then the instruction immediately after the then clause If the predicate is false, the instructions in the else clause are executed then the instruction immediately after the then clause Compound If
frontIsClear leftIsClear rightIsClear facingNorth facingSouth facingEast facingWest nextToABeeper noBeepersInBeeperBag frontIsBlocked leftIsBlocked rightIsBlocked notFacingNorth notFacingSouth notFacingEast notFacingWest notNextToABeeper anyBeeperInBeeperBag Karel’s Predicates
if (nextToABeeper) { PickBeeper(); } if (frontIsClear) { Move(); } else { TurnLeft(); } void FaceNorthIfFacingSouth() { if (facingSouth) { TurnLeft(); TurnLeft(); } } Examples
void Escape() { if (frontIsClear) { Move(); TurnLeft(); } else { TurnLeft(); Move(); } } void GiveOrTake() { if (nextToABeeper) { if (anyBeepersInBeeperBag) { PutBeeper(); } else { PickBeeper(); } } }
Original code: if (nextToABeeper) { PickBeeper(); } Move(); Code with braces omitted if (nextToABeeper) PickBeeper(); Move(); Braces can be omitted when the then or else clause contains only one statement