-----BASIC C++ PROGRAM TEMPLATE----- #include using namespace std; int main (int argc, char **argv) { /* Variable Declaration */ /* Instructions */ return 0; } ------ COMMENTS --------------- /* Put explanatory messages for yourself and other programmers (not the computer) in comments like this one */ //single line comments look like this ------EDIT SAVE COMPILE RUN ------------- or EDIT, SAVE, COMPILE, FIX COMPILER ERRORS, RUN, CHECK OUTPUT 1) Edit your code with an editor like emacs or nano (learning to navigate in at least one editor on polaris is going to be important for this class) E.g. emacs -nw my program.cpp OR nano myprogram.cpp Remember to save you changes! 2) Compile your code with a compiler (translates human readable source code into executable format the computer needs to actually run the program) E.g. g++ myprogram.cpp Fix any compiler errors! Go to first problem by it's line number and fix. 3) Run your program E.g. ./a.out Check that the output of the program is what you expect -----SIMPLE TYPES----- TYPE EXAMPLES int 0,1, -1, 2, -2,... unsigned int 0, 1, 2,3, 4, ... float 2.89, 67777799.0, -1000000000.0 double char 'a', 'Z', '\n' bool true, false string "August", "This sentence is a string" possible numeric values are not infinite like in math - e.g. there is a fixed amount of space to store an int and so unlike in real like there is a maximum integer unsigned int vs int - use space to store all positives vs half positive and half negative unsigned and int vs float float can store bigger and smaller numbers but to do so can give up precision float vs double - more space used for both bigger numbers and more precise numbers -----SAMPLE VARIABLE DECLARATIONS------ int month; char answer; bool isReady = false; char initial = 'A'; float wage = 8.50; string name = "John Smith"; unsigned int year = 1996; Remember to use descriptive variable names!! -----INPUT/OUTPUT---- Read data from user into a variable cin >> variable; Write data out to user cout << "Hi\n"; cout << "Hi " << name << "\n"; cout << "Hi " << name << endl; ----- ARITHMETIC OPERATORS------- + add * multiple - subtract / divide (remember for ints gives just whole number part of answer, cuts off any decimal portion) % modulus (gives integer remainder after division) remember order of operations like in math can use parentheses to force/clarify the order you want ----- ASSIGNMENT STATEMENTS------- Example assignment statements hoursPerMonth = daysPerMonth*24; age = age+1; index = index -1; total_price = num_item1 * item1_price + num_item2 *item2_price; ------------------------------- Normal arithmetic expression: x = x+1; A few shortcuts worth knowing that do the same thing: x++; ++x; x++ uses x and then increments it ++x increments x and then uses it. If only use is incrementing then they do the same thing. ------- BOOLEAN EXPRESSIONS -------- boolean expressions evaluate to true or false Example boolean expressions bool isTransferStudent; (isTransferStudent) (month > 2) (answer == 'Y') ------ COMPARE OPERATORS ----------- == equal (Remember one = sets something equal. Two == tests if two things are equal) (Also remember that it is dangerous to test doubles with == they may be very very close but not identical in precision) != not equal > greater than >= greater than or equal < less than <= less than or equal ------ BOOLEAN OPERATORS ---------- && AND || OR Combine boolean expressions to make a larger boolean expression ((month >=1) && (month <= 12)) ((answer == 'Y') || (answer == 'y')) TODO: Practice reading compound boolean expressions to see if they are true or false e.g. What is wrong with one? ((answer == 'Y') && (answer == 'y')) ------ IF STATEMENTS --------------- if (boolean expression) { true_statement1; true_statement2; } come_back_to_whether_true_or_false; if (boolean expression) { true_statement1; true_statement2; } else { false_statement1; false_statment2; } come_back_to_here_true_or_false; Note: Always using {} in your if statments is safer else clause is optional Always come back to main line code after the if!! ------ IF-ELSE IF-ELSE STATEMENTS --------------- if (booleanExpression_option1) { option1_true_statement1; option1_true_statement2; } else if (booleanExpression_option2) { option1_false_option2_true_statement1; option1_false_option2_true_statement2; } else if (booleanExpression_option 3) { option1_false_option2_false_option3_true_statement1; option1_false_option2_false_option3_true_statement2; } else { option1_false_option2_false_option3_false_statement1; option1_false_option2_false_option3_false_statement2; } come_back_to_here_regardless_of_which_option; Note: Take first option that matches even if later ones could have matches also Evaluated one at a time and take first option that matches! Don't take multiple branches even if match multiple Always have exactly 1 if, can have 0-N else if, can have 0 or 1 elses EXAMPLE: unsigned y; if (y==1) { cout << "1"; } else if (y< 10) { cout << "0 or 2-9"; } else if (y==5) { cout << "This will never happen.. do you see why?\n"; } else if (y < 20){ cout << "10-19"; } else { cout << "20+"; } Boolean expressions can be about different variables if (sky == BLUE) { //if sky is blue it will go here ( even if it is also Friday) } else if (day == FRIDAY) { //fridays but not fridays with blue skies } else { //Sat - Thurs where sky not blue } ----------- NESTED IF STATEMENTS -------------- if (fromTheUnitedStates){ //what state if (fromNY){ } else if (fromVT){ ..... } else if (fromOH){ } fromUS_but_regardless_of_which_state; } else{ //not from the United States //what country if (fromCanada){ } else if (fromMexico){ .... } else if (fromGermany){ } notfromUS_and_regardless_of_which_other_country; } regardless_of_whether_US_or_not; TODO: Practice following the flow of code through if clauses and nested if clauses. Debugger is helpful for that. ---------------------------------------------- READING IN MULTIWORD STRINGS cout << "What is your motto? "; //XXXX cin will just get the first word //cin >> motto; std::getline(cin, motto, '\n'); REMEMBER IMPORTANT DIFFERENCE BETWEEN cin and getline cin leaves trailing white space like '\n' unconsumed getline as shown above will consume the '\n' SO whenever getline follows a cin, must do something like this: string endOfLastLine; std::getline(cin, endOfLastLine, '\n'); std::getline(cin, motto, '\n'); ------------- Style --------------------------- Not just a matter of correctness, make code clear, readable, elegant How? - Identation - Comments - Good Variable Names - Consistency - Go for obviously correct and readable rather than "tricky" Other ways to add clarity - enums and const variables to introduce "readable" names rather than numbers ---------------- Enums -------------------------- enum TemperatureScale {CELSIUS=1, FAHRENHEIT, KELVIN, REAUMUR, RANKINE}; enum Month {JANUARY=1, FEBRUARY, MARCH, APRIL, MAY, JUNE, JULY, AUGUST, SEPTEMBER, OCTOBER, NOVEMBER, DECEMBER}; Give value to start with ( in both these cases 1), all others will be given numbers in order starting with that number ------------- Constant Variables ------------------- const double DELTA= 0.00001; Constant variables cannot be changed later const double DELTA= 0.00001; delta = 0.01; //COMPILER ERROR!!!!! ------------------------------------------------ Software Lifecycle 1. Analysis and specification of the task (problem definition) Keep in mind that in the real world specification of the problem can change often 2. Design of the software ( data representation and algorithm design) 3. Implementation ( coding) Just because have a plan all written out doesnt mean add all the code at once - add by spoonfuls and keep compiling 4. Testing Can't do exhaustive testing - chosing which cases to test is a key skill! 5. Maintenance and evolution Keep in mind that good programs are easy to read and modify by others ----------------------------------------------------- Designing a loop What goes in the body of the loop? Body Statement What is the conditions for ending the loop? Loop Condition What will happen in the loop to let the loop end? Update actions What do we need to do to set up for the loop? Initializing statements What do we need to do after the loop? Completion actions ----------WHILE LOOP-------------------------- InitializationActions while ( LoopCondition) { BodyStatements UpdateActions } CompletionActions Example: int i; cin > i; while ( i > 0){ cout << i << "\n"; i--; } ----------DO WHILE LOOP-------------------------- InitializationActions do { BodyStatements UpdateActions } while ( LoopCondition); CompletionActions Example: char answer; do { cout << "You are amazing!\n"; cout << "Should I say that again? [y/n]\n"; cin >> answer; } while ( answer == 'y'); ----------FOR LOOP-------------------------- for (InitializationAction; LoopCondition; UpdateAction) { BodyStatements } CompletionActions More InitializationActions for (InitializationAction; LoopCondition; UpdateAction) { BodyStatements More Update Actions } CompletionActions Example: int bottle; for (bottle=99; bottle >1; bottle--) { cout << bottle << " bottles on the wall\n"; } cout << "1 bottle on the wall\n"; cout << "No bottles on the wall\n"; ======================================= Any loop you want to write can be written using any of these three styles ( while, do-while or for) So which one do you use? Matter of style but generally processing an array => for loop fixed number of iterations => for loop unsure how many times through loop => while or do-while do-while if do you want the loop body to run at least once no matter what Some easy types of loops to practice - Loop asking for input until you get valid input - Count up or down - Do until the user says to stop - Loop over an array or multidimensional array doing something to each element (e.g. stats like total, average, max, min) Harder types of loops - Nibble away at a problem a little at a time (e.g. make change, arabic to roman numberals) =============ARRAYS=================================== Arrays group together many of the same type of object float homeworkGrade[10]; int bigArray[1000]; int foo[4]; //notice that the first array element is [0] not [1]!! foo[0] = 8; foo[1] = -9; foo[2] = 7853; foo[3] = 0; for (int i=0; i< 4; i++){ cout << "foo[" << i << "] is " << foo[i] << "\n"; } ============= MULTIDIMENSIONAL ARRAYS=================================== int foo[4][2]; Gives you 4*2 = 8 ints foo[0][0] foo[0][1] foo[1][0] foo[1][1] foo[2][0] foo[2][1] foo[3][0] foo[3][1] just like for loops perfect for traversing arrays nested for loops perfect for traversing multidimensional arrays int foo[NUM_ROWS][NUM_COLS]; for (int row=0; row< NUM_ROWS; row++){ for (int col=0; col< NUM_COLS; col++){ cout << foo[row][col] << "\n"; } } Can have more than 2D - for example 4D arrray - int bar[8][5][3][16]; Gives you 8*5*3*16 = 1920 ints! ================== COMMAND LINE ================ In our basic template we have: main (int argc, char **argv) argc is the number if arguments on the command line and argv is an array of those arguements (C-style strings) THis loop will print out all the command line arguements for (int i=0; i< argc; i++){ cout << "argv[" << i << "] is " << argv[i] << "\n"; } You can use this to pass in values from the user to the program like the name of a file to open etc. instead of asking the user a question during the program ===============NESTING======================== All of these constructs ( if, if-else, if-elseif-if, do-while, while, for) can be combined via nesting For example an if inside a for inside another if if (totalHours >= 40.0){ overtimeHours = totalHours - 40.0; } else { overtimeHours = 0; for (int day=0; day 10.0){ overtimeHours = overtimeHours + hoursPerDay[day] - 10.0; } } } Always indent when you start a new level of nesting! It will help make it clear what is inside or dependent on what ========================== FUNCTIONS ============================== functions are like a small program Type_Returned Function_Name(Parameter_List) { //variable declarations //instructions } Type_Returned can be void if you don't want to return anything Parameter_List can be void if you don't want to pass anything in Some examples int doubleIt(int num){ return 2*num; } int sumThem(int num1, int num2){ return num1+ num2; } void printFoo(void){ cout << "foo\n"; } ----------------------------------------------------- Functions used to break down a larger problem into smaller sub problems divde and conquer modularity void drawFlower(){ drawCenter(); for (int i=0; i< numPetals; i++){ drawPetal(i); } drawStem(); } ----------------------------------- Many preexisting functions you can use like srand(seed); Seeds the random number generator rand(); Requests a new value in the current sequence of "random" numbers ------------------------------------------- 4 ways to "get me out of here" exit() - gets you out of the whole program exit(0); return - get you out of the current function - in main that gets you out of the whole program return 0; break - gets you out of a loop or switch break; continue - gets you out of current iteration of loop continue; ------------------------------------------- Call By Value parameters Any changes made inside the function will not be visible to the caller of the function void dontChangeMe(int num){ //can add 1 inside the function but won't change what is passed in num = num+1; } --------------------------------------------- Call By Reference parameters Any changes made inside the function will be visible to the caller The & before the variable name makes it call by reference void changeMe(int &num){ //this change to num will be permanent ie the caller will see it num = num+1; } ----------------------------------------------- Arrays are a little different - they are automaically call by reference and to make then call by value must say const void dontChangeMe(const int numArray[]){ //this change to the array is not even allowed // numArray[0] = 45; int foo = numArray[0] + 45; } void changeMe(int numArray[]){ //this change to the array will be permanent ie the caller will see it numArray[0] = 45; } ----------------------------------------------------------- Return values vs call by reference parameters Can only have one return value, but can use call by reference parameters to "return" more values Return value is set with the return command inside the function If return value is void then no value returned Call by reference parameters can also be used to send in input values if you want int changMe (int num){ return num+1; } versus void changeMe (int &num){ //this change to num will be permanent ie the caller will see it num = num+1; } void changeMe (int &num, int &num2, int &num3 ){ //this change to num will be permanent ie the caller will see it num = num+1; num2 = 2; num3 = 3; } -------------------------------------------------------- Function practice 1) Practice following how functions are called from call site to function 1a) Know the syntax of a function call (no types here, just variables passed in) 2) Practice matching up parameters supplied with the call to parameters names in the function itself and then following how they are used 2a) Practice with call by value parameters - both individual types and arrays 2b) Practice with call by reference parameters - both individual types and arrays With call by reference parameters, follow updates made in function back into caller 3) Practice following the return value of a function and what happens to it back in the caller ---------------------------------------------------- Know difference between function declaration or prototype, the function body ( full implementation) and a function call -------------------------------------------------- often return values are used to return success/failure conditions or int for error codes and all real outputs sent back through reference parameters /* Preconditions: array must exist and be at least as large as indicated numInArray must be >0 Postconditions: stats will be set and return value will be true if successful or false if error */ bool computeStats(const int array[], int numInArray, int &min, int &max, float &average); min, max and average are not really used as inputs/ingredients at all! ------------------------------------------ global vs local variables variables declared outside any functions ( even main) are visible to all functions if a function has a parameter or a local variable with that name then that overrides the global variable can have variables that are local to an if statement or for loop also rule is most local match wins can even declare in a for loop ===============OPENING A FILE======================== /* Notice new include lines */ #include #include using namespace std; int main (int argc, char **argv) { /* ofstream for file you want to write to ifstream for file you want to read from */ ofstream output_stream; output_stream.open("hello.txt"); /* Notice checking if file can be opened */ if (outut_stream.fail()){ cout << "Cannot open output file hello.txt\n"; exit (1); } output_stream << "hi there\n"; output_stream.close(); return 0; } =============== LOOP TO READ ALL NUMBERS IN A FILE ======================== runningTotal = 0; howManyNumbers = 0; /* Notice that the loop condition *is* the read In addition to reading it returns true/false whether it was able to read more data */ while(input_stream >> currentNumber){ runningTotal += currentNumber; howManyNumbers++; } --------- C strings --------------- what is a c string? C-strings are an array of characters with a '\0' to show were the valid characters stop char cstring1[MAX_SIZE]; don't have to have MAX_SIZE in every string terminate by '\0' example cstring1[0] = 'H'; cstring1[1] = 'I'; cstring1[2] = '\0'; NOT THE SAME AS JUST cstring1[0] = 'H'; cstring1[1] = 'I'; Useful functions on cstrings atoi - string to integer int x = atoi("1234"); atof - string to float float x = atof("12.34"); -------------------------------------------------- Cstrings vs C++ strings 1) How to declare C++strings: string cppstring1, cppstring2; Cstrings: const int MAX_STRING = 100; char cstring1[MAX_STRING+1], cstring2[MAX_STRING+1]; 2) How to assign a value C++strings: cppstring1 = "Hi"; cppstring2 = "Hi"; Cstrings: //won't compile //cstring1 = "Hi"; strncpy(cstring1, "Hi", MAX_STRING); strncpy(cstring2, "Hi", MAX_STRING); 3) Testing for equality C++strings: if (cppstring1 == cppstring2){ cout << "They are equal (1)\n"; } Cstrings: if (strncmp(cstring1, cstring2, MAX_STRING) ==0){ cout << "They are equal (3)\n"; } 4) Concatenating C++strings: cppstring1 += " there"; Cstrings: strncat(cstring1, " there", MAX_STRING); 5) Determining length C++strings: cppstring2.length() Cstrings: strnlen(cstring1, MAX_STRING) 6) Getting a C string from a C++-string cppstring1.c_str(); Needed when you functions like file open or atoi atoi(cppstring1.c_str()); output_stream.open(fileName.c_str()); -------character I/O--------------------- char next_symbol; infile.get(next_symbol); will not skip over blanks or other whitespace like \n or \t infile.putback(next_symbol); puts next_symbol back into the stream as if it had never been read infile.peek(next_symbol); somewhat like a get followed by a putback - peeks to see what would be next if you did a get on it outfile.put(next_symbol); Writes the character into an output file Useful functions on chars isdigit - is this character '0' through '9' isspace - is whitespace (space, tab, return, etc.) isalpha - is this character 'a' through 'z' or 'A' through 'Z' islower - is this character 'a' through 'z' isupper - is this character 'A' through 'Z' tolower - convert uppercase to lower case toupper - convert lowercase to upper case ------------------------------- Pointers * and & operators * is used to declare a pointer to something But there is another use of * when you have a pointer the * operator produced the the variable it points to This is called deferencing a pointer the & operator tells the address of something OR in other words in produces a pointer to the variable Example 1 int i; int *p; i= 0; cout << "i is " << i << endl; p = &i; *p = 9; cout << "i is " << i << endl; Example 2 char * cstring1; char cstring2[MAX_STRING+1]; //BOTH POINT TO THE SAME ARRAY cstring1 = cstring2; //THEY POINT TO 2 DIFFERENT ARRAYS OF SIZE MAX_STRING+1 cstring1 = (char *) malloc ((MAX_STRING+1) * sizeof(char)); cstring1 and cstring2 are both arrays Literally they are pointers to the beginning of an array Now can understand notation for call by value vs call by reference for arrays vs plain parameters int &num => call by reference, pass pointer to the caller's variable but for arrays they are already a pointer so if want call by value must say const int number[] => call by value