using i8 = char;
using u8 = unsigned char;
using i16 = short;
using u16 = unsigned short;
using i32 = int;
using u32 = unsigned int;
using i64 = long long;
using u64 = unsigned long long;
using f32 = float;
using f64 = double;
#define rigid constexpr
//---------------------------------------------------------------------------------------
rigid u32 CHAR_BITS = 8;
// 특정 타입의 most significant bit의 위치를 리턴
// ex ) 32bit type -> 31
template< typename T >
inline rigid auto msb()
{
return sizeof( T ) * CHAR_BITS - 1;
}
// 특정 타입의 most significant bit를 1로 둔 값을 리턴
// ex ) 32bit type -> 0x80000000
template< typename T >
inline rigid auto msb_value()
{
return (T)1 << msb< T >();
}
// 특정 타입의 most significant bit를 제외시키는 마스크를 리턴
// ex ) 32bit type -> 0x7FFFFFFF
template< typename T >
inline rigid auto msb_mask()
{
return (T)~msb_value< T >();
}
// 편하게 쓰자
#define msb_pos( var ) msb< decltype( var ) >()
#define msb_val( var ) msb_value< decltype( var ) >()
// dst 의 가장 큰값 위치에 bits 값을 얹음
template< typename T0, typename T1 >
inline void set_msbs( T0& dst, const T1 bits )
{
*( (T1*)&dst + ( sizeof dst / sizeof bits - 1 ) ) |= bits;
}
//---------------------------------------------------------------------------------------
// 문자열로부터 부호없는 연속한 숫자를 리턴
// 포인터를 숫자의 끝 다음으로 이동시킴
inline u32 atou32( char*& s )
{
u32 value;
for( value = 0; *s <= '9' && *s >= '0'; ++s )
value = value * 10 + ( *s - '0' );
return value;
}
// 문자열로부터 부호있는 연속한 숫자를 리턴
// 포인터를 숫자의 끝 다음으로 이동시킴
inline i32 atoi32( char*& s )
{
if( *s == '-' )
return -(i32)atou32( ++s );
return atou32( s );
}
// 문자열로부터 부호처리된 부동소수 및 지수값을 리턴
// 포인터를 숫자의 끝 다음으로 이동시킴
template< typename T = f64 >
inline T atof( char*& s )
{
char* p = s;
u32 sign = 0;
T digit = 0.;
T base = 1.;
T step = 1.;
for( i8 token; token = *p++; )
{
switch( token )
{
case '-':
sign = msb_val( sign );
break;
case '.':
step = 10;
break;
case 'E':
case 'e':
digit *= (T)std::pow( 10., (f64)atof< T >( s = p ) );
goto exit;
default:
if( token <= '9' && token >= '0' )
{
digit = digit * (T)10. + ( token & 0xF );
base *= step;
continue;
}
goto exit;
}
}
exit:
if( s < p - 1 ) s = p - 1;
set_msbs( digit, sign );
return T( digit / base );
}
// 편하게 쓰자
inline auto atof32( char*& s )
{
return atof< f32 >( s );
}
inline auto atof64( char*& s )
{
return atof< f64 >( s );
}
//---------------------------------------------------------------------------------------
#include <type_traits>
// 타입에 맞게 문자열의 숫자를 해독해서 param 에 넣음
template< typename T >
inline char* parse_number( const char* string, T& param )
{
char* s = (char*)string;
while( *s == ' ' || *s == ' ' || *s == ' ' ) s++;
if( std::is_same< T, i32 >::value )
param = (T)atoi32( s );
if( std::is_same< T, u32 >::value )
param = (T)atou32( s );
if( std::is_same< T, f32 >::value )
param = (T)atof32( s );
if( std::is_same< T, f64 >::value )
param = (T)atof64( s );
return s;
}
// 복수 params
template< typename T, typename... Ts >
inline char* parse_number( const char* string, T& param1, Ts&... rest )
{
return parse_number( parse_number( string, param1 ), rest... );
}
//---------------------------------------------------------------------------------------
#include <iostream>
using namespace std;
int main()
{
i32 a, b;
u32 c, d;
f64 e;
f32 f;
parse_number( "-1 0 1 2 1.23e2 1.23456", a, b, c, d, e, f );
cout << a << " " << b << " " << c << " " << d << " " << e << " " << f << endl;
getchar();
return 0;
}
실행 결과 :
-1 0 1 2 123 1.23456
나답지않게 짱 친절한 주석. 데헷~
이것에 템플릿과 모오던 C++을 짬뽕하였으니 진정한 쓰까언어로세
근데 왜 rigid라고 바꿔 써여?
줄맞추기 쉬우라구유~
constexpr 너무 길어서 const 보다 탭이 더나감 ㅋㅋ
저기 while 문 안에 white space 들은 스페이스, 탭, 개행 임유~.
http://ideone.com/tJxarB