0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

stox系(C++11)が使えない時の文字列→数値変換

Posted at

はじめに

stox系(C++11)が使えない環境の場合にatoi/atofの強化版を自作してみた記事になります

文字列→数値変換の基本

atoi/atofでは数値以外の文字列が入った場合、エラーにならず0を返すという仕様になっています

下記のように記述して出力してみました

void OutputLog( const std::string& str )
{
	try
	{
		std::cout << str << "をatoiで変換:" << atoi( str.c_str() ) << std::endl;
	}
	catch( std::exception e )
	{
		std::cout << str << "の変換に失敗!!" << std::endl;
	}
	try
	{
		std::cout << str << "をatofで変換:" << atof( str.c_str() ) << std::endl;
	}
	catch( std::exception e )
	{
		std::cout << str << "の変換に失敗!!" << std::endl;
	}

	std::cout << std::endl;
}

int main()
{
	OutputLog( "" );
	OutputLog( "0aaa" );
	OutputLog( "00aaa" );
	OutputLog( "-00aaa" );
	OutputLog( "-0aaa" );
	OutputLog( "009" );
	OutputLog( "    12345" );
	OutputLog( "  12345" );    // 全角スペース
	OutputLog( " \t  \n \r 12345" );
	OutputLog( " \t  \n  \r 0" );
	OutputLog( "-.32f" );
	OutputLog( "あああああ" );
	OutputLog( "-あああああ" );
	OutputLog( "01弐参" );
	OutputLog( "零壱23" );
	return 0;
}

出力結果↓

をatoiで変換:0
をatofで変換:0

0aaaをatoiで変換:0
0aaaをatofで変換:0

00aaaをatoiで変換:0
00aaaをatofで変換:0

-00aaaをatoiで変換:0
-00aaaをatofで変換:-0

-0aaaをatoiで変換:0
-0aaaをatofで変換:-0

009をatoiで変換:9
009をatofで変換:9

    12345をatoiで変換:12345
    12345をatofで変換:12345

  12345をatoiで変換:0
  12345をatofで変換:0


 12345をatoiで変換:12345

 12345をatofで変換:12345


 0をatoiで変換:0

 0をatofで変換:0

-.32fをatoiで変換:0
-.32fをatofで変換:-0.32

あああああをatoiで変換:0
あああああをatofで変換:0

-あああああをatoiで変換:0
-あああああをatofで変換:0

01弐参をatoiで変換:1
01弐参をatofで変換:1

零壱23をatoiで変換:0
零壱23をatofで変換:0

エラーにはならず、0が返ってきてしまいます
これをエラーにする判定処理を入れて作ってみました

判定処理を作ってみた

// 文字列の置換
void ReplaceStart( std::string& inoutStr, const std::string& oldStr, const std::string& newStr )
{
	size_t str_pos = 0;
	std::string::size_type  pos( GetFirstPos( inoutStr, oldStr ) );

	while( str_pos + oldStr.length() < inoutStr.length() && pos == str_pos )
	{
		inoutStr.replace( pos, oldStr.length(), newStr );
		pos = GetFirstPos( &inoutStr[ pos + newStr.length() ], oldStr );

		str_pos += newStr.length();
	}
}


// 文字列の前の空白や改行を除去する
void TrimStart( std::string& inoutStr )
{
	while( inoutStr.front() == ' ' || 
		   inoutStr.front() == '\n' || 
		   inoutStr.front() == '\r' ||
		   inoutStr.front() == '\t' )
	{
		ReplaceStart( inoutStr, " ", "" );
		ReplaceStart( inoutStr, "\n", "" );
		ReplaceStart( inoutStr, "\r", "" );
		ReplaceStart( inoutStr, "\t", "" );
	}
}

// 文字列を数値に変換する
template<typename T> 
T ConvertToNum( const std::string& numStr ) // 文字の先頭にあるスペースを削除して数値を取得する
{
	std::string bufStr = numStr;
	double checkNum = atof( numStr.c_str() );

	T convertNum = ( T ) checkNum;
	TrimStart( bufStr );

	if( checkNum == 0 && bufStr.front() != '0' && ( bufStr[ 0 ] == '-' && bufStr[ 1 ] == '0' ) == false )
	{
		throw std::invalid_argument( "この文字列は変換できません" );
	}

	return convertNum;}

GetFirstPosは下記で記述してるので今回は割愛

最初に空白がある可能性があるので取り除いた後にatofで変換し、変換した値が0の場合に本当に0なのかチェックをしています

先程のチェックコードに作った関数を入れて確認してみます

void OutputLog( const std::string& str )
{
	try
	{
		std::cout << str << "をatoiで変換:" << atoi( str.c_str() ) << std::endl;
	}
	catch( std::exception e )
	{
		std::cout << str << "の変換に失敗!!" << std::endl;
	}
	try
	{
		std::cout << str << "をatofで変換:" << atof( str.c_str() ) << std::endl;
	}
	catch( std::exception e )
	{
		std::cout << str << "の変換に失敗!!" << std::endl;
	}

	std::cout << std::endl;

	try
	{
		int num = ConvertToNum<int>( str );
		std::cout << str << "をintに変換:" << num << std::endl;
	}
	catch( std::exception e )
	{
		std::cout << str << "の変換に失敗!!" << std::endl;
	}
	try
	{
		float num = ConvertToNum<float>( str );
		std::cout << str << "をfloatに変換:" << num << std::endl;
	}
	catch( std::exception e )
	{
		std::cout << str << "の変換に失敗!!" << std::endl;
	}

	try
	{
		float num = ConvertToNum<double>( str );
		std::cout << str << "をdoubleに変換:" << num << std::endl;
	}
	catch( std::exception e )
	{
		std::cout << str << "の変換に失敗!!" << std::endl;
	}

	std::cout << std::endl;
}

結果↓

をatoiで変換:0
をatofで変換:0

の変換に失敗!!
の変換に失敗!!
の変換に失敗!!

0aaaをatoiで変換:0
0aaaをatofで変換:0

0aaaをintに変換:0
0aaaをfloatに変換:0
0aaaをdoubleに変換:0

00aaaをatoiで変換:0
00aaaをatofで変換:0

00aaaをintに変換:0
00aaaをfloatに変換:0
00aaaをdoubleに変換:0

-00aaaをatoiで変換:0
-00aaaをatofで変換:-0

-00aaaをintに変換:0
-00aaaをfloatに変換:-0
-00aaaをdoubleに変換:-0

-0aaaをatoiで変換:0
-0aaaをatofで変換:-0

-0aaaをintに変換:0
-0aaaをfloatに変換:-0
-0aaaをdoubleに変換:-0

009をatoiで変換:9
009をatofで変換:9

009をintに変換:9
009をfloatに変換:9
009をdoubleに変換:9

    12345をatoiで変換:12345
    12345をatofで変換:12345

    12345をintに変換:12345
    12345をfloatに変換:12345
    12345をdoubleに変換:12345

  12345をatoiで変換:0
  12345をatofで変換:0

  12345の変換に失敗!!
  12345の変換に失敗!!
  12345の変換に失敗!!


 12345をatoiで変換:12345

 12345をatofで変換:12345


 12345をintに変換:12345

 12345をfloatに変換:12345

 12345をdoubleに変換:12345


 0をatoiで変換:0

 0をatofで変換:0


 0をintに変換:0

 0をfloatに変換:0

 0をdoubleに変換:0

-.32fをatoiで変換:0
-.32fをatofで変換:-0.32

-.32fをintに変換:0
-.32fをfloatに変換:-0.32
-.32fをdoubleに変換:-0.32

あああああをatoiで変換:0
あああああをatofで変換:0

あああああの変換に失敗!!
あああああの変換に失敗!!
あああああの変換に失敗!!

-あああああをatoiで変換:0
-あああああをatofで変換:0

-あああああの変換に失敗!!
-あああああの変換に失敗!!
-あああああの変換に失敗!!

01弐参をatoiで変換:1
01弐参をatofで変換:1

01弐参をintに変換:1
01弐参をfloatに変換:1
01弐参をdoubleに変換:1

零壱23をatoiで変換:0
零壱23をatofで変換:0

零壱23の変換に失敗!!
零壱23の変換に失敗!!
零壱23の変換に失敗!!

image.png
↑は全角が前にある場合の変換なので失敗にしています

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?