CS 228 lecture -*- Outline -*- * statements (HR A.13) ** syntax *** overview ----------------------- KINDS OF STATEMENTS expression: cout << 4; declaration: int count = 7; extern double cos(double); empty: ; compound: x = 1; y = 2; block: { int i; i = x + y; x = i; } control: if (alpha == 3) { cout << "it's 3\n"; } ----------------------- we'll talk about control in a second. ---------------------------- SYNTAX NOTES Statements end in semicolon Generally don't put a semicolon after } but do put a semicolon before } { int i; i = x + y; x = i; } ---------------------------- Q: any question about the details? *** reading a grammar (HR 6.2, HR Appendix K, DD Appendix A) There are also syntax charts for C++ in HR Appendix J -------------------------- READING A BNF GRAMMAR Example rules: ::= 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 ::= 0 | ::= | ::= -------------------------- Q: can you give some examples of these? Caveat: the above grammar is lexical, that is the terminals are characters instead of symbols ------------------------------ STATEMENT GRAMMAR (A SUBSET OF C++) ::= | | ; | ; | | while ( ) { } | do { } while ( ) ; | for ( ; ){ } | break ; | continue ; | | return ; | return ; ------------------------------- Explain the sematics of each. The above is really a lie, you don't need all these { and }, but this is what I use, and it's safe. Note has its own semicolon at end -------------------------------- ::= if ( ) { } | if ( ) { } else { } | if ( ) { } else -------------------------------- Give examples of above, this is to avoid terrible indentation example: quadratic with test for 0 discriminant, negative discriminant, positive modify it one more time, show "if" syntax and variations ------------------------------- ::= { } ::= | ::= ::= switch ( ) { } | switch ( ) { } ::= | ::= break ; ::= | ::= case : ::= default: break ; | default: ------------------------------- The above rule is sensible, but more limiting than reality. See the references for the gory details. -------------------------- EXTENSIONS TO BNF GRAMMARS Headington and Riley optional text: ::= [ ] zero or more repetitions: ::= { } quotation of terminals: ::= "0" | Deitel and Deitel: optional text: ::= opt -------------------------- In general, read the preface to the grammar to get familiar with the notation ** examples of while loops *** infinite loops ------------------------------ // powers-of-2.C #include int main() { int i = 1; while (1) { cout << i << "\n"; i *= 2; } // ASSERT: false (never get here) } ---------------------- Run this by piping output to "more"... Lessons from this: finiteness of C++ int type (and others) see limits.h for limits on each machine/compiler. arithmetic overflows not checked (wrapping to 0) how to use the OS to stop an infinite loop to get out of a loop, the condition has to become false (0). *** count char types (switch, while, char input, end-of-file) ----------------------- PROBLEM Write a program to count the number of digits, operators (+, -, *, /) and other characters typed as input. ------------------------ develop this in class Compare to DD Fig 2.2 **** psuedo-code outline SNAPSHOT 1 // count-char-types.C // Name: Gary T. Leavens // TA: Bjarne Stroustrup // Section: A1 #include int main() // MODIFIES: cin, cout // POST: a prompt is written to cout, // then characters are input from cin up to an EOF, // then summary information about the number of // digits, operators (+, -, *, /) and other non-whitespace characters // is written to cout. { // prompt for input // initialize state // while still have input, update the state according to the char type // print summary info return 0; } **** first draft SNAPSHOT 2 // count-char-types.C // Name: Gary T. Leavens // TA: Bjarne Stroustrup // Section: A1 #include #include "prompt.h" int main() // MODIFIES: cin, cout // POST: a prompt is written to cout, // then characters are input from cin up to an EOF, // then summary information about the number of // digits, operators (+, -, *, /) and other non-whitespace characters // is written to cout. { // prompt for input prompt("Type input for char type counting, please.\n" "End input with an end-of-file (EOF) character.\n"); // initialize state int digitCount = 0; int operatorCount = 0; int otherCount = 0; char ch; cin >> ch; while (cin) { // update the state cin >> ch; } // print summary info return 0; } **** commentary on loop initialization (setup) and progress above draft is typical of loops: initialization code somewhere in loop, have to make sure making progress **** C++ details adjacent strings in prompt are concatenated; so don't have to continue over lines. ***** cin in tests The use of cin in the test for a while is explained in DD 11.4, for now it's just and idiom that is false when cin has reached EOF (or an error). ***** cin and whitespace cin >> ch skips over whitespace. See DD chapter 11 for ways around this (using cin.get() or cin.unsetf(ios::skipws)) Alternative: int ch = cin.get(); ... while (ch != EOF) { ... } ***** side effects in tests and redundancy someone may already object to not using side effects in exprs. note you can do that, and it does eliminate redundancy **** loop body SNAPSHOT 3 // count-char-types.C // Name: Gary T. Leavens // TA: Bjarne Stroustrup // Section: A1 #include #include "prompt.h" int main() // MODIFIES: cin, cout // POST: a prompt is written to cout, // then characters are input from cin up to an EOF, // then summary information about the number of // digits, operators (+, -, *, /) and other non-whitespace characters // is written to cout. { // prompt for input prompt("Type input for char type counting, please.\n" "End input with an end-of-file (EOF) character.\n"); // initialize state int digitCount = 0; int operatorCount = 0; int otherCount = 0; char ch; cin >> ch; while (cin) { // update the state switch (ch) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': digitCount++; break; case '+': case '-': case '*': case '/': case '%': operatorCount++; break; default: otherCount++; break; } cin >> ch; } // print summary info cout << "\nSummary counts for the characters you typed:\n" << " Number of digits = " << digitCount << "\n" << " Number of operators = " << operatorCount << "\n" << " Number of other characters = " << otherCount << "\n"; return 0; } *** student exercise -------------------------- FOR YOU TO DO Write a program that reads numbers and prints their average. Assume the numbers are type double Assume all inputs are numbers. -------------------------- ** for loops discuss definite iteration vs. indefinite *** example ------------------------- PROBLEM Write a program that inputs two integers, x and y, with y>0, and outputs x to the y power. ------------------------- **** student exercise --------------------------- FOR YOU TO DO Write a program that inputs an integer n, and outputs sum from 1 to n of 1/(n^2 + 1). Use double precision numbers, and a for loop. --------------------------- ** do loops note seldom used. Syntax errors possible, as needs semicolon at end. *** example (if time) convert quadratic program to ask user if wants to do any more solutions before exiting, do { // existing stuff } while( ask_yn("another (y/n)") ); ** break and continue in loops show how to do test in the middle iterations *** example (if time) quadratic with break out of loop when input has negative discriminant quadratic with continue when discriminant is 0 SNAPSHOT OMEGA // quadratic.C // Name: Gary T. Leavens // TA: Bjarne Stroustrup // Section: A1 #include #include #include "prompt.h" #include "ask_yn.h" int main() // MODIFIES: cin, cout // POST: cout has prompts for a, b, and c written to it, // and after each prompt, the corresponding double is read from cin; // finally cout has the two roots printed. { double a, b, c; int ret_code; do { // read in a, b, and c prompt("a? "); cin >> a; prompt("b? "); cin >> b; prompt("c? "); cin >> c; double discriminant = b*b - 4*a*c; double a_twice = 2*a; double minus_b = -b; if (discriminant > 0.0) { double sqrt_d = sqrt(discriminant); cout << "The positive root is: "; cout << (minus_b + sqrt_d)/(a_twice) << endl; cout << "The negative root is: "; cout << (minus_b - sqrt_d)/(a_twice) << endl; ret_code = 0; } else if (discriminant == 0.0) { cout << "roots same" << endl; continue; } else { cerr << "the discriminant is negative" << endl; ret_code = 1; break; } cout << "end of it" << endl; } while (ask_yn("another one (y/n)? ")); return ret_code; } ///////////////////////// // ask_yn.h #include "pretend_bool.h" extern bool ask_yn(char * promptstring); // MODIFIES: cout, cin // POST: cout has prompt added to it, and cin has a character read from it // and FCTVAL is true if either 'y' or 'Y' was read, and false otherwise. //////////////////////////// // ask_yn.C #include #include "prompt.h" #include "ask_yn.h" bool ask_yn(char * promptstring) { prompt(promptstring); char ch; cin >> ch; return cin && (ch == 'y' || ch == 'Y'); } // @(#)$Id: pretend_bool.h,v 1.2 1994/09/25 22:59:26 leavens Exp $ #ifndef pretend_bool_h #define pretend_bool_h typedef int bool; enum {false=0, true=1}; #endif