2014年12月26日金曜日

ニコ生アラート(壁) for Windows ver1.0.2公開

ニコ生アラート(壁) for Windows ver1.0.2を公開します。

変更点
・同じコミュニティをアラート条件に追加しようとすると異常終了する問題を修正。
・設定画面でコミュニティ通知の追加ボタンが正常に機能しない問題を修正。
・Windowsのシャットダウンやログオフ時にアプリケーションを自動的に終了するように変更。

ダウンロード
http://scarabdev.net/

2014年11月3日月曜日

ニコ生アラート(壁) for Windows ver1.0.0公開

ニコ生アラート(壁) for Windows ver1.0.0を公開します。

アプリ名を変更しています。 アプリ画面はほぼ変更ありませんが、バックグラウンドは大幅に変更となり専用サーバを使用して早くデータ取得ができるようになりました。

ホームページを作成したので、そのほかの変更点やアプリのダウンロードについてはそちらで確認をお願いします。

 http://scarabdev.net/

 

2014年3月20日木曜日

クラスや構造体を順序付けして配列に追加する方法を考える(STLを使用した二分挿入ソート)

二分探索したいんです!
二分探索を行う場合に配列はソートされている必要がある。
配列がソートされた状態を維持するように要素を追加する処理を考える。
ネットには int などスカラ値を使用した例は多いがクラスや構造体を使用する例が少ないので忘れないようにまとめておく。

サンプルソース
#include <iostream>
#include <cstdlib>
#include <vector>
#include <algorithm>
using std::vector;
using std::cout;
using std::endl;
using std::lower_bound;

class Info {
public:
    int id;
};

struct InfoAscending {
    bool operator()(const Info* lhs, const Info* rhs) {
        return lhs->id < rhs->id;
    }
    bool operator()(const Info* lhs, int rhs) {
        return lhs->id < rhs;
    }
//  bool operator()(int lhs, const Info* rhs) {
//      return lhs < rhs->id;
//  }
};

void append(vector<Info*>& vec, Info& info) {
    vector<Info*>::iterator lower =
        lower_bound(vec.begin(), vec.end(), &info, InfoAscending());
    vec.insert(lower, &info);
}

void print(Info* info) {
    cout << info->id << ' ';
}

void delete_info(Info* info) {
    delete info;
}

int find(vector<Info*>& vec, int id) {
    vector<Info*>::iterator lower =
        lower_bound(vec.begin(), vec.end(), id, InfoAscending());
    if (lower != vec.end() && (*lower)->id == id)
        {
        return lower - vec.begin();
        }
    return -1;
}

int main() {
    srand((unsigned int)time(NULL));

    //オブジェクトの追加
    int value;
    vector<Info*> vec;
    for (int i = 0; i < 5; ++i) {
        Info* info = new Info();
        info->id = value = rand() % 99;
        cout << "Add " << info->id << endl;
        append(vec, *info);
    }

    //コレクション一覧
    cout << "Vector { ";
    std::for_each(vec.begin(), vec.end(), print);
    cout << '}' << endl;

    //最後に追加したidを検索
    cout << "Find(" << value << ") : vec[" << find(vec, value) << ']' << endl;
    //存在しないidを検索
    value = 99;
    cout << "Find(" << value << ") : vec[" << find(vec, value) << ']' << endl;

    std::for_each(vec.begin(), vec.end(), delete_info);
    return 0;
}
実行結果
Add 88
Add 10
Add 89
Add 36
Add 23
Vector { 10 23 36 88 89 }
Find(23) : vec[1]
Find(99) : vec[-1]

要素の追加はappend()で行っている。
append()内では std::lower_bound で比較対象以上の値を持つ最初の要素を取得し、その前方に挿入することによりソート済み状態を維持する。
std::lower_bound の第4引数には関数オブジェクトを指定し InfoAscending::operator()(Info* lhs, Info* rhs) が呼び出される。

要素の検索はfind()で行っている。
もともと二分探索による検索は std::binary_search があるが対象の有無しかわからないので不便。
find()では見つけた要素のインデックスを返すようにしている。見つからない場合には-1を返す。

また、ソートキーであるidを指定して検索できるように InfoAscending::operator()(Info* lhs, int rhs) を実装している。
この関数がないと検索するために、Infoクラスのインスタンスが必要になる。

・余談
std::upper_bound を使用する場合には InfoAscending::operator()(int lhs, Info* rhs) のように引数が逆になるので注意が必要。

2014年1月18日土曜日

eclipse CDTでBoost.Logを使おうとしたらエラーが出る

・2014/01/25追記
ビルドエラー追加
eclipseバージョン修正

・バージョン
boost:1.55.0
eclipse:4.3.1

boost_1_54_0から標準で含まれているBoost.Logを使ってみます。

#include <boost/log/trivial.hpp>
int main()
    {
    BOOST_LOG_TRIVIAL(trace) << "Hello Boost.Log";
    return 0;
    }

eclipseだとマクロのトークン連結演算子がうまく処理できないようで、
下記、2つのビルドエラーが発生する場合、Code Analysisの設定を変更します。


Function 'BOOST_PP_SEQ_ENUM_BOOST_PP_SEQ_SIZE' could not be resolved

Invalid arguments '
Candidates are:
boost::log::v2s_mt_posix::record open_record()
boost::log::v2s_mt_posix::record open_record(const #10000 &)


Code Analyzerの設定はプロジェクトごとかワークスペース全体でできるので好きなほうを変更する。
プロジェクトはプロジェクトを右クリックして[Properties] → [C/C++ General] → [Code Analysis]
ワークスペースはメニューから[Window] → [Preferences] → [C/C++] → [Code Analysis]

[Syntax and Semantic Errors] 内の [Function Cannot be resolved] と [Invalid arguments]のチェックをオフもしくはSeverityをWarningかInfoに変更する。

boostを使っているとたまに出るエラー。
頭の片隅においておくと助かるときがあるはず。

次はリンクエラー。

undefined reference to `boost::log::v2s_mt_posix::attribute_name::get_id_from_string(char const*)'

これはBoost.Logを動的にリンクするようにオプションを設定していないため。
対処として全てのソースファイルにBOOST_LOG_DYN_LINK もしくは BOOST_ALL_DYN_LINKを定義します。
全ソースファイルに定義するのが面倒なときには boost/config/user.hpp に定義しましょう。
これはこのあたりに書いてあります。
http://www.boost.org/doc/libs/1_55_0/libs/log/doc/html/log/rationale/namespace_mangling.html

そしてcURLppを使うのをやめた

・バージョン
cURLpp:0.7.3

メンテナンスされていない感じがするのでcURLppの使用をやめました。

きっかけは curlpp::options::BoostWriteFunction がないとビルドエラーが発生したことから。
調べたらconfig.hを編集しないといけないことが判明。
でもconfig.hを編集しろなんてマニュアルには書いてない。
(見逃している可能性があるけど…)

マニュアルの最終更新が2006年1月。
ソースの最終更新は2009年12月。
4年近くマニュアルが更新されていないのは怖い。

あとは、curlpp::Cleanup クラスが非推奨となっているのに
全てのexample内で使用している。
これだとプログラムを作成するときにexampleを参考にできないのでツライ。

そんなわけでcURLppは封印します。

変わりにlibcurlを使おうと思います。
C言語のインターフェースしかないけどね。