You may copy this file for noncommercial use. Please report errors to Matt Mahoney at mmahoney@cs.fit.edu. The latest version is located at cs.fit.edu/~mmahoney/cse1502/introcpp.html updated Aug. 30, 2007. This guide is a condensed version of the longer reference at cs.fit.edu/~mmahoney/cse2050/how2cpp.html. Advanced features have been omitted.
C++ is a compiled language, producing Windows or UNIX/Linux executable programs that are typically very fast. Programs are portable between operating systems only to the extent of text I/O (input/output) and file I/O. There are Windows and UNIX/Linux libraries supporting network I/O, the mouse, and graphics, but these differ between operating systems and are beyond the scope of this document.
The g++ compiler is free for most operating systems. For Windows, it is easiest to download the MinGW g++ installer. (MinGW_Toolbox_Setup.exe, 23 MB). After installing, add C:\mingw\bin to your PATH.
Digital Mars C++ Compiler 8.49 is free. Unzip stlport.zip (2 MB) and dm849c.zip (3 MB) in C:\ to install in C:\dm and add C:\dm\bin to your PATH.
Borland C++ 5.5 is free for Windows after registering. Click on "compiler", register, and download the installer (8.7 MB). After installing, add C:\Borland\BCC55\bin to your PATH and create the file C:\Borland\BCC55\bcc32.cfg exactly as shown below:
-I"c:\Borland\Bcc55\include" -L"c:\Borland\Bcc55\lib"
There are also commercial compilers such as Microsoft Visual Studio and Intel C++. Many commercial compilers include an integrated develop environment (IDE) with a graphical user interface, editor, debugger, extra libraries, and other tools. These are beyond the scope of this document.
g++, Borland 5.5 and Mars are command line compilers. You write programs with a text editor (such as Notepad) and compile them using commands from a UNIX/Linux shell or a Windows command window. The output of a compiler is an executable program that you also run from a shell or command window. To open a command window in Windows, click Start/Run and type "cmd".
Create a text file with a .cpp extension, e.g. hello.cpp, e.g.
#include <iostream> using namespace std; int main() { cout << "Hello world\n"; return 0; }
In Windows, compile as follows (producing hello.exe):
MinGW: g++ hello.cpp -o hello.exe Borland: bcc32 hello.cpp Mars: dmc hello.cpp -IC:\dm\stlport\stlport To run: helloTo compile and run in Unix or Linux:
g++ hello.cpp -o hello ./helloUseful g++ options (other compilers will differ):
-o file (rename output file, default is a.out in UNIX/Linux or a.exe in Windows) -O (Optimize, compiles slower but runs faster) -Wall (Display all warnings) -s (Strip debugging info from executable to make it smaller) --help (List all available options)
// Standard library headers, include as needed #include <iostream> // cin, cout (standard input/output) #include <fstream> // ifstream, ofstream (files) #include <string> // string (sequence of characters) #include <vector> // vector (an array with stack operations) #include <map> // map (associative array) #include <algorithm> // min(), max(), swap(), sort(), copy(), fill() #include <cstdlib> // rand(), abs(), atoi(), exit() #include <cctype> // isalpha(), isdigit(), tolower() #include <cmath> // pow(), log(), exp(), sqrt(), sin(), cos(), atan() #include <ctime> // time() using namespace std; // Required if any headers are present // Global type, object, and function declarations... int main() { // Execution starts here // Statements and local type and object declarations... return 0; // Execution ends here }For example:
// hello.cpp - prints "Hello" and a newline character to the screen #include <iostream> // Defines object cout (standard output) #include <string> // Defines type string using namespace std; // Always after the last header int main() { // There must be one function main() returning int string s="Hello\n"; // Declaration: create object s of type string cout << s; // Statement: output s return 0; // main()'s return value actually doesn't matter } // End of main()
The // symbol indicates a comment to the end of the line. It is used to document the program, and is ignored by the compiler. You can also use /* ... */ for multiline comments.
Objects and types can be declared globally, or local to a function or {block}. Functions can only be declared globally, not inside another function. The syntax of an object declaration is a type name followed by a list of objects to be created (with possible initialization), and ending with a semicolon. The following examples declare objects of the most common types.
// Declaring objects of existing types (global or local) int i, j=3; // Integers, i's initial value is undefined double x=3.5, y=j; // Real numbers, y is 3.0 bool t=false, u=true; // Logical e.g. if (t && u) {...} string s, hi="hello"; // s is initially an empty string, "" in <string> char c='a', c2=hi[1]; // Character, c2 is 'e' vector<int> a(5); // Array a[0] through a[4] of int in <vector> map<string, int> m; // Associative array, e.g. m["hi"]=5; in <map> ifstream in("file.txt"); // Input file e.g. while (getline(in, s)) {...} in <fstream> ofstream out(s.c_str()); // Output file e.g. out << "hello\n"; in <fstream> const double PI=3.14159; // Not a variable, e.g. PI=4; is an error // Functions (must be global) int sum(int a, int b) {return a+b;} // e.g. i=sum(j, 2); sets i=5 void swap(int& a, int& b) { // Pass by reference, no return value int tmp=a; a=b; b=tmp; // e.g. swap(i, j); must be variables } // Scope of a, b, and tmp ends here, implied return; void print(const string& s) {cout << s;} // Pass large objects by const reference // Declaring new types (global or local) typedef double Real; // Real z; declares object z of type double struct Complex { // Complex a; declares a.re, a.im type double Real re, im; // Data members Complex(double r=0, double i=0) {re=r; im=i;} // Initialization code };Objects, types, and functions may be given names using letters, digits, and underscores, and starting with a letter. C++ is case sensitive. Thus, x_3 and X_3 are two different names. Normally, we use lower case, except that new type names are usually Capitalized and global constants are often UPPER CASE.
Initialization is optional for all types. For the built in types int, double, bool, and char, the initial value is undefined, so initialization is recommended. For the library types string, vector, and map (those that require a header), the initial value is empty. For a vector or map of built in types, the elements are initially 0 or false.
A statement is either a control statement like if, while, for, return, break, or an expression. For example, the following are expressions.
cin >> s; // Input, read one word into s s = "Hello, " + s; // Concatenation and assignment cout << s << '\n'; // Output s and a newlineControl statements have the following general forms.
if (t) {...} // If t is true, execute the block else if (t) {...} // May appear 0 or more times else {...} // May appear 0 or 1 times while (t) {...} // Repeat the block 0 or more times while t is true do {...} while (t); // Repeat the block 1 or more times while t is true for (d; t; s) {...} // Equivalent to: d; while (t) {... s;} break; // Jump out of a while or for loop return x; // Return from a function with value xA block {...} may contain 0 or more statements and declarations (which are local to the block). If there is only one statement, then the braces may be omitted.
if (s=="hello") // Compare strings (case sensitive) cout << "hi"; // If true else cout << "bye"; // If falsebreak exits a loop. For instance, the following reads from the keyboard until the user types "bye"
while (true) { // Loop forever? string s; // Local declaration cin >> s; // Input a word if (s=="bye") break; } // Scope of s ends here cout << s; // Error, undefined object sA for loop is normally used to iterate through a sequence. The first statement may declare an object which is local to the loop.
for (int i=0; i<5; ++i) // Loop 5 times, ++i means i+=1 or i=i+1 cout << i << ' '; // Prints 0 1 2 3 4 cout << i; // Error, undefined object i
x[i] f(...) T(x) x.m p->m Index, function call, conversion, struct/iterator member -x !x ++x --x *p Unary: Minus, not, increment, decrement, iterator contents x*y x/y x%y Multiply, divide, mod x+y x-y Add or concatenate, subtract cin>>x cout<<x; Input, output x<y x<=y x>y x>=y Comparison (less than, or equal, greater than, or equal) x==y x!=y Comparison (equals, not equal) t&&u And then t||u Or else x=y x+=y x-=y x*=y x/=y x%=y Assignment combined with arithmetic, e.g. x+=y means x=x+yOperators of equal precedence are evaluated left to right except for unary operators and assignment.
a-b-c; // (a-b)-c a=b=0; // a=(b=0), assigns 0 to b, then b to a f()[i] // i'th element of string/vector/map returned by f()Assignment may be combined with arithmetic operators. Assignments return the object assigned to. The left side of an assignment must be a variable (or lvalue). It cannot be an expression, a const, or an ifstream, ofstream, or cin, cout, or cerr.
a*=b; // a=a*b; (a+=b)+=c; // a=a+b+c; a+b=c; // Error, assignment to expressionIncrement and decrement operators add or subtract 1 and return the new value. There is also a postfix form that returns the original value.
int a = 5, b = ++a; // Prefix, a=6; b=6; cout << b--; // Postfix, b=5, prints 6Expressions are loosely typed, with conversions occurring as needed. A conversion may also be made explicit by using the notation T(x) or (T)x to convert x to type T.
double(3)/2 // 1.5, explicit double(3), implicit double(2)The meaning of most other operators depend on the type of the operands as described below. The notation <header> means that to use the features described, your program must have
#include <header>
Arithmetic, returns int: + - * / % -x ++ -- Comparison, returns bool: == != < <= > >=Division rounds toward 0, e.g. 5/3 is 1, -5/3 is -1. % is the remainder, e.g. -5%3 is -2. Division or mod by 0 is a run time error.
On most machines, an int can only represent 32 bit signed integers, i.e. from -231 = -2147483648 to 231-1 = 2147483647. If a result is outside this range (e.g. 1000000*1000000) then the result is reduced modulo 232.
!t // not t t&&u // t and then u, true if both t and u are true t||u // t or else u, true if either t or u is true bool(x) // true if int x is not 0 bool(cin) // true if last input was successful int(t) // 1 if true, 0 if falseThe && and || operators do not evaluate the right operand unless necessary, e.g. (j!=0 && i/j > 1) cannot cause a division by 0 error.
A test condition in an if, for or while loop implicitly converts an expression to bool.
while (cin >> s) // Loop until input fails if (i=3) // Legal but probably wrong, = means assignment, returns bool(3) or true
Arithmetic: returns double: + - * / -x (not % ++ --) Comparison: < > Conversion: int(x) rounds toward 0, double(i) does not change the valueAn expression mixing int and double is double, e.g. 5/4 is 1 but 5.0/4 or 5/4.0 is 1.25. Comparison using == and != are not meaningful because of round off error, e.g. 0.1*10==1 is false (differing by about 10-14) because 0.1 does not have an exact representation as a binary fraction.
The header <cmath> defines mathematical functions taking int or double and returning double.
sin(x); cos(x); tan(x); // Trig functions, x in radians asin(x); acos(x); atan(x);// Inverses atan2(y, x); // atan(y/x) sinh(x); cosh(x); tanh(x);// Hyperbolic exp(x); log(x); log10(x); // e to the x, log base e, log base 10 pow(x, y); sqrt(x); // x to the y, square root ceil(x); floor(x); // Round up or down (as a double) fabs(x); fmod(x, y); // Absolute value, x mod y
On most machines the valid range of a double is about -1.7e308 (-1.7 * 10308) to 1.7e308 with about 14 significant digits of precision.
// Convert UPPER CASE input to lower case output char c; while (in.get(c)) { // Read c, loop while successful if (c >= 'A' && c <= 'Z') // if (isupper(c)) c += 'a' - 'A'; // c = tolower(c) (or c += 32) cout << c; // Print c as a character } cout << 'a' - 'A'; // Print 32 (not a space, arithmetic always results in an int) cout << char(32); // Print a space (convert int to char modulo 256)Characters are written enclosed in single quotes. Some special characters may be escaped with a \
'a' // lowercase a ' ' // space '\n' // newline '\r' // carriage return '\t' // tab '\\' // backslash '\'' // single quote '\"' // double quote '\x7F' // ASCII code in hexadecimal '\x00' to '\xFF'The header <cctype> defines character tests and conversion functions.
isalnum(c); // Is c a letter or digit? isalpha(c); isdigit(c); // Is c a letter? Digit? islower(c); isupper(c); // Is c lower case? Upper case? c=tolower(c); c=toupper(c); // Convert c to lower/upper case
Comparison: == != < <= > >= Concatenation: s+s s+=s Substring: s.substr(i,j), s.substr(i) Length: int(s.size()) Index: s[i] where i is 0 to int(s.size())-1 Input: cin >> s; getline(cin, s); Output: cout << s;Comparison is case sensitive, and is done by comparing the ASCII codes of the first nonmatching characters, i.e. "A" and "a" are different. Either operand, but not both, may be a literal.
string s="cat"; s > "Cat"; // true, lower case comes after upper case "cat" == "cat" // false, comparing literals is not meaningful s += "alog" // "catalog" "cat" + "alog" // Error, one operand must be a strings.substr(i,j) returns a substring of size j (or to the end if omitted) after skipping the first i characters.
string s="abcdefg"; s.substr(3, 2); // "de" s.substr(3); // "defg"s.size() is an unsigned type, which can lead to errors in expressions involving negative numbers. Therefore, it should always be converted to int.
s.size() > -1 // false! -1 is silently converted to a huge unsigned number int(s.size()) > -1 // trueThe elements of a string have type char and may be assigned to. There is no run time checking of array bounds.
string s="hello"; s[0]='j'; // "jello" char c=s[4]; // 'o' s[5]=s[-1]; // Program may crash
./a.out <file1 >file2causes the program a.out to read from file1 through cin and to create and write to file2 through cout. Writing to cerr still goes to the screen, and is useful for printing error messages that you want the user to see. cout and cerr support the same operations:
cout << x; // Write int, double, bool, char, or string to standard output cerr << x; // Write to standard error cout << x << y; // Write more than one object. cin.get(c); // Read char c (including '\n'), true if successful c=cin.get(); // Read char c as an int, or EOF (-1) if there is no more input getline(cin, s); // Read a line into string s (discarding '\n'), true if successful cin >> s; // Read one word delimited by spaces or newlinesInput operations return cin, which converts to false at end of file.
while (cin.get(c)) cout << c; // Copy input to output one char at a time while (getline(cin, s)) cout << s << "\n"; // Copy one line at a time
// Copy inputfile to outputfile string inputfile="input.txt", outputfile="output.txt"; ifstream in(inputfile.c_str()); // Might fail, file not found ofstream out(outputfile.c_str()); // Might fail, permission denied or bad path if (!in) cerr << inputfile << " not found\n"; if (!out) cerr << outputfile << " not created\n"; char c; while (out && in.get(c)) // copy until disk full or end of input out << c;
In Windows, text files normally end in a carriage return and linefeed ("\r\n"), but in UNIX and Linux, the carriage return is omitted. To maintain text file compatibility, when a linefeed ("\n") is output, it is converted to "\r\n". When "\r\n" is input, the "\r" is discarded. To prevent this conversion, open a file in binary mode:
ifstream in(inputfile.c_str(), ios::in | ios::binary); ofstream out(outputfile.c_str(), ios::out | ios::binary);cin, cout and cerr are always in text mode.
vector<T> v(n); // n elements of type T int(v.size()) // n v[i] // i'th element, 0 <= i < n v.push_back(x) // Increase size by 1 and append x v.resize(n) // Change size to n vector<T> v; // Size defaults to 0 == != < <= > >= // ComparisonT is the type of the element. If T is numeric, the initial values are 0. If string, then "". Indexing is not bounds checked. Comparison is by the first nonmatching element.
// Read lines of input and print them in reverse order vector<string> v; string s; while (getline(cin, s)) v.push_back(s); for (int i=int(v.size())-1; i>=0; --i) cout << v[i] << "\n";
map<K,V> m; // Map, initially empty m[k]=v; // Associate v (type V) with key k (type K) m[k] // v int(m.size()) // Number of unique keysTo retrieve a sorted list of stored keys, we use iterators. An iterator points to one key-value pair in the map.
map<K,V>::iterator p; // Pointer to a key-value pair p=m.begin() // Points to first pair sorted by key p=m.end() // Points 1 past the last pair ++p; // Point to next pair --p; // Point to previous pair p==q p!=q // true if they point to same/different pairs p->first // key p->second // value, may be assigned to map<K,V>::const_iterator p; // Like iterator, but you can't change the valueThe following sorts a text file using a map<string, int>. It associates each line in the file (the key) with the number of times it occurs. The sorted keys are then printed the number of times indicated by the value.
map<string, int> m; string s; while (getline(cin, s)) ++m[s]; for (map<string, int>::const_iterator p=m.begin(); p!=m.end(); ++p) for (int i=0; i<p->second; ++i) cout << p->first << '\n';If you want to retrieve m[k] and don't know if k was referenced, and you don't want to increase the map size if it wasn't, use m.find(k).
p=m.find(k); // m.end() if not found if (p!=m.end()) p->second; // Value m.erase(p); // Remove pair, also m.erase(k)
min(x,y) // Smaller of x or y max(x,y) // Larger of x or y swap(x,y); // Exchange the values of x and y sort(v.begin(), v.end()); // Sort a vector or string (but not a map) copy(v.begin(), v.end(), d.begin()); // Copy v to d, d.size() >= v.size() fill(v.begin(), v.end(), x); // Set all elements of v to xYou can specify a slice of a vector or string by adding to begin() or subtracting from end().
sort(v.begin()+1, v.end()-1); // Sort all but first and last element copy(v.begin(), v.begin()+v.size()/2, v.begin()+v.size()/2); // Copy first half to second
By default, sort() orders elements using <. You can specify your own order by passing a function that compares two elements and returns true if the first is less than the second. Use stable_sort() to preserve the order of equal elements. The following groups even numbers before odd in a vector<int> v
bool evenFirst(int a, int b) { // true if a is even and b is odd return a%2==0 && b%2==1; } // ... stable_sort(v.begin(), v.end(), evenFirst);
No run time checking is done that a valid range of elements is specified. In particular, copy() does not check if the destination is large enough to hold the result. The program may crash if not. Specifying a slice with negative size can also be disaster.
vector<int> v(10), d; fill(v.begin()-1, v.end()+1, 0); // Crash, writes off ends of v fill(v.end(), v.begin(), 0); // Crash, negative size copy(v.begin(), v.end(), d.begin()); // Crash, d.size() is 0
atoi(s.c_str()) // Convert string to int, e.g. atoi("35") is 35 atof(s.c_str()) // Convert string to double, e.g. atof("35") is 35.0 abs(i) // Absolute value of int i rand() // Pseudo-random int from 0 to RAND_MAX (at least 32767) srand(n) // Initialize rand(), e.g. srand(time(0)); system(s.c_str()) // Execute OS command s, e.g. system("ls"); if (getenv(s.c_str)) s=getenv(s.c_str()) // Environment variable e.g. getenv("PATH") exit(n); // Kill program, return status n, e.g. exit(0);
double(clock())/CLOCKS_PER_SEC // Time in seconds since program started time(0) // Time in seconds, usually since Jan. 1, 1970
An array is like a vector, but its size is fixed at compile time. However, arrays can be initialized and can have more than one dimension. The only valid operation on array x is x[i] where i ranges from 0 to the size - 1. After a partial initialization, the rest of the elements are 0. However if there is no initialization, the elements are random. Array bounds are not checked.
int a[5] = {3,10,15,20,0}; // a[0] is 5, a[4] is 0 int b[2][3] = {{10,20,30},{40,50,60}}; // array of 2 arrays, b[1][2] is 60 int c[1000] = {3}; // c[1]...c[999] are all 0 int d[1000]; // d[0]...d[999] are randomArrays have no .size(), .begin() or .end(). To sort, use the array name for .begin() and add the size to get the end.
sort(a, a+5); // {0,3,10,15,20} stable_sort(a, a+5, evenFirst); // {10,20,0,3,15}A quoted literal string is actually an array of char with a (nonprinting) zero byte to mark the end. There is an automatic conversion to string, which removes the zero byte. The reverse conversion is done with .c_str().
char e[4] = "dog"; // same as char e[4]={'d','o','g',0}; string s=e; // value is "abc", int(s.size()) is 3 cout << int(s.c_str()[3]); // 0Note that 'a' (char) and "a" (array of char) are different types, and both are distinct from string.
T f(T1 x1, T2 x2, ... ) {...}where f is the name of the function, T is the return type, and x1, x2, ... is a list of 0 or more parameters with types T1, T2, ... When the function is called, the local declarations and statements in the block are executed. The last statement executed must return an expression of type T. For instance:
#include <iostream> using namespace std; int division_error=0; // Global object, visible from here on int divide(int x, int y) { // Global function, visible from here on if (y==0) return division_error; else return x/y; } // Scope of x and y ends here int main() { division_error = -1; cout << divide(7+1, 2) << "\n"; // Print 4 return 0; }
A function may return void, in which case it does not need to execute a return statement. It returns when the closing brace is reached. Function parameters may be passed one of three ways:
void assign(bool t, string& dest, const string& src) { // value, ref, const ref if (t) dest=src; } int main() { assign(true, "hi", "ho"); // Error, dest refers to a constant expressionFunction names may be overloaded (reused) as long as they can be distinguished by the types of their parameters.
void swap(int& a, int& b) {...} void swap(string& a, string& b) {...} int main() { int i=1, j=2; swap(i, j); // Calls the first swap()To pass an array of T to a function, declare the parameter as type T*, or as const T* if the elements will not be changed. This has the effect of passing by reference or const reference. Note that the function will not know the size of the array.
// print msg, then sort n elements of a void sortArray(const char* msg, int* a, int n) { cout << msg << "\n"; // assumes msg ends in a zero byte sort(a, a+n); } int main() { int x[5]={6,2,4,3,8}; sortArray("sorting...", x, 5);Command line arguments may be passed to main by giving it parameters (int argc, char** argv), where argv is an array of argc arrays of char, each containing one word from the command line. For example, if echo.cpp is:
#include <iostream> using namespace std; int main(int argc, char** argv) { for (int i=0; i<argc; ++i) cout << argv[i] << '\n'; return 0; } g++ echo.cpp ./a.out hello world ./a.out hello world
struct T { // Creates T as a new type // declarations (without initialization) };By convention, new type names are capitalized. For example:
struct Person { // Person is a new type string name; // a data member int age; // another member }; Person x; // x is an object, x.name is "", x.age is not not initialized Person y = {"Joe", 25}; // y.name is "Joe", y.age is 25 x = y; // Assigns x.name = y.name, x.age = y.age if (x == y) // Error, comparison is not supported vector<Person> v(5); // vector of 5 Persons, not initialized v[4].age = 10; // assign to member of object v[4]
A class is a struct with member functions. A class is divided into a public section, whose members can be accessed as in a struct, and a private section, whose members can be accessed only by the member functions. Member functions are declared in the class like ordinary functions but are called as object.function().
A special member function called a constructor initializes objects of the class. It is not called directly, but rather by passing arguments in the declaration of the object. A constructor has the same name as the class and no return type.
class Person { private: string name; int age; public: void setName(const string& n) {name=n;} // member function string getName() const {return name;} // const member function won't modify members Person(const string& n, int a) {name=n; age=a;} // constructor }; Person x("Joe", 25"); // Calls constructor with n="Joe", a=25 Person y; // Error, constructor requires two arguments Person y = x; // OK, copy y = x; // Assignment y.name = "Bob"; // Error, name is private y.setName("Bob"); // OK, setName() is public cout << x.age; // Error, age is privateA member function may be declared const (as in getName()) to indicate it does not modify any data members. Only const member functions can be called on const objects (including objects passed by const reference).
const Person c = x; // Initialization of const object c (or by constructor is OK) c = x; // Error, assignment to const c.setname("Alice"); // Error, setName() is not const cout << c.getName(); // OK, getName() is constIt is normal in good object oriented design to make all data members private, and only make public enough member functions to make the object usable (including constructors). Member functions that don't modify data members should always be const.
Also, the code for member functions should be moved outside the class unless the code is very short as in this example. Otherwise the compiler takes the inlined code as an optimization hint to replace the function call with inlined code, which increases the size of the executable. The code can be separated by replacing the {...} with ; and writing the function again in the form class::function
class Person { public: void setName(const string& n); string getName() const; Person(const string& n, int a); private: string name; int age; }; void Person::setName(const string& n) { name=n; } string Person::getName() const { // Note const is repeated return name; } Person::Person(const string& n, int a) { // constructor name=n; age=a; }