210 likes | 341 Views
Simplifying C++ for Introductory Programming. Athens, 2 5 February 2004. by Pedro Guerreiro pg@di.fct.unl.pt , http://ctp.di.fct.unl.pt/~pg Departamento de Informática Faculdade de Ciências e Tecnologia Universidade Nova de Lisboa 2829-516 Caparica, Portugal. Plan. Why?
E N D
Simplifying C++ for Introductory Programming Athens, 25 February 2004 by Pedro Guerreiro pg@di.fct.unl.pt, http://ctp.di.fct.unl.pt/~pg Departamento de Informática Faculdade de Ciências e Tecnologia Universidade Nova de Lisboa 2829-516 Caparica, Portugal Simplifying C++ for Introductory Programming
Plan • Why? • Learning programming with C++ (!) • Simple classes. • Using the STL. • Library functions. • Introducing inheritance. • Visual programs. • Conclusion. Simplifying C++ for Introductory Programming
Why do we want do simplify C++ Suppose we have decided to use C++ to teach introductory programming. Yes, we know that: • C++ is a complex language. • C++ encompasses several programming paradigms. • C++ allows different styles of programming. • It is unrealistic to teach everything. So being, is it reasonable to use C++ for introductory programming? Yes, provided we simplify it. Simplifying C++ for Introductory Programming
Ways of using C++ C++, according to its author, Bjarne Stroustrup, can be used in four different ways, and combinations thereof: • As a better C. • For programming with abstract data types. • For object oriented programming. • For generic programming. No, thanks. YES, but... OK, but not yet. Yes, we will use this also. And C++ was not meant to be used for teaching programming, as other languages were. Simplifying C++ for Introductory Programming
Classes for abstract data types • An abstract data type is a type or set of types, together with the functions that are applicable to instances of the abstract data type. • A class is an abstract data type together with an implementation. (This is from Bertand Meyer’s book, Object-Oriented Software Construction.) • In the first programs, we will program one class and that class only has one object. (This is a very limited abstract data type…) • That class simply encapsulates the “global variables” and the functions that operate on those variables. Simplifying C++ for Introductory Programming
Example: class Score class Score { public: int maxPoints; double examWeight; double labWeight; Score() { maxPoints = 15; examWeight = 0.70; labWeight = 0.30; } int FinalScore(int exam, int lab) { return static_cast<int>(exam * examWeight + static_cast<double>(lab) / maxPoints * 20 * labWeight + 0.5); } int FinalScoreWithBonus(int exam, int lab) { return Bonus(FinalScore(Bonus(exam), lab)); } int Bonus(int x) { return x == 9 ? 10 : x; } }; This is for computing the final grade of a student in a course. There’s a maximum number of points he can get in the labs. The lab component has a certain weight in the final score and so does the exam. The final score is from 0 to 20, integer. Observe: all functions are defined in the class declaration. There will be no .cpp file. Observe: conditional operator instead of if-else statement. Simplifying C++ for Introductory Programming
Using the class #include <iostream> #include "Score.h" int main() { Score s; int exam; int lab; int with_bonus; int final; for (;;) { std::cin >> exam >> lab >> with_bonus; if (!std::cin) break; if (with_bonus) final = s.FinalScoreWithBonus(exam, lab); else final = s.FinalScore(exam, lab); std::cout << "Score : " << final << std::endl; } } Includes. Function main. Local variables. One of them, s, is of the class type. Infinite loop... ... breaks at the end of file. Functions are called for the target object. Simplifying C++ for Introductory Programming
Simple classes Restricted set of rulesfor classes: • All data members and functions are public. • Default constructor only. • No destructor. • No static members. • No virtual functions. • No consts. • No default arguments. • No overloading. • Pass by value only. • And also: • Each class is defined in a .h file. • The .h file has no #includes and needs no control for repeated inclusion. • The only .cpp file is the file where function main is programmed. • All the #includes are done in the .cpp file. Simplifying C++ for Introductory Programming
Using the STL STL makes life much simpler: • std::string s is better than char *s. • std::vector<int> v is better than int[1000] v. • std::sort readily available for sorting vectors. • Lists come for free with std::list<T>. • std::pair<T, U> useful for simple aggregation. And we can use all this without ever mentioning pointers! Simplifying C++ for Introductory Programming
Simple example with the STL A class for a table of squares: #include <iostream> #include <vector> #include "Squares.h" int main() { Squares s; std::cout << "Up to? "; int n; std::cin >> n; s.Compute(n); for (int i = 0; i < static_cast<int>(s.squares.size()); i++) std::cout << " " << s.squares[i]; std::cout << std::endl; } class Squares { public: std::vector<int> squares; void Compute(int limit) { squares.clear(); for (int i = 0; i*i <= limit; i++) squares.push_back(i * i); } }; Simplifying C++ for Introductory Programming
Library functions First programs need a lot of vector writing. We provide generic Write functions for writing generic vectors to an output stream, the items being separated parametrically: namespace mas { template <class T> void Write(const std::vector<T>& v, const std::string& separator = " ", std::ostream& output = std::cout) { for (typename std::vector<T>::const_iterator i = v.begin(); i != v.end(); i++) output << (i != v.begin() ? separator : "") << *i; } template <class T> void WriteLine(const std::vector<T>& v, const std::string& separator = " ", std::ostream& output = std::cout) { Write(v, separator, output); output << std::endl; } // ... } Yes, these functions use a lot of advanced techniques. There are many other functions like these. Simplifying C++ for Introductory Programming
Simple example with the STL Our main .cpp file for the squares example now becomes: #include <iostream> #include <vector> #include "Utilities.h" #include "Squares.h" int main() { Squares s; std::cout << "Up to? "; int n; std::cin >> n; s.Compute(n); mas::WriteLine(s.squares); } Using generic classes and generic functions is much easier than programming them. Simplifying C++ for Introductory Programming
Introducing inheritance We introduce inheritance with numerical examples. First, a class that computes the solution of equation ex-2=0 using Newton’s method. Do we need to program all this for each new equation? class RealFunction { public: double Function(double x) { return ::exp(x) - 2.0; } double Derivative(double x) { return ::exp(x); } double Newton(double x0, double tolerance) { double x = x0; for (;;) { double delta = Function(x) / Derivative(x); if (::fabs(delta) < tolerance) break; x -= delta; } return x; } }; Simplifying C++ for Introductory Programming
Abstract classes and virtual functions We replace the previous class by this abstract class with two pure virtual functions, one for Function, one for Derivative. This class cannot be used directly, but only through derivation. class RealFunction { public: virtual double Function(double x) = 0; virtual double Derivative(double x) = 0; double Newton(double x0, double tolerance) { double x = x0; for (;;) { double delta = Function(x) / Derivative(x); if (::fabs(delta) < tolerance) break; x -= delta; } return x; } // other functions programmed in terms of Function and Derivative }; Simplifying C++ for Introductory Programming
Derived classes Now we want to compute the zeros of tan(x) – x – 0.5. We define a class Tan1 that inherits from RealFunction and redefine the two virtual functions. Observe: class Tan1: public RealFunction { public: double Function(double x) { return ::tan(x) - x - 0.5; } double Derivative(double x) { return ::pow(1.0 / ::cos(x), 2) - 1; } }; This is how we use it: This is more effective than introducing inheritance with examples such as “a cat is an animal” or “a student is a person”. int main() { Tan1 r; std::cout << std::fixed << std::setprecision(15); x = r.Newton(0.85, 0.000001); std::cout << x << " " << r.Function(x) << std::endl; } Simplifying C++ for Introductory Programming
Visual programs • We want to teach students to write graphical programs that use buttons, menus, etc. • With Microsoft Visual C++, it is not too difficult, even for novice programmers, to design dialog-based programs, provided they stick to a simple set of guidelines. • There is a major complication, however. Classes supplied Microsoft use CString, not std::string. We have to provide adapters that convert from one to the other. In the process, we simplify the usage, by keeping only the arguments that are needed at this stage. • A second complication arises for programs that draw: we do not want to have to deal with device contexts, allocating pens, COLORREFs, … Simplifying C++ for Introductory Programming
Visual programs, example Here is an example of a OnBnClickedButton function, in a graphical variant of the Score problem: void CScoreVisualDlg::OnBnClickedButton1() { Score s; double x = mas::GetDouble(m_exam); int y = mas::GetInt(m_lab); int z = s.FinalScore(x, y); mas::SetInt(m_final, z); } These functionsGetDouble, GetInt and SetInt come from our library. Simplifying C++ for Introductory Programming
Visual utilities The visual utilities are provided in a library. They involve advanced programming techniques, but are not difficult to use: int AsInt(const CString& s, int base = 10) { int result; char *endp; errno = 0; result = ::strtol(s, &endp, base); if (s.IsEmpty() || errno || *endp) { errno = 0; std::string message("\"" + s + "\" is not a legal int value."); throw message; } return result; } int GetInt(CWnd& x) { CString s; x.GetWindowText(s); return AsInt(s); } There are many functions like these. Simplifying C++ for Introductory Programming
Class SimpleGraphics (1) For programs that draw, we use a class SimpleGraphics: class SimpleGraphics { protected: CPaintDC dc; COLORREF penColor; COLORREF penThickness; COLORREF brushColor; public: COLORREF black; COLORREF blue; // ... public: SimpleGraphics(CWnd* pWnd): dc(pWnd) { black = RGB(0, 0, 0); blue = RGB(0, 0, 255); // ... penColor = black; penThickness = 1; brushColor = white; } //... //... void SetPenColor(COLORREF color) { penColor = color; } void SetPenThickness(int thickness) { penThickness = thickness; } void SetBrushColor(COLORREF color) { brushColor = color; } // ... Simplifying C++ for Introductory Programming
Class SimpleGraphics (2) void DrawLine(const CPoint& p1, const CPoint& p2) {...} void DrawPolyline(const std::vector<CPoint>& points) {...} void DrawPolygon(const std::vector<CPoint>& points) { CPen pen(PS_SOLID, penThickness, penColor); CPen* pOldPen = dc.SelectObject(&pen); CBrush brush(brushColor); CBrush* pOldBrush = dc.SelectObject(&brush); CPoint *p = new CPoint[static_cast<int>(points.size())]; for (int i = 0; i < static_cast<int>(points.size()); i++) p[i] = points[i]; dc.Polygon(p, static_cast<int>(points.size())); delete [] p; dc.SelectObject(pOldPen); dc.SelectObject(pOldBrush); } void DrawText(const std::string& s, const CPoint& p) { dc.TextOut(p.x, p.y, s.c_str()); } }; Observe that polylines and polygons are represented externally by vectors of points (std::vector<CPoint>) and internally by arrays of points that are dynamically allocated. Simplifying C++ for Introductory Programming
Conclusion • Yes, we can teach introductory programming with C++. • But we should use a simplified C++. • Simplification also means using the STL immediately. • Complications are avoided by utility functions and classes that must be provided. • With the help of the utility functions ,dialog-based programs with buttons, menus, etc., can be a part of introductory programming. • And so can programs that make simple drawings. • The rest of C++ comes afterwards, in a course of Object-Oriented Programming with C++. Simplifying C++ for Introductory Programming