16 Utilities
16 Utilities
Programming
16. Utilities
Federico Busato
2023-11-14
Table of Context
1 I/O Stream
Manipulator
ofstream/ifstream
2 Math Libraries
3 Strings and std::print
std::string
Conversion from/to Numeric Values
std::string view
std::format
std::print
1/77
Table of Context
4 Random Number
Basic Concepts
C++ <random>
Seed
PRNG Period and Quality
Distribution
Quasi-random
5 Time Measuring
Wall-Clock Time
User Time
2/77
System Time
Table of Context
6 Std Classes
std::byte
std::pair
std::tuple
std::variant
std::optional
std::any
7 Filesystem Library
Query Methods
Modify Methods
3/77
I/O Stream
I/O Stream
buffered: the content of the buffer is not write to disk until some events occur
4/77
I/O Stream (manipulator) 1/3
• flush and endl force the program to synchronize with the terminal → very
slow operation!
5/77
I/O Stream (manipulator) 2/3
6/77
I/O Stream (manipulator) 3/3
<iomanip>
7/77
I/O Stream - std::cin
std::cin is an example of input stream. Data coming from a source is read by the program.
In this example cin is the standard input
#include <iostream>
int main() {
int a;
std::cout << "Please enter an integer value:" << endl;
std::cin >> a;
int b;
float c;
std::cout << "Please enter an integer value "
<< "followed by a float value:" << endl;
std::cin >> b >> c; // read an integer and store into "b",
} // then read a float value, and store
8/77
// into "c"
I/O Stream - ofstream/ifstream 1/3
• Get a pointer to the stream buffer object currently associated with the stream
my file.rdbuf()
can be used to redirect file stream
11/77
I/O Stream - Example 1
Open a file and print line by line: An alternative version with redirection:
12/77
I/O Stream - Example 2
Another example:
#include <iostream>
#include <fstream>
example.txt:
int main() {
23 70 44\n std::ifstream fin("example.txt");
char c = fin.peek(); // c = '2'
\t57\t89
while (fin.good()) {
int var;
The input stream is independent from the fin >> var;
std::cout << var;
type of space (multiple space, tab, new-
} // print 2370445789
line \n, \r\n, etc.) fin.seekg(4);
c = fin.peek(); // c = '0'
fin.close();
} 13/77
I/O Stream -Check the End of a File
16/77
Math Libraries
<cmath> Math Library 1/2
<cmath>
• fabs(x) computes absolute value, |x |, C++11
• exp(x) returns e raised to the given power, e x
Math functions in C++11 can be applied directly to integral types without implicit/explicit
casting (return type: floating point).
en.cppreference.com/w/cpp/numeric/math
18/77
<limits> Numerical Limits
<limits> C++11
19/77
<numeric> Mathematical Constants
<numeric> C++20
The header provides numeric constants
• e Euler number e
• pi π
√
• phi Golden ratio 1+ 5
2
√
• sqrt2 2
20/77
Integer Division
value 1
• Rounded Division: +
div 2
unsigned round_div(unsigned value, unsigned div) {
return (value + div / 2) / div;
} // note: may overflow
More flexible and safer than raw char array but can be slower
#include <string>
int main() {
std::string a; // empty string
std::string b("first");
22/77
std::string - Capacity and Search 2/4
• find(string) returns the position of the first substring equal to the given character
sequence or npos if no substring is found
• rfind(string) returns the position of the last substring equal to the given character
sequence or npos if no substring is found
• find first of(char seq) returns the position of the first character equal to one of the
characters in the given character sequence or npos if no characters is found
• find last of(char seq) returns the position of the last character equal to one of the
characters in the given character sequence or npos if no characters is found
npos special value returned by string methods
23/77
std::string - Operations 3/4
• c str()
returns a pointer to the raw char sequence 24/77
std::string - Overloaded Operators 4/4
25/77
Conversion from/to Numeric Values
28/77
std::string view 1/3
#include <string>
#include <string_view>
29/77
std::string view 2/3
31/77
std::format 1/2
• Type-safe
• Support positional arguments
• Extensible (support user-defined types)
• Return a std::string
32/77
std::format - Example 2/2
Integer formatting
std::format("{}", 3); // "3"
std::format("{:b}", 3); // "101"
Alignment
std::format("{:>6}", 3.27); // " 3.27"
std::format("{:<6}", 3.27); // "3.27 "
Argument reordering
std::format("{1} - {0}", 1, 3); // "3 - 1"
33/77
std::print
34/77
Random Number
Random Number
36/77
see Lavarand
Basic Concepts
• The state of a PRNG describes the status of the generator (the values of its variables),
namely where the system is after a certain amount of transitions
• The seed is a value that initializes the starting state of a PRNG. The same seed always
produces the same sequence of results
• PRNGs produce uniformly distributed values. PRNGs can also generate values according
to a probability function (binomial, normal, etc.) 37/77
C++ <random> 1/2
The problem:
C rand() function produces poor quality random numbers
• C++14 discourage the use of rand() and srand()
Simplest example:
#include <iostream>
#include <random>
int main() {
unsigned seed = ...;
std::default_random_engine generator(seed);
std::uniform_int_distribution<int> distribution(0, 9);
It generates two random integer numbers in the range [0, 9] by using the default
random engine
39/77
Seed 1/3
std::random_device rnd_device;
std::default_random_engine generator(rnd_device());
41/77
Seed 3/3
#include <random>
#include <chrono>
std::random_device rnd;
std::default_random_engine generator1(rnd());
42/77
PRNG Period and Quality
PRNG Period
The period (or cycle length) of a PRNG is the length of the sequence of numbers that the
PRNG generates before repeating
PRNG Quality
(informal) If it is hard to distinguish a generator output from truly random sequences, we call it
a high quality generator. Otherwise, we call it low quality generator
43/77
Random Engines
The table shows after how many iterations the generator fails the statistical tests
45/77
Space and Performance
46/77
Distribution
47/77
Examples
48/77
References
PRNG Quality:
Recent algorithms:
49/77
Performance Comparison
50/77
Random number generators for C++ performance tested
Quasi-random 1/2
• The concept of low-discrepancy is associated with the property that the successive
numbers are added in a position as away as possible from the other numbers that
is, avoiding clustering (grouping of numbers close to each other)
51/77
Quasi-random 2/2
52/77
Time Measuring
Time Measuring 1/5
Wall-Clock/Real time
It is the human perception of the passage of time from the start to the completion of
a task
User/CPU time
The amount of time spent by the CPU to compute in user code
System time
The amount of time spent by the CPU to compute system calls (including I/O calls)
executed into kernel code
Note: if the system workload (except the current program) is very low and the
program uses only one thread then
Wall-clock time = User time + System time 53/77
Time Measuring - Wall-Clock Time 1 2/5
54/77
Time Measuring - Wall-Clock Time 2 3/5
std::chrono C++11
# include <chrono>
55/77
Time Measuring - User Time 4/5
std::clock
# include <chrono>
56/77
Time Measuring - User/System Time 5/5
# include <sys/times.h>
57/77
Std Classes
std::byte
58/77
std::pair 1/2
<utility>
std::pair class couples together a pair of values, which may be of different types
Construct a std::pair
• std::pair<T1, T2> pair(value1, value2)
• std::pair<T1, T2> pair = {value1, value2}
• auto pair = std::make pair(value1, value2)
Data members:
• first access first field
• second access second field
Methods:
• comparison ==, <, >, ≥, ≤
• swap std::swap 59/77
std::pair 2/2
# include <utility>
swap(pair1, pair2);
cout << pair2.first; // print "zzz"
cout << pair2.second; // print 4
60/77
std::tuple 1/3
<tuple>
std::tuple is a fixed-size collection of heterogeneous values. It is a generalization of
std::pair . It allows any number of values
Construct a std::tuple (of size 3)
• std::tuple<T1, T2, T3> tuple(value1, value2, value3)
• std::tuple<T1, T2, T3> tuple = {value1, value2, value3}
• auto tuple = std::make tuple(value1, value2, value3)
Data members:
std:get<I>(tuple) returns the i-th value of the tuple
Methods:
• comparison ==, <, >, ≥, ≤
• swap std::swap 61/77
std::tuple 2/3
• std::ignore
an object of unspecified type such that any value can be assigned to it with no
effect 62/77
std::tuple 3/3
# include <tuple>
std::tuple<int, float, char> f() { return {7, 0.1f, 'a'}; }
<variant> C++17
std::variant represents a type-safe union as the corresponding objects know
which type is currently being held
# include <variant>
Another useful method is index() which returns the position of the type currently
held by the variant
# include <variant>
std::get<bool>(v) = true
cout << v.index(); // return 2
65/77
std::variant + Visitor 3/3
It is also possible to query the index at run-time depending on the type currently being
held by providing a visitor
# include <variant>
struct Visitor {
void operator()(int& value) { value *= 2; }
std::visit(v, Visitor{});
<optional> C++17
std::optional provides facilities to represent potential “no value” states
As an example, it can be used for representing the state when an element is not found
in a set
# include <optional>
67/77
std::optional 2/2
# include <optional>
68/77
std::any
<any> C++17
std::any holds arbitrary values and provides type-safety
# include <any>
var.reset();
cout << var.has_value(); // print 'false'
69/77
Filesystem Library
Filesystem Library
C++17 introduces abstractions and facilities for performing operations on file systems
and their components, such as paths, files, and directories
70/77
Basic concepts
• file name: a string of characters that names a file. Names . (dot) and ..
(dot-dot) have special meaning at library level
72/77
path Methods
namespace fs = std::filesystem;
75/77
Filesystem Methods - Modify
• Copy files
copy file(src path, src path, [fs::copy options::recursive])
namespace fs = std::filesystem;
fs::path p1 = "/usr/tmp/my_file.txt";
fs::create_directory("/my_dir/");
fs::copy(p1.parent_path(), "/my_dir/", fs::copy_options::recursive);
fs::copy_file(p1, "/my_dir/my_file2.txt");
fs::remove(p1);
77/77
fs::remove_all(p1.parent_path());