2009:Fall 2009 C++ tutorial: Difference between revisions
Programming (talk | contribs) (Moved 2008 C++ notes into wiki. Edited to simplify and clarify - Bear) |
m (Fall 2009 C++ tutorial moved to 2009:Fall 2009 C++ tutorial) |
(No difference)
|
Latest revision as of 19:34, 30 December 2009
[[../../../../../programming/index.html|../../../../../programming/index.html]] C++ Programming Examples and Exercises
Part 0: Hello, World!
- [[../../../../../programming/learn/00/hello.cpp|Hello World Example]]: Use this simple example to ensure that you are able to compile and run programs with the development environment. To compile and run with DevC++:
- Download the program (right-click, save link target as...)
- Save to your computer - It is recommended that you make a new folder (directory) for each example.
- Open the file in DevC++.
- Go to the "Execute" menu. Click "Compile and Run".
Part 1: Program Basics, Variable Declaration, Arithmetic Operators, and Comments
- [[../../../../../programming/learn/01/basics.cpp|Basics Example]]: This example shows the very basics of programming in C++, as described below.
- The Basics:
- Program Flow: Programs are made up of statements. The statements are read and run one at a time, generally in order. All statements end with a semicolon, ‘;’
- Statements: Statements are a single operation for the program to perform. A statement does some operation and usually will store a result in a variable or tell the program which statement to look at next. Statements end with a semi-colon (;) (like a sentence ends with a period!).
- Compound statements: Compound statements group a bunch of related statements together. Compound statements are grouped by surrounding them with braces { }. A compound statement does NOT end with a semicolon, it ends with a closing brace.
- Variables: A variable is a piece of data that the program will operate on. Variables have a type that tells the program what the variable represents (a number, a character, etc.).
- Functions: A function is a group of related statements that do a particular job. Usually you would create and use a function to represent something that you might use in your program many, many times. It is also a good way to break a really large, difficult program into smaller, easier to understand pieces
- Classes: A class is a bunch of related data and functions that acts like a new data type. The WPI library contains many classes that represent common parts of a robot.
- Comments: Comments are text that explains what the program does to other people. The computer doesn’t do anything with them. COMMENTS ARE IMPORTANT!
- Variable Declaration: Before you can use a variable, you have to tell the computer what it’s called and what its type is. This is called a variable declaration. The name can be whatever you want; generally you should use names that say what the variable is representing. For example, if you make an integer to hold the speed that a wheel is turning, a sensible name might be "wheelspeed" - avoid something like "s" (oh, "s" means speed didn't you know?!?).
- Variable types Some common variable types:
- int – an integer, a number without a decimal point:1, 31767, -200, 0
- float – a number with a decimal point: 20.12, 0.0003, -12.003
- bool – a truth value: true, false
- char – a single character: "a", "X", "5", "?"
- Assignment: You give variables value by using the assignment operator. The assignment operator is the equals sign '='.
- Arithmetic: Computer programs are all about math! Here are the basic math operators:
- Addition: The '+' sign. Example:
sum = a + b;
- Subtraction: The '-' sign. Example:
difference = a - b
- Multiplication: The '*' symbol. Example:
product = a * b
- Division: The '/' symbol. When dividing integers (whole numbers), any decimal part (remainder) is discarded! Example:
quotient = a / b;
- Remainder: You can use this to get the remainder of an un-even integer division, or to find out if something divides something else evenly. Also call "modulus" operator. The '%' symbol. Example:
remainder = a % b;
- Negation: You can use the '-' symbol to make a positive negative or a negative a positive. Example:
negativea = -a;
- Literals: We've been using examples with variables (a and b), but you can use literal values in your source code too:
result = x + 10;
- Complex Arithmetic: You can do multiple operations in one statement, and you can use parenthesis to enforce order of operations. Example:
average = (a + b + c) / 3;
- [[../../../../../programming/learn/01/temperature.cpp|Arithmetic Exercise]]: Download the source file and open it in Dev C++ as you did with the examples above. The exercise has 3 variables holding Celsius temperatures. Convert these to their Kelvin and Fahrenheit equivalents. Put your answers into the variables provided, and they will print at the end of the program! If you get it right, you should get something like this:
<dir><dir>
Fahrenheit: 32 Celsius: 0 Kelvin: 273 Fahrenheit: 68 Celsius: 20 Kelvin: 293 Fahrenheit: 104 Celsius: 40 Kelvin: 313
</dir> </dir>
Part 2: Conditions and Loops
- [[../../../../../programming/learn/02/loops.cpp|Loops Example]]: This example illustrates the use of loops and conditions.
- Conditions and Comparisons: We can compare two variables, or a variable and a literal value, using conditional operators. There are many conditional operators that compare two numbers:
a < 3 | |
Greater than |
b > 200 |
Equal to |
b == 205 (NOTE: two = signs!) |
Not equal to |
speed != 55 |
Greater than or equal to |
500 >= x |
Less than or equal to |
b <= a |
- Loops: A loop is a convenient way to execute the same statements many times. The body of the loop is executed until the "condition" of the loop is no longer true. The body of the loop is the part in braces - { ... } - following the start of the loop. If you don't use braces, the body of the loop is just the next single statement. C++ has 3 different types of loops:
- "for" loops: A "for" loop has three main parts, all within parenthesis:
<dir><dir>
- Initialization (
i = 1
in the example): This expression is executed only once, at the beginning of the loop. You typically use this to set up a counter variable (like "i" in the example). - Test (
i <= 25
in the example): Executed each iteration through the loop. If it evaluates "true", the body of the loop runs. If "false", the loop ends. Note that if this test is false when the loop initially begins, the body is skipped entirely. - Increment (
++i
in the example): Executed at the end of each iteration of the loop, after the loop body executes but before the test condition. You typically use this to increment or add to a loop counter variable.
</dir> </dir>
- While loops: A while loop has only one main part, a "test", similar to the "test" in the "for" loop. It looks like the following:
<dir><dir><dir><dir>
while (test) { body }
At the beginning of the loop, the "test" condition is executed. If it is true, the body executes once. The test is then executed again - if true, the body executes again. This continues until the test is false.
</dir> </dir> </dir> </dir>
- Do-While loops: These are similar to "while" loops, but the "test" is not done the first time through the loop. We won't use these very much, so they are not in the example, but the general structure is like this:
<dir><dir><dir><dir>
do { body } while (test);
</dir> </dir> </dir> </dir>
- Loop Exercise: Use your temperature converter from the last part as a starting point. Instead of converting the three temperatures given in the original exercise, convert ALL Celsius temperture values from 0 to 37. You can use any form of "loop" you wish to do this. Use the loop example as a reference! When complete, you should be able to run it and get something like this:
<dir><dir>
Fahrenheit: 32 Celsius: 0 Kelvin: 273 Fahrenheit: 34 Celsius: 1 Kelvin: 274 ... Fahrenheit: 100 Celsius: 37 Kelvin: 310
</dir> </dir>
Part 3: Functions and Arrays
- [[../../../../../programming/learn/03/functions.cpp|Functions and Arrays Example]]: This example illustrates the use of functions and arrays.
- Functions: Functions are a way to enclose a commonly used part of a progam into something that can be re-used many times. Functions also give us one way to solve a small part of a very large problem. Functions should be:
- Simple: A function should perform one simple task that can be easily described.
- Well documented: A function should include good documenting comments about what it does and what value(s) it operates on.
- Function structure: A function takes arguments to operate on and returns one value. In C++, functions have two distinct components:
- Function Prototype: The prototype is a brief description of what the function does. It tells what the function name is, what argument types it expects, and what type of value the function returns. It tells us what the function is and what it does, without actually having the code that does it! See the top of the example for the "distance" function's prototype.
- Function Definition: The definition of a function contains the actual code that performs the work of the function. The beginning of the definition matches the prototype exactly. See the example for the definition of "distance".
- Function arguments: The function arguments let the user of the function (the caller) pass specific values for the function to work with. Each time the caller uses the function, different values can be given in the arguments. Inside the function, the arguments can be used just like any other variable. Note: The functions we are doing now are called pass-by-value. This means that if the function modifies (assigns to) the arguments, the modifications are not visible to the caller. The function is effectively working on a copy of the argument!
- Function return: A function can return a value to the code using the function (the caller) by using the return keyword. See the example and the next item for how a caller uses the returned value.
- Using a function: Once you have a function, you use it by "calling" it. You call a function in code by using the name of the function, followed by the arguments you want to call it with in parenthesis. The return value can be saved by assigning to a variable! See the example. Here's another example:
<dir><dir>
/* Prototype for a function to compute x to the second power */ int square(int x); // ... somewhere else in the file, perhaps in main function ... int squareme = 30; int squared = square(squareme); // Call square with value of // squareme. Assuming square // works like it says it does, // squared will be 30 * 30 squared = square(10); // Example of calling with a literal
</dir> </dir>
- Arrays: Arrays are simply a set of variables held together in the computers memory. We can use arrays as an easy way to hold a series of related numbers. In the example, the array "points" holds a series of points we want to move between.
- Array Declaration: We declare arrays just like variables, except that we add to the end the size (number of elements). In the example, we make an array that has 8 integers. Just like with variables, we can chose to initialize the array immediately (as in the example) or to wait until later. Again, like with variables, the value of the array elements are undefined until they are given a value!
To give an array all its values at once, we can use the notation in the example; a series of comma-separated values in braces. - Array Indexing: We use or assign to one element of an array by indexing the array. This is done by using the array name followed by an index in brackets []. Array elements are numbered starting at zero, and continue up to the size of the array minus one. For example, a 10-element array has indexes 0 through 9. Here are a few examples:
<dir><dir>
int example[5] = { 10, 20, 30, 40, 50 }; x = example[0] + example[2]; // x = 10 + 30 example[2] = 6; // Change 3rd element to 6 y = example[1] + example[2]; // y = 20 + 6 z = example[5]; // PROBLEM! This will compile but // run unpredictably! There is no // 6th element!
</dir> </dir>
- [[../../../../../programming/learn/03/powers.cpp|Functions and Arrays Exercises: ]]This exercise starts with you writing a function to raise a number to a power. It continues to have you change the values used to test the function from those provided to a different set. Do these in order! The places to insert code for each part are noted in the comments!
- Part A, Functions: The exercise has an empty function for Raising a number to a power. You need to create this function. Don't forget to return your result! Hint for those reading directions! Use a loop!
When completed, you should get output like this:1 raised to the 1 is 1
2 raised to the 2 is 4 3 raised to the 3 is 27 ... 9 raised to the 9 is 387420489
- Part B, Arrays: Right now, your main function tests using numbers 1 to 9, raising each to itself (as above). Change it to compute and print the following:
<dir><dir><dir><dir>
10 raised to the 3 is 1000 7 raised to the 2 is 49 2 raised to the 6 is 64 1 raised to the 70 is 1 5 raised to the 3 is 125 6 raised to the 4 is 1296
Hint again! Use two arrays and a loop! </dir> </dir> </dir> </dir> Part 4: If-Else
- [[../../../../../programming/learn/04/ifelse.cpp|If-Else Example]]: This example illustrates the use of if and else by telling you if a number is even or odd!
- If-Else: We use 'if' and 'else' in a program to make decisions about what the program should do next. The general structure of an if-else is shown below:
<dir><dir>
if (test) { /* all the code here gets executed if 'test' was true! */ ... } else { /* all the code here gets executed if 'test' was false! */ ... } /* * Either way, we end doing code here after doing either the 'if' block * or the else block! */ ...
The "test" is any of the tests we used for loops, such as all the numeric comparisons we talked about. The "else" section is optional! If you leave it out and the test is false, the if block is just skipped and execution continues after the if block!
Short Version: If you do only one statement in the body of the if or else, you can leave out the braces {}!
See the example above for a working program, and here's a shortened concrete example. This basically says "if the money I have is more than 10, then go out and buy some lunch and feel full. Otherwise, fell hungry! If I feel really hungry, then my stomach grumbles!"
int money = check_wallet(); if (money > 10) { money -= buy_lunch(); stomach += 20; } else { stomach -= 20; } if (stomach < 15) { grumble(); }
</dir> </dir>
- [[../../../../../programming/learn/04/absvalue.cpp|If-Else Exercise: ]]This exercise requires you to make a function to compute absolute value. Numbers for test code in the main function have been provided for you. Comments show where to insert your code. You need to do the following (easiest if you do these in order!!!):
- Create a function prototype for your absolute value function. Put the prototype near the comment at the top of the file.
- Create the definition of your function. Do this near the comment at the bottom of the file.
- Finish the test code in the main function to call your function using the provided array of test values.
Part 5: Data Types
- [[../../../../../programming/learn/05/integers.cpp|Integer Data Type Examples]]: Shows the differences in size and range for each integer type.
- Integer Types: Until now we've only used the "int" data type. C++ has four basic integer data types: char, short, int, and long. You use each of these in the same way we have been using int (see below). All are used to represent integer (whole number) variables. They differ in the following respects:
- Size (memory): Each different type can take up different amounts of memory in the computer. char will always be the smallest type, followed by short, int, and then long using the most memory.
- Range: The different types can represent different ranges of integer values. The smaller the type (see above) the smaller the range of numbers the variable can hold.
- Details of Types are System Dependant: The exact size, and range, of each of the integer types are not uniform on all systems you may compile and run your program on. C++ doesn't specify how big/what range the types must be/cover! Good example: On current Windows sytems, int is 32 bits. On 2004-2008 robot controllers, int was 16 bits!
- Signed and unsigned: Each of the integer types have both a signed and an unsigned version. The signed version is the default (except for char, which is unspecified): if you just use a type name (int, short, etc) you get a variable that holds positive and negative numbers. The unsigned types hold only positive numbers. But, because of this, their range is extended further. See this in the example!
- Declaring variables - other types: You declare (create) variables of these other types the same way we have been doing for the simple integer type. Here are some examples:
<dir><dir>
int my_integer; short some_short = 50; unsigned int rthunder = 1511; signed long reallybig = -100000;
</dir> </dir>
- [[../../../../../programming/learn/05/datatypes.cpp|Data Types - Second Example]]: This example shows non-integer data types, as well as arithmetic with all data types to help understand the limitations and benefits of each.
- Non-Integer Types: C++ has two more basic types to represent non-integer data, float and double. These both represent real numbers (known in the programming/computer world as "floating point" numbers). They both work similarly: they are both signed, and both represent decimal numbers. The difference between them is similar to that for the different integer types: float uses less memory and has less precision, double uses more memory but has greater precision. Note: That's a difference in precision (the number of digits of accuracy after the decimal point), not range of values like integers!
- Arithmetic with integer types: We have already done basic arithmetic with integers (int) in previous parts. Using the other integral types is the same, however you need to be aware of the potential for overflow and underflow. This happens when your addition, subtraction, or multiplication results in a value that cannot be stored in the type of the variable you are using. The result is undefined, but generally the number will "roll over": adding past a maximum will give you a number near the minimum for the type; subtracting below the minimum will give you a really big number (near the maximum).
- Arithmetic with non-integer types: The most important changes from integer arithmetic are that you have decimal values! No more lost fractions of a number when dividing! Note that generally speaking, floating point (float, double) math takes the computer longer to do than integer math. Don't use float/double for everything!
Part 6: Multiple File Programs, Classes and Objects
- [[../../../../../programming/learn/06/classes.zip|Classes and Objects Example]]: This is our first example of a multi-file program. It is a ZIP file. Open the zip file and extract everything to a new folder. Then open Dev C++ and make a new C++ project. Add all the files to the project and save the project. It should then compile and run.
- Classes: A class is a way to group together, logically, program data (variables) and operations (functions) into one unit or module. Classes enable us to separate out related parts of a program, and to think about the program as a set of operations on various objects. Classes:
- Are a way to define our own data type. Up until now, we've only used the basic, primitive data types in C++ (int, long, float, etc). By defining a class, we can make our own, more complex types to represent different things.
- Enforce the "Object Oriented" approach to programming. This means we take the problem our program is seeking to tackle and break it into distinct modules to handle various aspects of the problem. Our program manipulates these modules, or "objects", in a meaningful way to solve the problem at hand. Before "Object Oriented" programming, the main model was procedural programming, where you basically write a bunch of functions and pass around data to operate on.
- Give us one more way to split up a difficult task into pieces that can be worked on by multiple people in a larger group. Each person or small group can be writing well-defined modules that can be hooked together at a later time.
- Objects: A class is just a plan or blueprint. It tells the compiler what your new user-defined type will do and how it does it. When a part of your program wants to use a class, it creates an object, or instance of the class. For any given class you could create hundreds of objects and be using them all in various parts of your program.
- Class Definitions: A class definition provides the overall interface of a class, without defining how each of the classes operations actually perform their work. This is like a prototype for a function - the function prototype gives us the interface to call the function, but doesn't actually contain the code that does the work of the function.
Class definitions are typically placed in a ".h", or header, file. This file can be referenced by any part of the program that uses the class. The actual programming code that implements the functions of a class are usually defined separately in a ".cpp" file.
The example has one .h file to define a class, a .cpp file containing the actual code that implements the class's functions, and a .cpp file with a main method that uses the class in various ways. - Structure: Classes are made up of these parts - refer to the example program to see each of these:
- Data Members: These are variables the class uses over the life of the object - they are usually important properties or state information about the object. The data can be labelled private, which means that the only code that can modify it is functions that are a part of the class, or public, which means any code in the program can "reach into" the object and modify the data.
Best practice is usually to use private variables to limit the way that your object can have its data modified. - Member Functions: Member functions are the functions that are defined as part of the class. They can operate on all the classes data. Other than that, they are just like the functions we have been writing! Sometimes these are called methods. You prefix the name of your member function with the class name and two colons to say that this function is a member of your class, not just an ordinary function:
int ordinaryFunction(int someArgument) { // ... } int MyClass::memberFunctionName(int someArgument) { // ... }
- Constructor: This is a special function that is called when you make an object of the class. The constructor gives you a place to set the data members to meaningful initial values. This function always has the same name as the class, and has no return value. (see example)
- Destructor: Another special function, this is called when an object of the class is destroyed. This lets you clean-up any data members that need special attention. Like the constructor, the destructor has no return value. It is named the same as the class with a tilde (~) character in front (~MyClassName) and takes no arguments.
- Creating Objects of a Class: You create objects of a class by declaring them, just like the integer or float type, except that you can pass arguments to the constructor of the class in parathesis:
int someInteger; // Assuming I have a class named "Speaker" somewhere, with a constructor // that takes a single float argument ( Speaker(float volume) ) Speaker leftSpeaker(10.5);
You do not need to call the destructor for a class - it gets run automatically when your object is destroyed (at the end of the function or code block that is using it, for example). - Calling member functions of a class: You can call any member function of a class by using the member operator, which is a single period (.). If my Speaker class from above has member function to change volume called setVolume taking a single float as an argument, then I can call it with:
leftSpeaker.setVolume(3.2);
- Documentation: Class definitions should be well documented using comments to allow other programmers to use your class without having to read all the code. There are many tools on the internet that will produce nice documentation from specially formatted comments. One such tool is Doxygen.
- Classes Exercise: We will work together to come up with a class definition of a cube. You will implement the class using the class definition as a guide. Based on the class we developed, here is a main function which [[../../../../../programming/learn/06/main.cpp|will test your class]]. You should get output like this:
My cube of side 30 has surface area of 5400 and volume of 27000 My other cube of side 11 has surface area of 726 and volume of 1331
Part 7: Multiple File Programs, Classes and Objects <dir> </dir>
- Class Heirarchy: Sometimes our program will need several modules which can share some common data, functionality, or other traits. We can make several classes build on or share their implementation code or a common interface to achieve this. You can have several classes that "derive from" or "inherit from" a common parent class (also called a super-class). All the child classes can share the common interface (member functions) of the parent class, and even benefit from any common code in the parent class. Sub-classes can also extend the functionality of a basic parent class in meaningful ways. Sub-classes can then, in turn, be subclassed further as needed to build a whole tree of more and more specialized or refined classes. The
- Sub-Classing/Inheritance: To create a sub-class of a class, you specify the name of the super-class you are inheriting from after a colon in the class definition:
class MySubClass : public MySuperClass { ... };
- Virtual member functions: A "virtual" member function is a member function that can be changed or extended in a sub-class. Non-virtual functions of a class are fixed operations that cannot be changed or extended. Generally, when you write a class that will eventually be extended, you will make all the functions virtual.
class MySuperClass { virtual int myMemberFunction(int someArgument); };
- "Pure" Virtual member functions: A "pure" virtual function is a way to have a super-class give an interface to a function without actually making a function. This makes the super-class be "abstract" since it is no longer fully defined, but still, it lets other parts of a program work with a common interface regardless of the subclass that the object is an instance of. The subclass(es) provide their implementations of these otherwise empty functions. To declare a function as "pure" you add "= 0" to the end of its prototype in the class definition:
class MyAbstractClass { virtual int myPureFunction(int someArgument) = 0; };
[[../../../../../programming/index.html|Back up to Programming Main Site]]