Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
Tags
- Reflect
- ranges
- WebView
- AES
- SHA512
- c++
- CustomTab
- RAII
- web
- Functional
- stringprintf
- template
- coroutines
- ChromeTab
- kotlin
- program
- Scala
- SHA1
- haskell
- Clojure
- sha256
- Android
- Observer
- go
- traits
- Chrono
- sprintf
- async
- type_traits
- design pattern
Archives
- Today
- Total
프로그래밍 검색 블로그
stringprintf string반환 sprintf 2 본문
여기서는 %로 받는 형식문자열을 추론해서 알아본다.
1 2 3 4 5 6 7 8 9 10 | template <typename _Any> struct is_c_style_string : public false_type{}; template <> struct is_c_style_string<const char*> : public true_type{}; template <> struct is_c_style_string<char*> : public true_type{}; template <> struct is_c_style_string<const char[]> : public true_type{}; template <> struct is_c_style_string<char[]> : public true_type{}; | cs |
이런 구조체를 추가하여 c_style의 문자열인지 알아낼 수 있도록 한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | template<typename _Enum, typename = typename std::enable_if<std::is_enum<_Enum>::value>::type> inline std::ostringstream& operator<<(std::ostringstream& o, _Enum e){ o << ((long long)e); return o; } std::string stringprintf_internal(std::stringstream&& os, const char* str){ for(; *str; str++){ if(*str == '%' && *(++str) != '%'){ //stringprintf("%d")같은 상황을 체크했을때 //throw std::runtime_error("%d"); } else{ os << *str; } } return os.str(); } template<typename Arg, typename... Args> std::string stringprintf_internal(std::stringstream&& os, const char* str, Arg&& arg, Args&&... args){ for(; *str; str++){ //%%는 % //그외에는 Arg가 들어감 if(*str == '%'){ const char nextChar = *(++str); switch(nextChar){ case 'u': case 'c': case 'd': if(std::is_integral<Arg>() == false){ throw std::runtime_error("bad format specifier"); } break; case 'f': if(std::is_floating_point<Arg>() == false){ throw std::runtime_error("bad format specifier"); } break; case 's': if(is_c_style_string<Arg>() == false){ throw std::runtime_error("bad format specifier"); } break; } os << arg; return stringprintf_internal(std::move(os), ++str, std::forward<Args>(args)...); } else{ os << *str; } } //stringprintf("abcde", 1,2,3,4,5); 같이 들어왔을때 던질려면 //throw std::invalid_argument("argument"); return os.str(); } template<typename... Args> std::string stringprintf(const char* str, Args&&... args) { if(str == nullptr){ // null str이 들어왔을때 던질려면 //throw std::invalid_argument("null"); return std::string(""); } std::stringstream os; return stringprintf_internal(std::move(os), str, std::forward<Args>(args)...); } | cs |
테스트
1 2 3 4 5 6 7 | #include <iostream> using namespace std; int main(int argc, const char * argv[]) { auto s = stringprintf("%d 1%d23 %d %% 4%d 5%d6 test %d 1%%", 1,2,3,4,5,6); cout << s<<endl; } | cs |
'C++ 유틸' 카테고리의 다른 글
함수가 끝날때 같이 해제하기 defer (0) | 2017.10.06 |
---|---|
시간 관련 API (0) | 2017.10.04 |
stringprintf string반환 sprintf 1 (0) | 2017.10.04 |
C++ Traits (0) | 2017.10.03 |
type_trait / is_nullptr nullptr인지 검사 (0) | 2017.10.03 |
Comments