TDDD38 APiC++ Basic C++ 1 Basic C++ TDDD38 APiC++ Basic C++ 2 The classic first C++ program • compilation model /* * hello.cc */ #include <iostream> using namespace std; • keywords and identifiers with special meaning • objects, declarations, and initialization • data types and type conversion • pointers int main() { cout << "Hello, world" << endl; • references • pointers and dynamic memory handling • aggregates and list initialization return 0; // this return statement is optional } • declarations and definitions • expressions and operators • multi-line and single-line comments • statements • include directive – import stuff from the environment, in this case from the standard input/output library (streams) • functions and parameter passing • using directive – opens the standard namespace std – without require qualified names • strings std::cout << "Hello, world" << std::endl; • tuples • streams • function main() is found in all (normal) C++ programs – this is where the execution starts and normally ends • string streams – function prototype – function body Note 1: A lot of concepts and terminology to follow… • statements Note 2: Much of the stuff related to streams is mainly for self study (page 33 ff.) File: Basic-CPP-OH-en TDDD38 APiC++ © 2015 Tommy Olsson, IDA, Linköpings universitet (2015-01-21) Basic C++ 3 Compilation model (1) File: Basic-CPP-OH-en © 2015 Tommy Olsson, IDA, Linköpings universitet (2015-01-21) TDDD38 APiC++ Basic C++ 4 Compilation model (2) source code → preprocessor → compiler → linker → executable A slightly simplified picture: • source code – include files (*.h) – declarations and definitions required by client code – “module specification” include files (headers) link libraries iostream *.so.* – also standard headers, e.g. <iostream> – implementation files (*.cc, *.cpp, …) – e.g. separate definitions for declarations in a corresponding header file *.h *.a • preprocessor -Idir – works before the actual compilation takes place – avoid when possible *.cc • compiler -Ldir -llib pure C++ – file inclusion, macro substitution, conditional compilation, … cpp compiler object code -c – takes the preprocessor output as input linker a.out -o filename – produces, in cooperation with linker, an executable (a.out, e.g.) – separate compilation to object code, if requested (*.o files) – stops before linking phase *.o • options can modify the translation process in many ways – preprocessing, compilation, linking – GCC/Linux examples: g++ hello.cc g++ -c program.cc g++ -g -std=c++11 -Wpedantic -Wall -Wextra hello.cc g++ -I/home/tao/include -o program program.cc -lcurses gccfilter g++ ... File: Basic-CPP-OH-en © 2015 Tommy Olsson, IDA, Linköpings universitet (2015-01-21) File: Basic-CPP-OH-en © 2015 Tommy Olsson, IDA, Linköpings universitet (2015-01-21) TDDD38 APiC++ Basic C++ 5 Keywords and identifiers with special meaning TDDD38 APiC++ Basic C++ 6 Data types and type conversion alignas continue friend register true The type system design have great influence on safety, efficiency, etc. alignof decltype goto reinterpret_cast try • C++ is a strongly, statically typed language asm default if return typedef – each object and expression has a distinct type auto delete inline short typeid – in polymorphic contexts we have a distinction between static type and dynamic type bool do int signed typename break double long sizeof union case dynamic_cast mutable static unsigned catch else namespace static_assert using char enum new static_cast virtual char16_t explicit noexcept struct void – implicit (automatic) char32_t export nullptr switch volatile – explicit (coded) class extern operator template wchar_t – three different syntaxes… const false private this while const_cast float protected thread_local constexpr for public throw – standard type conversions relaxes strong typing • two main type categories – fundamental types – compound types • type conversions static_cast<T>(x) // type conversion operators – prefer these! (checked) T(x) // functional form (unchecked!) (T)x // C cast (unchecked!) • export is removed but kept for the future use (related to compiling templates) • register is deprecated (don’t use) • final and override – identifiers (not keywords) with special meaning in specific contexts (classes, member functions) File: Basic-CPP-OH-en © 2015 Tommy Olsson, IDA, Linköpings universitet (2015-01-21) TDDD38 APiC++ Basic C++ 7 Fundamental types File: Basic-CPP-OH-en © 2015 Tommy Olsson, IDA, Linköpings universitet (2015-01-21) TDDD38 APiC++ Basic C++ 8 Compound types (1) Compound types can be constructed in many ways – some common compound types: = “keeping it simple” • arrays are indexed data types made up of elements of the same type (prefer std::array or std::vector) fundamental types int a[100]; arithmetic types void • pointers to objects or functions of a certain type, or to void (“anything”) int* p{ a }; integral types floating point types float integer types char bool File: Basic-CPP-OH-en int& r{ a[0] }; // lvalue reference void fun(string&& s); // rvalue reference – binds e.g. temporary objects • class types (class, struct or union) made up of named components of possibly different type, including member functions char16_t char32_t • references to objects or functions of a certain type double long double wchar_t // same as int* p = a; or int* p = &a[0]; signed integer types unsigned integer types signed char unsigned char short int unsigned short int int unsigned int long int unsigned long int long long int unsigned long long int struct Person { string name; unsigned age; float length; }; Note: arrays and simple class types are aggregates. © 2015 Tommy Olsson, IDA, Linköpings universitet (2015-01-21) File: Basic-CPP-OH-en © 2015 Tommy Olsson, IDA, Linköpings universitet (2015-01-21) TDDD38 APiC++ Basic C++ 9 TDDD38 APiC++ Basic C++ Compound types (2) Type definition • functions have parameters of different types and return either void (nothing) or some type • an alias declaration is used to declare a simple name for a “complicated” type // Type: int(int,int) or int (*)(int, int) int max(int x, int y); 10 using Func = int (*)(int, int); • enumeration types Func f{ max }; // max was declared on the previous slide • typedef also (this was earlier the only possibility – regarded as less readable) enum Alert { Red, Orange, Yellow, Blue, Green }; – the values are called enumerators struct List_Node { string data; List_Node* next; }; – an enumerator can be implicitly converted to and compared with int – they are effectively integers • scoped enumeration types enum class Colour : unsigned int { Red, Orange, Yellow, Green, Blue, Indigo, Violet }; Colour c{ Colour::Red }; c = Colour::Blue; // error – no implicit conversion for scoped enumerations int i{ Colour::Red }; typedef List_Node* List; // using List = List_Node*; void insert(Type x, List& list); // List_Node*& list List head{ nullptr }; // List_Node* head – enum class or enum struct – semantically equivalent • Func and List are not distinct types – only synonyms for the actual type – there is no implicit conversion to int or bool • an alias declaration can contain attribute specifiers – a typedef declaration can not – the enumerators of a scoped enumeration have enumeration scope – the same enumerator can occur in several enumerations – the underlying type can be can be specified – must be an integral type File: Basic-CPP-OH-en © 2015 Tommy Olsson, IDA, Linköpings universitet (2015-01-21) TDDD38 APiC++ Basic C++ 11 File: Basic-CPP-OH-en © 2015 Tommy Olsson, IDA, Linköpings universitet (2015-01-21) TDDD38 APiC++ Basic C++ CV-qualification Pointers A type like int is a cv-unqualified type: A pointer is an object storing an address (pointer) to another object. int x; 12 { T x; // variable of type T T* p{ nullptr }; // pointer to T, initialized with a null pointer value p = &x; // p is assigned the address of x, using the address operator & cout << p; // the address stored in p is printed cout << *p; // p is dereferenced with the dereferencing operator *, the value of x is printed p = new T; … // allocate a dynamic object of type T with the new operator and store a pointer to it in p delete p; … // deallocate the object p is pointing at All cv-unqualified types have three corresponding cv-qualified versions. • const-qualified – such an object is a const object const int MAX{ 1000 }; constexpr const int MAX{ 1000 }; constexpr int MAX{ 1000 }; – const objects must be initialized • volatile-qualified – such an object is a volatile object volatile int bird; – volatile is a hint to the implementation to avoid optimization involving the object – its value might be changed by means undetectable by the implementation • const-volatile-qualified – such an object is a const volatile object } // x and p goes out of scope volatile const int x; • objects created with operator new are allocated on the heap – const means that the code cannot change the value of the object – does not mean that the value of the object cannot be changed by means outside the code – volatile • p must not outlive x – possible if p was declared in an outer scope • it is very important to deallocate dynamic objects properly – operator delete – memory leaks must be avoided • cv-qualification distinguishes in function overloading – can be ignored in some contexts • smart pointers are available in the standard library – unique_ptr, shared_ptr, weak_ptr File: Basic-CPP-OH-en © 2015 Tommy Olsson, IDA, Linköpings universitet (2015-01-21) File: Basic-CPP-OH-en © 2015 Tommy Olsson, IDA, Linköpings universitet (2015-01-21) TDDD38 APiC++ Basic C++ 13 References TDDD38 APiC++ Basic C++ 14 Pointers and dynamic memory handling • Dynamic memory is allocated on a global heap – pointers are used to handle such objects { T x; // variable of type T T& r{ x }; // (lvalue) reference to T • No garbage collection can be expected – deallocating dynamic memory when no longer needed is very important – smart pointers can be a good choise • Memory allocation and deallocation operators are available in several versions. cout << r; // r is implicitly dereferenced – the value of x is printed – ordinary versions for allocating/deallocating either an object of none-array type or an object of array type: } • a reference can be thought of as a name of an object – in the example above r is another name for x, an alias X* p{ new X }; delete p; X* p{ new X[100] }; delete[] p; – must always be initialized – there is no “null reference” – nothrow versions – a null pointer is returned when allocation fails, instead of exception bad_alloc thrown; non-array version: – references are quite different from pointers semantically and there need not be any value stored for a reference • in C++11 there are two kind of references – lvalue references and rvalue references X* p{ new(std::nothrow) X }; // nullptr is returned on failure – have much in common regarding semantics if (p != nullptr) … – one of the main uses of references is as function parameters and return types – the most anticipated function overloadings are void fun(const T& x); // matches any kind of argument (as do also plain T) void fun(T&& x); // but this will be a better match for rvalues, e.g. temporary objects – placement versions are used to construct objects in some already available memory, not necessarily heap memory; array version: – closely related to temporary objects, but not exclusively, and move semantics – typical use is in move constructors and move assignment operators – does not leave the source unchanged TDDD38 APiC++ © 2015 Tommy Olsson, IDA, Linköpings universitet (2015-01-21) Basic C++ // non-heap memory, can store 10 objects of type X X* p{ new(place) X[10] }; // create 10 default initialized X objects in place for (int i = 0; i < 10; ++i) p[i].~X(); // explicit destructor calls Note: no special call syntax for nothrow and placement versions of delete. “Every time I think I have grasped rvalue references, they evade me again.” File: Basic-CPP-OH-en alignas(X) char place[10 * sizeof(X)]; 15 File: Basic-CPP-OH-en © 2015 Tommy Olsson, IDA, Linköpings universitet (2015-01-21) TDDD38 APiC++ Basic C++ 16 Aggregates and initializer lists (1) Aggregates and initializer lists (2) An aggregate is either • aggregates can be initialized by an initializer list (braced-init-list) – list initialization: • an array int a[10]{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; int data[10]; Person p{ "Foo", 21, 1.82 }; • or a class with int_or_double iod{ 17 }; – no user-provided constructors Person* ptr = new Person{ "Foo", 21, 1.82 }; – no private or protected non-static data members – no base classes // in a new expression • there may be fewer elements in the initializer list than members or elements in the aggregate – no virtual functions – no brace-or-equal-initializers for non-static data members (removed in C++14) int a[10]{}; // empty list, all 10 elements are initialized to 0 Basically something very simple like Person p{ "Foo" }; // same as { "Foo", 0, 0.0 } struct Person { string name; unsigned age; float length; }; • class aggregates can also be assigned an initializer list p = { "Fie", 17, 1.67 }; (More about aggregates and list initialization in one of the exercises). union int_or_double { int i; double d; }; File: Basic-CPP-OH-en © 2015 Tommy Olsson, IDA, Linköpings universitet (2015-01-21) File: Basic-CPP-OH-en © 2015 Tommy Olsson, IDA, Linköpings universitet (2015-01-21) TDDD38 APiC++ Basic C++ 17 TDDD38 APiC++ Basic C++ Implicit type conversion Explicit type conversion • implicit type conversion (in a general meaning) can be of two kinds Explicit type conversions can be expressed using – conversions are potentially unsafe – e.g. from int to short int 18 • cast notation (comes from C) – unchecked – avoid! – promotions are safe – e.g. from int to long int // suppose x is int, d is double x = (int)d; • the standard defines a number of standard type conversions • functional notation (early C++) – unchecked – avoid! – lvalue-to-rvalue conversion (1) – array-to-pointer conversion (1) x = int(d); – function-to-pointer conversion (1) • type conversion operators – checked – integral promotions (2) – floating point promotion (2) static_cast<int>(d) between related types (e.g. different arithmetic types) – floating point conversions (2) reinterpret_cast<int>(p) between types not related (e.g. integer and pointer) – floating-integral conversions (2) dynamic_cast<Derived*>(bp) within a polymorphic class hierarchy (e.g. from base class pointer to subclass pointer) const_cast<int>(c) removes const – integral conversions (2) – pointer conversions (2) – pointer to member conversions (2) – boolean conversions (2) The expression T() creates a (value-initialized) value of type T – especially useful if T is a template type parameter – qualification conversions (3) • a standard conversion sequence is a sequence of up to three standard conversions – zero or one from set (1), zero or one from set (2) or a user defined conversion, and zero or one from set (3) File: Basic-CPP-OH-en TDDD38 APiC++ © 2015 Tommy Olsson, IDA, Linköpings universitet (2015-01-21) Basic C++ 19 auto x = int(); // x obtains type int, and is initialized to 0 (zero-initialized, one kind of value-initialization) auto x{ int() }; // x may not obtain the type you expect… (to be fixed in future C++) File: Basic-CPP-OH-en TDDD38 APiC++ © 2015 Tommy Olsson, IDA, Linköpings universitet (2015-01-21) Basic C++ Declarations and definitions (1) Declarations and definitions (2) Declarations generally specify how names are to be interpreted. Declarative regions and scope rules are not trivial. • a declaration may introduce a name into a translation unit, or re-declare a name introduced by a previous declaration • C++ is basically a block structured language, with related scope rules • a declaration is a definition if it basically results in some code 20 – block scope (local scope) – namespace scope int a; extern int a; extern int a{0}; // defines a // declares a // defines a int square(int x) { return x*x; } int square(int x); // defines square // declares square struct point { int x; int y; }; struct point; // defines point // declares point enum { UP, DOWN }; namespace N { int m; } // defines UP and DOWN // defines N and N::m using N::m; // declares m – class scope – function prototype scope (function parameters) – function scope (labels) – template parameter scope – enumeration scope (scoped enumerators) • raises questions about name look up, name hiding, accessibility, ambiguities, etc. – not always obvious or simple • ODR – one definition rule – no translation unit shall contain more than one definition of any variable, function, class type, enumeration type, or template File: Basic-CPP-OH-en © 2015 Tommy Olsson, IDA, Linköpings universitet (2015-01-21) File: Basic-CPP-OH-en © 2015 Tommy Olsson, IDA, Linköpings universitet (2015-01-21) TDDD38 APiC++ Basic C++ 21 TDDD38 APiC++ Basic C++ 22 Storage duration and object lifetime Expressions and operators (1) Storage duration is the property of an object that defines the minimum potential lifetime of the storage containing the object. There are may operators in C++ and extensive possibilities to compose expressions. • the storage duration is determined by the construct used to create the object and is one of the following: • the common set of operators, such as additive, multiplicative, relational, logical, etc., but also, e.g.: – static storage duration (global objects) – subscripting: [] – automatic storage duration (local variables and parameters – the old meaning of the, until C++11, never used keyword auto) – function call: () – dynamic storage duration (programmer controlled – new, delete) – class member access: . and -> – thread local storage (every thread can have its own storage, or share) – pointer-to-member operators: .* and ->* – eleven assignment operators: =, +=, -=, *=, /=, … • the lifetime of an object – conditional operator: ?: – begins when storage is obtained and the object is fully initialized – comma operator: , – ends when the object’s destructor call starts, if the object is a class type, and the storage is reused or released • many precedence (priority) levels • temporary objects are created in several contexts – binding a reference to a value (prvalue) – some with left associativity, some with right associativity – returning a value from a function (prvalue) – gives basically natural semantics – parentheses can be used for specifying a required evaluation order, or for clarity – a type conversion that creates a value (prvalue) • most operators are overloadable for compound types (class types, enumeration types, pointer types, …) – throwing an exception – entering a exception handler – some initializations – rvalue reference is a kind of reference which can bind to temporary objects, and other rvalues File: Basic-CPP-OH-en © 2015 Tommy Olsson, IDA, Linköpings universitet (2015-01-21) TDDD38 APiC++ Basic C++ 23 File: Basic-CPP-OH-en TDDD38 APiC++ Expressions and operators (2) Expressions and operators (3) • an expression is a sequence of operators and operands that specifies a computation Categorization of expressions. a * b - 1 Basic C++ 24 expression x = y + 1 + fun(); • an expression can result in a value and can cause side effects ++x © 2015 Tommy Olsson, IDA, Linköpings universitet (2015-01-21) x++ glvalue • lvalue – “can be assigned to” – can be on the left hand side of an assignment rvalue lvalue xvalue prvalue T& T&& T const T& – designates an object or a function x = y = z = 0; – glvalue – general lvalue – lvalue or an xvalue – “something that can be changed” – ++ and = have side effect, but, it is usually the main purpose, to modify the value of the operand – the resulting value of the prefix ++ expression is the value x obtain after incrementation – the resulting value of the postfix ++ expression is the value x had before incrementation (may carry a cost) • operators have precedence and associativity • rvalue – “can be copied” – something that can be on the right hand side of an assignment – an rvalue is an xvalue, a temporary object, or a value that is not associated with an object – prvalue – pure rvalue – an rvalue that is not an xvalue – function return value, literal • xvalue – eXpiring value – object usually near the end of its lifetime a * b - 1 is evaluated (a * b) - 1 * have precedence over - a + b - 1 is evaluated (a + b) - 1 + and - have same precedence, are left associative x = y = 0 is evaluated x = (y = 0) = is right associative – can be pilfered – its resources can moved – functions returning rvalue-reference (&&) typically involved • every expression belongs to exactly one of the fundamental classifications lvalue, xvalue, or prvalue – its value category The name rule: if something has a name, it’s an lvalue, if not, it’s an rvalue • in most cases the evaluation order of operands is not specified – exceptions are &&, ||, ?: and , (comma operator) – an lvalue is something you can take the address of (with the address operator &) • value is a bit misleading, these are not really values (expression categories) if (p != nullptr && p->value == 0) … int min{x < y ? x : y}; File: Basic-CPP-OH-en © 2015 Tommy Olsson, IDA, Linköpings universitet (2015-01-21) File: Basic-CPP-OH-en © 2015 Tommy Olsson, IDA, Linköpings universitet (2015-01-21) TDDD38 APiC++ Basic C++ 25 TDDD38 APiC++ Basic C++ Statements (1) Statements (2) Mainly traditional, but some are rather “low level” constructs. The switch statement, case labelled statement, and break statement. • declaration statements – int i; int main() { char c; • empty statement – ; • expression statements – expression; • compound statement, or block, to encapsulate a sequence of statements – { … } cout << "Say y = Yes, or n = No: "; cin >> c; • labelled statement – label : statement (label is an identifier, case or default) • selection statements switch (c) { case ’y’: case ’Y’: cout << "You said Yes"; break; case ’n’: case ’N’: cout << "You said No"; break; default: cout << "Wrong choise!"; break; } – if – with or without else – switch – to a case label or default (labelled statements) • iteration statements – while – logical pretest – do – logical posttest – for – basically logical pretest, but can also model count pretest – range-based for – a simple-to-use for statement to iterate over, e.g., an array or a container (C++11) • jump statements – break – out of a switch or an iteration – continue – with the next step in an iteration – return – from a function // break fall-through, jump out of switch // if selected, fall-through to next case statement // break fall-through, jump out of switch // select if no case matched // optional, the switch statement is anyway exited soon } File: Basic-CPP-OH-en © 2015 Tommy Olsson, IDA, Linköpings universitet (2015-01-21) Basic C++ 27 File: Basic-CPP-OH-en © 2015 Tommy Olsson, IDA, Linköpings universitet (2015-01-21) TDDD38 APiC++ Statements (3) Statements (4) Iteration statements. The range-based for statement. while { if if // } // if selected, fall-through to next case statement return 0; – goto – a labelled statement TDDD38 APiC++ 26 (cin >> x) int a[5]{ 1, 2, 3, 4, 5 }; (x > MAX) break; (x == 0) continue; … for (int& x : a) x *= 2; Basic C++ 28 vector<Person> v{ 1, 2, 3, 4, 5 }; do { for (const auto& p : v) cout << p << ’\n’; cout << "Give me five! "; cin >> x; // … // const Person& The beginning and end of the range is determined as follows: } while (x != 5); • if an array a with dimension N – a – a+N for (int i = 0; i < MAX; ++i) { if (i % 2 == 0) continue; // … } • if an object c of class type – begin() and end() return iterators – c.begin() – c.end() • otherwise, for an object x – begin() and end() return iterators for (auto it = begin(v); it != end(v); ++it) cout << *it << ’\n’; – begin(x) – end(x) File: Basic-CPP-OH-en © 2015 Tommy Olsson, IDA, Linköpings universitet (2015-01-21) File: Basic-CPP-OH-en © 2015 Tommy Olsson, IDA, Linköpings universitet (2015-01-21) TDDD38 APiC++ Basic C++ 29 TDDD38 APiC++ Functions and parameter passing (1) Functions and parameter passing (2) • Functions can be overloaded Semantic parameter passing modes: – differences in parameter lists distinguish Basic C++ 30 • by value – for in parameters of simple type (possibly const, no big deal which) – return type does not participate in overload resolution void fun(string s); void fun(const string); • Member functions (classes) can be overridden if virtual – identical parameter list • by lvalue reference – for in/out or out parameters – usually same return type (covariant types allowed) • Function parameters can have default arguments void fun(string& s); – used when no corresponding argument is given in a call • by lvalue reference to constant – for in parameters of “complicated” type void increment(int& value, int amount = 1); void fun(const string& s); • Syntactically we have two parameter passing mechanisms • by rvalue reference – typically for catching temporaries and applying move semantics on the argument – call by value void fun(string&& s); void fun(string s); • by pointer – for pointers argument, of course, but also allows for “no value present” (if nullptr argument) – call by reference void fun(string* p); void fun(const string* p); void fun(string*& p); void fun(string& s); // there are more combinations for const… – but five “semantic” parameter passing techniques (next slide) • function parameters are always lvalues (something that have a memory address) according to the name rule File: Basic-CPP-OH-en © 2015 Tommy Olsson, IDA, Linköpings universitet (2015-01-21) TDDD38 APiC++ Basic C++ 31 File: Basic-CPP-OH-en TDDD38 APiC++ Strings Tuples Two possibilities to handle strings: Can be instantiated with any number of arguments. • null terminated character sequences, “C strings” – well known trouble maker… char s1[72]{}; char s2[]{ "C string" }; const char* p{ "C++" }; Basic C++ 32 tuple<int, string, double> fragrance{ 4711, "Eau de Cologne", 39.39 }; // dimension 72, all elements initialized to \0 // dimension deduced to 9, initialized to C string\0 // character pointer, must be const here – standard library utilities for handling such strings are found in, e.g., <cstring>, <cctype>, and <cstdlib> strcpy(s1, s2); © 2015 Tommy Olsson, IDA, Linköpings universitet (2015-01-21) // equivalent to assigning (s1 = s2) • strings are in most cases much better handled using std::string int number; string name; double price; tie(number, name, price) = fragrance; get<2>(fragrance) = 49.95; auto t = tuple_cat(fragrance, tuple{"SEK"}); // tuple<int, string, double, string> tuple<int, int, int> fun(); int a, b, c; // function returning three int #include <string> string s1; string s2{ "C++ string" }; const string cs{ "C++" }; // default initialized, empty string // initial size is 10 // constant string tie(a, b, c) = fun(); – a large set of operations are supplied by member functions and other functions – well-behaved concerning initialization, copying, comparing, etc. tie(a, ignore, ignore) = fun(); // we are only interested in the first value tie(a, b, c) = make_tuple(b, c, a); // rotate (a, b, c) -> (b, c, a) – the implementation is actually a template, basic_string – string is an instance for char Not as flexible as one may expect, or wish, but still useful. – designed as a container type for storing characters, with iterators and all File: Basic-CPP-OH-en © 2015 Tommy Olsson, IDA, Linköpings universitet (2015-01-21) File: Basic-CPP-OH-en © 2015 Tommy Olsson, IDA, Linköpings universitet (2015-01-21) TDDD38 APiC++ Basic C++ 33 TDDD38 APiC++ Basic C++ Streams Stream classes hierarchy The stream library is for reading and writing streams Very simplified: • a stream is a sequences of elements of a certain type, typically characters 34 ios_base • stream types ios – in streams – istream, ifstream <ios> – out streams – ostream, ofstream istream – in- and out streams – iostream, fstream ostream <istream> <ostream> – string-based streams – istringstream, ostringstream, stringstream iostream • operations provided to – open and close streams ifstream istringstream fstream stringstream <iostream> ofstream ostringstream <fstream> <sstream> – read and write streams – text or binary – check the state of a stream – e.g. end-of-stream, error conditions – manipulate character streams – e.g. to modify input- or output format Object-oriented constructs and several other advanced features are used: • all classes except ios_base are templates (the classes above are actually instances for char; add basic_ for the primaries) – parameterized on character type and a character traits class providing character and string manipulation utilities • single inheritance – all except iostream • multiple inheritance – iostream • repeated inheritance – ios to iostream – DDD, the “Deadly Diamond of Derivation” – virtual inheritance – there are things in ios that must not be inherited into iostream in multiple instances • polymorphic classes (all) File: Basic-CPP-OH-en TDDD38 APiC++ © 2015 Tommy Olsson, IDA, Linköpings universitet (2015-01-21) Basic C++ 35 File: Basic-CPP-OH-en TDDD38 APiC++ Using the streams library Formatted I/O #include <iostream> For character streams, character file streams and string streams. © 2015 Tommy Olsson, IDA, Linköpings universitet (2015-01-21) Basic C++ 36 • the standard library provide overloadings for operator<< and operator>> for fundamental types and string types – the stream classes istream, ostream och iostream • operator<< perform formatted output – the standard streams cin, cout, cerr and clog – manipulators without parameters, e.g. endl, noskipws, oct cout << x #include <iomanip> – the internal representation for the value of x is transformed to the corresponding text representation before printed • operator>> perform formatted input – parameterized manipulators, e.g. setw(10), setprecision(2) cin >> x #include <iosfwd> – leading whitespace is ignored (can be manipulated) – instead of <iostream> if only type definitions from <iostream> required – you can, e.g., declare function parameters (ostream&, istream&) but not use cin and cout – characters are read as long as they together can represent a value for x – reading stops if the next character is whitespace, end of stream, or cannot belong to a text representation for a value for x #include <fstream> – the read text is transformed to internal representation and stored in x – the stream classes ifstream, ofstream and fstream – if reading fail – the stream did not contain anything that could be interpreted as an x value – failbit is set – support for handling files as streams – if something disastrous occurred badbit is set – <fstream> include <iostream> #include <sstream> – the string stream classes istringstream, ostringstream and stringstream File: Basic-CPP-OH-en © 2015 Tommy Olsson, IDA, Linköpings universitet (2015-01-21) File: Basic-CPP-OH-en © 2015 Tommy Olsson, IDA, Linköpings universitet (2015-01-21) TDDD38 APiC++ Basic C++ 37 Reading and writing standard streams TDDD38 APiC++ Basic C++ 38 Member functions for handling stream state #include <iostream> using namespace std; A stream have three state bits (flags): int main() { int x; • badbit – indicates an irrecoverable error • failbit – indicates that an input operation failed to read expected characters, or an output operation failed to generate desired characters • eofbit – indicates that an input operation reached the end of an input sequence Member functions for handling state: while (cin >> x) { cout << x << ’\n’; } return 0; } The program can read input from a text file, and write output to a text file by redirection on the command line. a.out < input.txt // cin is redirected to input.txt a.out > output.txt // cout is redirected to output.txt cin.clear(); resets all state bits for cin – possible if failbit but not if badbit if (cin.good()) … returns true if none of the state bits are set for cin if (cin.fail() ) … returns true if failbit or badbit is set for cin if (cin.bad()) … returns true if badbit is set for cin if (cin.eof()) … returns true if eofbit is set for cin if (!cin) … returns fail(); operator! if (cin) … returns ! fail(); type converting member operator function, operator bool() Note: using eof() to construct input loops if often a bad choice. a.out < input.txt > output.txt File: Basic-CPP-OH-en TDDD38 APiC++ © 2015 Tommy Olsson, IDA, Linköpings universitet (2015-01-21) Basic C++ 39 Making stream state changes throw exception File: Basic-CPP-OH-en © 2015 Tommy Olsson, IDA, Linköpings universitet (2015-01-21) TDDD38 APiC++ Basic C++ 40 Stream manipulators for input An alternative to check state of a stream explicitly is to let stream operations throw exceptions. cin >> ws read whitespace until the next nonwhite character • member function exceptions() is used to specify for which cases exceptions shall be thrown cin >> skipws skip leading whitespace before reading a value (default) cin >> noskipws don’t skip leading whitespace cin >> dec integer input shall be interpreted as decimal numbers (digits are 0-9) cin >> oct integer input shall be interpreted as octal numbers (digits are 0-7) cin >> hex integer input shall be interpreted as hexadecimal numbers (digits are 0-9, A-F) cin >> boolalpha bool input shall be given as false or true cin >> noboolalpha bool input shall be given as 0 or 1 (default) cin >> setw(32) at most 32 character can be read into the destination (typically an array) input.exceptions(ios::failbit | ios::badbit); // throw if failbit or badbit is set try { while (input >> x) { cout << x << ’\n’; } } catch (const ios::failure& e) { if (input.bad()) { // irreparable... } else if (input.fail()) { input.clear(); ... } } File: Basic-CPP-OH-en // if read fails or stream turns bad here // we will be thrown to here char word[32]; cin >> setw(32) >> word; cin.width(32); // alternative, member function // reset state to “good” Note: Manipulators having parameters, as setw, require inclusion of <iomanip>. © 2015 Tommy Olsson, IDA, Linköpings universitet (2015-01-21) File: Basic-CPP-OH-en © 2015 Tommy Olsson, IDA, Linköpings universitet (2015-01-21) TDDD38 APiC++ Basic C++ 41 Member functions for unformatted input TDDD38 APiC++ Basic C++ 42 Formatted output flags c = cin.get() extract and return one character, converted to int, from cin left output is padded to the field width appending fill characters at the end while (cin.get(c)) … extract one character from cin, store in c; the return value is the stream right output is padded to the field width appending fill characters at the beginning cin.getline(s, 256) extract (maximum) 255 characters into character array s and append a ’\0’; extraction also stops if a ’\n’ or end-of-file is reached; if ’\n’ is found it is extracted and discarded internal output is padded to the field width by inserting fill characters at a specified internal point dec / oct / hex read/write integral values using decimal/octal/hexadecimal base format cin.getline(s, 256, ’;’) as above but with ’;’ instead of ’\n’ as delimiter character fixed write floating point values in fixed-point notation (x.d) cin.get(s, 256) as the corresponding getline above, but if ’\n’ is found it is not extracted scientific write floating-point values in scientific notation (x.dEn) cin.get(s, 256, ’;’) as the corresponding getline above, if ’;’ s found it is not extracted uppercase if (cin.peek() == ’\n’) read and return the next character without extracting it uppercase letters are used instead of lowercase for representations involving stream-generated letters, like some hexadecimal representations and numerical base prefixes cin.putback(c); c becomes the next character to extract boolalpha bool values are inserted/extracted as false and true instead of 0 and 1 cin.unget(); make the last character that was read available again as the next to read showbase cin.read(x, sizeof(int)); reads sizeof(int) characters into x (binary mode) numerical values are prefixed with their C++ base format prefix, i.e. 0x for hexadecimal values, 0 for octal values and no prefix for decimal values n = cin.readsome(s, 30) as read but stops if the buffer runs out of characters, eve in not end-of-file showpoint the decimal point is always written for floating point values, even for whole numbers extracts 100 character from the input sequence and discards them; the extraction ends when 100 characters have been extracted or when a ’;’ is found, which is also extracted showpos a plus sign (+) precedes every non-negative numerical value, including zeros unitbuf the buffer is flushed after each insertion operation n = cin.gcount() returns the number of characters extracted by the last unformatted input operation width getline(cin, s) as getline above but for std::string determines the minimum number of characters to be written in some output representations, padded with fill characters if required getline(cin, s, ’;’) as getline above but for std::string fill the character used to fill spaces when padding results to the field width precision for the default floating-point notation the precision specifies the maximum number of significant digits to display before and after the decimal point; in both the fixed and scientific notations, the precision specifies how many digits to display after the decimal point cin.ignore(100, ’;’) File: Basic-CPP-OH-en © 2015 Tommy Olsson, IDA, Linköpings universitet (2015-01-21) TDDD38 APiC++ Basic C++ 43 Manipulators for managing format flags File: Basic-CPP-OH-en © 2015 Tommy Olsson, IDA, Linköpings universitet (2015-01-21) TDDD38 APiC++ Basic C++ 44 Manipulators for formatted output cout << left sets left, unsets right and internal cout << setw(32) << word sets the number of characters to be used as field width for the next output operation to 32 cout << right sets right, unsets left and internal cout << setfill(’#’) sets the fill character to ’#’ cout << internal sets internal, unsets left and right cout << setprecision(3) cout << dec sets dec, unsets oct and hex cout << oct sets oct, unsets dec and hex sets the decimal precision to be used by output operations to 3; in fixed and scientific notations the precision specifies how many digits to display after the decimal point; in the default floating-point notation the precision specifies the maximum number of significant digits cout << hex sets hex, unsets dec and oct cout << setbase(8) sets the numerical radix to be used to 8; should be 8, 10, or 16 cout << fixed sets fixed, unsets scientific cout << flush unwritten characters in the buffer are written to output (“flushed”), as soon as possible cout << scientific sets scientific, unsets fixed cout << endl inserts a new-line character (’\n’); flush the buffer, if a buffered stream cout << uppercase sets uppercase ss << ends inserts a null character (’\0’) cout << nouppercase unsets uppercase cout << boolalpha sets boolalpha cout << noboolalpha unsets boolalpha cout << showbase sets showbase cout << noshowbase unsets showbase cout << showpoint sets showpoint cout << noshowpoint unsets showbase cout << showpos sets showpos cout << noshowpos unsets showbase File: Basic-CPP-OH-en Member functions are available for some of these: cout.setw(32); char old_fill{cout.fill(’#’)}; cout.precision(3); © 2015 Tommy Olsson, IDA, Linköpings universitet (2015-01-21) File: Basic-CPP-OH-en © 2015 Tommy Olsson, IDA, Linköpings universitet (2015-01-21) TDDD38 APiC++ Basic C++ 45 Member functions for unformatted output Basic C++ 46 File streams cout.put(c) writes the character c to the cout cout.write(s, n) writes the block of data pointed by s, with a size of n characters, to cout cout.flush() unwritten characters in the output buffer are written to cout as soon as possible int main(int argc, char* argv[]) { if (argc != 2) { cout << "Usage: " << argv[0] << ": file\n"; return 1; } vector<double> v; // Populate v with doubles // Save the doubles in v, on file in the internal binary representation ofstream output{ "result.bin", ios::binary }; for (auto i : v) { output.write(reinterpret_cast<const char*>(&i), sizeof(double)); } output.close(); // use an input file stream to read the file if (!input) { cout << "Could not open file: " << argv[1] << ’\n’; return 2; } // file opened successfully? // end of file should be reached if (!input.eof()) { cout << "Something when wrong...\n"; return 3; } ... © 2015 Tommy Olsson, IDA, Linköpings universitet (2015-01-21) Basic C++ ifstream input{ argv[1] }; while (input >> x) { cout << x << ’\n’; } while (input.read(reinterpret_cast<char*>(&x), sizeof(double))) { cout << x << ’\n’; } File: Basic-CPP-OH-en // command line: program name file name int x; ifstream input{ "result.bin", ios::binary }; double x; TDDD38 APiC++ TDDD38 APiC++ 47 File mode flags File: Basic-CPP-OH-en TDDD38 APiC++ © 2015 Tommy Olsson, IDA, Linköpings universitet (2015-01-21) Basic C++ 48 String streams (1) in the file shall be readable and exist A string is a sequence of characters – stream operations could be useful also to operate on strings. out the file shall be writeable; if it does not exist create a new file, otherwise it shall be overwritten • “serialization” – e.g. creating a text representation for a class object with data members of different types app the file must be writeable; if it does not exist, create a new file, otherwise append new data at the end trunc if the file exists, it shall be overwritten ate move to the end of the file after opening binary treat file as a binary file string serialize() { ostringstream os; os << ... << ... << ... ; return os.str(); } Combining file mode flags: • reading one of two types – e.g. read integers from a stream until “STOP” occurs in | out the file shall be both readable and writeable; it shall exist in | out | trunc the file shall be both readable and writeable; if it does not exist, it is created; if it does exist, it shall be overwritten in | out | app the file shall be both readable and writeable; if it does not exist, it is created; if it does exist, all updates shall occur at the end out | trunc the file shall be writeable; if it does not exist, it is created, if it does exist it shall be overwritten fstream f; f.open(name, ios::in | ios::out | ios::binary); vector<int> v; string next; int x; while (cin >> next) { if (next == "STOP") break; istringstream is{ next }; is >> x; v.push_back(x); } f.close(); File: Basic-CPP-OH-en © 2015 Tommy Olsson, IDA, Linköpings universitet (2015-01-21) File: Basic-CPP-OH-en © 2015 Tommy Olsson, IDA, Linköpings universitet (2015-01-21) TDDD38 APiC++ Basic C++ 49 String streams (2) • localizing errors in input – can be easier to read one line at a time into a variable and then process that line string line; int x, y; getline(cin, line); istringstream is{ line }; is >> x; if (is) { is >> y; if (is) cout << "x = " << x << ", y = " << y << endl; else cout << "Wrong input: " << is.str() << endl; } else { cout << "Wrong input: " << is.str() << endl; } File: Basic-CPP-OH-en © 2015 Tommy Olsson, IDA, Linköpings universitet (2015-01-21)