MW211 EXIT

devlog
設計/多階層のステータス管理
2013年01月15日
┌───┐
│○┬○│○…正常、×…異常、?…不明
│  └○│
└───┘
二階層以上でそれぞれステータスを持つ場合、上位ステータスが異常となった場合
下位ステータスにどのように反映させるか、以下の三つのパターンがある。
            ┌───┬───┬───┐
            │  A  │  B  │  C  │
┌───┐  ┌───┬───┬───┐  ┌───┐
│○┬○│  │×┬○│×┬×│×┬?│  │○┬○│
│  └○│  │  └○│  └×│  └?│  │  └○│
├───┤  ├───┼───┼───┤  ├───┤
│○┬×│  │×┬×│×┬×│×┬?│  │○┬×│
│  └○│  │  └○│  └×│  └?│  │  └○│
├───┤→├───┼───┼───┤→├───┤
│○┬○│  │×┬○│×┬×│×┬?│  │○┬○│
│  └×│  │  └×│  └×│  └?│  │  └×│
├───┤  ├───┼───┼───┤  ├───┤
│○┬×│  │×┬×│×┬×│×┬?│  │○┬×│
│  └×│  │  └×│  └×│  └?│  │  └×│
└───┘  └───┴───┴───┘  └───┘
  A:下位に反映させない      下位ステータス(正常)の遷移としては、○→○→○
  B:下位にすべて反映させる  下位ステータス(正常)の遷移としては、○→×→○
  C:下位をすべて不明とする  下位ステータス(正常)の遷移としては、○→?→○

外部向け(画面表示等)と内部管理で、分けるというのも一つの手だ。
たいてい、内部管理ではBを採用しづらい。
更新の量が莫大になり、差分による処理(履歴追加)なども莫大になりかねないからだ。
なので、内部的にはAで、外部向けとしてBもしくはCとするのが一般的か。
その間は、外部的には下位ステータスは×か?なのだから、
「○→×」的な遷移が発生しては辻褄が合わなくなることに注意だ。
分類:設計
C言語/可変引数関数
2013年01月14日
「f("%d", 1);」でも「f("%d-%d", 1, 2);」でも大丈夫な
可変引数をもつ関数の作り方。
┌──────────────────────────────────────┐
│#include <stdarg.h>                                                         │
│void f(const char *format, ...) {                                           │
│    va_list ap;                                                             │
│    char    buff[1024];                                                     │
│                                                                            │
│    va_start(ap, format);                                                   │
│    if (vsnprintf(buff, sizeof(buff), format, ap) < 0) {                    │
│        buff[0] = '\0';                                                     │
│    }                                                                       │
│    va_end(ap);                                                             │
│                                                                            │
│    printf("%s", buff);                                                     │
│}                                                                           │
└──────────────────────────────────────┘
「va_start()」から「va_end()」の区間において
「vsnprintf()」(他に「vsprintf()、vasprintf()」があるらしい)で、
文字列を統合して取得して、後はそれを使えばいいらしい。

詳しいことは追々。。。
分類:C/C++
C言語/文字列のコピー総集編
2013年01月13日
文字列の場合は、代入式は使えない。ということで以下はダメ。
┌──────────────────────────────────────┐
│出力先 = 入力元;                                                            │
└──────────────────────────────────────┘
「&出力先 = 入力元;」とか「&出力先 = &入力元;」とか足掻いてみてもダメ。
構造体の場合は代入式が使えるので、よく勘違いしがちだ。

では、どうするか?

まず、最凶なのは、「memcpy()」。これならなんでもできる。
┌──────────────────────────────────────┐
│memcpy(出力先, 入力元, sizeof(出力先));                                     │
└──────────────────────────────────────┘
ただし、末尾の「\0」を保証してくれないので、入力元の文字数が多いとアウト。
んな訳で、以下のような小細工を施したりする。
┌──────────────────────────────────────┐
│memset(出力先, 0 sizeof(出力先));                                           │
│memcpy(出力先, 入力元, sizeof(出力先) - 1);                                 │
└──────────────────────────────────────┘
まあ、なんつーか、文字をメモリとして機械的扱う感じだ。

じゃ次は、せっかくだから文字として扱ってやろうという話。
代表的なのはこれ、「strcpy()」。
┌──────────────────────────────────────┐
│strcpy(出力先, 入力元);                                                     │
└──────────────────────────────────────┘
こいつは、入力元の「\0」までを強制的にコピーしてしまうので、
扱いにはかなり慎重にならなければなるまい(メモリ侵犯しやすい)。
あらかじめ、出力先と入力元のサイズの関係が保証される時に使う感じか。
ま、予防策を講じるなら以下のような感じか。オールオアナッシングだけど。
┌──────────────────────────────────────┐
│if (strlen(入力元) < sizeof(出力先)) {                                      │
│    strcpy(出力先, 入力元);                                                 │
│}                                                                           │
└──────────────────────────────────────┘

続いて、進化形(?)の「strncpy()」。
┌──────────────────────────────────────┐
│strncpy(出力先, 入力元, sizeof(出力先));                                    │
└──────────────────────────────────────┘
サイズを指定できて、しかも入力元が短い場合、残りを「\0」で埋めてくれる。
ってことで、「strcpy()」よりも遅いらしい。
そしてなによりもこいつも末尾の「\0」を保証してくれない。
前出の「memcpy()」とほとんど同じやん。
やっぱり以下となってしまうのか?(これじゃあんまり使い道ないね)
┌──────────────────────────────────────┐
│memset(出力先, 0 sizeof(出力先));                                           │
│strncpy(出力先, 入力元, sizeof(出力先) - 1);                                │
└──────────────────────────────────────┘

そして、別分野から参入の「snprintf()」。これは使える。
┌──────────────────────────────────────┐
│snprintf(出力先, sizeof(出力先), "%s", 入力元);                             │
└──────────────────────────────────────┘
これだと「出力先≦入力元」でも、最後の末尾に「\0」を押し込めてくれる。
ま、その分最後の一文字は犠牲になるのだが、
「\0」がなくて例外になるよりはかなりまし。
多少速度が犠牲になるらしいが、「memset()」とか使って実装するなら、
一行で済むこいつにしてしまった方がいいのかも。

ま、これらをコングロマリット(?)してできた案が以下。
┌──────────────────────────────────────┐
│if (strlen(入力元) < sizeof(出力先)) {                                      │
│    strcpy(出力先, 入力元);                                                 │
│} else {                                                                    │
│    snprintf(出力先, sizeof(出力先), "%s", 入力元);                         │
│}                                                                           │
└──────────────────────────────────────┘
ま、速度が気になるなら一考かも。
分類:C/C++
設計/論理組合せ
2013年01月12日
真と偽を組み合わせて、16通りの結果を求める式は以下の通り。
─────────┬─────────┬─────────┬─────────
(×&&×)&&×  →×│(×≠×)&&!× →×│×&&×        →×│×||(×&&×)  →×
(×&&○)&&×  →×│(×≠○)&&!○ →×│×&&○        →×│×||(○&&×)  →×
(○&&×)&&×  →×│(○≠×)&&!× →○│○&&×        →×│○||(×&&×)  →○
(○&&○)&&×  →×│(○≠○)&&!○ →×│○&&○        →○│○||(○&&×)  →○
─────────┼─────────┼─────────┼─────────
!(×||×)     →○│(×&&×)||!× →○│×=×        →○│×||(×=×)  →○
!(×||○)     →×│(×&&×)||!○ →×│×=○        →×│×||(×=○)  →×
!(○||×)     →×│(○&&×)||!× →○│○=×        →×│○||(○=×)  →○
!(○||○)     →×│(○&&×)||!○ →×│○=○        →○│○||(○=○)  →○
─────────┼─────────┼─────────┼─────────
!×&&(×≠×) →×│×≠×        →×│(×&&×)||×  →×│×||×        →×
!×&&(×≠○) →○│×≠○        →○│(×&&×)||○  →○│×||○        →○
!○&&(○≠×) →×│○≠×        →○│(○&&×)||×  →×│○||×        →○
!○&&(○≠○) →×│○≠○        →×│(○&&×)||○  →○│○||○        →○
─────────┼─────────┼─────────┼─────────
!×||(×&&×) →○│!(×&&×)     →○│(×=×)||×  →○│(×&&×)||○  →○
!×||(○&&×) →○│!(×&&○)     →○│(×=○)||○  →○│(×&&○)||○  →○
!○||(×&&×) →×│!(○&&×)     →○│(○=×)||×  →×│(○&&×)||○  →○
!○||(○&&×) →×│!(○&&○)     →×│(○=○)||○  →○│(○&&○)||○  →○
─────────┴─────────┴─────────┴─────────
  ○:真、×:偽、=:等号、≠:不等号、&&:論理積、||:論理和、!:否定

他にも方法がありそうだけど。。。
分類:設計
C言語/ビット演算子と論理演算子
2013年01月11日
ビット演算子と論理演算子の組み合わせ対比表って以下みたいなのでいいのかな?
┌─────────┬─────────┬─────────┐
│                  │   ビット演算子   │    論理演算子    │
├─────────┼─────────┼─────────┤
│論理積            │  ○ & ○   → ○ │ (偽 && 偽) → 偽 │
│                  │  ○ & ●   → ○ │ (偽 && 真) → 偽 │
│                  │  ● & ○   → ○ │ (真 && 偽) → 偽 │
│                  │  ● & ●   → ● │ (真 && 真) → 真 │
├─────────┼─────────┼─────────┤
│論理和            │  ○ | ○   → ○ │ (偽 || 偽) → 偽 │
│                  │  ○ | ●   → ● │ (偽 || 真) → 真 │
│                  │  ● | ○   → ● │ (真 || 偽) → 真 │
│                  │  ● | ●   → ● │ (真 || 真) → 真 │
├─────────┼─────────┼─────────┤
│排他的論理和      │  ○ ^ ○   → ○ │ (偽 != 偽) → 偽 │
│                  │  ○ ^ ●   → ● │ (偽 != 真) → 真 │
│                  │  ● ^ ○   → ● │ (真 != 偽) → 真 │
│                  │  ● ^ ●   → ○ │ (真 != 真) → 偽 │
├─────────┼─────────┼─────────┤
│論理積の否定      │~(○ & ○)  → ● │!(偽 && 偽) → 真 │
│                  │~(○ & ●)  → ● │!(偽 && 真) → 真 │
│                  │~(● & ○)  → ● │!(真 && 偽) → 真 │
│                  │~(● & ●)  → ○ │!(真 && 真) → 偽 │
├─────────┼─────────┼─────────┤
│論理和の否定      │~(○ | ○)  → ● │!(偽 || 偽) → 真 │
│                  │~(○ | ●)  → ○ │!(偽 || 真) → 偽 │
│                  │~(● | ○)  → ○ │!(真 || 偽) → 偽 │
│                  │~(● | ●)  → ○ │!(真 || 真) → 偽 │
├─────────┼─────────┼─────────┤
│排他的論理和の否定│~(○ ^ ○)  → ● │ (偽 == 偽) → 真 │
│                  │~(○ ^ ●)  → ○ │ (偽 == 真) → 偽 │
│                  │~(● ^ ○)  → ○ │ (真 == 偽) → 偽 │
│                  │~(● ^ ●)  → ● │ (真 == 真) → 真 │
└─────────┴─────────┴─────────┘
分類:C/C++
C言語/全角判定
2013年01月10日
Shift_JISの場合、1バイト目(上位バイト)が
「0x81~0x9F、0xE0~0xFC」であれば全角文字とみてよい。
分類:C/C++
C言語/文字チェック
2013年01月09日
PHPとかJavaScriptとかの今風の言語だと、正規表現で一発で判定できたりするのだが、
C言語だと地道に一文字ずつチェックしていくしか他ない。

一文字チェック関数をまとめた。
┌─────┬────────────────────────────────┐
│isalnum() │英数字(0~9[0x30~0x39]、A~Z[0x41~0x5A]、a~z[0x61~0x7A])    │
├─────┼────────────────────────────────┤
│isalpha() │英字(A~Z[0x41~0x5A]、a~z[0x61~0x7A])                        │
├─────┼────────────────────────────────┤
│isdigit() │数字(0~9[0x30~0x39])                                          │
├─────┼────────────────────────────────┤
│islower() │英小文字(a~z[0x61~0x7A])                                      │
├─────┼────────────────────────────────┤
│isupper() │英大文字(A~Z[0x41~0x5A])                                      │
├─────┼────────────────────────────────┤
│isxdigit()│16進(0~9[0x30~0x39]、A~F[0x41~0x46]、a~f[0x61~0x66])      │
└─────┴────────────────────────────────┘
┌─────┬────────────────────────────────┐
│isascii() │ASCII文字(0x00~0x7F)                                           │
├─────┼────────────────────────────────┤
│iscntrl() │制御文字(0x00~0x1F、0x7F)                                      │
├─────┼────────────────────────────────┤
│isgraph() │表示可能文字(0x21~0x7E)                                        │
├─────┼────────────────────────────────┤
│isprint() │印字可能文字(0x20~0x7E)                                        │
├─────┼────────────────────────────────┤
│ispunct() │区切文字(0x00~0x1F、0x20、0x7F)                                │
├─────┼────────────────────────────────┤
│isspace() │空白文字                                                        │
│          │→0x09(\t)、0x0A(\n)、0x0B(\v)、0x0C(\f)、0x0D(\r)、0x20( )     │
└─────┴────────────────────────────────┘
判定が真の時に0以外を返却し、偽の時は0を返却するというややこしい仕様だが、
これは速度向上のためらしい。

とにかく、該当しなかったら0ということでエラーにしていきゃいいと覚えるか。
といっても複合条件とか絡んでくると0以外で判定する場面は多々ありそう。
分類:C/C++
jQuery/表示・非表示と対象以外の指定
2013年01月08日
例えば、class属性が「xyz」の列(tdタグ)を表示・非表示させる場合は、
以下のような感じで、toggle()メソッドを使う。
┌──────────────────────────────────────┐
│$('td.xyz').toggle();                                                       │
└──────────────────────────────────────┘

では、その列以外を対象としたい場合には?

こんな感じ。
┌──────────────────────────────────────┐
│$('td:not(.xyz)').toggle();                                                 │
└──────────────────────────────────────┘
「:not()」の使い方をマスタすればいろいろ使えそうだ。
分類:jQuery
JavaScript/配列合体
2013年01月07日
配列二つを合体させる方法。
┌──────────────────────────────────────┐
│var 新配列 = 旧配列壱.concat(旧配列弐);                                     │
└──────────────────────────────────────┘
これだと「旧配列壱」の後ろに「旧配列弐」が追加される。
分類:JavaScript
JavaScript/split()メソッド
2013年01月06日
┌──────────────────────────────────────┐
│var 配列 = 文字列.split(',');                                               │
└──────────────────────────────────────┘
split()メソッドは、指定した区切文字で配列に分割してくれる便利なメソッドだ。

で、区切文字を複数指定したい場合は?「,」と「 」とか。
┌──────────────────────────────────────┐
│var 配列 = 文字列.split(/,| /);                                             │
└──────────────────────────────────────┘
こんな感じで正規表現を使う。

ちなみに第二引数で配列の上限数を指定できる。
┌──────────────────────────────────────┐
│var 配列 = 文字列.split(',', 3);                                            │
└──────────────────────────────────────┘
これだと分割されて四つ目以降の配列となる予定だったものは切り捨てられる。
あらかじめ、分割数が想定される場合には使えるかも。
分類:JavaScript
前へ 1 … 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 … 156 次へ