Jump to navigation
| 1 |
2004年 4月 04日 (日曜日)
- Work on miau's blog?
今日も出勤とかしてますが。
C の const 修飾子周りでてこずってました。
#include <stdio.h>
#include <string.h>
void move_next(const char **pp)
{
if (IsDBCS(**pp)) {
(*pp) += 2;
} else {
(*pp)++;
}
}
int main()
{
char str[] = "hogeほげ";
char *p = str;
while (*p != '\0') {
if (IsDBCS(**pp)) {
/* なんか処理 */
} else {
*p = toupper(*p);
}
move_next(&p);
}
return 0;
}
これをコンパイルするとエラー発生。
move_next() は const char ** を渡すべきであって char ** は渡しちゃダメなんだそうで。
const char * に char * を代入したりできるから、てっきり上記も OK だと思っていたんだけど。
const char *q;
:
:
q = p;
move_next(&q);
(これなら文法的には OK。ただここでやりたいことは実現できてない。)
move_next() の宣言から const を外せばいいんですけど。見てのとおり move_next() の中で文字列を操作しているわけじゃないので、気持ち悪い。
んー・・・これって C の仕様がおかしいんじゃないの?
とか思ったけど、よく考えると C++ のオーバーロードとかそのへんに対応するためなのかも。つまり
void move_next(const char **pp);
void move_next(char **pp);
を別の関数として実装できるから、区別できないと困るわけだ。
結局
move_next((const char**)&q);
とするしかないっぽい。キャストは極力避けたい気もするんだけど、仕方ないか。
(2004/08/29 追記)
すいません。
> よく考えると C++ のオーバーロードとかそのへんに対応するためなのかも。
ってとこ、思いっ切り嘘ついてます。
C FAQ 11.10 参照のこと。
確かにオーバーロード対応だったら
> const char * に char * を代入したりできる
ってのが理屈に合わないですね。
2004年 4月 07日 (水曜日)
- Work on miau's blog?
SELECT 文で NULL をベタ書きすると、エラーになってしまう。
(とりあえず DB2 でのお話。今ほかの DBMS 環境ないので。)
db2 => SELECT ID, VALUE, NULL FROM TEST
SQL0206N 使用されているコンテキストで、"NULL" は無効です。 SQLSTATE=42703
ということで、とりあえず NULLIF で対応。
db2 => SELECT ID, VALUE, NULLIF(0, 0) FROM TEST
ID VALUE 3
------------ ---------- -----------
1. aaa -
2. あああ -
ほかにいい方法ありますかね?
ちなみに、なんで NULL を選択する必要があるのかというと、INSERT INTO 〜 SELECT 〜 を動的に生成していて、条件分岐で NULL を挿入したいから。
char strFormat[] = "INSERT INTO TEST SELECT ID, VALUE, %s FROM TEST WHERE ID=%d";
sprintf(strSql, strFormat, (intSomeFlag) ? ("0") : ("NULLIF(0, 0)"), intId);
EXEC SQL EXECUTE IMMEDIATE :strSql;
あ。ちなみに CHAR やら VARCHAR の列の場合は NULLIF('', '') とかやって型合わせないとダメっぽい。
2004年 4月 08日 (木曜日)
- Work on miau's blog?
同僚が作ったプログラムで怪しげな処理を見かけたのでちょっと確認。
怪しげな処理っていうのは、DECIMAL のフィールドを比較処理。
(1) VB の ADODB.RecordSet で DECIMAL 型のフィールドを普通に取得
(2) CStr$() で文字列に変換
(3) 文字列の比較
とかやってて。それだと 11 < 2 とか評価されちゃうのでは?と思ったわけで。
とりあえず DB2 で試してみた。
db2 => CREATE TABLE TEST (ID DECIMAL(10))
db2 => select id, cast(id as char(12)) from test
ID 2
------------ ------------
0. 0000000000.
1. 0000000001.
2. 0000000002.
10. 0000000010.
-1. -0000000001.
-2. -0000000002.
6 レコードが選択されました。
あれ。CAST した場合は 0 でパディングされるのね。
ということは、場合によっては文字列に変換後でも問題ないんだろうな。
ま、一応確認。
db2 => select id, cast(id as char(12)) from test order by 1
ID 2
------------ ------------
-2. -0000000002.
-1. -0000000001.
0. 0000000000.
1. 0000000001.
2. 0000000002.
10. 0000000010.
6 レコードが選択されました。
CHAR にキャストした後も↑みたいな大小関係があればいいんだけど・・・
db2 => select id, cast(id as char(12)) from test order by 2
ID 2
------------ ------------
-1. -0000000001.
-2. -0000000002.
0. 0000000000.
1. 0000000001.
2. 0000000002.
10. 0000000010.
6 レコードが選択されました。
やっぱりダメでした。
負数は代償関係が逆になってしまいますね。
この方法での比較は フィールド値 > 0 が保証されている場合のみ有効、と。
で・・・ふと自分の PC に SQLServer がインストールされているのを思い出し、この環境でも試してみた。
1> select id, cast(id as char(10)) from test
2> go
id
------------ ----------
0 0
1 1
2 2
10 10
-1 -1
-2 -2
(6 件処理されました)
おー、これこれ。当初は CAST したらこう(0 埋めされず、左寄せに)なると思ってたんだよね。
ということは・・・。
1> select id, cast(id as char(10)) from test order by 1
2> go
id
------------ ----------
-2 -2
-1 -1
0 0
1 1
2 2
10 10
(6 件処理されました)
これはまぁ当然の結果として・・・
1> select id, cast(id as char(10)) from test order by 2
2> go
id
------------ ----------
0 0
1 1
-1 -1
10 10
2 2
-2 -2
(6 件処理されました)
こうな・・・る・・・あれ?
負号の位置が予想と違う・・・。
・・・まぁ SQLServer の照合順序って結構特殊だし、こんなもんかも。
なんか環境によって色々違いそうなので、結局 VB も試してみることに。
同僚がやってたように、CAST は行わず、CStr$() による変換。
Dim cnn As New ADODB.Connection
Dim rs As New ADODB.Recordset
cnn.Open "dsn=hoge;uid=hoge;pwd=hoge;"
Set rs = cnn.Execute("SELECT ID FROM TEST")
Do While rs.EOF = False
Debug.Print "[" & CStr$(rs.Fields(0)) & "]"
rs.MoveNext
Loop
cnn.Close
超手抜きコード。さて、結果は・・・
[0]
[1]
[2]
[10]
[-1]
[-2]
どうやら左寄せの文字列になってしまう模様。やっぱダメじゃん。
ということで、結論。
INTEGER とかに収まりきらない DECIMAL はできるだけ DB 上で比較しましょう、と。
2004年 4月 09日 (金曜日)
- Work on miau's blog?
スレッド表示にしている場合。
-hoge
Re: hoge
Re[2]: hoge
となっていた場合は Re: hoge や Re[2]: hoge の中も検索してくれるけど、
+hoge
みたいに折りたたまれてると Re: hoge や Re[2]: hoge は検索対象にならないらしい。
対応策としては
・一時的にスレッド表示を解除して検索
・クエリー検索
のどちらか?
オプション設定からは見つからなかったような。
これまで仕事で「そんなメール届いてないっすよ?」みたいな場面が何度かあったけど、実は検索の仕方が悪かったのかも・・・。
2004年 4月 15日 (木曜日)
- Work on miau's blog?
先週末に風邪ひいて連泊記録は1ヶ月ほどで終了。
ちなみに風邪ひいた原因は・・・もちろん無茶な生活で抵抗力が落ちてたんだろうけど、それ以上に会社の空調に問題が。
夕方になるとむぁっと暑くなる→薄着になる→夜中になると次第に冷える(この時は疲れ果てて睡眠中)
というのを繰り返した結果ではないかと。
2004年 4月 20日 (火曜日)
- Work on miau's blog?
どの作業にどれくらいの時間を費やしたか、というのを毎日記録しているのですが。
「えーと・・・昨日は10時出勤で寝たのが4時くらいだから
24 - (10 - 4) - 1(昼休み)= 18
で 17 時間か・・・」
とかなんとか
24h - 睡眠時間
の引き算になってるのがなんか嫌です。
普通に (退社時刻) - (出社時刻) で計算したい。
| 1 |