バグ:文字列の変換

Posted: 2012年10月29日

文字列の変換する際によく書いてしまうバグを紹介します。

プログラムプログラム:

 #include  <stdio.h>
 #include <stdlib.h>

 int main(int argc, char *argv[])
 {
    CString strSrc = _T("12345");
    int nData = 0;

    // 変換
    nData = _ttoi(strSrc);
    if (nData == 0) {
        // エラー
        return 1;
    }

    return 0;
 }

このプログラムにどのような文字列変換関連のバグがあると思いますか?

  • エラーになった場合0が返されるが
     それが正しいのか、誤りかが不明
  • 10進数でしか変換ができない

改善版プログラム改善版プログラム:

 #include  <stdio.h>
 #include <errno.h>
 #include <stdlib.h>

 int main(int argc, char *argv[])
 {
    CString strSrc = _T("12345");
    int nData = 0;

    TCHAR *pEnd = NULL;
    // 変換
    nData = _tcstol(strSrc, &pEnd, 10);
    if (*pEnd == NULL) {
        // エラー(変換エラー)
        return 1;
    }
    if (errno == ERANGE) {
        // エラー(オーバフロー、アンダーフロー)
        return 1;
    }
    return 0;
 }

解説解説:

_tcstolは整数に変換してくれる関数です。
プログラム中では、CStringの変換を行なっていますがもちろん
char*,wchar*やSTLのstringなどの変換も可能です。

pEndには変換が成功したアドレスを設定してくれます。
つまり、文字列の最後(NULL)かどうかをチェックすることでエラーが無いことを確認しています。
_tcstolの第3引数(10)は10進数で変換を表しています。
16にした場合は、16進数の変換を行うことも可能です。
※16進の場合は、「0xFFF」ではなく「FFF」を指定する
 0xが存在すると変換エラーになるため事前に取り除く必要があります。

_ttoi(strSrc)は、_tcstol(strSrc, NULL, 10)と同等の動作であるため
今まで使用していた_ttoiを置換すれば問題なく同様の動作になります。

数値型によりそれぞれ関数名が異なるため以下に一覧

atoi系列 strtol系列
int atoi, wtoi, _ttoi strtol, wcstol, _tcstol
long atol, wtol, _ttol strtol, wcstol, _tcstol
long long atoi64, wtoi64, _ttoi64 _strtoi64, _wcstoi64, _tcstoi64
double atof, wtof, _ttof strtod, wcstod, _tcstod

※マルチバイト用(char), ユニコード用(wchar_t), テンプレート(切り替え)

詳しい変換処理の一覧はこちらを参照してください
http://msdn.microsoft.com/ja-jp/library/0heszx3w.aspx

カテゴリー: バグ, プログラム | タグ: , , , | 2 コメント »

2 コメント on “バグ:文字列の変換”

  1. 1. 投稿者: ずんが  日付 : 2015年03月13日 09時49分:

    _tcstol()の第2引数はTCHAR **です。pEndではTCHAR *です。

  2. 2. 投稿者: todesmarz  日付 : 2015年03月13日 14時53分:

    仰るとおりです。
    &pEndでした
    指摘ありがとうございます。


コメント