- ベストアンサー
BCD形式で時刻を!
「時刻文字列・YYYYMMDDhhmmを unsigned char u_str[5]というような変数に、 BCD形式でYYMMDDhhmm(5バイト)で格納したい」 というのがやりたいことです。 BCD形式の意味はわかったんですが、 1バイトにどうやって2文字分を入れるのかわかりません。 また、できたら戻し方のアドバイスもお願いします。 (BCD形式5バイト→YYYYMMDDhhmm形式12バイト) 質問を見てわかるように初心者です。 何卒、アドバイスよろしくお願い致します!
- みんなの回答 (5)
- 専門家の回答
質問者が選んだベストアンサー
BCD形式というのは(大雑把に言えば)、10進数の各桁をバラバラに2進数化して、くっつけ直したものです。 例えば、27(10進)という値は、各桁が 2(10進) → 0010(2進の2) 7(10進) → 0111(2進の7) なので、BCD形式では 00100111(2進) となります。(10進で表すと、39) つまり、1バイトを上下4ビットずつに分けて、それぞれに10進数の各桁を格納するわけです。 では、「どうやって上下4ビットに値を入れるか」についてですが、これは「シフト」を使えば簡単にできます。 (10の桁を上位に、1の桁を下位に格納するとします。) 1.それぞれの桁に該当する「数字」を「数値」に変換します。 数字から数値への変換ですが、文字列の中の1文字の変換なので、文字コード操作('0' を引く)で十分でしょう。 2.10の桁は4ビット分上位へずらす必要があるので、4ビット分左へシフトします。 3.その値を1の桁の値とくっつけます。 これは足し算かビット論理和で行えます。(普通はビット論理和を使います。) これをコード化するとこんな感じ。 int DecStr2BCD(const char *str) { int keta10, keta1; keta10 = str[0] - '0'; keta1 = str[1] - '1'; keta10 <<= 4; return keta10 | keta1; } ※これは2バイトの数字列→BCDコードの下請け関数なので、日時文字列から必要なアドレスを取り出し、ループしながら DecStr2BCD() を呼び出す関数を作成する必要があります。 また、BCDコードから数字列への逆変換ですが、これは次のような手順になります。 1.1バイトのBCDコードを、上下4ビットに分解して2つの値を取り出す。 4ビットずつの分解には、シフト以外にマスクという手法を用います。 マスクとは、ビット論理積を使い、特定のビットを0にしてしまう方法です。 2.それぞれの値を文字列して、バッファに書き込む。 コード化するとこんな感じ。 void BCD2DecStr(char *str, int bcd) { int keta10, keta1; keta10 = bcd >> 4; keta1 = bcd & 15; /* 15 は 00001111 */ str[0] = keta10 + '0'; str[1] = keta1 + '0'; } ※同様に下請け関数なので、5バイトのBCDコードを1バイトずつ、その結果を書き込む日時文字列内のアドレスと共に BCD2DecStr に渡す関数を作る必要があります。 また年については、00~は20xxにし、~99は19xxにする必要があります。境目はプログラムの用途に応じて変えるとよいでしょう。 多少難しいと思いますので、分からないところは補足してください。
その他の回答 (4)
- leaz024
- ベストアンサー率75% (398/526)
No.4の回答で、1ヶ所間違ってました。 関数 DecStr2BCD の、 keta1 = str[1] - '1'; という部分は、正しくは keta1 = str[1] - '0'; です。 確認不足でした。ごめんなさい。
お礼
わざわざご丁寧にありがとうございました。 ほんとに参考になりました。
- ShaneOMac
- ベストアンサー率39% (356/898)
意図からすればビットフィールド構造体を使うのではどうでしょう? struct dateset{ unsigned int year : 11; unsigned int mon : 4; unsigned int day : 5; unsigned int hour : 5; unsigned int min : 6; }; これで32bit以内に収まっていますし。
お礼
こんな方法もあるんですね。 参考にさせて頂きます。 ご回答ありがとうございました。
- taka_tetsu
- ベストアンサー率65% (1020/1553)
自分で文字から数値に変換しましょう。 方法は、atoi()等の文字列→数値変換関数を使ったり、 strncpy(buf, ymd, 2); buf[2] = '\0'; u_str[0] = atoi(buf); とか、 足し算を駆使して入れてみたり u_str[0] = (ymd[0] - '0') * 10 + ( ymd[1] - '0' ); なんてのもいいんでは?
お礼
再びのご回答ありがとうございます。 どうやら、少し難しく考えすぎていたようです。
- taka_tetsu
- ベストアンサー率65% (1020/1553)
Cの文字(Character)は、文字コードという数値で文字を あらわします。 で、unsigned charという型は、0から255までの数値を入れることが出来ます。 ということは、2桁の数字なら余裕で入りますよね。
お礼
早速のご回答ありがとうございます。 おっしゃってることはわかるんですが。。 具体的に教えて頂けると助かります。 例えば、下記のような場合なら どうすれば、変数sに変数strの値が入るのでしょうか? char str[2] = "10"; unsigned char s;
お礼
ご回答ご丁寧にありがとうございます。 まさに、こうゆうことを知りたかった!という感じです。 参考にがんばってみます。 ありがとうございました。