38
Chapter 6 Chapter 6 Writing a Program Writing a Program Bjarne Stroustrup Bjarne Stroustrup www.stroustrup.com/Programming www.stroustrup.com/Programming

6_writing

Embed Size (px)

DESCRIPTION

writing

Citation preview

Page 1: 6_writing

Chapter 6Chapter 6Writing a ProgramWriting a Program

Bjarne StroustrupBjarne Stroustrup

www.stroustrup.com/Programmingwww.stroustrup.com/Programming

Page 2: 6_writing

OverviewOverview

Some thoughts on software developmentSome thoughts on software development The idea of a calculatorThe idea of a calculator Using a grammarUsing a grammar Expression evaluationExpression evaluation Program organizationProgram organization

33Stroustrup/Programming/2015Stroustrup/Programming/2015

Page 3: 6_writing

Stroustrup/Programming/2015Stroustrup/Programming/2015 44

Page 4: 6_writing

Building a programBuilding a program

AnalysisAnalysis Refine our understanding of the problemRefine our understanding of the problem

Think of the final use of our programThink of the final use of our program

DesignDesign Create an overall structure for the programCreate an overall structure for the program

ImplementationImplementation Write codeWrite code DebugDebug TestTest

Go through these stages repeatedlyGo through these stages repeatedly

55Stroustrup/Programming/2015Stroustrup/Programming/2015

Page 5: 6_writing

Writing a program: StrategyWriting a program: Strategy

What is the problem to be solved?What is the problem to be solved? Is the problem statement clear?Is the problem statement clear? Is the problem manageable, given the time, skills, and tools available?Is the problem manageable, given the time, skills, and tools available?

Try breaking it into manageable partsTry breaking it into manageable parts Do we know of any tools, libraries, etc. that might help?Do we know of any tools, libraries, etc. that might help?

Yes, even this early: Yes, even this early: iostreamiostreams, s, vectorvector, etc., etc. Build a small, limited version solving a key part of the problemBuild a small, limited version solving a key part of the problem

To bring out problems in our understanding, ideas, or toolsTo bring out problems in our understanding, ideas, or tools Possibly change the details of the problem statement to make it manageablePossibly change the details of the problem statement to make it manageable

If that doesn’t workIf that doesn’t work Throw away the first version and make another limited versionThrow away the first version and make another limited version Keep doing that until we find a version that weKeep doing that until we find a version that we’’re happy withre happy with

Build a full scale solutionBuild a full scale solution Ideally by using part of your initial versionIdeally by using part of your initial version

66Stroustrup/Programming/2015Stroustrup/Programming/2015

Page 6: 6_writing

Programming is also a practical stillProgramming is also a practical still

We learn by exampleWe learn by example Not by just seeing explanations of principlesNot by just seeing explanations of principles Not just by understanding programming language rulesNot just by understanding programming language rules

The more and the more varied examples the betterThe more and the more varied examples the better You won’t get it right the first timeYou won’t get it right the first time ““You can’t learn to ride a bike from a correspondence course”You can’t learn to ride a bike from a correspondence course”

Stroustrup/Programming/2015Stroustrup/Programming/2015 77

Page 7: 6_writing

Writing a program: ExampleWriting a program: Example

I’ll build a program in stages, making lot of I’ll build a program in stages, making lot of ““typical mistakestypical mistakes”” along the way along the way Even experienced programmers make mistakesEven experienced programmers make mistakes

Lots of mistakes; itLots of mistakes; it’s a necessary part of learning’s a necessary part of learning

Designing a good program is genuinely difficultDesigning a good program is genuinely difficult ItIt’s often faster to let the compiler detect gross mistakes ’s often faster to let the compiler detect gross mistakes

than to try to get every detail right the first timethan to try to get every detail right the first time Concentrate on the important design choicesConcentrate on the important design choices

Building a simple, incomplete version allows us to Building a simple, incomplete version allows us to experiment and get feedbackexperiment and get feedback

Good programs are Good programs are “grown”“grown”

88Stroustrup/Programming/2015Stroustrup/Programming/2015

Page 8: 6_writing

A simple calculatorA simple calculator

Given expressions as input from the keyboard, Given expressions as input from the keyboard, evaluate them and write out the resulting valueevaluate them and write out the resulting value For exampleFor example

Expression: 2+2Expression: 2+2 Result: 4Result: 4 Expression: 2+2*3Expression: 2+2*3 Result: 8Result: 8 Expression: 2+3-25/5Expression: 2+3-25/5 Result: 0Result: 0

Let’s refine this a bit more …Let’s refine this a bit more …

99Stroustrup/Programming/2015Stroustrup/Programming/2015

Page 9: 6_writing

Pseudo CodePseudo Code

A first idea:A first idea:

int main()int main() {{

variablesvariables // // pseudo codepseudo codewhile (get a line) {while (get a line) { // // whatwhat’’s a line?s a line?

analyze the expressionanalyze the expression // // what does that what does that mean?mean?

evaluate the expressionevaluate the expressionprint the resultprint the result

}}}}

HHow do we represent ow do we represent 45+5/745+5/7 as data? as data? HHow do we find ow do we find 45 + 5 / 45 + 5 / andand 7 7 in an input string? in an input string? How do we make sure that How do we make sure that 45+5/745+5/7 means means 45+(5/7)45+(5/7) rather than rather than (45+5)/7(45+5)/7?? Should we allow floating-point numbers (sure!)Should we allow floating-point numbers (sure!) CCan we have variables? an we have variables? v=7; m=9; v*mv=7; m=9; v*m (later) (later) 1010Stroustrup/Programming/2015Stroustrup/Programming/2015

Page 10: 6_writing

A simple calculatorA simple calculator

Wait!Wait! We are just about to reinvent the wheel!We are just about to reinvent the wheel! Read Chapter 6 for more examples of dead-end approachesRead Chapter 6 for more examples of dead-end approaches

What would the experts do?What would the experts do? Computers have been evaluating expressions for 50+ yearsComputers have been evaluating expressions for 50+ years There There hashas to be a solution! to be a solution! What What diddid the experts do? the experts do?

Reading is good for youReading is good for you Asking more experienced friends/colleagues can be far more effective, Asking more experienced friends/colleagues can be far more effective,

pleasant, and time-effective than slogging along on your ownpleasant, and time-effective than slogging along on your own ““Don’t re-invent the wheel”Don’t re-invent the wheel”

1111Stroustrup/Programming/2015Stroustrup/Programming/2015

Page 11: 6_writing

Expression GrammarExpression Grammar This is what the experts usually do – write a This is what the experts usually do – write a grammargrammar::

Expression :Expression :TermTermExpression Expression ‘‘++’’ Term Term e.g.e.g., , 1+21+2,, (1-2)+3 (1-2)+3,, 2*3+1 2*3+1Expression Expression ‘‘--’’ Term Term

Term :Term :PrimaryPrimaryTerm Term ‘‘**’’ Primary Primary e.g.e.g., , 1*21*2, , (1-2)*3.5(1-2)*3.5Term Term ‘‘//’’ Primary PrimaryTerm Term ‘‘%%’’ Primary Primary

Primary :Primary :NumberNumber e.g.e.g., , 11, , 3.53.5‘‘((‘‘ Expression Expression ‘‘))’’ e.g.e.g., , (1+2*3)(1+2*3)

Number :Number :floating-point literalfloating-point literal e.g.e.g., , 3.143.14, , 0.274e10.274e1, or , or 42 42 – as defined for – as defined for C++C++

A program is built out of Tokens (A program is built out of Tokens (e.g.e.g., numbers and operators)., numbers and operators). 1212Stroustrup/Programming/2015Stroustrup/Programming/2015

Page 12: 6_writing

A side trip: GrammarsA side trip: Grammars

What’s a What’s a grammargrammar? ? A set of (syntax) rules for expressions.A set of (syntax) rules for expressions.

The rules say how to analyze (The rules say how to analyze (“parse”) an expression.“parse”) an expression. Some rules seem hard-wired into our brainsSome rules seem hard-wired into our brains Example, you know what this means:Example, you know what this means:

2*3+4/22*3+4/2 birds fly but fish swimbirds fly but fish swim

You know that this is wrong:You know that this is wrong: 2 * + 3 4/22 * + 3 4/2 fly birds fish but swimfly birds fish but swim

How can we teach what we know to a computer?How can we teach what we know to a computer? Why is it right/wrong?Why is it right/wrong? How do we know?How do we know?

1313Stroustrup/Programming/2015Stroustrup/Programming/2015

Page 13: 6_writing

Grammars – Grammars – ““EnglishEnglish””

1414Stroustrup/Programming/2015Stroustrup/Programming/2015

Page 14: 6_writing

Grammars - expressionGrammars - expression

1515Stroustrup/Programming/2015Stroustrup/Programming/2015

Page 15: 6_writing

Grammars - expressionGrammars - expression

1616Stroustrup/Programming/2015Stroustrup/Programming/2015

Page 16: 6_writing

Grammars - expressionGrammars - expression

1717Stroustrup/Programming/2015Stroustrup/Programming/2015

Page 17: 6_writing

Functions for parsingFunctions for parsing

WWe need functions to match the grammar rulese need functions to match the grammar rules

get()get() //// read characters and compose tokensread characters and compose tokens//// calls calls cincin for input for input

expression()expression() //// deal with + and –deal with + and –//// calls calls term() term() andand get() get()

term()term() //// deal with *, /, and %deal with *, /, and %//// calls calls primary() primary() andand get() get()

primary()primary() //// deal with numbers and parenthesesdeal with numbers and parentheses//// calls calls expression() expression() andand get() get()

NoteNote: each function deals with a specific part of an expression and leaves: each function deals with a specific part of an expression and leaveseverything else to other functions – this radically simplifies each function.everything else to other functions – this radically simplifies each function.

AnalogyAnalogy: a group of people can deal with a complex problem by each person: a group of people can deal with a complex problem by each personhandling only problems in his/her own specialty, leaving the rest for colleagues.handling only problems in his/her own specialty, leaving the rest for colleagues.

1818Stroustrup/Programming/2015Stroustrup/Programming/2015

Page 18: 6_writing

Function Return TypesFunction Return Types

What should the parser functions return? What should the parser functions return? How about the result?How about the result?

Token get_token();Token get_token(); //// read characters and compose tokensread characters and compose tokensdouble expression();double expression(); //// deal with + and –deal with + and –

//// return the sum (or difference)return the sum (or difference)double term();double term(); //// deal with *, /, and %deal with *, /, and %

//// return the product (or …)return the product (or …)double primary();double primary(); //// deal with numbers and parenthesesdeal with numbers and parentheses

//// return the valuereturn the value

What is a What is a TokenToken??

1919Stroustrup/Programming/2015Stroustrup/Programming/2015

Page 19: 6_writing

What is a token?What is a token?

We want to see input as a stream of tokensWe want to see input as a stream of tokens We read charactersWe read characters 1 + 4*(4.5-6) 1 + 4*(4.5-6) (That(That’s 13 characters incl. 2 spaces)’s 13 characters incl. 2 spaces) 9 tokens in that expression: 9 tokens in that expression: 1 + 4 * ( 4.5 - 6 )1 + 4 * ( 4.5 - 6 ) 6 kinds of tokens in that expression: number 6 kinds of tokens in that expression: number + * ( - )+ * ( - )

We want each token to have two partsWe want each token to have two parts A A ““kindkind””; e.g., number; e.g., number A value; e.g., A value; e.g., 44

We need a type to represent this We need a type to represent this ““TokenToken”” idea idea WeWe’’ll build that in the next lecture, but for now:ll build that in the next lecture, but for now:

get_token()get_token() gives us the next token from input gives us the next token from input t.kindt.kind gives us the kind of the token gives us the kind of the token t.valuet.value gives us the value of the token gives us the value of the token

2020

+number

4.5

Stroustrup/Programming/2015Stroustrup/Programming/2015

Page 20: 6_writing

Dealing with + and -Dealing with + and -

Expression:Expression:TermTermExpression '+' TermExpression '+' Term // // Note: every Expression starts with a TermNote: every Expression starts with a TermExpression '-' TermExpression '-' Term

double expression()double expression() // // read and evaluate: 1 1+2.5 1+2+3.14 etc.read and evaluate: 1 1+2.5 1+2+3.14 etc.{{

double left = term(); double left = term(); // // get the Termget the Termwhile (true) {while (true) {

Token t = get_token();Token t = get_token(); // // get the next token…get the next token…switch (t.kind) {switch (t.kind) { // // … and do the right thing with it… and do the right thing with itcase '+':case '+': left += term(); break; left += term(); break;case '-':case '-': left -= term(); break; left -= term(); break;default:default: return left;return left; // // return the value of the return the value of the

expressionexpression}}

}}}}

2121Stroustrup/Programming/2015Stroustrup/Programming/2015

Page 21: 6_writing

Dealing with *, /, and %Dealing with *, /, and %

double term()double term() // // exactly like expression(), but for *, /, and %exactly like expression(), but for *, /, and %{{

double left = primary(); double left = primary(); // // get the Primaryget the Primarywhile (true) {while (true) {

Token t = get_token();Token t = get_token(); // // get the next Token…get the next Token…switch (t.kind) {switch (t.kind) {case '*':case '*': left *= primary(); break; left *= primary(); break;case '/':case '/': left /= primary(); break; left /= primary(); break;case '%': left %= primary(); break;case '%': left %= primary(); break;default:default: return left;return left; // // return the valuereturn the value}}

}}}}

Oops: doesnOops: doesn’’t compilet compile % isn% isn’’t defined for floating-point numberst defined for floating-point numbers

2222Stroustrup/Programming/2015Stroustrup/Programming/2015

Page 22: 6_writing

Dealing with * and /Dealing with * and /Term :Term :

PrimaryPrimaryTerm Term ‘‘**’’ Primary Primary // // Note: every Term starts with a PrimaryNote: every Term starts with a PrimaryTerm Term ‘‘//’’ Primary Primary

double term()double term() // // exactly like expression(), but for *, and /exactly like expression(), but for *, and /{{

double left = primary(); double left = primary(); // // get the Primaryget the Primarywhile (true) {while (true) {

Token t = get_token();Token t = get_token(); // // get the next Tokenget the next Tokenswitch (t.kind) {switch (t.kind) {case '*':case '*': left *= primary(); break; left *= primary(); break;case '/':case '/': left /= primary(); break; left /= primary(); break;default:default: return left;return left; // // return the valuereturn the value}}

}}}}

2323Stroustrup/Programming/2015Stroustrup/Programming/2015

Page 23: 6_writing

Dealing with divide by 0Dealing with divide by 0double term()double term() // // exactly like expression(), but for * and /exactly like expression(), but for * and /{{

double left = primary(); double left = primary(); // // get the Primaryget the Primarywhile (true) {while (true) {Token t = get_token();Token t = get_token(); // // get the next Tokenget the next Tokenswitch (t.kind) {switch (t.kind) {case '*':case '*':left *= primary();left *= primary();break;break;case '/':case '/': {{ double d = primary();double d = primary();if (d==0) error("divide by zero");if (d==0) error("divide by zero");left /= d;left /= d;break;break; }}default:default:return left;return left; // // return the valuereturn the value}}}}

}}

2424Stroustrup/Programming/2015Stroustrup/Programming/2015

Page 24: 6_writing

Dealing with numbers and parenthesesDealing with numbers and parentheses double primary()double primary() // // Number or Number or ‘‘((‘‘ Expression Expression ‘‘))’’{{

Token t = get_token();Token t = get_token();switch (t.kind) {switch (t.kind) {case '(':case '(': // // handle handle ‘‘((’’expression expression ‘‘))’’ {{ double d = expression();double d = expression();

t = get_token();t = get_token();if (t.kind != ')') error("')' expected");if (t.kind != ')') error("')' expected");return d;return d;

}}case '8':case '8': // // we use we use ‘‘88’’ to represent the to represent the ““kindkind”” of a number of a number

return t.value;return t.value; // // return the numberreturn the number’’s values valuedefault:default:

error("primary expected");error("primary expected");}}

}}2525Stroustrup/Programming/2015Stroustrup/Programming/2015

Page 25: 6_writing

Program organizationProgram organization

Who calls whom? Who calls whom? (note the loop)(note the loop)2626

primary()

expression()

term()

main()

istreamcin>>

error()Token

ostreamcout<<

get_token()

Stroustrup/Programming/2015Stroustrup/Programming/2015

Page 26: 6_writing

The programThe program

#include "std_lib_facilities.h"#include "std_lib_facilities.h"

// // Token stuff (explained in the next lecture)Token stuff (explained in the next lecture)

double expression(); // double expression(); // declaration so that primary() can call declaration so that primary() can call expression()expression()

double primary() { /* double primary() { /* …… */ } */ } // // deal with numbers and parenthesesdeal with numbers and parenthesesdouble term() { /* double term() { /* …… */ } */ } //// deal with * and / (pity about %)deal with * and / (pity about %)double expression() { /* double expression() { /* …… */ } */ } //// deal with + and –deal with + and –

int main() { /* int main() { /* …… */ } */ } // // on next slideon next slide

2727Stroustrup/Programming/2015Stroustrup/Programming/2015

Page 27: 6_writing

The program – main()The program – main()

int main()int main()try {try {

while (cin)while (cin) cout << expression() << '\n';cout << expression() << '\n';

keep_window_open();keep_window_open(); // // for some Windows versionsfor some Windows versions}}catch (runtime_error& e) {catch (runtime_error& e) {

cerr << e.what() << endl;cerr << e.what() << endl;keep_window_open ();keep_window_open ();return 1;return 1;

}}catch (…) {catch (…) {

cerr << "exception \n";cerr << "exception \n";keep_window_open ();keep_window_open ();return 2;return 2;

}}2828Stroustrup/Programming/2015Stroustrup/Programming/2015

Page 28: 6_writing

A mysteryA mystery

22 33 44 22 an answeran answer 5+65+6 55 an answeran answer XX Bad tokenBad token an answer (finally, an expected answer)an answer (finally, an expected answer)

2929Stroustrup/Programming/2015Stroustrup/Programming/2015

Page 29: 6_writing

A mysteryA mystery

Expect “mysteries”Expect “mysteries” Your first try rarely works as expectedYour first try rarely works as expected

That’s normal and to be expectedThat’s normal and to be expected Even for experienced programmersEven for experienced programmers

If it looks as if it works be suspiciousIf it looks as if it works be suspicious And test a bit moreAnd test a bit more

Now comes the debuggingNow comes the debugging Finding out why the program misbehavesFinding out why the program misbehaves

And don’t expect your second try to work eitherAnd don’t expect your second try to work either

Stroustrup/Programming/2015Stroustrup/Programming/2015 3030

Page 30: 6_writing

A mysteryA mystery

1 2 3 4+5 6+7 8+9 10 11 121 2 3 4+5 6+7 8+9 10 11 12 11 an answeran answer 44 an answeran answer 66 an answeran answer 88 an answeran answer 1010 an answeran answer

Aha! Our program “eats” two out of three inputsAha! Our program “eats” two out of three inputs How come?How come? LetLet’’s have a look at expression()s have a look at expression()

3131Stroustrup/Programming/2015Stroustrup/Programming/2015

Page 31: 6_writing

Dealing with + and -Dealing with + and -

Expression:Expression:TermTermExpression Expression ‘‘++’’ Term Term // // Note: every Expression starts with a TermNote: every Expression starts with a TermExpression Expression ‘‘--’’ Term Term

double expression()double expression() // // read and evaluate: 1 1+2.5 1+2+3.14 etc.read and evaluate: 1 1+2.5 1+2+3.14 etc.{{

double left = term(); double left = term(); // // get the Termget the Termwhile (true) {while (true) {

Token t = get_token();Token t = get_token(); // // get the next token…get the next token…switch (t.kind) {switch (t.kind) { // // … and do the right thing with it… and do the right thing with itcase '+':case '+': left += term(); break; left += term(); break;case '-':case '-': left -= term(); break; left -= term(); break;default:default: return left;return left; // // <<< doesn’t use “next token”<<< doesn’t use “next token”}}

}}}} 3232Stroustrup/Programming/2015Stroustrup/Programming/2015

Page 32: 6_writing

Dealing with + and -Dealing with + and -

So, we need a way to “put back” a token!So, we need a way to “put back” a token! Put back into what?Put back into what? ““the input,” of course: we need an input stream of tokens, a “token stream”the input,” of course: we need an input stream of tokens, a “token stream”

double expression()double expression() // // deal with + and -deal with + and -{{

double left = term(); double left = term(); while (true) {while (true) {

Token t = ts.get();Token t = ts.get(); // // get the next token from a get the next token from a ““token streatoken streamm””

switch (t.kind) {switch (t.kind) {case '+':case '+': left += term(); break; left += term(); break;case '-':case '-': left -= term(); break; left -= term(); break;default:default: ts.putback(t); // ts.putback(t); // put the unused token backput the unused token back

return left;return left;}}

}}}}

3333Stroustrup/Programming/2015Stroustrup/Programming/2015

Page 33: 6_writing

Dealing with * and /Dealing with * and / Now make the same change to Now make the same change to term()term()

double term()double term() // // deal with * and /deal with * and /{{

double left = primary(); double left = primary(); while (true) {while (true) {

Token t = ts.get();Token t = ts.get(); // // get the next Token from inputget the next Token from inputswitch (t.kind) {switch (t.kind) {case '*':case '*':

// // deal with *deal with *case '/':case '/':

// // deal with /deal with /default:default:

ts.putback(t);ts.putback(t); // // put unused token back into input streamput unused token back into input streamreturn left;return left;

}}}}

}}

3434Stroustrup/Programming/2015Stroustrup/Programming/2015

Page 34: 6_writing

The programThe program

It “sort of works”It “sort of works” ThatThat’’s not bad for a first trys not bad for a first try

Well, second tryWell, second try Well, really, the fourth try; see the bookWell, really, the fourth try; see the book

But But “sort of works” is not good enough“sort of works” is not good enough When the program When the program “sort of works” is when the work (and “sort of works” is when the work (and

fun) really startfun) really start Now we can get feedback!Now we can get feedback!

3535Stroustrup/Programming/2015Stroustrup/Programming/2015

Page 35: 6_writing

Another mysteryAnother mystery

2 3 4 2+3 2*32 3 4 2+3 2*3 22 an answeran answer 33 an answeran answer 44 an answeran answer 55 an answeran answer

What! No “6” ?What! No “6” ? The program looks ahead one tokenThe program looks ahead one token

ItIt’s waiting for the user’s waiting for the user

So, we introduce a So, we introduce a “print result” command“print result” command While weWhile we’re at it, we also introduce a “quit” command’re at it, we also introduce a “quit” command

3636Stroustrup/Programming/2015Stroustrup/Programming/2015

Page 36: 6_writing

The main() programThe main() program

int main()int main(){{

double val = 0;double val = 0;while (cin) {while (cin) {

Token t = ts.get();Token t = ts.get(); // // rather than get_token()rather than get_token()if (t.kind == 'q') break;if (t.kind == 'q') break; // // ‘‘qq’’ for for ““quitquit””if (t.kind == ';')if (t.kind == ';') // // ‘‘;;’’ for for ““print nowprint now””

cout << val << '\n';cout << val << '\n'; // // print resultprint resultelseelse

ts. ts. putbackputback(t);(t); // // put a token back into the input put a token back into the input streamstream

val = expression();val = expression(); // // evaluateevaluate}}keep_window_open();keep_window_open();

}}// // … exception handling …… exception handling …

3737Stroustrup/Programming/2015Stroustrup/Programming/2015

Page 37: 6_writing

Now the calculator is minimally usefulNow the calculator is minimally useful

2;2; 22 an answeran answer 2+3;2+3; 55 an answeran answer 3+4*5;3+4*5; 2323 an answeran answer qq

3838Stroustrup/Programming/2015Stroustrup/Programming/2015

Page 38: 6_writing

Next lectureNext lecture

Completing a programCompleting a program TokensTokens Recovering from errorsRecovering from errors Cleaning up the codeCleaning up the code Code reviewCode review TestingTesting

3939Stroustrup/Programming/2015Stroustrup/Programming/2015