Parent directory
entries-malformed.txt
entries.txt
io1.cpp
io2.cpp
io3.cpp
template4.cpp
to.cpp
{ "Barack Obama" , 44 }
{"Donald Duck",, 45}
{ "Joe Biden",46 }
{ "Barack Obama" , 44 }
{"Donald Duck", 45}
{ "Joe Biden",46 }
#include <iostream>
#include <iomanip>
using namespace std;
void print_io_states(ios& io)
{
cout << " fail()==" << io.fail();
cout << " bad()==" << io.bad();
cout << " eof()==" << io.eof();
}
int sum_ints(istream& is)
{
int i, sum = 0;
while (is >> i) {
sum += i;
cout << "current sum: " << setw(4) << sum;
cout << '\t';
print_io_states(is);
cout << '\n';
}
return sum;
}
int main()
{
int sum = sum_ints(cin);
cout << " final sum: " << setw(4) << sum;
cout << '\t';
print_io_states(cin);
cout << '\n';
}
#include <iostream>
#include <iomanip>
/*
* You can detach C++ I/O streams from C standard I/O by doing this:
*
* std::ios_base::sync_with_stdio(false);
*
* When sync_with_stdio is set to true (default mode), C++ streams are
* unbuffered, and each I/O operation on a C++ stream is immediately
* applied to the corresponding C stream's buffer. When it is set to
* false, the C++ streams are allowed to buffer their I/O independently,
* which may be considerably faster in some cases.
*
* But note the following when it is set to false:
*
* - you can no longer mix C & C++ I/O
* - C++ streams will no longer be thread-safe
* - '\n' may not flush standard output connected to terminal
*/
using namespace std;
void print_io_states(ios& io)
{
cout << " fail()==" << io.fail();
cout << " bad()==" << io.bad();
cout << " eof()==" << io.eof();
}
int sum_ints(istream& is)
{
int i, sum = 0;
while (!is.eof()) {
is >> i;
if (is.bad()) {
throw runtime_error{"bad istream"};
} else if (is.fail()) {
// fail(), but not bad()
if (is.eof()) {
// failbit && eofbit: this is normal (trailing whitespace)
break;
}
// failbit && !eofbit: probably non-digit; just skip it
is.clear();
char c;
is.get(c);
cout << " skipped: " << c << '\n';
} else {
// read i successfully;
// we could have hit eof or not (depends on trailing whitespace)
sum += i;
cout << "current sum: " << setw(4) << sum;
cout << '\t';
print_io_states(is);
cout << '\n';
}
}
return sum;
}
int main()
{
int sum = sum_ints(cin);
cout << " final sum: " << setw(4) << sum;
cout << '\t';
print_io_states(cin);
cout << '\n';
}
#include <iostream>
#include <iomanip>
#include <fstream>
using namespace std;
struct Entry {
string name;
int number;
};
ostream& operator<<(ostream& os, const Entry& e)
{
return os << "{\"" << e.name << "\", " << e.number << "}";
}
/*
* Read { "name" , number } pair from an istream.
*
* - code from "A Tour of C++", Sec 11.5 (3rd ed.) / Sec 10.5 (2nd ed.)
*/
istream& operator>>(istream& is, Entry& e)
{
char c, c2;
if (is>>c && c=='{' && is>>c2 && c2=='"') { // start with a { "
string name;
while (is.get(c) && c!='"') // anything before " is part of name
name+=c;
if (is>>c && c==',') {
int number = 0;
if (is>>number>>c && c=='}') { // read the number and a }
e = {name,number}; // assign to the entry
return is;
}
}
}
is.setstate(ios_base::failbit); // register the failure in the stream
return is;
}
int f1(istream& is);
int f2(istream& is);
int f3(const char *filename);
int main(int argc, char **argv)
{
try {
return f1(cin);
//return f2(cin);
//return f3(argv[1]);
} catch (const exception& x) {
cerr << x.what() << '\n';
}
}
int f1(istream& is)
{
Entry e;
while (is >> e) {
cout << e << '\n';
}
// istream::operator bool() returns false if fail(),
// which means failbit==1 or badbit==1
if (is.bad()) {
throw runtime_error{"bad istream"};
} else if (!is.eof()) {
throw invalid_argument{"bad entry format"};
} else {
return 0;
}
}
int f2(istream& is)
{
int r;
string str;
while (getline(is, str)) {
istringstream iss(str);
try {
r = f1(iss);
} catch (const invalid_argument& x) {
cerr << x.what() << ": " << str << '\n';
}
}
return r;
}
int f3(const char *filename)
{
ifstream ifs { filename };
if (!ifs) {
if (filename)
throw runtime_error{"can't open file: "s + filename};
else
throw runtime_error{"no file name"};
}
return f2(ifs);
}
#include <string>
#include <vector>
#include <iostream>
template <typename T>
class Vec {
public:
Vec() : sz{0}, cap{1}, a{new T[cap]} {}
~Vec() {
delete[] a;
}
Vec(const Vec&) = delete;
Vec& operator=(const Vec&) = delete;
// Vec(const Vec&) = default;
// Vec& operator=(const Vec&) = default;
Vec(Vec&& ia) : sz{ia.sz}, cap{ia.cap}, a{ia.a} {
ia.sz = ia.cap = 0;
ia.a = nullptr;
std::cout << "move ctor" << std::endl;
}
Vec& operator=(Vec&& ia) {
if (this != &ia) {
delete[] a;
sz = ia.sz;
cap = ia.cap;
a = ia.a;
ia.sz = ia.cap = 0;
ia.a = nullptr;
}
std::cout << "move assignment" << std::endl;
return *this;
}
T& operator[](int i) { return a[i]; }
const T& operator[](int i) const { return a[i]; }
int size() const { return sz; }
int capacity() const { return cap; }
void push_back(T x) {
if (sz == cap) {
// Separate cap*=2 to preserve invariant on exception
// T *a2 = new T[cap *= 2];
T *a2 = new T[cap * 2];
cap *= 2;
std::copy(a, a+sz, a2);
delete[] a;
a = a2;
}
a[sz++] = x;
}
private:
size_t sz;
size_t cap;
T *a;
};
template <typename T>
std::ostream& operator<<(std::ostream& os, const Vec<T>& ia)
{
for (int i = 0; i < ia.size(); i++) {
os << ia[i] << " ";
}
std::cout << "(cap=" << ia.capacity() << ")" << std::flush;
return os;
}
using namespace std;
Vec<int> createVecInt()
{
Vec<int> ia;
for (int i = 0; i < 20; i++) {
ia.push_back(i);
cout << ia << endl;
}
return ia;
}
Vec<string> createVecStr()
{
Vec<string> ia;
for (char c = 'A'; c <= 'Z'; c++) {
string s;
s += c;
ia.push_back(s);
cout << ia << endl;
}
return ia;
}
int main()
{
// Vec<int> ia { createVecInt() };
// Vec<string> ia2 { createVecStr() };
vector<string> v;
for (char c = 'A'; c <= 'Z'; c++) {
string s;
s += c;
v.push_back(s);
for (const auto& e : v) {
cout << e << " ";
}
cout << '\n';
}
// Lecture plan:
//
// 1. IntArray code walk-through
//
// - ctor initializer syntax
// - =delete & =default
// - invariants
//
// 2. move ctor
//
// - rvalue reference
// - -fno-elide-constructors
//
// 3. move assignment
//
// - casting to rvalue reference
//
// 4. IntArray to Vec<T>
//
// - Vec<int>
// - Vec<string>
//
// 5. vector<string>
//
// - range for loop
}
#include <iostream>
#include <iomanip>
#include <sstream>
using namespace std;
/*
* Type-covert Source to Target
*
* - code from "A Tour of C++", Sec 11.7.3 (3rd ed.) / Sec 10.8 (2nd ed.)
*/
template <typename Target = string, typename Source = string>
Target to(Source arg)
{
stringstream interpreter;
Target result;
if (!(interpreter << arg) || // write arg into stream
!(interpreter >> result) || // read result from stream
!(interpreter >> std::ws).eof()) // stuff left in stream?
{
throw runtime_error{"to<>() failed"};
}
return result;
}
int main()
{
cout << to(40'000) << '\n';
cout << to<string,unsigned short>(80'000) << '\n';
}