Recently in programming Category
今日読んでいるコードに、知らなかったプリプロセッサ命令が出てきたのでメモ。
#include <stdio.h>
#define tcat(x,y,z) x ## y ## z
#define cat(x) # x
#define abc "Hello"
int main(void)
{
printf("%s\n", tcat(a, b, c));
printf("%s\n", cat(a b c));
return 0;
}
実行すると、
chome@sid:~/src/test$ ./a.out
Hello
a b c
となる。
Debianパッケージの作成プロセスを自動化するコマンドであるdpkg-buildpackageのメモ。dpkg-buildpackageは以下の手順でパッケージを作成する。
- 環境変数の準備。dpkg-architectureでBuild archやHost arch等を設定し、またCCFLAGS、CXXFLAGS、LDFLAGS等を設定
- build-dependencyとbuild-conflictsのチェック。(-d でスキップ)
- debian/rule clean (-nc でスキップ)
- dpkg-source (-b, -B, -A のいずれかが設定されているとスキップ)
- -b, -B, -Aオプションによって以下のいずれかに分岐
- debian/rules build (デフォルトまたは-b)
- debian/rules binary-arch (-B)
- debian/rules binary-indep (-A)
- dscファイルを署名 (-us でスキップ)
- dpkg-genchanges でchangesファイルを生成
- changesファイルを署名 (-uc でスキップ)
- もしも-tcが指定されていたら、debian/rules clean
-j で、並列に動かすCPUの数を指定することができる。はしょったところもあるので、dpkg-buildpackage(1)を確認のこと。
SingletonパターンをC++でまじめに書いてみた。Singletonは生成は簡単なんだけれど、後始末が難しい。GoF本とかには、後始末のことはあまり詳しく書かれていなかったような気がする。あとModern C++ Designにこのことは詳しくかかれている。
今回は最初に思いついたリンクカウントを採用してみた。Singletonを参照しているオブジェクトの数を数えておいて、0になったらdeleteする。
#ifndef _SINGLETON_H
#define _SINGLETON_H
namespace impl{
template <class T>
class Singleton{
public:
static Singleton* initInstance()
{
if(linkcount == 0){
instance = new Singleton();
linkcount = 1;
}else{
linkcount+=1;
}
return instance;
}
void destroy()
{
if(0 == (linkcount-=1)){
delete instance;
}
}
T* object(){
return &obj;
}
private:
Singleton(){
}
public:
virtual ~Singleton(){
}
private:
static Singleton *instance;
static int linkcount;
T obj;
};
template <class T> Singleton<T> *Singleton<T>::instance;
template <class T> int Singleton<T>::linkcount = 0;
}
template <class T>
class Singleton{
public:
Singleton(){
s = impl::Singleton<T>::initInstance();
}
T* operator->(){
return s->object();
}
~Singleton(){
s->destroy();
}
private:
Singleton(const Singleton&){}
private:
impl::Singleton<T> *s;
};
#endif // _SINGLETON_H
で、一つしかインスタンスを作りたくないクラスを定義してあげて、::Singletonのテンプレート引数に入れてあげればよい。例えばこんな感じ。
#include "singleton.h"
using namespace std;
class Hello
{
public:
Hello()
{
i = 0;
}
void run()
{
i += 1;
cout<< "Hello World "<< i<< endl;
}
~Hello()
{
cout<< "destroy"<< endl;
}
int i;
};
int main(void)
{
Singleton<Hello> i1;
Singleton<Hello> i2;
Singleton<Hello> i3;
i1->run();
i2->run();
i3->run();
return 0;
}
このテストコードを実行すると、次のようになる。
Hello World 1 Hello World 2 Hello World 3 destroy
同じテンプレート引数の::Singletonインスタンスを複数生成しているが、それらは同じインスタンス変数にアクセスしており、デストラクタは1度しか呼ばれていない。ちゃんと動いているようだ。ただこのコードでは、Helloの初期化をデフォルトコンストラクタでしかできない。これではちょっとカッコ悪い。もう少し考えなければ。
WHATWGでHTML5仕様がLast Callになった。徐々にではあるが、Web Application が普及する環境が整いつつある。(どうもW3Cは聞いていなかったらしく、ちょっと揉めそうな感じみたいだが。)
さて、以前もここで書いたとおりHTML5はそれまでの文書の構造化に加え、振る舞いの要素の追加が行われており、スクリプト言語のインターフェースも規定されている。このスクリプト言語は仕様の上では指定されているわけではないが、事実上JavaScriptだろう。ということでそろそろちゃんとJavaScriptを書けるようにならなきゃいかんのかなぁ。ということで、まずはクロージャーからやってみた。
<html lang="ja">
<head>
<title>Closure Test</title>
<meta http-equiv="Content-Type" content="text/plain;charset=UTF-8">
</head>
<body onload="onLoad()">
<script type="text/javascript">
var countUp;
function makefunc()
{
var x=0;
return function(){return x++;};
}
function onLoad()
{
countUp = makefunc();
window.setInterval(onTimer, 100);
}
function onTimer()
{
document.getElementById('count').innerHTML = countUp();
}
</script>
<div id="count"></div>
</body>
</html>
このコードは、100ms毎にカウントアップして表示するもの。makefuncがカウントアップする関数オブジェクトを作り、onloadハンドラでグローバル変数countupに保存しておく。それを100ms毎に呼び出している。実行すると下のようになる。
久しぶりにshell (bash) script。一つのデータが一行ごとに並んでいるファイルから必要な部分を取り出すスクリプト。今回はbashの組み込み関数である getopts を使ってみた。
#!/bin/bash
#
# clip.sh -f FROM -t TO FILE
#
while getopts "f:t:" i;do
case $i in
f) FROM=$OPTARG;; # Time From
t) TO=$OPTARG;; # Time To
esac
done
shift $(($OPTIND - 1))
FILE=$1
LINES=`wc --line $FILE | cut -d " " -f 1`
FLINE=`grep -n $FROM $FILE | cut -d : -f 1 | head -n 1`
TLINE=`grep -n $TO $FILE | cut -d : -f 1 | head -n 1`
if [ $FLINE -ge $TLINE ]; then
TMP=$FLINE;
FLINE=$TLINE;
TLINE=$TMP;
fi
HEAD=$(($TLINE-$FLINE))
TAIL=$(($LINES-$FLINE+1))
tail -n $TAIL $FILE | head -n $HEAD
たとえばこのようなファイルがあるとすると
11:00:17 24.93 72.9 11:00:17 24.94 72.8 11:00:17 24.94 72.7 11:00:18 24.95 72.4 11:00:19 24.96 72.1 11:00:20 24.97 71.9 11:00:21 24.97 71.8 11:00:22 24.98 71.7 11:00:23 24.99 71.4 11:00:24 25.00 71.2 ....
このファイルをdata.txtというファイル名として、この中から12:00:00から13:00:00まで取り出したいとすると、
$ clip.sh -f 12:00:00 -t 13:00:00 data.txt
とすれば標準出力に出力される。
ふ、例によって誰もついて来れまい。あ、ぴらふとCZDの二氏は除く。ってかこのくらいのコマンドは、textutilあたりにありそう。良い解法があればコメントよろ。
前回の記事のhaveの指摘に従い、参照渡しをやめてヴェクタを返す関数にしてみた。
std::vector<string>
slice(const std::string source, const std::string dem)
{
std::string::size_type i1 = 0;
std::string::size_type i2 = source.find(dem);
std::vector<string> retval;
if(std::string::npos == i2)
return retval;
std::string s = source + dem;
do{
retval.push_back(s.substr(i1, i2-i1));
i1 = i2+1;
}while(std::string::npos != (i2 = s.find(dem, i1)));
return retval;
}
ちょっと効率は落ちたが、Atomicになったので前回のコードにくらべ、マルチスレッドプログラミングで安全に使えるようになった。
Thanks! nice comment > Have
C++を書いていて、JavaのSttringTokenizerのようなことをやりたいことがある。C++標準ライブラリだけで書いてみた。
void slice(const std::string source,
const std::string dem,
std::vector<std::string> *retval)
{
std::string::size_type i1 = 0;
std::string::size_type i2 = source.find(dem);
if(std::string::npos == i2)
return;
std::string s = source + dem;
do{
retval->push_back(s.substr(i1, i2-i1));
i1 = i2+1;
}while(std::string::npos != (i2 = s.find(dem, i1)));
}
この関数は、sourceで指定した文字列をdemで指定した文字で切り分けて、切り分けた結果をretvalで指定したヴェクタに格納ものである。テストしてみると。
using namespace std;
int main(void)
{
string source =
"DCV_,___,___,-00.0073E-3,DCV_,___,___,+00.000E-3,6247865";
vector<string> vec;
vec.clear();
slice(source, ",", &vec);
if(vec.empty()){
cout<< "not found"<< endl;
return -1;
}
cout<< vec[3]<< " "<< vec[7]<< endl;
return 0;
}
$ ./a.out
-00.0073E-3 +00.000E-3
ちゃんと値は切り出せている。listに結果を格納するようにすれば、もっとStringTokenizerっぽくなるかな。
久しぶりにschemeでコードを書いてみた。実用のコードでは初かな。処理系はGaucheで、標準入力から数値を入力して標準偏差を計算するコード。
(define (ave-list lst)
(/ (fold + 0 lst) (length lst)))
(define (var lst)
(let ((ave (ave-list lst)))
(/ (fold + 0
(map (lambda (x) (* x x))
(map (lambda (x) (- x ave)) lst)))
(length lst))))
(define (sd lst)
(sqrt (var lst)))
(display (sd
(map string->number (port->string-list
(current-input-port)))))
リストを修正するコードの連鎖と高階関数。この感覚がLISPっぽい。
新しいカメラは届きました。
2009-06-06 追記
はぁ?LET?とか言われそうなので(誰に?)、LETなしバージョンは、sdをこうすれば良い。
(define (var lst)
((lambda (ave)
(/ (fold + 0
(map (lambda (x) (expt x 2))
(map (lambda (x) (- x ave)) lst)))
(length lst)))
(ave-list lst)))
もう誰もついてきてないか....
あと写真を追加しました。
Microsoft Speech APIを触ってみた。.NETだとすごく簡単だった。Hello Worldは以下のとおり。Microsoft Windows XP上で、Microsoft Speech SDK 5.1をインストールし、Visual C# 2005 Express Editionで作成した。最初に参照設定で、"Microsoft Speech Object Library"を追加すること。
このコードは、インストールされているすべてのVoiceで"It's fine today"と発音する。
using System;
using System.Collections.Generic;
using System.Text;
using SpeechLib;
namespace TTSTest
{
class Program
{
static void Main(string[] args)
{
SpVoice voice = new SpVoice();
ISpeechObjectTokens token = voice.GetVoices("", "");
for (int i = 0; i < token.Count; i++)
{
voice.Voice = token.Item(i);
Console.WriteLine(token.Item(i).GetDescription(0));
voice.Speak("it's fine today", SpeechVoiceSpeakFlags.SVSFlagsAsync);
}
while (voice.Status.RunningState == SpeechRunState.SRSEIsSpeaking) ;
}
}
}
今月からJava読書会に参加する予定だ。課題図書はJavaネットワークプログラミングの神髄である。予習課題が出ているので早速やってみた。


