// C++ Cheat Sheet for CMSC 331 // revised 3/13/2014 // comments look like this /* or like this */ // use the command g++ cppcs2.cpp to compile this file on gl #include // the built-in stream I/O package #include #include #include using namespace std; // a relatively new feature in C++ #include // This is C's assert macro, which works fine in C++ // class rational // inspired largely by Budd's well-known data structures textbook class rational { public: // these member functions can be called from anywhere /* constructors have the same name as the class itself */ // these are function DECLARATIONS, not DEFINITIONS. Those come later. rational (); rational (int); rational (int,int); // const keyword keeps the object from being modified rational (const rational &); // destructors, if any, are named ~class e.g. // ~rational(); /* accessor functions */ int numerator () const; int denominator () const; /* assignments */ // could add *=, /=, and so forth // note the over-loading of = and += operators already in C++ void operator = (const rational &); void operator += (const rational &); /* arithmetic */ // friend functions aren't member functions of the class, but // they can still access private data friend rational operator + (const rational &, const rational &); friend rational operator - (const rational &, const rational &); friend rational operator - (const rational &); // unary -, i,e, negation /* comparison */ friend bool operator < (const rational &, const rational &); friend bool operator > (const rational &, const rational &); friend bool operator == (const rational &left, const rational &right); /* output */ friend ostream & operator << (ostream &, const rational &); private: // private data is only visible from member functions // of this class or derived classes, or friend functions /* data areas */ // in fractions, int top; // top can be pos or neg int bottom; // but let's make sure bottom is positive }; // Constructors // to have several forms of a given constructor for different // number and type of arguments is very common rational::rational() // make zero the default value { top = 0; // could also say this.top = 0; where this points to the current object bottom = 1; } rational::rational(int numerator) // integer x becomes rational x/1 { top = numerator; bottom = 1; } rational::rational(int numerator, int denominator) { assert( denominator != 0 ); // because that's bad top = numerator; // n.b. several functions with same name bottom = denominator; } rational::rational(const rational & value) // use one rational to { // initialize another // const qualifier prevents this member function from changing // the value - even though value's private data is visible! top = value.numerator(); // using accessor is not that different from bottom = value.bottom; // using private data } // Accessors int rational::numerator() const { return top; } int rational::denominator() const { return bottom; } // Assignments void rational::operator = (const rational &right) { top = right.numerator(); bottom = right.denominator(); } // older version //void rational::operator += (const rational &right) //{ // top = top * right.denominator() + right.numerator() * bottom; // bottom = bottom * right.denominator(); //} void rational::operator += (const rational &right) { // note that this is a pointer to the object being referred to *this = (*this)+right; } // Arithmetic rational operator + (const rational &left, const rational &right) { rational result( left.numerator() * right.denominator() + right.numerator() * left.denominator(), left.denominator() * right.denominator()); return result; } rational operator - (const rational &left, const rational &right) { rational result( left.numerator() * right.denominator() - right.numerator() * left.denominator(), left.denominator() * right.denominator()); return result; } rational operator - (const rational &r) // unary minus is negation { // create a rational == 0 using the appropriate constructor return (0 - r); } // multiplication and division could be defined in a similar fashion // Comparison bool operator < (const rational &left, const rational &right) { return (left.numerator() * right.denominator()) < (right.numerator() * left.denominator()); } bool operator > (const rational &left, const rational &right) { return (left.numerator() * right.denominator()) > (right.numerator() * left.denominator()); } bool operator == (const rational &left, const rational &right) { return (left.numerator() * right.denominator() == left.denominator() * right.numerator()); } // <= and >= and != could be defined in a similar fashion // I/O (well, just O for the time being) ostream & operator << (ostream & ostr, const rational &r) { ostr << r.numerator() << "/" << r.denominator(); return ostr; } // Other functions - not members or friends // although it would be easy enough to change that... rational invert(const rational &r) { assert( r.numerator() != 0 ); return rational(r.denominator(), r.numerator()); } rational abs(const rational &r) { if (r < 0) { return -r; } else { assert( (r == 0) || (r > 0) ); // demonstrate assert return r; } } void testControlStructures() { // enumeration types are lists of named integer constants enum options {option1=1, option2=2}; options op=option1; int i; // but manipulation of these as integers requires casts switch (op) { case 1: cout << "hello from option 1\n"; i = 5; while (i > 0) { cout << i-- << " "; } cout << "Blastoff!\n"; break; // don't forget the break! case 2: cout << "hello from option 2\n"; for (i = 1; i<10; i++) { cout << i << " "; } cout << i << endl; break; default: cout << "hello, whatever\n"; } } void testRationals() { // Test the different constructors (and output) rational w, t(3), x, y(3,4), z(-2,3), u(y), v(1,2); cout << "w = " << w << " (should equal 0)" << endl; cout << "t = " << t << " (should equal 3)" << endl; cout << "y = " << y << " (should equal 3/4)" << endl; cout << "z = " << z << " (should equal -2/3)" << endl; cout << "u = " << u << " (should equal y)" << endl; cout << "v = " << v << " (should equal 1/2)" << endl; // Test the assignment operators w = y; cout << "w = " << w << " (should equal y)" << endl; w += v; cout << "w = " << w << " (should equal w+v)" << endl; // Test the arithmetic operators w = y + z; cout << "w = " << w << endl; w = t - y; cout << "w = " << w << endl; t = -y; cout << "t = " << t << endl; // Test the invert and abs functions // The comparison operators are tested in abs w = invert(y); cout << "w = " << w << endl; x = abs(z); cout << "x = " << x << endl; } int countCharacters(string fileName) { // count the characters in the given file // no checking is done to see if the file exists, or whatever int nChars = 0; char ch; fstream inputStream; try { inputStream.open(fileName); } catch (int e) { cerr << "Some problem with opening " << fileName << endl; } while (inputStream.get(ch)) { // if there's a character to be read, put it in ch nChars += 1; } inputStream.close(); // not necessary in this instance, but a good habit return nChars; } void swap(int& x, int& y) // call by reference example { int t; t = x; x = y; y = t; } int main() { string yourName; cout << "What is your name?" << endl; cin >> yourName; cout << "Hello, " << yourName <