2017年11月アーカイブ

第13章練習問題2

| コメント(0)

 第12章の練習問題はやらず。グラフィックス関係は解答例もない。第13章は、勉強になりそうな、練習問題2をやる。練習問題は、下記の通り。

 角丸四角形を描画する。4つの直線と4つの弧で構成されるBOXクラスを定義する。


 仕様としては、Rectangleに、rrという引数を追加することにした。このrrは、弧の半径だ。Rectangleの実装を真似て作ったのが、下記の解答例。P.436のdraw_line()関数は、基底クラスのShapeで仮想関数として定義されている関数なので、派生クラスごとに、同じ名前の関数を用意する必要がある。この部分が、最初わからず、少し苦労した。解答例は、下記の通り。

#include "Simple_window.h"
#include "Graph.h"

struct Box : Shape {
    Box(Point xy, int ww, int hh, int rr);
    Box(Point x, Point y, int rr);
    void draw_lines() const;

    int height() const { return h; }
    int width() const { return w; }
private:
    int h;
    int w;
    int r;
    Point p;
};

Box::Box(Point xy, int ww, int hh, int rr)
    : w{ ww }, h{ hh }, r{ rr }, p{ xy }
{
    if (h<=0 || w<=0 || r<=0) error("Bad Box: non-positive side");
    if (h<=r*2 || w<=r*2) error("Bad Box: arc is too big");
}

Box::Box(Point x, Point y, int rr)
    : w{ y.x - x.x }, h{ y.y - x.y }, r{ rr }, p{ x }
{
    if (h <= 0 || w <= 0 || r <= 0) error("Bad Box: non-positive side");
    if (h <= r * 2 || w <= r * 2) error("Bad Box: arc is too big");
}

void Box::draw_lines() const
{

    fl_line(p.x + r, p.y , p.x + w - r, p.y );
    fl_line(p.x + r, p.y + h , p.x + w - r, p.y + h );
    fl_line(p.x , p.y + r, p.x , p.y + h - r);
    fl_line(p.x + w , p.y + r, p.x + w , p.y + h - r);
    fl_arc(p.x, p.y, r+r, r+r, 90, 180);
    fl_arc(p.x + w -r-r, p.y, r + r, r + r, 0, 90);
    fl_arc(p.x, p.y + h - r - r, r + r, r + r, 180, 270);
    fl_arc(p.x + w - r - r, p.y + h - r - r, r + r, r + r, 270, 360);
}

int main()
{
    using namespace Graph_lib;
    Point tl(100, 100);
    Simple_window win(tl, 600, 400, "Canvas");


    Box b{ Point{100,100},100,100,10};

    win.attach(b);
    win.wait_for_button();
}

 第12章から16章までは、グラフィック関係である。当然、何らかのライブラリーが必要になる。この本では、FLTKを使う。そのインストール方法は、付録に書いてある。FLTKのインストールうまくいき、FLTKを使ったテストコードも動く。ところが、次のステップのhttp://www.stroustrup.com/Programming/PPP2code/からソースコードを持ってきてP.424の構成にしてもも、うまくコンパイルできない。少しくらいなら、なんとかなるとおもっったっが、次々と問題があって、あきらめた。
 ここまできて、以前、この第1版を勉強したときに 「ストラウストラップのプログラミング入門」マテリアルのお世話になったことを思い出した。でも、今度は、ここに書いてある通りにやっても、うまくいかない。あの時となんかが変わったのだ。
 最終的に、P.424の構成のまま、この環境に、上記のおすなばセットのソースコードをそのままもってきて、うまく動くようになった。この環境構築に2日ほどっかかってしまった。

第11章練習問題10

| コメント(0)

 第11章は、標準入出力をカスタマイズする方法である。ホワイトスペースを追加するというカスタマイズの手法は、C++言語らしい方法で非常に参考になった。
 練習問題10は、以下の通り。

 vector<string> split(const string& s)関数を記述する。この関数は、引数sをホワイトスペースに基づいて部分文字列に分割し、それらを格納したvectorを返す。

 文字列ストリームを使う問題だろう、ということで、私の回答は、以下の通り。

#include "..\..\std_lib_facilities.h"

vector<string> split(const string& s) {
    istringstream is{ s };
    vector<string> svector;
    string str;

    while (true) {
        is >> str;
        if (is.eof()) return svector;
        svector.push_back(str);
    }
}

int main() {
    vector<string> result;
    string test = "This is test. ";

    result = split(test);
    for (int i = 0; i < result.size(); i++) cout << i << ":" << result[i] << endl;

    return 0;
}

 模範解答は、http://www.stroustrup.com/Programming/Solutions/Ch11/e11-9.cpp。私の回答は、eofを検出した時に、無限ループをreturnで抜けるという方法になっている。一夫、模範解答は、while (is>>buf)でループを作っている。明らかにこちらの方がいい。どうも、このあたりの私の悪い癖を直す必要がありそうだ。

第10章練習問題11

| コメント(0)

 第10章は、入力ストリームと出力ストリームである。実務上は、エラー処理に関わる多くの部分がこの範疇に属するので重要な章なのだが、退屈な章であることも確かである。最後のところに、「ところで、実際にコードと説明をすべて読んだだろうか。それとも、ぼんやり眺めて読み飛ばしただろうか。」という問いかけがあって、笑ってしまった。確かに、きっちりと読みには、つらい章である。
 練習問題11は、次の通り。

 テキストファイルに含まれている整数をすべて合計するプログラムを作成する。これらの整数はホワイトスペースで区切られた情愛で含まれている。

 基本的には、1文字読んで、読み戻し、読んだ1文字が数字なら数字として、読んだ1文字が数字以外なら文字列として読むという構造にした。読んだ1文字が'-'なら、マイナスとして取り扱うようにしている。私の回答は、下記の通り。

#include "..\..\std_lib_facilities.h"

int main(){

try {
    cout << "ファイル名を入力してください:";
    string iname;
    cin >> iname;
    ifstream ist{ iname };
    if (!ist) error("指定されたファイルは開けませんでした", iname);

    int sum = 0;
   
    while (true) {
        char ch;

        ist >> ch;

        if (ist.bad()) error("入力にエラーが発生しました");
        if (ist.eof()) break;


        if ((ch >= '0') && (ch <= '9')) {
            ist.unget();
            int n;
            ist >> n;
            sum += n;
        } else if (ch=='-') {
            ist >> ch;
            if ((ch >= '0') && (ch <= '9')) {
                ist.unget();
                int n;
                ist >> n;
                sum -= n;
            }
        } else {
            ist.unget();
            string s;
            ist >> s;
        }
    }

    cout << "合計は:" << sum << endl;
    return 0;
}
catch (exception& e) {
    cerr << "exception: " << e.what() << endl;
    char c;
    while (cin >> c&& c != ';');
    return 1;
}
catch (...) {
    cerr << "exception\n";
    char c;
    while (cin >> c && c != ';');
    return 2;
}

}

 

 模範解答http://www.stroustrup.com/Programming/Solutions/Ch10/e10-11.cppは、少し方針が異なる。文字のチェックなどを関数にしていて、確かにその方が見通しがいいと思う。’-‘の処理は方針が違うようだ。

このアーカイブについて

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

前のアーカイブは2017年10月です。

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

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

ウェブページ

  • about
Powered by Movable Type 6.3.6