#include <iostream>
#include <fstream>
int i;
std::ifstream fin{"data.in"};
while (fin >> i) {
std::cout << i << "\n";
}
fin.close();
std::ofstream fout{"data.out"};
fout << i;
fout.close();
#include <iostream>
#include <fstream>
int main () {
// Below line only works C++17
if (auto in = std::ifstream{"data.in"}; in) { // attempts to open file, checks it was opened
for (auto i = 0; in >> i;) { // reads in
std::cout << i << '\n';
}
if (in.bad()) {
std::cerr << "unrecoverable error (e.g. disk disconnected?)\n";
} else if (not in.eof()) {
std::cerr << "bad input: didn't read an int\n";
}
} // closes file automatically <-- no need to close manually!
else {
std::cerr << "unable to read data.in\n";
}
}
#include <iostream>
#include <iomanip> // to use the setprecision manipulator
int main() {
std::cout << 1331 << std::endl; // 1331
std::cout << "In hex " << std::hex << 1331 << std::endl; // In hex 533
std::cout << 1331.123456 << std::endl; // 1331.12
std::cout.setf(std::ios::scientific, std::ios::floatfield);
std::cout << 1331.123456 << std::endl; // 1.331123e+03
std::cout << std::setprecision(3) << 1331.123456 << std::endl; // 1.331e+03
std::cout << std::dec << 1331 << std::endl; // 1331
std::cout.fill(’X’);
std::cout.width(8);
std::cout << 1331 << std::endl; // XXXX1331
std::cout.setf(std::ios::left, std::ios::adjustfield);
std::cout.width(8);
std::cout << 1331 << std::endl; // 1331XXXX
}
Be careful using these, these are not the best style
std::string name = "Obama";
int age = 17;
age = name; // error
// Implicit type conversion
#include <iostream>
int main() {
int age = 17;
double agePrecise = age;
std::cout << age;
}
double pi = 3.14;
int piInteger1 = pi; // What happens here?
int piInteger2 = (int)pi; // C-style
int piInteger3 = static_cast<int>(pi); // C++ style
int x = 5, y = 2;
// Note how the order of operations is not immediately obvious with C-style casts
double slope = (double)x / y; // C-style
double slope = static_cast<double>(x) / y; // C++ style
#include <array>
#include <iostream>
int main() {
// C-style. Don't do this
// int ages[3] = { 18, 19, 20 };
// for (int i = 0; i < 3; ++i) {
// std::cout << ages[i] << "\n";
// }
// C++ style. This can be used like any other C++ container.
// It has iterators, safe accesses, and it doesn't act like a pointer.
std::array<int, 3> ages{ 18, 19, 20 };
for (int i = 0; i < ages.size(); ++i) {
std::cout << ages[i] << "\n";
}
for (auto it = ages.begin(); it != ages.end(); ++it) {
std::cout << *it << "\n";
}
for (const auto& age : ages) {
std::cout << age << "\n";
}
}
template <typename T>
T Min(T a, T b) {
return a < b ? a : b;
}
int main() {
Min(1, 2); // uses int min(int, int);
Min(1.1, 2.2); // double min(double, double);
}
Container
Container
Algorithm
Container
Iterator
Iterator
#include <iostream>
#include <vector>
#include <string>
int main() {
std::vector<std::string> names;
for (auto iter = names.begin(); iter != names.end(); ++iter) {
std::cout << *iter << "\n";
}
for (std::vector<std::string>::iterator iter = names.begin(); iter != names.end(); ++iter) {
std::cout << *iter << "\n";
}
}
#include <iostream>
#include <vector>
int main() {
std::vector<int> ages;
ages.push_back(18);
ages.push_back(19);
ages.push_back(20);
// type of iter would be std::vector<int>::iterator
for (auto iter = ages.begin(); iter != ages.end(); ++iter) {
(*iter)++; // OK
}
// type of iter would be std::vector<int>::const_iterator
for (auto iter = ages.cbegin(); iter != ages.cend(); ++iter) {
//(*iter)++; // NOT OK
}
// type of iter would be std::vector<int>::reverse_iterator
for (auto iter = ages.rbegin(); iter != ages.rend(); ++iter) {
std::cout << *iter << "\n"; // prints 20, 19, 18
}
// Can also use crbegin and crend
}
Operation | Output | Input | Forward | Bidirectional | Random Access |
---|---|---|---|---|---|
Read | =*p | =*p | =*p | =*p | |
Access | -> | -> | -> | -> [] | |
Write | *p= | *p= | *p= | *p= | |
Iteration | ++ | ++ | ++ | ++ -- | ++ -- + - += -= |
Compare | == != | == != | == != | == != < > <= >= |
More powerful
Input
Output
Forward
Bidir.
Random
"->" no longer specified as of C++20
An algorithm requires certain kinds of iterators for their operations
A container's iterator falls into a certain category
stack, queue are container adapters, and do not have iterators
#include <fstream>
#include <iostream>
#include <iterator>
int main() {
std::ifstream in("data.in");
std::istream_iterator<int>begin(in);
std::istream_iterator<int> end;
std::cout << *begin++ << "\n"; // read the first int
++begin; // skip the 2nd int
std::cout << *begin++ << "\n"; // read the third int
while (begin != end) {
std::cout << *begin++ << "\n"; // read and print the rest
}
}
O(1)+ means amortised constant time
Sequential container | Description |
---|---|
std::vector | Dynamically sized array |
std::list | Doubly linked list |
std::forward_list | Singly linked list |
std::deque | <vector> with fast operations for element at beginning |
std::array | C-style array wrapper |
#include <iostream>
#include <vector>
// Begin with numbers 1, 2, 3 in the list already
int main() {
// In C++17 we can omit the int if the compiler can determine the type.
std::vector<int> numbers {1, 2, 3};
int input;
while (std::cin >> input) {
numbers.push_back(input);
}
std::cout << "1st element: " << numbers.at(0) << "\n"; // slower, safer
std::cout << "2nd element: " << numbers[1] << "\n"; // faster, less safe
std::cout << "Max size before realloc: " << numbers.capacity() << "\n";
for (int n : numbers) {
std::cout << n << "n"
}
}
#include <iostream>
#include <map>
#include <string>
int main() {
std::map<std::string, double> m;
// The insert function takes in a key-value pair.
std::pair<std::string, double> p1{"bat", 14.75};
m.insert(p1);
// The compiler will automatically construct values as
// required when it knows the required type.
m.insert({"cat", 10.157});
// This is the preferred way of using a map
m.emplace("cat", 10.157);
// This is very dangerous, and one of the most common causes of mistakes in C++.
std::cout << m["bat"] << '\n';
auto it = m.find("bat"); // Iterator to bat if present, otherwise m.end()
// This is a great example of when to use auto, but we want to show you what type it is.
for (const std::pair<const std::string, double>& kv : m) {
std::cout << kv.first << ' ' << kv.second << '\n';
}
}