• ベストアンサー

BCD形式で時刻を!

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

質問者が選んだベストアンサー

  • ベストアンサー
  • leaz024
  • ベストアンサー率75% (398/526)
回答No.4

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
hideto333
質問者

お礼

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

全文を見る
すると、全ての回答が全文表示されます。

その他の回答 (4)

  • leaz024
  • ベストアンサー率75% (398/526)
回答No.5

No.4の回答で、1ヶ所間違ってました。 関数 DecStr2BCD の、     keta1 = str[1] - '1'; という部分は、正しくは     keta1 = str[1] - '0'; です。 確認不足でした。ごめんなさい。

hideto333
質問者

お礼

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

全文を見る
すると、全ての回答が全文表示されます。
  • ShaneOMac
  • ベストアンサー率39% (356/898)
回答No.3

意図からすればビットフィールド構造体を使うのではどうでしょう? struct dateset{   unsigned int year : 11;   unsigned int mon : 4;   unsigned int day : 5;   unsigned int hour : 5;   unsigned int min : 6; }; これで32bit以内に収まっていますし。

hideto333
質問者

お礼

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

全文を見る
すると、全ての回答が全文表示されます。
  • taka_tetsu
  • ベストアンサー率65% (1020/1553)
回答No.2

自分で文字から数値に変換しましょう。 方法は、atoi()等の文字列→数値変換関数を使ったり、 strncpy(buf, ymd, 2); buf[2] = '\0'; u_str[0] = atoi(buf); とか、 足し算を駆使して入れてみたり u_str[0] = (ymd[0] - '0') * 10 + ( ymd[1] - '0' ); なんてのもいいんでは?

hideto333
質問者

お礼

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

全文を見る
すると、全ての回答が全文表示されます。
  • taka_tetsu
  • ベストアンサー率65% (1020/1553)
回答No.1

Cの文字(Character)は、文字コードという数値で文字を あらわします。 で、unsigned charという型は、0から255までの数値を入れることが出来ます。 ということは、2桁の数字なら余裕で入りますよね。

hideto333
質問者

お礼

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

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • c言語 型変換について

    c言語 型変換について 下記のように文字コードは、unsigned int型('B')をunsigned char 型(str[1] ) 格下げする型変換する規則を教えてください。 *質問ソースプログラム: int main(void) { char str[4]; /* 文字列を格納する配列 */ str[0] = 'A'; /* 代入 */ str[1] = 'B'; /* 代入 */ ・・・・・・ printf("size B %u\n",(unsigned)sizeof('B')); printf("size str[1] %u\n",(unsigned)sizeof(str[1])); * 実行結果 size B 4 size str[1] 1

  • C言語:小文字を大文字に変換する関数を作成

    C言語超初心者です。学校の課題で次のような問題が出されました。 ・問題・ 次に挙げる縛りに沿い、以下の関数とメイン関数を作り、処理結果を画面に作成しなさい。 char *tst(char *str) ・strの中の文字列も小文字を大文字に変換し、変換した文字列が格納されているchar *に返す。 ・引数strの中の文字列は受け取った状態で手を加えない。 ・関数内でmalloc関数を使用し、領域を確保して大文字に変換した文字列を格納しreturnでポインタを返す。 ・malloc関数を使用する。 ---------------------------------------------------------------------------------- 大文字に変換するには while(*str != '\0') { if(*str >= 'a' && *str <= 'z') { *str -= 'a'- 'A'; } ++str; } というのは分かったのですがここから何をすするか全く分かりません。初心者なのでなるべく分かりやすく教えてもらえると有難いです。 お願いします。

  • 文字列で表現された時刻の変形

    文字列で表現された時刻の変形 13:23:23のような時刻を秒単位で表したいと思っています。そこで以下のように #include <stdio.h> int main() { char str[9]; int i; int j; scanf("%s",str); for(i=0;i<9;i++) printf("%c\n",str[i]); return 0; } 時刻を文字列の配列に置き換えることまでは考えつきましたが、この先に進めません。 どうしたらよいでしょうか?なお特別なライブラリなどは使用はできません。 よろしくお願い致します。

  • unsigned char SJis[2]からstd::stringに変換

    開発環境は VC++ 2008 Express Edition あるDLLの関数で戻り値としてShiftJISの1文字が格納された unsigned char SJis[2] が返され,これを呼び出し側のプログラムで使っている文字列 std::string str に順に追加していこうと思っています. そこで, unsigned char tmpSJis[3]; tmpSJis[0] = SJis[0]; tmpSJis[1] = SJis[1]; tmpSJis[2] = '\0'; str += std::string(tmpCode); というコードを書いてループさせたのですが, error C2440: '<function-style-cast>' : 'unsigned char *' から 'std::string' に変換できません。 というエラーが出てしまいうまく変換できません. これを解決する方法はありませんか?

  • C言語

    文字列を逆順にするプログラムを考えているのですが分かりません。(例)qwerならrewqです。入力終了は、EOFです。考えたのですが、分かりません。(コンパイルエラーです。)教えてください。宜しくお願いします。#include <stdio.h> unsigned str_length(const char str[]) { unsigned len=0; while (str[len]) len++; return (len); } void put_rstring(const char str[]) { unsigned i = str_length(str): while (i-- >0) putchar(str[i]); } int main(void) { char str[30]; int ch; printf("文字列を入力\n"); /* ----この文字列を入力したあとに、Ctrl+Zを押すと、逆から表示               で反対から、文字列が表示----*/ while (1) { ch=getchar(); if (ch==EOF) break; } printf("逆から表示"); put_rstring(str); puts("です。"); return(0); }

  • C言語の変換する関数について教えてください。

    キーボードからローマ字で入力された名前の英文字を変換する関数を定義し、その関数の機能を確認するプログラムを作成する問題について教えてください。 (1)英小文字であればそれを英大文字に変換する関数 (2)英大文字であればそれを英小文字に変換する関数 (3)英小文字であればそれを英大文字に、英大文字であればそれを英小文字に変換する関数 ただし、キーボードから入力された名前を格納する配列と、変換後の名前を格納する配列を別にする。 また、名前は関数main()内で表示する #include <ctype.h> #include <stdio.h> void name_toupper(char str[]) { unsigned i = 0; while (str[i]) { str[i] = toupper(str[i]); i++; } } void name_tolower(char str[]) { unsigned i = 0; while (str[i]) { str[i] = tolower(str[i]); i++; } } int main(void) { char str[100]; printf("文字"); scanf("%s", str); name_toupper(str); printf("大文字: %s\n", str); name_tolower(str); printf("小文字: %s\n", str); return 0; } 自分で作った上のプログラムではKa siと入力すると(1)ではKA、(2)ではkaと表示されsiが消えてしまいます。原因がよくわかりません。 あと(3)ができないし、ただしを満たしているのかもあいまいです。 文字列の入力の形式:char *gets(char *buffer)を用いればどうにかなるのではと思っていますがどうですか? 説明が長くなって申し訳ありませんが教えてください。 よろしくお願いします。

  • 改行文字を消す方法を教えて頂けませんか。

    こんにちは。 C言語で、改行まで文字列として格納した変数から、改行のみを削除する事は可能でしょうか。構想としては、 char *str = "text改行" ↓ 改行部分を削除 ↓ str == "text" になるのがベストです。 良い方法をご存知であれば教えて頂けないでしょうか。どうぞよろしくお願いします。

  • C++ basic_ostreamの拡張

    UTF-16文字列を扱うためのostreamを用意したいのですが、wcoutの代わりに、unsigned shortを用いたostreamを使いたいと思いました。 そこで、basic_ostreamのクラスのunsigned short型のインスタンスを作ったのですが、以下のエラーが出てしまってコンパイルが出来ませんでした。 「error C2296: '<<' : 無効です。左オペランドには型 'u16ostream (__cde cl *)(void)' が指定されています。」 「error C2297: '<<' : 無効です。右オペランドには型 'u16char *' が指定 されています。」 コンパイラはVC++2008です。 それとついでですが、通常通りwcoutを使う時みたいに、localeを設定する必要はあるのでしょうか? 回答、よろしくお願いします。 /* 以下ソースコード */ #include <iostream> typedef unsigned short u16char; typedef basic_ostream<u16char> u16ostream; int main() { u16ostream ucout(); u16char* str = (u16char*)(L"ああ"); ucout << str << '\n'; return 0; }

  • int型の変数値をバイト列としてコピー

    あるint型の変数に格納されている情報を、バイト列としてコピーする方法で困っています。 変数の入っている領域をそのままコピーしたいので、memcpyを使うかと思うですが、 コピーされた結果を見ると文字列の並びが逆転しているように見えます。 --サンプルコード抜粋 unsigned int i= 12345; unsigned char *c; c = (char *)malloc(sizeof(int)); printf("i_hex=%x\n",i); memcpy(c,(int *)&i,sizeof(int)); 出力結果 i_hex=3039 cの出力結果 3930000000 単純にmemcpyではダメなのでしょうか? 実行環境は、CentOS(32bit)+gccです。よろしくお願いします。

  • unsigned *という宣言について

    char *str = "\x01\x23\x45\x67\x89\xab\xcd\xef"; unsigned *u = (unsigned *)(str + 1); このようなコードをみかけたのですが、 unsigned *uという宣言が理解できません。 これはどのような型として解釈されているのでしょうか? 暗黙でunsigned int* uと解釈されるのでしょうか?

このQ&Aのポイント
  • オンラインゲーム起動中にPCの回線速度が1~8Mbpsに落ちる現象が起きています。PCの方だけで、ps4など他のデバイスでは問題なく動作しています。
  • LANケーブルやモジュラーケーブルを新しくしても改善しないため、auひかりとプロバイダに問い合わせても解決策は得られませんでした。
  • ゲーム起動中に回線速度が低下する原因は不明ですが、一時的な問題かもしれません。解決策としては、ルーターの再起動やゲーム設定の見直しを試すことが挙げられます。
回答を見る