Skip to content

Commit

Permalink
Merge pull request EzoeRyou#115 from asciidwango/master
Browse files Browse the repository at this point in the history
見落としの修正など。
  • Loading branch information
EzoeRyou authored Aug 23, 2019
2 parents 24bf001 + 38441d8 commit c90f238
Show file tree
Hide file tree
Showing 23 changed files with 123 additions and 116 deletions.
4 changes: 4 additions & 0 deletions 000-preface.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,7 @@ C++知識のブートストラップを意識した入門書の執筆はなか
本書の著者近影の撮影は、著者の古くからの友人でありプロのカメラマンである三浦大に撮影してもらった。

三浦大のWebサイト: <http://www.masarumiura.jp/>

<div style="text-align: right;">
江添亮
</div>
6 changes: 3 additions & 3 deletions 002-build.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ GCCのコンパイラーオプションをいくつか学んでいこう。
g++ -std=c++17 -Wall --pedantic-errors -o 出力ファイル名 入力ファイル名
~~~

ところで、GCCのオプションはとても多い。すべてを知りたい読者は、以下のようにしてgccのマニュアルを読むとよい
ところで、GCCのオプションはとても多い。すべてを知りたい読者は、以下のようにしてGCCのマニュアルを読むとよい

~~~
$ man gcc
Expand Down Expand Up @@ -383,15 +383,15 @@ $ make run
$ make clean
~~~

これで生成されたファイルをすべて削除できる
これで生成されたファイルをすべて削除できる

テキストエディターにはVimを使っているがわざわざVimからターミナルに戻るのが面倒だ。

~~~
:make
~~~

VimはノーマルモードからMakeを呼び出すことができる。もちろん、`:make run``:make clean`もできる
VimはノーマルモードからMakeを呼び出すことができる。もちろん、`:make run``:make clean`もできる

### 依存関係を記述するルール

Expand Down
8 changes: 4 additions & 4 deletions 004-debug-compile-error.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

+ コンパイルエラーは普通
+ コンパイルエラーが出たらありがとう
+ コンパイルエラーがでたら大喜び
+ コンパイルエラーが出たら大喜び

熟練のプログラマーは自分の書いたコードがコンパイルエラーを出さずに一発でコンパイルが通った場合、逆に不安になるくらいだ。

Expand Down Expand Up @@ -270,15 +270,15 @@ int main()
~~~c++
int main()
{
// 引数を3つとって足して返す関数
// 引数を3つ取って足して返す関数
auto f = [](auto a, auto b, auto c)
{ return a + b + c ; } ;

std::cout << f(1+(2*3),4-5,6/(7-8))) ;
}
~~~

GCCによるコンパイルエラーメッセージだけ抜粋すると以下のとおり
GCCによるコンパイルエラーメッセージだけ抜粋すると以下のとおり

~~~
main.cpp: In function ‘int main()’:
Expand All @@ -301,7 +301,7 @@ main.cpp:7:40: error: expected ‘;’ before ‘)’ token

抜粋されたソースコードに示された問題の箇所、つまり7行目40列目にあるトークンは`')'`だ。この前に`';'`が必要とはどういうことだろう。

問題を探るため、7行目のトークンを詳しく分解してみよう。以下は7行目と同じソースコードだが、トークンをわかりやすく分解してある
問題を探るため、7行目のトークンを詳しく分解してみよう。以下は7行目と同じソースコードだが、トークンをわかりやすく分解してある

~~~
std::cout << // 標準出力
Expand Down
4 changes: 2 additions & 2 deletions 005-the-restaurant-at-the-end-of-the-branch.md
Original file line number Diff line number Diff line change
Expand Up @@ -834,7 +834,7 @@ true

`bool`型の値と演算はこれで全部だ。値は`true`/`false`の2つのみ。演算は`==`, `!=`, `!``&&``||`の5つだけだ。

読者の中には納得のいかないものもいるだろう。ちょっと待ってもらいたい。`bool`の大小比較できないのだろうか。`bool`の四則演算はできないのか。`"if(123)"`などと書けてしまうのはなんなのか
読者の中には納得のいかないものもいるだろう。ちょっと待ってもらいたい。`bool`の大小比較できないのだろうか。`bool`の四則演算はできないのか。`"if(123)"`などと書けてしまうのは何なのか

好奇心旺盛な読者は本書の解説を待たずしてすでに自分でいろいろとコードを書いて試してしまっていることだろう。

Expand All @@ -850,7 +850,7 @@ int main()
}
~~~

このコードを実行すると、出力は`"false"`だ。`"true \< false"`の結果が`"false"`だということは、`true``false`より大きいということになる
このコードを実行すると、出力は`"false"`だ。`"true \< false"`の結果が`"false"`だということは、`true``false`より大きいということになる

四則演算はどうか?

Expand Down
16 changes: 8 additions & 8 deletions 008-loop.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ skip :

`2`を出力すべき文の実行が飛ばされていることがわかる。

これだけみると`"if (false)"`と同じように見えるが、`goto文`はソースコードの上に飛ぶこともできるのだ。
これだけだと`"if (false)"`と同じように見えるが、`goto文`はソースコードの上に飛ぶこともできるのだ。

~~~cpp
void hello()
Expand Down Expand Up @@ -739,11 +739,11 @@ int main()
}
~~~

このコードでは、"`(x=1)`"と"`1`"が等しいか"`==`"どうかを判断している。"`(x=1)`"という式は変数`x``1`を代入する式だ。`代入式`の値は、代入された変数の値になる。この場合変数`x`の値だ。変数`x`には`1`が代入されているので、その値は1、つまり"`(x=1) == 1`"は"`1 == 1`"と書くのと同じ意味になる。この結果は`true`だ。
このコードでは、"`(x=1)`"と"`1`"が等しい"`==`"かどうかを判断している。"`(x=1)`"という式は変数`x``1`を代入する式だ。`代入式`の値は、代入された変数の値になる。この場合変数`x`の値だ。変数`x`には`1`が代入されているので、その値は1、つまり"`(x=1) == 1`"は"`1 == 1`"と書くのと同じ意味になる。この結果は`true`だ。

さて、このことを踏まえて、"`( x = input() ) != 0`"を考えてみよう。

"`( x = input() )`"は変数`x`に関数`input`を呼び出した結果を代入している。関数`input`はユーザーから入力を得て、その入力をそのまま返す。つまり変数`x`にはユーザーの入力した値が代入される。その結果が`0`と等しくないか"`!=`"どうかを判断している。つまり、ユーザーが`0`を入力した場合は`false`、非ゼロを入力した場合は`true`となる。
"`( x = input() )`"は変数`x`に関数`input`を呼び出した結果を代入している。関数`input`はユーザーから入力を得て、その入力をそのまま返す。つまり変数`x`にはユーザーの入力した値が代入される。その結果が`0`と等しくない"`!=`"かどうかを判断している。つまり、ユーザーが`0`を入力した場合は`false`、非ゼロを入力した場合は`true`となる。

`while(条件)``条件``true`となる場合に繰り返し実行をする。結果として、ユーザーが`0`を入力するまで繰り返し実行をするコードになる。

Expand Down Expand Up @@ -783,7 +783,7 @@ int main()
`goto文`でインデックスループを書くときに学んだように、

1. `n < 0`ならば関数を終了
2. 変数iを作り値を0にする
2. 変数`i`を作り値を0にする
3. `i != n`ならば繰り返し実行
4. 出力
5. `++i`
Expand All @@ -801,7 +801,7 @@ void hello_n( int n )
// 2. 変数iを作り値を0にする
int i = 0 ;

//3. i != nならば繰り返し実行
// 3. i != nならば繰り返し実行
while( i != n )
{ // 4. 出力
std::cout << "hello\n"s ;
Expand Down Expand Up @@ -896,7 +896,7 @@ int main()
9*1 9*2 9*3 9*4 9*5 9*6 9*7 9*8 9*9
~~~

これをみると`"a*b"`のうちの`a``1`から`9`までインクリメントし、それに対して`b``1`から`9`までインクリメントさせればよい。つまり、9回のインデックスループの中で9回のインデックスループを実行することになる。ループの中のループだ。
これを見ると`"a*b"`のうちの`a``1`から`9`までインクリメントし、それに対して`b``1`から`9`までインクリメントさせればよい。つまり、9回のインデックスループの中で9回のインデックスループを実行することになる。ループの中のループだ。

~~~c++
while ( 条件 )
Expand Down Expand Up @@ -1403,7 +1403,7 @@ void f( int x ) { g( x+1 ) ; }
int main() { f( 0 ) ; }
~~~
これをみると、関数`main`は関数`f`に引数`0`を渡し、関数`f`は関数`g`に引数`1`を渡している。これをもっと再帰的に考えよう。
これを見ると、関数`main`は関数`f`に引数`0`を渡し、関数`f`は関数`g`に引数`1`を渡している。これをもっと再帰的に考えよう。
~~~cpp
void until_ten( int x )
Expand Down Expand Up @@ -1555,7 +1555,7 @@ int convert( int n )
~~~cpp
// OK
solve(10111101) ;
// ありえない
// あり得ない
solve(2) ;
~~~
Expand Down
6 changes: 3 additions & 3 deletions 009-vector.md
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@ min = 4
`vector`の変数を`v`、要素数を`size`とする。変数`min`には現在わかっている中で最も小さい要素へのインデックスが代入される。
1. 変数`min`に0を代入する
1. 変数`min`に0を代入する
2. `size`回のループを実行する
3. 変数`index`に`0`から`size-1`までの整数を代入する
4. `'v.at(index) < v.at(min)'`ならば`min = index`
Expand Down Expand Up @@ -393,7 +393,7 @@ int main()
^
~~~

こんどは4番目の`3`だ。これも先頭と交換する
今度は4番目の`3`だ。これも先頭と交換する

~~~
3 4 8 9 7
Expand Down Expand Up @@ -477,7 +477,7 @@ int main()

変数とまったく同じだ。

しかし、変数`a`に変数bの値を代入すると、変数`a`の元の値は消えてしまう。
しかし、変数`a`に変数`b`の値を代入すると、変数`a`の元の値は消えてしまう。

~~~cpp
int main()
Expand Down
2 changes: 1 addition & 1 deletion 010-debug-printf.md
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ a = b ; // a = 1
b = a ; // b = 1
~~~

変数`a`, `b`の値を交換したい場合、変数`a`に変数`b`を代入したあとに、変数`b`に変数`a`を代入する処理は誤りだ。なぜならば、変数`b`の代入のときには、変数`a`の値は変数bの値になってしまっているからだ
変数`a`, `b`の値を交換したい場合、変数`a`に変数`b`を代入したあとに、変数`b`に変数`a`を代入する処理は誤りだ。なぜならば、変数`b`の代入のときには、変数`a`の値は変数`b`の値になってしまっているからだ

前章で学んだように、こういう場合、別の変数に値を代入して退避させておく。

Expand Down
2 changes: 2 additions & 0 deletions 011-integer.md
Original file line number Diff line number Diff line change
Expand Up @@ -246,8 +246,10 @@ $-1$は1の補数表現では、1(`0b00000001`)の各ビットを反転させた

同様に、$-2$は`0b11111110`に、$-3$は`0b11111101`になる。

<!--
00000011
11111100
-->

2の補数表現の$-1$と$-2$を足すと以下のようになる。

Expand Down
8 changes: 4 additions & 4 deletions 016-algorithm.md
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ int main()
{
std::vector<int> v = {1,2,3,4,5} ;

// 引数をリファレンスでとって2倍にする関数
// 引数をリファレンスで取って2倍にする関数
auto twice = [](auto & value){ value = 2 * value ; } ;

std::for_each( std::begin(v), std::end(v), twice ) ;
Expand Down Expand Up @@ -923,7 +923,7 @@ auto copy = []( auto first, auto last, auto result )
{ *result = *iter ; }

return result ;
}
} ;
~~~


Expand All @@ -940,7 +940,7 @@ auto transform = []( auto first, auto last, auto result, auto op )
{ *result = op(*iter) ; }

return result ;
}
} ;
~~~

使い方は`copy`と似ているが、値をコピーをする際に関数を適用することができる。
Expand Down Expand Up @@ -1030,7 +1030,7 @@ auto fill_n = []( auto first, auto n, auto value )
{
*first = value ;
}
}
} ;
~~~


Expand Down
3 changes: 1 addition & 2 deletions 019-operator-overloading.md
Original file line number Diff line number Diff line change
Expand Up @@ -481,7 +481,7 @@ int main()
分数クラスの足し算を考えよう。

+ 分母が同じならば分子を足す
+ 分母が異なるならば互いの分母を掛けて、分母をそろえて足す
+ 分母が異なるならば互いの分母を掛けて、分母をそろえて足す

コードにすると以下のようになる。

Expand Down Expand Up @@ -626,7 +626,6 @@ int main()
演算子としてではなく、関数と同じように呼び出すこともできる。

~~~cpp

struct S { } ;

// S f( S, S )のようなもの
Expand Down
2 changes: 1 addition & 1 deletion 024-more-array.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ struct array
using value_type = T ;
using reference = T & ;

using size_type = std::size_t
using size_type = std::size_t ;

value_type storage[N] ;

Expand Down
14 changes: 7 additions & 7 deletions 025-array-iterator.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ int main()

~~~cpp
// イテレーターを表現するクラス
struct array_iterator { }
struct array_iterator { } ;

template < typename T, std::size_t N >
struct array
Expand Down Expand Up @@ -189,7 +189,7 @@ struct array
// 黒魔術2: *this
// 黒魔術3: iterator(*this)
{ return iterator(*this) ; }
}
} ;
~~~

黒魔術1は`array_iterator_begin<array>`の中にある。この`array``array<T,N>`と同じ意味になる。つまり全体としては、`array_iterator_begin<array<T,N>>`と書いたものと同じだ。クラステンプレートの中でクラス名を使うと、テンプレート実引数をそれぞれ指定したものと同じになる。
Expand Down Expand Up @@ -335,15 +335,15 @@ struct array_iterator
{
Array & a ;

array_iterator_begin( Array & a )
array_iterator( Array & a )
: a( a ) { }

// 次の要素を指す
array_iterator & operator ++() ;
// 前の要素を指す
array_iterator & operator --() ;

//いま参照している要素へのリファレンスを返す
// いま参照している要素へのリファレンスを返す
Array::reference operator *() ;
} ;
~~~
Expand Down Expand Up @@ -399,7 +399,7 @@ struct array_iterator
array_iterator( Array & a, std::size_t i )
: a( a ), i(i) { }

//いま参照している要素へのリファレンスを返す
// いま参照している要素へのリファレンスを返す
Array::reference operator *()
{
return a[i] ;
Expand Down Expand Up @@ -1066,7 +1066,7 @@ struct array_const_iterator

// コンストラクター
array_const_iterator( Array const & a, std::size_t i )
a(a), i(i) { }
: a(a), i(i) { }
} ;
~~~
Expand Down Expand Up @@ -1097,7 +1097,7 @@ struct array_const_iterator

// array_iteratorからの変換コンストラクター
array_const_iterator( typename array_iterator<Array>::iterator const & iter )
a( iter.a ), i( iter.i ) { }
: a( iter.a ), i( iter.i ) { }
} ;
~~~
Expand Down
16 changes: 8 additions & 8 deletions 026-exception.md
Original file line number Diff line number Diff line change
Expand Up @@ -444,14 +444,14 @@ main is destructed.

なぜこの順番に出力されるか考えてみよう。

1. プログラムの実行は関数`main`から始まる。そのためまず`main`が構築される
2. 関数`main`は関数`g`を呼ぶ。`g`が構築される
3. 関数`g`は関数`f`を呼ぶ。`f`が構築される
4. 関数`f`は例外を投げるので、`f`は破棄される
5. 関数`g`に巻き戻ったが`catch`がないのでさらに巻き戻る。`g`が破棄される
6. 関数`main`に巻き戻ったところ対応する`catch`があるのでスタックアンワインディングは停止する
7. `caught.`が出力される
8. `main`が破棄される
1. プログラムの実行は関数`main`から始まる。そのためまず`main`が構築される
2. 関数`main`は関数`g`を呼ぶ。`g`が構築される
3. 関数`g`は関数`f`を呼ぶ。`f`が構築される
4. 関数`f`は例外を投げるので、`f`は破棄される
5. 関数`g`に巻き戻ったが`catch`がないのでさらに巻き戻る。`g`が破棄される
6. 関数`main`に巻き戻ったところ対応する`catch`があるのでスタックアンワインディングは停止する
7. `caught.`が出力される
8. `main`が破棄される

例外が投げられると通常の実行は飛ばされるので、例外が投げられるかもしれない処理のあとに、例外の有無にかかわらず絶対に実行したい処理がある場合は、クラスのデストラクターに書くとよい。

Expand Down
2 changes: 1 addition & 1 deletion 028-pointer-semantics.md
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ int * pointer = 0 ;

### 無効な参照先の作り方

ポインターやリファレンスによって参照先が参照される時点では有効だったが、あとに無効になる参照先を作ることができてしまう
ポインターやリファレンスによって参照先が参照される時点では有効だったが、後に無効になる参照先を作ることができてしまう

例えば以下のコードだ。

Expand Down
4 changes: 2 additions & 2 deletions 031-iterator-operations.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ struct array_iterator
std::size_t i ;

array_iterator( Array * a, std::size_t i )
a(a), i(i) { }
: a(a), i(i) { }

reference operator *() const
{ return a[i] ; }
Expand Down Expand Up @@ -857,7 +857,7 @@ int main()

前方イテレーター以上のイテレーターの例として、`iota_iterator<T>`を実装してみよう。

このイテレーターはT型の整数を保持し`operator *`でリファレンスを返し、`operator ++`でインクリメントする。
このイテレーターは`T`型の整数を保持し`operator *`でリファレンスを返し、`operator ++`でインクリメントする。

以下のように使える。

Expand Down
2 changes: 1 addition & 1 deletion 034-vector-memory-allocation.md
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ int main()

~~~cpp
vector( const allocator_type & alloc ) noexcept
alloc( alloc )
: alloc( alloc )
{ }
~~~
Expand Down
Loading

0 comments on commit c90f238

Please sign in to comment.