unsigned intを文字列に変換するプログラム

先日、とある掲示板で「Cでunsigned int の値を10進数の文字列に変換する関数を作成しなさい」という課題が出ていたので作ってみました。なかなかよくできたのでここに記録します。

#include <stdio.h>
#define BUFFER_SIZE 32

char *ultos_recur(char *buf, unsigned int num, char *bufend)
{
  if (num >= 10) {
    buf = ultos_recur(buf, num / 10, bufend);
  }
  if (buf != bufend) {
    *buf++ = num % 10 + '0';
  }
  return buf;
}

void ultos(char *buf, unsigned int num, int buffer_size)
{
  *ultos_recur(buf, num, buf + buffer_size - 1) = '\0';
}

int main()
{
  char buf[BUFFER_SIZE];
  unsigned int num;
  
  num = 0;
  ultos(buf, num, BUFFER_SIZE);
  printf("[%u] -> [%s]\n\n", num, buf);
  
  num = 1000;
  ultos(buf, num, BUFFER_SIZE);
  printf("[%u] -> [%s]\n\n", num, buf);
  
  num = 1234567890;
  ultos(buf, num, BUFFER_SIZE);
  printf("[%u] -> [%s]\n\n", num, buf);
  
  num = (unsigned int)-1;
  ultos(buf, num, BUFFER_SIZE);
  printf("[%u] -> [%s]\n\n", num, buf);
  
  num = (unsigned int)-1;
  ultos(buf, num, 4);
  printf("[%u] -> [%s]\n\n", num, buf);
  
  return 0;
}

中身を簡単に説明します。

関数ultosは指定されたunsigned intの値を文字列に変換し、指定されたバッファに格納します。第3引数はバッファサイズです。内部ではultos_recurを呼び出し、バッファに書き込まれた文字列の最後に終端文字('\0')を格納しています。

関数ultos_recurは再帰を使ってunsigned intを文字列に変換しています。

mainではいくつかの数を引数としてultosを呼び出し、元の値と変換された文字列を並べて表示しています。最後から2番目に表示されるのは“-1”をunsigned int形式にしたもので、おそらくunsigned intの最大値です。最後のものは、最後から2番目のものをバッファサイズ4で文字列に変換しています。バッファには終端文字('\0')が含まれるため、実際に表示されるのは3文字になっています。

実行結果は次のようになります。(codepadの出力)

[0] -> [0]

[1000] -> [1000]

[1234567890] -> [1234567890]

[4294967295] -> [4294967295]

[4294967295] -> [429]

変換のコア部分(ultos_recur)は再帰できれいにまとまりました。久しぶりに満足できるプログラムが書けたと思います。自己満足ですが(笑)