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 x
A 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 false
break 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 s
A 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 random
Arrays 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]); // 0
Note 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 expression
Function 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 private
A 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 const
It 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;
}