Accelerated C++ Chapter 10
どもです。
腰の具合が思ったよりも悪く,歩くと結構痛いですが,そこは
断固桜木で,いろいろと用事を済ませてきましたよっと。
メモ
- 関数へのポインタ
void f(void); // ... void (*p_f)(void); p_f = f; // これと, p_f = &f; // これは同じこと。 // 呼び出し p_f(); // これと (*p_f)(); // これは同じ事。 // でも,ポインタであることをわかりやすくするために, // (*p_f)() の方がいいかも。と,CUnit のソースを眺めていて思いました。
-
- 関数へのポインタの定義は大変
- typedef を使おう。
- 関数へのポインタの定義は大変
typedef void (*fp)(void); fp func_ptr; // func_ptr は,シグニチャとして,void fp(void) をもつ関数へのポインタ。
-
-
- 読み方は,K&R に詳しい。かった記憶がある。
-
void (*fp)(void) の場合は,fp is a pointer to a function, expecting void, returning void.
だったはず。
- ファイルの扱い
- 読み込み
- ifstream
- ifstream("file.txt");
- スコープ抜けたら自動でファイルが閉じられる。
- ifstream
- 書込み
- ofstream
- 読み書き
- fstream
- ポインタの扱い
- ある関数の中で,ローカル変数のへのポインタを返すとか危険よ。参照もだけど。
- static, dynamic allocation
- ある関数の中で,ローカル変数のへのポインタを返すとか危険よ。参照もだけど。
- 動的メモリ割り当て
- new, delete, delete[]
T *p = new T(); p = new T; // デフォルト初期化 delete p; // 配列 p = new T[n]; delete[] p;
-
- 要するに,new なら delete, new ならdelete。
↑は,「要するに,new なら delete, new[] なら delete[]。」と書いてます。 はい来ました。[] 単体なら消えないが,new[] と書くと,[] が消える。 はてなの仕様?
-
- 自分で管理するのは大変。必ずどこかに抜けが生じる。オレだけか?
- Input / Output
- cin
- stdin
- cout
- stdout
- cerr
- stderr
- clog
- ログ用。バッファリングされる。
- cin
Exercises
なげーどー。
Exercise 10-2
median.hh
#ifndef GUARD_MEDIAN_H #define GUARD_MEDIAN_H #include <vector> #include <stdexcept> #include <algorithm> #include <iostream> template<class Iter> typename std::iterator_traits<Iter>::value_type median(Iter beg, Iter end) { typename std::iterator_traits<Iter>::difference_type size = std::distance(beg, end); if (beg == end) { throw std::domain_error("median on the empty container"); } else if (size == 1) { return *beg; } typedef typename std::iterator_traits<Iter>::value_type ValType; std::vector<ValType> vec(beg, end); std::sort(vec.begin(), vec.end()); size_t mid = size / 2; if (size % 2 == 0) { return (*(vec.begin() + mid - 1) + *(vec.begin() + mid)) / 2; } else { return *(vec.begin() + mid); } } #endif // GUARD_MEDIAN_H
Exercise 10-4, 10-5
- String_list.hh
#ifndef GUARD_STRING_LIST_H #define GUARD_STRING_LIST_H #include <string> #include <cstddef> #include <memory> //////////////////////////////////////////////////////////////////////////////// class String_list_node { friend class String_list; friend class String_list_iterator; private: String_list_node(const std::string& s) : str_(s), next_(0), prev_(0) {} std::string str_; String_list_node *next_, *prev_; }; //////////////////////////////////////////////////////////////////////////////// class String_list_iterator { public: String_list_iterator(String_list_node *node) : node_(node) {} std::string* operator->() { return &(node_->str_); } std::string& operator*() { return node_->str_; } String_list_iterator& operator++() { node_ = node_->next_; return *this; } String_list_iterator& operator--() { node_ = node_->prev_; return *this; } bool operator==(const String_list_iterator arg) { return node_ == arg.node_; } bool operator!=(const String_list_iterator arg) { return node_ != arg.node_; } private: String_list_node *node_; }; //////////////////////////////////////////////////////////////////////////////// class String_list { public: typedef size_t size_type; typedef std::string value_type; typedef String_list_iterator iterator; String_list() : head_(0), tail_(0), size_(0) {} String_list(const String_list& arg); String_list(size_t n, const std::string& s); ~String_list(); String_list& operator=(const String_list& arg); void push_back(const std::string& s); size_type size() const { return size_; } bool empty() const { return size_ == 0; } iterator begin() { return String_list_iterator(head_); } iterator end() { return String_list_iterator(tail_); } private: String_list_node *head_, *tail_; // tail_ is a sentinel. size_type size_; }; #endif // GUARD_STRING_LIST_H
- String_list.cc
#include <string> #include <iostream> #include <cassert> #include <cstddef> #include "String_list.hh" using namespace std; String_list::String_list(size_t n, const std::string& s) : head_(0), tail_(0), size_(0) { head_ = new String_list_node(s); tail_ = head_; String_list_node *prev = head_, *tmp; --n; for (size_t i = 0; i < n; ++i) { tmp = new String_list_node(s); prev->next_ = tmp; tmp->prev_ = prev; prev = tmp; tail_ = tmp; } tmp = new String_list_node(string("dummy")); tmp->prev_ = tail_; tail_->next_ = tmp; tail_ = tmp; size_ = n + 1; } String_list::String_list(const String_list& arg) { size_ = arg.size_; if (size_ == 0) { head_ = tail_ = 0; return; } // Copy each node const String_list_node *from = arg.head_; head_ = new String_list_node(from->str_); size_t n = size_ - 1; String_list_node *p = 0, *pp = head_; from = from->next_; for (size_t i = 0; i < n; ++i) { p = new String_list_node(from->str_); pp->next_ = p; p->prev_ = pp; pp = p; } } String_list::~String_list() { if (head_ == 0) { return; } String_list_node *p = head_, *pp = 0; //int i = 0; while (p != 0) { pp = p; p = p->next_; // // DEBUG // cout << "(" << i++ << ") Deleting..." << endl; delete pp; } } void String_list::push_back(const string& s) { if (head_ == 0) { assert(tail_ == 0); head_ = new String_list_node(s); tail_ = new String_list_node(string("dummy")); head_->next_ = tail_; tail_->prev_ = head_; ++size_; return; } assert(tail_ != 0); String_list_node *new_node = new String_list_node(s); String_list_node *p = tail_->prev_; p->next_ = new_node; new_node->prev_ = p; new_node->next_ = tail_; tail_->prev_ = new_node; ++size_; }
Exercise 10-6
#include <iostream> #include <string> #include <gtest/gtest.h> #include "String_list.hh" using namespace std; static String_list split(const string& s) { String_list ret; string::const_iterator iter = s.begin(); while (iter != s.end()) { while (iter != s.end() && isspace(*iter)) { ++iter; } if (iter == s.end()) { break; } string::const_iterator beg = iter; while (iter != s.end() && !isspace(*iter)) { ++iter; } ret.push_back(string(beg, iter)); } return ret; } TEST(String_list, split) { String_list sl = split(string("a b c d e f")); EXPECT_EQ(6, sl.size()); String_list::iterator iter = sl.begin(); EXPECT_STREQ("a", iter->c_str()); EXPECT_STREQ("b", (++iter)->c_str()); EXPECT_STREQ("c", (++iter)->c_str()); EXPECT_STREQ("d", (++iter)->c_str()); EXPECT_STREQ("e", (++iter)->c_str()); EXPECT_STREQ("f", (++iter)->c_str()); } int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); }