アプリ版:「スタンプのみでお礼する」機能のリリースについて

「時刻文字列・YYYYMMDDhhmmを
unsigned char u_str[5]というような変数に、
BCD形式でYYMMDDhhmm(5バイト)で格納したい」
というのがやりたいことです。
BCD形式の意味はわかったんですが、
1バイトにどうやって2文字分を入れるのかわかりません。
また、できたら戻し方のアドバイスもお願いします。
(BCD形式5バイト→YYYYMMDDhhmm形式12バイト)
質問を見てわかるように初心者です。
何卒、アドバイスよろしくお願い致します!

A 回答 (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にする必要があります。境目はプログラムの用途に応じて変えるとよいでしょう。

多少難しいと思いますので、分からないところは補足してください。

参考URL:http://www5c.biglobe.ne.jp/~ecb/assembler/3_1.html
    • good
    • 0
この回答へのお礼

ご回答ご丁寧にありがとうございます。
まさに、こうゆうことを知りたかった!という感じです。
参考にがんばってみます。
ありがとうございました。

お礼日時:2002/06/11 15:40

No.4の回答で、1ヶ所間違ってました。


関数 DecStr2BCD の、
    keta1 = str[1] - '1';
という部分は、正しくは
    keta1 = str[1] - '0';
です。
確認不足でした。ごめんなさい。
    • good
    • 0
この回答へのお礼

わざわざご丁寧にありがとうございました。
ほんとに参考になりました。

お礼日時:2002/06/11 15:41

意図からすればビットフィールド構造体を使うのではどうでしょう?



struct dateset{
  unsigned int year : 11;
  unsigned int mon : 4;
  unsigned int day : 5;
  unsigned int hour : 5;
  unsigned int min : 6;
};

これで32bit以内に収まっていますし。
    • good
    • 0
この回答へのお礼

こんな方法もあるんですね。
参考にさせて頂きます。
ご回答ありがとうございました。

お礼日時:2002/06/11 15:41

自分で文字から数値に変換しましょう。



方法は、atoi()等の文字列→数値変換関数を使ったり、

strncpy(buf, ymd, 2);
buf[2] = '\0';

u_str[0] = atoi(buf);

とか、


足し算を駆使して入れてみたり
u_str[0] = (ymd[0] - '0') * 10 + ( ymd[1] - '0' );

なんてのもいいんでは?
    • good
    • 0
この回答へのお礼

再びのご回答ありがとうございます。
どうやら、少し難しく考えすぎていたようです。

お礼日時:2002/06/11 15:38

Cの文字(Character)は、文字コードという数値で文字を


あらわします。

で、unsigned charという型は、0から255までの数値を入れることが出来ます。

ということは、2桁の数字なら余裕で入りますよね。
    • good
    • 0
この回答へのお礼

早速のご回答ありがとうございます。
おっしゃってることはわかるんですが。。
具体的に教えて頂けると助かります。
例えば、下記のような場合なら
どうすれば、変数sに変数strの値が入るのでしょうか?
char str[2] = "10";
unsigned char s;

お礼日時:2002/06/10 19:57

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!