Basic C++ The classic first C++ program

advertisement
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)
Download