2005年08月23日

BASICのMID$()をC++で再現してみる

いろいろPCのトラブルとか暇無いとか忘れてたとかで、やっと記事第1号を書く事になった。いや忘れてたは無いだろ忘れてたは、とか言うツッコミを期待恐れながら、記念すべき第1号記事を書いてみたいと思う。

閑話休題。
さて、第1号記事の内容はこのblog作った当初から決めていて、『BASICMID$()をC++で再現する』というものだ。ネタ元はcppllの投稿『[cppll:11798] BASIC の MID$』。

一部のBASIC実装に在ったMID$()という関数をC++で実装するには?というもの。この関数、ただの関数ではなく代入の左辺に使うことも出来る

10 STR$ = "hogehoge"
20 RES$ = MID$(STR$, 3, 4) ' STR$の(1バイト文字単位で)3文字目から4文字取得
30 PRINT RES$
40 MID$(STR$, 3, 4) = "PIYO" ' STR$の3文字目から4文字をPIYOに変える
50 PRINT STR$
geho
hoPIYOge

20行のようなものは普通に書ける(というか普通の関数はこういう仕様)が、40のようなものを書けるようにする為には……?

早速思いついたので書いてみたのがこれ

class Mid;

class MidSub {
    std::string &str_;
    std::string::size_type start_, len_;
public:
    MidSub(std::string &to, std::string::size_type start,
           std::string::size_type len) :
        str_(to), start_(start), len_(len) { };

    std::string &operator=(std::string &from) {
        // 略
    }

    operator std::string() {
        // 略
    }
};

class Mid {
public:
    MidSub operator() (std::string &to, std::string::size_type start,
        std::string::size_type len) {
        return MidSub(to, start - 1, len);
    }
} mid;

mid.operator()()で処理用オブジェクトMidSubを生成するようになっている。何でこんな回りくどい事になっているかというと、mid(str, 1, 2) = "ほげ"の場合、普通にやるとmid(str, 1, 2)(多分operator()になるだろう)の戻り値に"ほげ"を代入する、という変な処理となってしまう為だ。

しかし、どうも『Midが実質的に何もしていない』『midがインスタンス』という点が気持ち悪いように思っていた。

ある日、C++を猛勉強していた専門学校でのクラスメートYに(ネタとして)見せていると、偶然通りかかったM先生の目に止まる。

天井冴太『〜でキモチワルイんですけど、どうにかなりませんかねぇ。』
M先生『なるよ』
天井冴太『(゚д゚)ナンダッテー』

いろいろ話をして、思いついたのがこれ

class mid {
    std::string &str_;
    std::string::size_type start_, len_;

public:
    mid(std::string &str, std::string::size_type start,
        std::string::size_type len = std::string::npos)
        : str_(str), start_(start - 1), len_(len) {
        // 略
    }

    std::string &operator=(const std::string &from) { // [mid() = string] ver
        // 略
    }

    operator std::string() const { // [string = mid()] ver
        // 略
    }
};

mid()一時オブジェクト生成のシンタックスを利用するようにした。よくよく考えたら関数のシンタックスと同じなんじゃないか、これって。これによって、midを1つのクラスにまとめる事が出来た。

ひとつ残念だったのは、グローバルなoperator=()が記述できない点。どうやら言語仕様上そうなっているらしい。operator=(std::string, mid)を定義出来たらスッキリしたのだが……仕方が無いのでoperator std::string()を使っている。なので、下手したらキャストする必要が出てきてしまうが、それはまぁ、ご愛嬌という事で。

mid1.cppmid2.cppの最後の行にある#include "midtest.cpp"は今回のコードのテスト用のmainが書いてある。一応アップしたので、テスト用にどうぞ。
midtest.cpp

タグ:C++
posted by 天井冴太 at 21:19 | Comment(0) | TrackBack(0) | Hack | このブログの読者になる | 更新情報をチェックする
投票お願いします 人気blogランキング - 投票する
この記事へのコメント
コメントを書く
お名前: [必須入力]

メールアドレス:

ホームページアドレス:

コメント: [必須入力]

コメント欄右下をドラッグ&ドロップすると、コメント欄の拡大縮小が出来ます。
認証コード: [必須入力]


※画像の中の文字を半角で入力してください。

この記事へのトラックバック
×

この広告は180日以上新しい記事の投稿がないブログに表示されております。