前へ 目次 次へ
文字列操作関数
 

マイコン側でセンサーを用いて計測した値を、 パソコン側に送るということが多いと思いますので、 そのために数値を文字に変換して送信する関数を考えることにします。

今回も、BestTechnologyの、 GCC Developer Liteに付属する sci.cの関数を利用することにします。

sci.cには、

  • long->16進数文字列変換関数 IntToHex
  • long->10進数文字列変換 IntToDec
  • long->2進数文字列変換 IntToBin
という関数が用意されています。 これらを見ていきましょう。

 
long->16進数文字列変換関数 IntToHex
 
/*-----------------------------------------------*/
/* 文字列操作                                    */
/*-----------------------------------------------*/

// long->16進数文字列変換

char *IntToHex (long v, _BYTE len, char *s)
{
  char  hex[] = "0123456789ABCDEF";  // 16進数文字列リスト

  s[len--] = 0;
  do {
    s[len] = hex[v & 0xf];
    v >>= 4;
  } while (len--);
  return s;
}
 

char *IntToHex (long v, _BYTE len, char *s)

long型を16進数の文字列に変換する関数IntToHexは、 引数に

  • long型
  • _BYTE型
  • char型のポインタ
を取ります。

long型は変換したい数値を渡します。

_BYTE型はunsigned charの別名として定義されています。 これは、変換後の文字列の長さを与えます(最大3桁なら3)。

char型のポインタは結果の16進数文字列を代入するために渡します。 たとえば、IntToHexを呼び出す前に配列を定義して、 その配列名を渡してやれば良いことになります。

関数の前のchar *は、この関数がchar型のポインタ(変換結果の16進数文字列の格納場所)を返すという意味です。 実際、後でreturn sという行がでてきます。


char hex[] = "0123456789ABCDEF"

16進数で使う文字のリストを配列として定義しています。 hex[0]に0が、hex[1]に1がというふうに、配列の要素番号と値が対応していることが重要です。

ここでは配列の要素数を明示していませんが、 この場合には最後にナル文字が入るので、 char hex[17]のように指定することもできます。


s[len--] = 0;

これは、

s[len]=0;
len--;
と書くこともできます。

文字列を表示するのには、配列の最後にナル文字や0を入れておくと便利です。

s[len]=0;
は、このための操作です。

len--;
はlenの値を1減らしています。


s[len] = hex[v & 0xf];

vの下位4ビットを論理積で取りだし、 対応する数字を配列sに代入しています。

例えば、vの最下位4ビットが1011の場合で考えてみましょう (8ビット分だけ書いてみました)。

8ビット目7ビット目6ビット目5ビット目 1011

vの最下位4ビットと0vfとの論理積を取るということは、 赤く示した最下位4ビットをそのまま取り出すことになります。 つまり、この場合結果は、

(v & 0xf)=1011=7

です。このことからhex[v & 0xf]は今の場合hex[7]となり、 ここには文字7が入っているというわけです。


v >>= 4;

vを4ビットシフトします。 上の例では、

12ビット目11ビット目10ビット目9ビット目 8ビット目7ビット目6ビット目5ビット目

のようになります。


while (len--);

lenを1ずつ減らしていき、0になるまで操作を繰り返します。


return s;

変換した文字列は、配列sに格納されているので、 その場所を返しています。

 
long->2進数文字列変換 IntToBin
 

2進数への変換も16進数への変換と同様に行うことができます。

// long->2進数文字列変換

char *IntToBin (long v, _BYTE len, char *s)
{
  char bin[] = "01"; // 2進数文字列リスト

  s[len--] = 0;
  do {
    s[len] = bin[v % 2];
    v = v / 2;
  } while (len--);
  return s;
}

v % 2

これは、vを2で割ったあまりを求めています。


v / 2

これは、vを2で割った値を求めています。 ただし、答えは整数値で、余りは切り捨てられます。 例えば、vが5ならばv/2は2です。

 
long->10進数文字列変換関数 IntToDec
 
/*-----------------------------------------------*/
/* 文字列操作                                    */
/*-----------------------------------------------*/

// long->10進数文字列変換
char *IntToDec (long v, _BYTE len, char *s)
{
  int   i;
  int   f;

  f = v < 0;
  v = labs(v);

  for (i = 0; i < len; i++) s[i] = ' ';
  s[len--] = 0;

  do {
    if (v < 10) break;
    s[len] = (v % 10) + '0';
    v /= 10;
  } while (len--);
  s[len--] = v + '0';
  if (f) s[len] = '-';
  return s;
}

f = v < 0

変数fは符号(プラスかマイナスか)を格納するための変数です。 v < 0は、vが0より小さければ真(正の値、通常1)、 0以上ならば偽(0)になります。 したがって、vが負ならばfには1が、 正ならば0が入ることになります。


v = labs(v)

labsは、longの絶対値を計算します。


for (i = 0; i < len; i++) s[i] = ' '

配列sの全てにスペースを入れています。


if (v < 10) break

vの値が10より小さくなったら、ループを出ます。


s[len] = (v % 10) + '0'

'0'は、文字0のアスキーコードを意味しています。 v % 10はvを10で割った余りですから、 (v % 10) + '0'はvを10で割った余りに対応するアスキーコードになります。 これは、0から9までのアスキーコードが連続していることを利用しています。


if (f) s[len] = '-'

fが1の場合、vは負の値だったということですから、 配列の最初に文字-を入れます。

 
やってみよう
 
  • 文字列操作関数の使い方をサンプルを作って、解説してください。
 
2003/06/02(Mon)
AKI-H8/3664 QFP版のトップページへ
トップページへ
SEO [PR] 爆速!無料ブログ 無料ホームページ開設 無料ライブ放送