2017年8月アーカイブ

第4章 練習問題11

| コメント(0)

 前回に引き続き第4章の練習問題。練習問題11を引用する。

 1~100の素数を全て見つけ出すプログラムを作成する。そのための方法の1つは、素数が順番に配列されたvectorを使用して、数字が素数かどうかをチェックする関数を記述することだ。つまり、このventorがprimesという名前であるとすればprimes[0]==2、primes[1]==3、primes[2]==5などを使用して、数字がそれよりも小さい素数で割りきれるかをチェックする。次に、1~100の各数字が素数かどうかをチェックし、検出された素数をvetorに格納するループを記述する。また検出された素数を一覧表示する別のループも記述する。素数のvecorをprimesと比較することで、結果をチェックするといいだろう。最初の素数は、2である。

 私の回答は、下記の通り。

#include "../../std_lib_facilities.h"

int main() {
    vector<int> primes;

    primes.push_back(2);

    for (int n = 3; n<=100; ++n) {
        int i;
        for (i = 0; i<primes.size(); ++i) {
            if (n % primes[i] == 0)
                break;
        }
        if (i >= primes.size())
            primes.push_back(n);
           
    }

    cout << "1~100の素数は\n"  ;

    for (int n: primes)
        cout << n << "\n";

    return 0;

}

 これは、明らかに間違ってる。問題文に「数字が素数かどうかをチェックする関数を記述する」とあるのに、メインルーチンだけで書いてしまっているからだ。しかも、素数判定のforループで、素数かどうかをforループを抜けた後のループ変数iの値で判定するため、ループ変数iの宣言をforループの外でやるとか、トリッキーなことをしている。素直に、回答例http://www.stroustrup.com/Programming/Solutions/Ch4/e4-11.cppのように、すべきであった。
 vectorの使いやすさがよくわかる練習問題であった。

第4章 練習問題3

| コメント(0)

 第4章では、vector型というC言語にはない型とその操作方法が出てくる。ここからが、いよいよC++言語の本らしくなる。練習問題3を引用する。

 一連のdouble型の値をvectorに読み込み、これらの値を特定のルートに沿った2つの都市間の距離として考える。総距離(すべての距離の合計)を計算して出力する。2つの隣接する都市の間の最短距離と最長距離、および平均距離を割り出して出力する。

 私の回答は、下記の通り。

#include "../../std_lib_facilities.h"
 
int main() {
    vector<double> distance;

    for (double x; cin >> x;) {
        if (x > 0)
            distance.push_back(x);
        else
            break;
    }
    if (distance.size() > 0) {
        double sum, min, max;
        sum = distance[0];
        min = distance[0];
        max = distance[0];
        for (int i = 1; i < distance.size(); ++i) {
            sum += distance[i];
            if (min > distance[i]) min = distance[i];
            if (max < distance[i]) max = distance[i];
        }
        cout << "総距離:" << sum << ",最短:" << min << ",最長:" << max << ",平均:" << sum / distance.size() << "\n";
    }
    else
        cout << "値が入力されていません\n";

    return 0;

}

 vectorの最初の値で、min、max、sumを初期化して、その後ろの値を、ループで回して比較するという構成にしている。回答例は、http://www.stroustrup.com/Programming/Solutions/Ch4/e4-3.cppだが、このコードは明らかに間違っている。minを0で初期化すると、minは0のままである。
 maxはシステムとしての最小値、minはシステムとしての最大値で初期化するのが定石である。が、私は、最初の値で初期化するという私の回答のやり方を好んでいる。

第3章 練習問題10

| コメント(0)

 前回に引き続き第3章の練習問題。練習問題10を引用する。

 以下に示すように、演算に続いて2つのオペランドを受け取り、結果を出力するプログラムを記述する。

 + 100 3.14
 * 4 5

 入力された演算はoperationという名前の文字列変数に読み込み、たとえばif (operation==”+”)のように、if文を使ってユーザーが望んでいる演算を特定する。オペランドはdouble型の変数に読み込む。これを+、-、*、/、plus、minus、mul、divの8つの演算に対して実装する。

 私の回答は、下記の通り。

#include "../../std_lib_facilities.h"

int main() {
    string operation;
    double val1,val2;

    cout << "演算、数値2個入力してください\n";
    cin >> operation >> val1 >> val2;

    if (operation == "+")
        cout << val1 + val2 << "\n";
    else if (operation == "-")
        cout << val1 - val2 << "\n";
    else if (operation == "*")
        cout << val1 * val2 << "\n";
    else if (operation == "/") {
        if (val2 == 0)
            cout << "0では割り算できません\n";
        else
            cout << val1 / val2 << "\n";
    } else if (operation == "plus")
        cout << val1 + val2 << "\n";
    else if (operation == "minus")
        cout << val1 - val2 << "\n";
    else if (operation == "mul")
        cout << val1 * val2 << "\n";
    else if (operation == "div") {
        if (val2 == 0)
            cout << "0では割り算できません\n";
        else
            cout << val1 / val2 << "\n";
    }
    else
        cout << "理解できない演算です\n";

    return 0;
}

 何の芸もない、ダラダラしたコードである。でも、わかりやすい。一方、回答例http://www.stroustrup.com/Programming/Solutions/Ch3/e3-10.cppは、コンパクトだ。

第3章 練習問題6

| コメント(0)

 前回に引き続き第3章の練習問題。練習問題6を引用する。

 ユーザーに整数値を3つ入力させ、それらの値をコンマ(,)で区切られた数列として出力するプログラムを記述する。ユーザーが、10 4 6と入力した場合、出力は4, 6, 10になる。2つの値が同じである場合あは、一緒に並べる。つまり、4 5 4という入力から4, 4, 5という出力が得られる。

 私の回答は、下記の通り。

#include "../../std_lib_facilities.h"

int main() {
    int val1, val2, val3, temp;

    cout << "整数を3個入力してください\n";
    cin >> val1 >> val2 >> val3;

    if (val1 > val2) {
        temp = val1;
        val1 = val2;
        val2 = temp;
    }

    if (val2 > val3) {
        temp = val2;
        val2 = val3;
        val3 = temp;
    }

    if (val1 > val2) {
        temp = val1;
        val1 = val2;
        val2 = temp;
    }

    cout << val1 << "," << val2 << "," << val3 << "\n";

    return 0;
}

 値を3つ入力しておいてから、val1、val2、val3を並びかえて、出力するという方法である。
 一方、回答例http://www.stroustrup.com/Programming/Solutions/Ch3/e3-6.cppは、場合分けで、smallest、middle、largestの値を決定するという方法だ。私の回答は、ちょっと勘違いして、ミスをしやすいことは確かだ。でも回答例も、間違いやすい気もする。

第3章 練習問題4

| コメント(0)

 第3章は、C言語プログラマにとっては、C++言語の表記方法を勉強する程度で、あまり大きな違和感はない。練習問題4を引用する。

ユーザーに整数値を1つ入力させるプログラムを記述する。これらの値はval1おyびval2という名前のint型の変数に代入する。それらの値の最小値、最大値、合計、差、積、比率を求め、ユーザーに報告する。

 この1つ入力というのは、明らかに2つ入力の間違いである。
 私の回答は、下記の通り。

#include "../../std_lib_facilities.h"

int main() {
    int val1, val2;
    cout << "整数を2個入力してください\n";
    cin >> val1 >> val2;

    cout << "整数1:" << val1 << ",整数2:" << val2 << "\n";

    cout << "最小値:";
    if (val1 < val2)
        cout << val1 << "\n";
    else
        cout << val2 << "\n";

    cout << "最大値:";
    if (val1 > val2)
        cout << val1 << "\n";
    else
        cout << val2 << "\n";

    cout << "合計:" << val1 + val2 << "\n";

    cout << "差2:";
    if (val1 > val2)
        cout << val1 - val2 << "\n";
    else
        cout << val2 - val1 << "\n";

    cout << "積:" << val1*val2 << "\n";

    cout << "比率:";
    if (val2 == 0)
        cout << "求められません\n";
    else
        cout << val1 / val2 << "\n";

    return 0;
}

 回答例は、http://www.stroustrup.com/Programming/Solutions/Ch3/e3-4.cppである。cinのエラーをチェックするコードが回答例には入っている。ファイル読み込みならともかく、キーボードからの入力を前提とした練習問題で、エラーチェックが必要なのかは難しいところだ。まあ、私の回答でも、特に問題ないと思われる。

 第1章は一般論、第2章は例によってHello Worldである。開発環境をセットアップすることが主である。
 私は、Windows10上にVisual Studio 2015をインストールし、デフォルトの作業ディレクトリーProjectsの直下にstd_lib_facilities.hを配置し、ソースコードからは#include "../../std_lib_facilities.h"で使えるようにした。
 本では、ソフトウエアの実行後、すぐに表示ウインドウが閉じられるのを避けるために、keep_window_open()という関数を使うことが推奨されていたが、Visual Studio 2015環境では、Cntl+F5で、同じようなことが可能なので、この関数は使わないことにした。

練習問題の解答

| コメント(0)

 本書の練習問題のいくつかは、Stroustrup: Programming - Exercise Solutionsに掲載されている。ただ、私のようなC++の初心者から見ても、あまり良いとは思えない回答例もあったりする。
 とはいえ、私のような初心者のコーディングよりは「まし」であるに違いないので、自分で問題を解く都度、この回答と見比べるということを繰り返した。

 本書の監修者の感想が、本の虫: Bjarne Stroustrupのプログラミング入門書の査読の感想に書かれている。結構きびしい内容である。
 第1版は読んだことがあって、第2版を今から勉強しようと考えている私にとって、本書の限界がわかってよかった。
 本書が初心者向けになっていない、という指摘は、全くその通りだと思う。私は、一応、C言語の経験はある(といっても、組み込み技術者なので、少し特殊な経験者だが)。全くの初心者は、最初の数章で挫折するのではないか、と思う。
 Cの経験者が、C++を学ぼうと思うときに、良さそうな本がなかったので、本書を勉強しようと思っている。でも、C++の正しい作法は、別途、勉強する必要があるのかもしれない。

C++の教科書を勉強する

| コメント(0)

 私は、組み込み技術者であり、プログラミング言語はC言語を主として使っている。ちょっと他の言語も習得しようと、夏休みにC++の勉強をしたことは、別のブログで書いた。

 勉強してから1年が経過し、その間、使ったのはやはりC言語で、結局C++言語は少し勉強しただけに終わった。
 この時勉強したのは、ストラウストラップのプログラミング入門という本なのだが、この本の原著の第2版の翻訳が出版された。せっかくなので、新しい版の本で勉強し直そうと思い立った。でも、勉強しただけでは、組み込み技術者の私には、実践でC++言語を使う場が少ないので、勉強の足跡をブログで整理しておこうと思い立った。書いてみることで定着しないかと思ったのである。
 少し恥ずかしいし、他人の勉強の足跡など、あまり読まれる記事になるとは思わないし、途中で挫折するかもしれないが、ちょっとづつ進めてみようと思う。

このアーカイブについて

このページには、2017年8月に書かれた記事が新しい順に公開されています。

次のアーカイブは2017年9月です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。

ウェブページ

  • about
Powered by Movable Type 6.3.6