- ¹®ÀÚ¿
- ¹®ÀÚ¿ Á¶ÀÎ&½ºÇø´
- ¹®ÀÚ¿ Á¿ìÀÇ °ø¹éÀ» Á¦°ÅÇϱâ
- ¹®ÀÚ¿¿¡¼ find & replace ¼öÇàÇϱâ
- find_first_not_of, find_last_not_of C ¹öÀü ±¸Çö
- ÄÁÅ×À̳Ê/¾Ë°í¸®Áò
- ¹®ÀÚ¿À» Ű·Î ¾²´Â map, set ¼º´É Çâ»ó½Ã۱â
- map/multimap -> vector/list º¯È¯
- Æ÷ÀÎÅÍ Ä÷º¼ÇÀ» Ⱦ´ÜÇÏ¸ç °´Ã¼ »èÁ¦Çϱâ
- °´Ã¼ÀÇ ¸®½ºÆ®¸¦ Ⱦ´ÜÇÏ¸é¼ ¸â¹ö ÇÔ¼ö È£ÃâÇϱâ
- set_intersection ¾Ë°í¸®ÁòÀÇ ´ë¾È
- ±âŸ
- numeric_limits<float>::min != numeric_limits<int>::min
- »ý¼ºÀÚ¿¡¼ °¡»ó ÇÔ¼ö È£ÃâÇϱâ
- static_cast vs reinterpret_cast
- ¹è¿ ¾ÈÀÇ ¾ÆÀÌÅÛ °¹¼ö ¾Ë¾Æ³»±â
- ºü¸¥ atan2
- ºü¸¥ sqrt
- Ç¥ÁØ ÀÔÃâ·Â ½ºÆ®¸² ¸®´ÙÀÌ·º¼ÇÇϱâ
- ¹ÌÈ®Á¤ ¸Å°³ º¯¼ö¸¦ ´Ù¸¥ ÇÔ¼öÀÇ ÀÎÀÚ·Î ´Ù½Ã ³Ñ±â±â
- ¹ÌÈ®Á¤ ¸Å°³ º¯¼ö ó¸®
- ÆÄÀÏ ·Î±× ÇÔ¼ö
- º¹»ç »ý¼ºÀÚ ¹× ´ëÀÔ ¿¬»êÀÚ ¸·±â
- Àӽà º¯¼ö ÇÊ¿ä ¾ø´Â ġȯ ¸ÅÅ©·Î
- ¼Ò¼ö üũÇϱâ
- 2ÀÇ ½Â¼ö üũÇϱâ
1 ¹®ÀÚ¿
#if defined(UNICODE) || defined(_UNICODE)
typedef std::basic_string<wchar_t> tstring;
typedef std::wstringstream tstringstream;
#else
typedef std::basic_string<char> tstring;
typedef std::stringstream tstringstream;
#endif
template <typename Iterator, typename Seperator>
tstring join(const Iterator& first, const Iterator& last, Seperator seperator)
{
tstringstream stream;
stream.imbue(std::locale::classic());
for (Iterator itr(first); itr != last; ++itr)
{
if (std::distance(itr, last) > 1)
stream << *itr << seperator;
else
stream << *itr;
}
return stream.str();
}
template <typename Iterator, typename Selector, typename Seperator>
tstring join(const Iterator& first, const Iterator& last, Selector selector, Seperator seperator)
{
tstringstream stream;
stream.imbue(std::locale::classic());
for (Iterator itr(first); itr != last; ++itr)
{
if (std::distance(itr, last) > 1)
stream << selector(*itr) << seperator;
else
stream << selector(*itr);
}
return stream.str();
}
template <typename Container>
void split(const tstring& text, TCHAR seperator, Container& result)
{
std::back_insert_iterator<Container> inserter(result);
size_t before = 0, end = 0;
tstring token = _T("");
while (before < text.size() && end < text.size())
{
if ((end = text.find_first_of(seperator, before)) != tstring::npos)
{
token = text.substr(before, end - before);
if (!token.empty())
*inserter = token;
before = end + 1;
}
else
{
token = text.substr(before, text.size() - before);
if (!token.empty()) { *inserter = token; }
break;
}
}
}
template <typename Container>
void split(const tstring& text, const tstring& seperators, Container& result)
{
std::back_insert_iterator<Container> inserter(result);
size_t before = 0, end = 0;
tstring token = _T("");
while (before < text.size() && end < text.size())
{
if ((end = text.find_first_of(seperators, before)) != tstring::npos)
{
token = text.substr(before, end - before);
if (!token.empty())
*inserter = token;
before = end + 1;
}
else
{
token = text.substr(before, text.size() - before);
if (!token.empty()) { *inserter = token; }
break;
}
}
} Á¶ÀÎÀÇ °æ¿ì, stringstream¿¡ Áý¾î³ÖÀ» ¼ö Àִ ŸÀÔÀ̶ó¸é ¾Æ¹« °Å³ª ¹®ÀÚ¿·Î ¸¸µé ¼ö ÀÖ´Ù.
1.2 ¹®ÀÚ¿ Á¿ìÀÇ °ø¹éÀ» Á¦°ÅÇϱâ
std::string trim_right(const std::string& source, const std::string& whitespaces=" \t\r\n")
{
std::string str(source);
return str.erase(str.find_last_not_of(whitespaces) + 1);
}
std::string trim_left(const std::string& source, const std::string& whitespaces=" \t\r\n")
{
std::string str(source);
return str.erase(0, str.find_first_not_of(whitespaces));
}
std::string trim(const std::string& source, const std::string& whitespaces=" \t\r\n")
{
std::string str(source);
return trim_left(trim_right(source, whitespaces), whitespaces);
}
std::wstring trim_right(const std::wstring& source, const std::wstring& whitespaces=L" \t\r\n")
{
std::wstring str(source);
return str.erase(str.find_last_not_of(whitespaces) + 1);
}
std::wstring trim_left(const std::wstring& source, const std::wstring& whitespaces=L" \t\r\n")
{
std::wstring str(source);
return str.erase(0, str.find_first_not_of(whitespaces));
}
std::wstring trim(const std::wstring& source, const std::wstring& whitespaces=L" \t\r\n")
{
std::wstring str(source);
return trim_left(trim_right(source, whitespaces), whitespaces);
} ¼Óµµ°¡ Áß¿äÇÏ´Ù¸é Á» ¸ð¾çÀÌ ±×·¸´Ù¸¸, ´ÙÀ½°ú °°Àº Äڵ尡 ³´´Ù. À§ Äڵ忡 ºñÇØ 2¹è Á¤µµ ºü¸£´Ù. Àӽà °´Ã¼¸¦ »ý¼ºÇÏÁö ¾Ê±â ¶§¹®ÀÌ´Ù.
std::string trim(const std::string& str, const std::string& whitespaces=" \t\r\n")
{
std::string result("");
size_t begin = source.find_first_not_of(whitespaces);
size_t end = source.find_last_not_of(whitespaces);
if (begin != std::string::npos && end != std::string::npos)
result = source.substr(begin, end - begin + 1);
return result;
}
1.3 ¹®ÀÚ¿¿¡¼ find & replace ¼öÇàÇϱâ
/// \brief ÁÖ¾îÁø ¹®ÀÚ¿ ³»¿¡ Á¸ÀçÇÏ´Â ¹®ÀÚ¿À» ´Ù¸¥ ¹®ÀÚ¿·Î ġȯÇÑ´Ù.
/// \param text ¿øº» ¹®ÀÚ¿
/// \param find_token ã°íÀÚ ÇÏ´Â ¹®ÀÚ¿
/// \param replace_token ġȯÇϰíÀÚ ÇÏ´Â ¹®ÀÚ¿
void replace(std::string& text, const std::string& find_token, const std::string& replace_token)
{
size_t i = 0;
while ((i = text.find(find_token)) != string::npos)
text.replace(i, find_token.size(), replace_token);
} ÀÀ¿ëÇÏ¸é ´ÙÀ½°ú °°Àº ÇÔ¼öµµ ¸¸µé ¼ö ÀÖ´Ù.
/// \brief ¹®Àå ³»ºÎ¿¡ ¿¬¼ÓÀûÀÎ ´ë»ó ¹®ÀÚ¸¦ Çϳª·Î ¸¸µç´Ù.
///
/// Áï targetÀ» ' '·Î ÁØ °æ¿ì, µÎ °³ ÀÌ»óÀÇ ' '¸¦ ÇϳªÀÇ ' '·Î ¸¸µç´Ù.
///
/// \param text ¿øº» ¹®ÀÚ¿
/// \param target ´ë»óÀÌ µÇ´Â ±ÛÀÚ
/// \return string º¯È¯ÇÑ ¹®ÀÚ¿
std::string squeeze(const std::string& text, char target)
{
std::string str(text);
replace(str, string(2, target), string(1, target));
return str;
}
1.4 find_first_not_of, find_last_not_of C ¹öÀü ±¸Çö
// find_first_not_of
const char* str_spnp(const char* str, const char* charset)
{
return str == NULL ? NULL : ((*(str += strspn(str, charset)) != 0) ? str : NULL);
}
// find_first_not_of
const wchar_t* wcs_spnp(const wchar_t* str, const wchar_t* charset)
{
return str == NULL ? NULL : ((*(str += wcsspn(str, charset)) != 0) ? str : NULL);
}
// find_last_not_of
const char* str_rspnp(const char* str, const char* charset)
{
const char* last = NULL;
const char* current = str;
for (; *current; ++current)
{
if (!strchr(charset, *current))
last = current;
}
return last;
}
// find_last_not_of
const wchar_t* wcs_rspnp(const wchar_t* str, const wchar_t* charset)
{
const wchar_t* last = NULL;
const wchar_t* current = str;
for (; *current; ++current)
{
if (!wcschr(charset, *current))
last = current;
}
return last;
}
#if defined(UNICODE) || defined(_UNICODE)
#define tstrspnp(str, charset) wcs_spnp(str, charset)
#define tstrrspnp(str, charset) wcs_rspnp(str, charset)
#else
#define tstrspnp(str, charset) str_spnp(str, charset)
#define tstrrspnp(str, charset) str_rspnp(str, charset)
#endif
2 ÄÁÅ×À̳Ê/¾Ë°í¸®Áò
2.1 ¹®ÀÚ¿À» Ű·Î ¾²´Â map, set ¼º´É Çâ»ó½Ã۱â
¹®ÀÚ¿(std::string)À» Ű·Î °¡Áö´Â ¸Ê °°Àº °æ¿ì, ¹®ÀÚ¿ ºñ±³ ÀÚü¿¡ °É¸®´Â ½Ã°£ ¶§¹®¿¡ °Ë»öÀÌ ´À·ÁÁú ¼ö ÀÖ´Ù. ÀÌ °æ¿ì, Ű·Î »ç¿ëÇÏ´Â ¹®ÀÚ¿ÀÌ º°·Î Áß¿äÇÑ ³»¿ëÀÌ ¾Æ´Ï¶ó¸é ¾Æ·¡¿Í °°Àº Ŭ·¡½º¸¦ »ç¿ëÇÔÀ¸·Î¼ ¼º´ÉÀ» ¾à°£ Áõ°¡½Ãų ¼ö ÀÖ´Ù.
////////////////////////////////////////////////////////////////////////////////
/// \class cStringKey
/// \brief STL ÄÁÅ×À̳ʸ¦ À§ÇÑ ¹®ÀÚ¿ Ű
////////////////////////////////////////////////////////////////////////////////
class cStringKey
{
private:
enum
{
BYTE_SIZE = 32,
};
char m_Text[BYTE_SIZE]; ///< ¹®ÀÚ¿
public:
/// \brief »ý¼ºÀÚ
cStringKey()
{
memset(m_Text, 0, sizeof(m_Text));
}
/// \brief »ý¼ºÀÚ
cStringKey(const char* text)
{
memset(m_Text, 0, sizeof(m_Text));
memcpy_s(m_Text, sizeof(m_Text), text, std::min(sizeof(m_Text), strlen(text)));
}
/// \brief »ý¼ºÀÚ
cStringKey(const std::string& text)
{
memset(m_Text, 0, sizeof(m_Text));
memcpy_s(m_Text, sizeof(m_Text), text.c_str(), std::min(sizeof(m_Text), text.size()));
}
/// \brief º¹»ç »ý¼ºÀÚ
cStringKey(const cStringKey& rhs)
{
memcpy_s(m_Text, sizeof(m_Text), rhs.m_Text, sizeof(m_Text));
}
public:
/// \brief ´ëÀÔ ¿¬»êÀÚ
inline const cStringKey& operator = (const cStringKey& rhs)
{
if (this != &rhs)
memcpy_s(m_Text, sizeof(m_Text), rhs.m_Text, sizeof(m_Text));
return *this;
}
/// \brief ºñ±³ ¿¬»êÀÚ
///
/// ÀÌ ÇÔ¼ö´Â ¾à°£ À¯ÀÇÇØ¾ß Çϴµ¥, ¼Óµµ¸¦ À§ÇØ ·çÇÁ¸¦ Ç®¾î¹ö·È±â ¶§¹®ÀÌ´Ù.
/// Ŭ·¡½ºÀÇ Å©±â°¡ º¯°æµÇ¸é, ÀÌ ÇÔ¼öµµ °°ÀÌ º¯°æÇØÁà¾ß ÇÑ´Ù.
inline bool operator < (const cStringKey& rhs) const
{
const int* buf1 = reinterpret_cast<const int*>(this);
const int* buf2 = reinterpret_cast<const int*>(&rhs);
if (*buf1 != *buf2) return *buf1 < *buf2; // 0-3
++buf1; ++buf2;
if (*buf1 != *buf2) return *buf1 < *buf2; // 4-7
++buf1; ++buf2;
if (*buf1 != *buf2) return *buf1 < *buf2; // 8-11
++buf1; ++buf2;
if (*buf1 != *buf2) return *buf1 < *buf2; // 12-15
++buf1; ++buf2;
if (*buf1 != *buf2) return *buf1 < *buf2; // 16-19
++buf1; ++buf2;
if (*buf1 != *buf2) return *buf1 < *buf2; // 20-23
++buf1; ++buf2;
if (*buf1 != *buf2) return *buf1 < *buf2; // 24-27
++buf1; ++buf2;
return *buf1 < *buf2; // 28-31
}
};
´ë¼Ò¹®ÀÚ ±¸º°¾øÀÌ ºñ±³¸¦ ÇÒ ¼ö ¾ø´Ù´Â Á¡ÀÌ Á» ¾Æ½±´Ù. ¾î¼Àºí¸®µµ Á» ¾È´Ù¸é ºñ±³ ¿¬»êÀÚ¸¦ Á» ´õ ±ò²ûÇÏ°Ô ¸¸µé ¼ö ÀÖÀ» ÅÙµ¥. ¾î·µç Å×½ºÆ®Çغ¸´Ï, ¸±¸®Áî ºôµå¿¡¼ ¾à 25~33% Á¤µµÀÇ ¼º´ÉÀÌ Çâ»óµÇ¾ú´Ù.
typedef std::map<std::string, std::string> OLD_MAP;
typedef std::map<cStringKey, std::string> NEW_MAP;
OLD_MAP oldMap;
NEW_MAP newMap;
for (int i=0; i<1000; ++i)
{
std::string key = generic::to_string(rand() % 1000, 4);
std::string value = generic::to_string(rand() % 1000, 4);
oldMap.insert(OLD_MAP::value_type(key, value));
newMap.insert(NEW_MAP::value_type(key, value));
}
DWORD begin = 0, oldTime = 0, newTime = 0;
int repetition = 200000;
begin = timeGetTime();
for (int i=0; i<repetition; ++i)
{
oldMap.find(generic::to_string(rand() % 1000, 4));
}
oldTime = timeGetTime() - begin;
begin = timeGetTime();
for (int i=0; i<repetition; ++i)
{
newMap.find(generic::to_string(rand() % 1000, 4));
}
newTime = timeGetTime() - begin;
std::cout << "OLD: " << oldTime << std::endl;
std::cout << "NEW: " << newTime << std::endl;
2.2 map/multimap -> vector/list º¯È¯
template <typename I, typename C>
inline void make_sequence(const I& first, const I& last, C& container)
{
std::back_insert_iterator<C> inserter(container);
for (I itr(first); itr != last; ++itr, ++inserter)
*inserter = itr->second;
}
std::map<int, int> myMap;
myMap[0] = 0;
myMap[1] = 1;
myMap[2] = 2
myMap[3] = 3
std::vector<int> myVector;
make_sequence(myMap.begin(), myMap.end(), myVector);
´õ ³ªÀº ¹æ¹ýÀÌ ÀÖÀ» °Íµµ °°Àºµ¥, ¸ø ã°Ú´Ù. ¾à°£ ÀÀ¿ëÇØº¸¸é ÀÌ·± °Íµµ ÀÖÀ» ¼ö ÀÖ°Ú´Ù.
template <typename I, typename C>
inline void make_sorted_sequence(const I& first, const I& last, C& container)
{
std::back_insert_iterator<C> inserter(container);
for (I itr(first); itr != last; ++itr, ++inserter)
*inserter = itr->second;
std::sort(container.begin(), container.end());
}
template <typename I, typename C, typename P>
inline void make_sorted_sequence(const I& first, const I& last, C& container, P comp)
{
std::back_insert_iterator<C> inserter(container);
for (I itr(first); itr != last; ++itr, ++inserter)
*inserter = itr->second;
std::sort(container.begin(), container.end(), comp);
} ÀÏ¹Ý ¹è¿µµ »ç¿ëÇÏ·Á¸é ÄÁÅ×À̳ÊÀÇ begin, end¸¦ ÀÎÀÚ·Î ¹Þ¾Æ¾ß ÇÑ´Ù. ÁöÀúºÐÇØ¼ ½ÈÀºµ¥ ¾î¶±ÇÏÁö.
2.3 Æ÷ÀÎÅÍ Ä÷º¼ÇÀ» Ⱦ´ÜÇÏ¸ç °´Ã¼ »èÁ¦Çϱâ
Effective STL¿¡ ³ª¿ÍÀÖ¾ú´ø °É·Î ±â¾ïÇϴµ¥, ÀÚ²Ù Âø°¢ÀÌ µÇ¾î¼ ±â·ÏÇØµÐ´Ù.
¼øÂ÷Çü(sequential) Ä÷º¼Ç
typedef std::list<OBJECT*> OBJECTS;
OBJECTS objects;
...
for (OBJECTS::iterator itr(objects.begin()); itr != object.end(); )
{
OBJECT* object = *itr;
if (should_delete(object))
{
itr = objects.erase(itr);
delete object;
}
else itr++;
} ¿¬°üÇü(associative) Ä÷º¼Ç
typedef std::map<int, OBJECT*> OBJECTS;
OBJECTS objects;
...
for (OBJECTS::iterator itr(objects.begin()); itr != object.end(); )
{
OBJECT* object = itr->second;
if (should_delete(object))
{
objects.erase(itr++);
delete object;
}
else itr++;
} ±¸ºÐÇØ¼ ¾²´Â °Ô ±ÍÂú´Ù¸é...
struct YES {};
struct NO {};
template <typename T>
struct is_ptr { enum { result = false }; typedef NO Result; };
template <typename T>
struct is_ptr<T*> { enum { result = true }; typedef YES Result; };
template <typename T>
struct is_ptr<T* const> { enum { result = true }; typedef YES Result; };
template <typename T>
struct is_ptr<T* volatile> { enum { result = true }; typedef YES Result; };
template <typename T>
struct is_ptr<T* const volatile> { enum { result = true }; typedef YES Result; };
template <typename T>
class is_pair
{
private:
template <typename U>
struct is_pair_imp
{
enum { value = false };
typedef NO Result;
};
template <typename U, typename V>
struct is_pair_imp < std::pair<U, V> >
{
enum { value = true };
typedef YES Result;
};
public:
enum { value = is_pair_imp<T>::value };
typedef typename is_pair_imp<T>::Result Result;
};
template <typename IS_POINTER>
struct do_delete {};
template <>
struct do_delete<YES>
{
template <typename U>
void operator()(U param) { delete param; }
};
template <>
struct do_delete<NO>
{
template <typename U>
void operator()(U param) {}
};
template <typename IS_ASSOCIATION>
struct delete_if_imp {};
template <>
struct delete_if_imp<YES>
{
template <typename CONTAINER, typename PREDICATE>
void operator()(CONTAINER& container, PREDICATE comp)
{
do_delete< is_ptr<CONTAINER::value_type::second_type>::Result > doDelete;
for (CONTAINER::iterator itr(container.begin()); itr != container.end();)
{
if (comp(itr->second))
{
doDelete(itr->second);
container.erase(itr++);
}
else ++itr;
}
}
};
template <>
struct delete_if_imp<NO>
{
template <typename CONTAINER, typename PREDICATE>
void operator()(CONTAINER& container, PREDICATE comp)
{
do_delete< is_ptr<CONTAINER::value_type>::Result > doDelete;
for (CONTAINER::iterator itr(container.begin()); itr != container.end();)
{
if (comp(*itr))
{
doDelete(*itr);
itr = container.erase(itr);
}
else ++itr;
}
}
};
template <typename CONTAINER, typename PREDICATE>
inline void delete_if(CONTAINER& container, PREDICATE comp)
{
delete_if_imp< is_pair<CONTAINER::value_type>::Result > imp;
imp(container, comp);
}
2.4 °´Ã¼ÀÇ ¸®½ºÆ®¸¦ Ⱦ´ÜÇÏ¸é¼ ¸â¹ö ÇÔ¼ö È£ÃâÇϱâ
¿¹¸¦ µé¾î ´ÙÀ½°ú °°Àº Ŭ·¡½ºµéÀÌ ÀÖ´Ù°í ÇÏÀÚ.
class myclass
{
public:
void heartbeat() { ... }
void set(int param) { ... }
};
std::list<myclass> obj_list;
std::list<myclass*> ptr_list;
¿ÀºêÁ§Æ® ÀÚü·Î ÀÌ·ç¾îÁø ¸®½ºÆ®µé µ¹¸é¼ myclassÀÇ heartbeat ÇÔ¼ö¸¦ È£ÃâÇÏ·Á¸é ´ÙÀ½°ú °°ÀÌ ÇÑ´Ù.
for_each(obj_list.begin(), obj_list.end(),
mem_fun(&myclass::heartbeat)); Æ÷ÀÎÅÍ·Î ÀÌ·ç¾îÁø ¸®½ºÆ®¸¦ µ¹¸é¼ myclassÀÇ heartbeat ÇÔ¼ö¸¦ È£ÃâÇÏ·Á¸é ´ÙÀ½°ú °°ÀÌ ÇÑ´Ù.
for_each(ptr_list.begin(), ptr_list.end(),
mem_fun<void, myclass>(&myclass::heartbeat)); Æ÷ÀÎÅÍ·Î ÀÌ·ç¾îÁø ¸®½ºÆ®¸¦ µ¹¸é¼ myclassÀÇ set ÇÔ¼ö¸¦ È£ÃâÇÏ·Á¸é ´ÙÀ½°ú °°ÀÌ ÇÑ´Ù.
for_each(ptr_list.begin(), ptr_list.end(),
bind2nd(mem_fun1<void, myclass, int>(&myclass::heartbeat), 99)); °³ÀÎÀûÀ¸·Î´Â ÀÌ Á¤µµ±îÁö´Â ÃßõÇÏÁö ¾Ê´Â´Ù. Â÷¶ó¸® for ·çÇÁ µ¹¸é¼ ÇÏ´Â °Ô °ü¸®ÇϱⰡ ÆíÇϱ⠶§¹®ÀÌ´Ù.
´ç¿¬ÇÏÁö¸¸, vector ¹× deque µî¿¡µµ Àû¿ëÇÒ ¼ö ÀÖ´Ù.
2.5 set_intersection ¾Ë°í¸®ÁòÀÇ ´ë¾È
template<class InputIterator1, class InputIterator2, class OutputIterator>
OutputIterator set_intersection(
InputIterator1 _First1,
InputIterator1 _Last1,
InputIterator2 _First2,
InputIterator2 _Last2,
OutputIterator _Result
);
template<class InputIterator1, class InputIterator2, class OutputIterator, class BinaryPredicate>
OutputIterator set_intersection(
InputIterator1 _First1,
InputIterator1 _Last1,
InputIterator2 _First2,
InputIterator2 _Last2,
OutputIterator _Result,
BinaryPredicate _Comp
); set_intersection ¾Ë°í¸®ÁòÀº Á¤·ÄµÈ µÎ °³ÀÇ ÄÁÅ×À̳ʿ¡¼ ±³ÁýÇÕÀ» ±¸ÇÏ´Â ¾Ë°í¸®ÁòÀε¥ ¾²±â°¡ Á» ¹¹ÇÏ´Ù. È£Ãâ½Ã output_iterator¸¦ ³Ñ±â´Âµ¥, ÀÌ output_iterator¿¡ ÇØ´çÇÏ´Â ÄÁÅ×À̳ʴ ȣÃâ Àü¿¡ ÃÖ¼Ò ±³ÁýÇÕÀÇ Å©±â¸¸ÅÀÇ °ø°£À» °¡Áö°í ÀÖ¾î¾ß Çϱ⠶§¹®ÀÌ´Ù. insert_iteratorµµ ½ÃµµÇغ¸¾ÒÀ¸³ª, VisualCpp 7.1¿¡¼´Â ¹º°¡ ¿¡·¯°¡ ³ª´Â °ü°è·Î ¾Ë°í¸®Áò Çì´õ¸¦ º¸°í ±×³É ¶«»§À¸·Î ¾Ë°í¸®ÁòÀ» ¸¸µé¾ú´Ù.
template <typename T>
void intersection(const T& c1, const T& c2, T& u)
{
T::const_iterator first1(c1.begin());
T::const_iterator last1(c1.end());
T::const_iterator first2(c2.begin());
T::const_iterator last2(c2.end());
for (; first1 != last1 && first2 != last2; )
{
if (*first1 < *first2)
++first1;
else if (*first2 < *first1)
++first2;
else
u.insert(*first1++), ++first2;
}
} ¾à°£ ÀÀ¿ëÇÏ¸é ±³ÁýÇÕÀ» °¡Áö´Â°¡ÀÇ ¿©ºÎ¸¦ ¹ÝȯÇÏ´Â ÇÔ¼öµµ ¸¸µé ¼ö ÀÖ´Ù.
template <typename T>
bool has_intersection(const T& c1, const T& c2)
{
T::const_iterator first1(c1.begin());
T::const_iterator last1(c1.end());
T::const_iterator first2(c2.begin());
T::const_iterator last2(c2.end());
for (; first1 != last1 && first2 != last2; )
{
if (*first1 < *first2)
++first1;
else if (*first2 < *first1)
++first2;
else
return true;
}
return false;
}
3 ±âŸ
3.1 numeric_limits<float>::min != numeric_limits<int>::min
numeric_limits<T>::min(), max() ÇÔ¼ö°¡ ¹ÝȯÇÏ´Â °ªÀº Á¤¼öÇüÀÏ ¶§¿Í ½Ç¼öÇüÀÏ ¶§ÀÇ Àǹ̰¡ Ʋ¸®´Ù.
- std::numeric_limits<int>::min() = -2147483648
- std::numeric_limits<int>::max() = 2147483647
- std::numeric_limits<float>::min() = 1.175494E-38
- std::numeric_limits<float>::max() = 3.402823E+38
Áï ½Ç¼öÇüÀÇ ÃÖ¼Ò°ªÀº À½¼ö ÂÊÀ¸·ÎÀÇ ÃÖ´ë°ªÀÌ ¾Æ´Ï¶ó, ½Ç¼öÇüÀ¸·Î Ç¥ÇöÇÒ ¼ö ÀÖ´Â °ª Áß¿¡¼ 0¿¡ °¡Àå °¡±î¿î °ªÀÌ´Ù. ÀÌ´Â º¸Åë »ç¿ëÇÏ´Â FLT_MIN, FLT_MAX °ªÀÇ °æ¿ì¿¡µµ ¸¶Âù°¡Áö´Ù. »ç½Ç Àú³ÑÀÌ ¸®ÅÏÇÏ´Â °ªÀÌ FLT_MIN, FLT_MAX °ªÀÌ´Ï...
¾î·µç Á¤¼öÇü°ú ºñ½ÁÇÑ Àǹ̷Πmin °ªÀ» ãÀ¸·Á Çß´Ù¸é, std::numeric_limits<float>::min()ÀÌ ¾Æ´Ï¶ó, -std::numeric_limits<float>::max()¸¦ È£ÃâÇØ¾ßÇÑ´Ù.
Á¤¼öÀÇ ¼¼°è¿¡¼ »ì´Ù°¡, ½Ç¼öÇüÀÇ ¼¼°è·Î µé¾î¿À´Ï ³°¨... -_-
3.2 »ý¼ºÀÚ¿¡¼ °¡»ó ÇÔ¼ö È£ÃâÇϱâ
CppDebuggingTips ÆäÀÌÁö¿¡µµ Àû¾î³õ¾ÒÁö¸¸, ±âº»ÀûÀ¸·Î »ý¼ºÀÚ¿¡¼ °¡»ó ÇÔ¼ö¸¦ È£ÃâÇÏ´Â °ÍÀº ÇÇÇØ¾ßÇÒ ÀÏÀÌ´Ù. ÇÏÁö¸¸ ÃÖÁ¾ Ŭ·¡½º°¡ ¾î¶² Ŭ·¡½º³Ä¿¡ µû¶ó º£À̽º Ŭ·¡½ºÀÇ µ¿ÀÛÀÌ ´Þ¶óÁ®¾ß ÇÏ´Â °æ¿ì°¡ ÀÖ´Ù¸é -- 3D ¿£Áø °°Àº °÷¿¡¼ ¸®¼Ò½º ÃʱâÈ¿Í °ü·ÃÇØ¼ ÀÌ·± ÀÏÀÌ ²Ï ÀÖ´Â ¸ð¾ç -- ¾Æ·¡¿Í °°Àº ¸ð¾çÀ¸·Î ÇÏ¸é µÈ´Ù.
#include <stdio.h>
class base
{
public:
base() { initialize(); };
protected:
virtual void virtual_function()
{
printf("callling base class virtual function\n");
};
base(int i) {};
void initialize(){ virtual_function(); init_more(); };
void init_more() { printf("some more base specific work here\n"); };
};
class derived : public base
{
public:
derived() : base(1) { initialize(); };
protected:
virtual void virtual_function()
{
printf("calling derived class virtual function\n");
};
void initialize() { base::initialize(); init_more(); };
void init_more(){ printf("some more derived specific work here\n"); };
};
int main()
{
base abc;
printf("=========\n");
derived def;
return 0;
}
callling base class virtual function
some more base specific work here
=========
calling derived class virtual function
some more base specific work here
some more derived specific work here
3.3 static_cast vs reinterpret_cast
3.4 ¹è¿ ¾ÈÀÇ ¾ÆÀÌÅÛ °¹¼ö ¾Ë¾Æ³»±â
3.5 ºü¸¥ atan2
¹º°¡ ³ÀâÇѵ¥... Á» Á¤¸®ÇؾßÇÒ µí.
#include <math.h>
#include <assert.h>
#define ASSERTS_ENABLED 1
#ifndef PI
#define PI 3.14159265358979323846
#endif
static inline float interp( float r, float a, float b )
{
return r*(b-a) + a;
}
enum {NUM_ATAN_ENTRIES =1000};
static float pATanTBL[NUM_ATAN_ENTRIES+1];
static void createTrigTBLS(void)
{
unsigned int i;
for(i=0; i < NUM_ATAN_ENTRIES+1; i++)
{
float y = 10.f;
float x = y / i * NUM_ATAN_ENTRIES;
pATanTBL[i] = (float)atan2(y, x);
}
}
inline float CheckReturnA(double Angle, double x)
{
#ifdef ASSERTS_ENABLED
static double maxerr = 0;
double err = ::fabs( Angle - x );
if ( err>maxerr ) maxerr = err;
#endif
/*
const double ERROR_VALUE = 1e-4;
if (Angle < (x) - ERROR_VALUE || Angle > (x) + ERROR_VALUE)
throw "Incompatible values found at CheckReturn()";
return float(x);
*/
return x;
}
#define CheckReturn(x) { CheckReturnA(Angle,(x)); return float(x); }
static double calcAngle( float x, float y )
{
float di = (y/x)*NUM_ATAN_ENTRIES;
unsigned int i = int( di );
if ( i>=NUM_ATAN_ENTRIES )
return ::atan2( y, x );
return interp( di-i, pATanTBL[i], pATanTBL[i+1] );
}
float MMATan2(float y, float x)
{
#if ASSERTS_ENABLED
float Angle = (float)atan2(y,x);
#endif
if(y == 0.f) // the line is horizontal
{
if( x > 0.f) // towards the right
{
// the angle is 0
CheckReturn(0.f);
}
// toward the left
//CheckReturn(PI);
return (PI);
}
// we now know that y is not 0 check x
if(x == 0.f) // the line is vertical
{
if( y > 0.f)
{
CheckReturn(PI/2.f);
}
CheckReturn(-PI/2.f);
}
// from here on we know that niether x nor y is 0
if( x > 0.f)
{
// we are in quadrant 1 or 4
if (y > 0.f)
{
// we are in quadrant 1
// now figure out which side of the 45 degree line
if(x > y)
{
CheckReturn(calcAngle(x,y));
}
CheckReturn((PI/2.f) - calcAngle(y,x));
}
// we are in quadrant 4
y = -y;
// now figure out which side of the 45 degree line
if( x > y)
{
CheckReturn(-calcAngle(x,y));
}
CheckReturn(-(PI/2.f) + calcAngle(y,x));
}
// we are in quadrant 2 or 3
x = -x; // flip x so we can use it as a positive
if ( y > 0)
{
// we are in quadrant 2
// now figure out which side of the 45 degree line
if ( x > y)
{
CheckReturn(PI - calcAngle(x,y));
}
CheckReturn(PI/2.f + calcAngle(y,x));
}
// we are in quadrant 3
y = -y; // flip y so we can use it as a positve
// now figure out which side of the 45 degree line
if( x > y)
{
CheckReturn(-PI + calcAngle(x,y));
}
CheckReturn(-(PI/2.f) - calcAngle(y,x));
}
3.6 ºü¸¥ sqrt
float InvSqrt(float x)
{
float xhalf = 0.5f*x;
int i = *(int*)&x;
i = 0x5f3759df - (i >> 1);
x = *(float*)&i;
x = x*(1.5f - xhalf*x*x);
return x;
}
float FastSqrt(float x) { return 1.0f / InvSqrt(x); }
FAST INVERSE SQUARE ROOT (PDF)
3.7 Ç¥ÁØ ÀÔÃâ·Â ½ºÆ®¸² ¸®´ÙÀÌ·º¼ÇÇϱâ
FILE *fpin, *fpout, *fperr;
bool in_redirected, out_redirected, err_redirected;
inredirected = outredirected = errredirected = false;
if ((fpin = freopen("stdin.txt","rt",stdin)) != NULL)
in_redirected = true;
if ((fpout = freopen("stout.txt","wt",stdout)) != NULL)
out_redirected = true;
if ((fperr = freopen("stderr.txt","wt",stderr)) != NULL)
err_redirected = true;
// do stuff with console redirected to files
if (in_redirected) freopen("CON","rt",stdin);
if (out_redirected) freopen("CON","wt",stdout);
if (err_redirected) freopen("CON","wt",stderr);
3.8 ¹ÌÈ®Á¤ ¸Å°³ º¯¼ö¸¦ ´Ù¸¥ ÇÔ¼öÀÇ ÀÎÀÚ·Î ´Ù½Ã ³Ñ±â±â
¹ÌÈ®Á¤ ¸Å°³ º¯¼ö(variable-length argument list)´Â printf ·ùÀÇ ÇÔ¼ö¿¡¼ "..." Çü½ÄÀ¸·Î ¾²ÀÌ´Â º¯¼öµéÀ» ¸»ÇÑ´Ù. °¡²û¾¿ ÀÌ º¯¼öµéÀ» ´Ù¸¥ ÇÔ¼öÀÇ ÀÎÀÚ·Î ³Ñ°Ü¾ßÇÒ ¶§°¡ Àִµ¥, ¿ø·¡ ÇÔ¼ö ¾Õ¿¡ v°¡ ºÙÀº ¹öÀü(printf -> vprintf, sprintf -> vsprintf)À» ÀÌ¿ëÇϸé ÇØ°áÇÒ ¼ö ÀÖ´Ù.
#include <stdio.h>
#include <stdarg.h>
#include <conio.h>
void inner(const char* fmt, va_list args)
{
vfprintf(stdout, fmt, args);
vfprintf(stderr, fmt, args);
}
void outer(const char* fmt, ...)
{
va_list args;
va_start(args, fmt);
inner(fmt, args);
va_end(args);
}
int main()
{
outer("%d%s\n", 999, "gogogo");
_getch();
return 0;
} ½ºÅà Á¤¸® µî ´õ ¾Ë¾ÆµÎ¸é ÁÁÀº ³»¿ëÀÌ Àִµ¥, ÀÌ¿¡ °üÇÑ °ÍÀº
Special Issues with Varargs Functions¸¦ Âü°íÇϽöó.
3.9 ¹ÌÈ®Á¤ ¸Å°³ º¯¼ö ó¸®
printf ·ùÀÇ ÇÔ¼ö ¸¸µé±â »ùÇà ¼Ò½º. µüÈ÷ ÀÌ·± ÇÔ¼ö¸¦ ¸¸µé ÀÏÀº ¾øÀ» °Í °°´Ù¸¸ Ȥ½Ã³ª ½Í¾î ±â·ÏÇØ µÐ´Ù. Visual C++ 8.0 ¿ëÀ¸·Î ¸¸µç ¼Ò½ºÀ̸ç, ´Ù¸¥ ÄÄÆÄÀÏ·¯¿¡¼ ÄÄÆÄÀÏÇϱâ À§Çؼ´Â xxx_s ·ùÀÇ ÇÔ¼ö¸¦ °íÃÄÁà¾ßÇÑ´Ù.
void my_sprintf(char* output, size_t length, char* fmt, ...)
{
va_list argptr;
int precision = 10; // À¯È¿ ÀÚ¸´¼ö´Â ±âº» 10ÀÚ¸®
int decimal = 0; // ¼Ò¼ýÁ¡ À§Ä¡
int nagative = 0; // À½¼ö ¿©ºÎ
char temp[256] = {0}; // Àӽà ¹öÆÛ
va_start(argptr, fmt);
for (char* cur=fmt; *cur; ++cur)
{
memset(temp, 0, sizeof(temp));
if (*cur != '%')
{
sprintf_s(temp, sizeof(temp), "%c", *cur);
strcat_s(output, length, temp);
continue;
}
switch (*(++cur))
{
case 'd':
_itoa_s(va_arg(argptr, long), temp, sizeof(temp), 10);
strcat_s(output, length, temp);
break;
case 'f':
_ecvt_s(temp, sizeof(temp), va_arg(argptr, double), precision, &decimal, &nagative);
memmove(temp + decimal + 1, temp + decimal, strlen(temp) - decimal + 1);
temp[decimal] = '.';
if (nagative)
{
memmove(temp + 1, temp, strlen(temp) + 1);
temp[0] = '-';
}
strcat_s(output, length, temp);
break;
case 's':
strcat_s(output, length, va_arg(argptr, char*));
break;
default:
strcat_s(output, length, cur);
break;
}
}
va_end(argptr);
}
3.10 ÆÄÀÏ ·Î±× ÇÔ¼ö
³ª¸§´ë·Î ¿©·¯¹ø °íÃļ ¸¸µç ÆÄÀÏ ·Î±× ÇÔ¼ö. ¾ÆÁ÷ ¸î °¡Áö ¿¡·¯ 󸮰¡ ºüÁ® ÀÖÁö¸¸, ²Ï ¾µ¸¸ÇÏ´Ù. ¤Ñ¤Ñ;
/// \brief ÆÄÀÏ¿¡´Ù ·Î±×Çϱâ
/// \param szFilename ·Î±×¸¦ Ãâ·ÂÇϰíÀÚ ÇÏ´Â ÆÄÀÏ À̸§. NULLÀÏ °æ¿ì,
/// ½ÇÇà ÆÄÀÏÀÇ À̸§¿¡´Ù ".log"¸¦ ºÙ¿©¼ Ãâ·Â ÆÄÀÏ·Î »ç¿ëÇÑ´Ù.
/// \param fmt ·Î±× Æ÷¸Ë
/// \param ... ·Î±× ³»¿ë
void filelog(const char* szFilename, char* fmt, ...)
{
ofstream file;
if (szFilename != NULL)
{
file.open(szFilename, ios::out | ios::app);
}
else
{
char szModulePathname[_MAX_PATH*2] = {0,};
::GetModuleFileName(NULL, szModulePathname, _MAX_PATH);
::strcat(szModulePathname, ".log");
file.open(szModulePathname, ios::out | ios::app);
}
if (file.is_open())
{
time_t now = time(0);
file << ctime(&now) << " : ";
va_list valist;
va_start(valist, fmt);
char stack_buf[512] = {0,};
int nchars = _vsnprintf(stack_buf, sizeof(stack_buf)-1, fmt, valist);
if (0 < nchars || nchars < sizeof(stack_buf))
{
stack_buf[sizeof(stack_buf)-1] = 0;
file << stack_buf << endl;
}
else
{
int buflen = sizeof(stack_buf);
char* heap_buf = NULL;
do {
buflen = buflen * 2;
heap_buf = reinterpret_cast<char*>(::realloc(heap_buf, buflen));
memset(heap_buf, 0, buflen);
nchars = _vsnprintf(heap_buf, buflen, fmt, valist);
} while (nchars < 0 || nchars >= buflen);
heap_buf[buflen-1] = 0;
file << heap_buf << endl;
::free(heap_buf);
}
va_end(valist);
}
}
3.11 º¹»ç »ý¼ºÀÚ ¹× ´ëÀÔ ¿¬»êÀÚ ¸·±â
ÄÄÆÄÀÏ·¯°¡ ÀÚµ¿À¸·Î »ý¼ºÇÏ´Â º¹»ç »ý¼ºÀÚ¿Í ´ëÀÔ ¿¬»êÀÚ´Â ÁÖÀÇÇÏÁö ¾ÊÀ¸¸é ¾Ë±â Èûµç ¹ö±×¸¦ ¸¸µé¾î³¾ ¶§°¡ ÀÖ´Ù. ±×·¯¹Ç·Î óÀ½ºÎÅÍ º¹»ç¸¦ ¿øÇÏÁö ¾Ê´Â Ŭ·¡½º¸¦ ¸¸µé ¶§´Â ¾Æ·¡¿Í °°Àº ¹æ½ÄÀ¸·Î ¸¸µå´Â °ÍÀÌ ÁÁ´Ù. BoostLibrary ³»ÀÇ boost::noncopyableÀ» Âü°í·Î ÇØ¼, ÇÊ¿äÇÑ ±â´ÉÀ» Ãß°¡ÇÑ °ÍÀÌ´Ù.
¼Ò½º
#pragma once
//////////////////////////////////////////////////////////////////////////////
/// \class Noncopyable
/// \brief º¹»ç »ý¼ºÀÚ³ª ´ëÀÔ ¿¬»êÀÚ°¡ »ç¿ëµÇ¸é °ï¶õÇÑ Å¬·¡½ºµéÀº ÀÌ Å¬·¡½º¸¦
/// privateÀ¸·Î »ó¼ÓÇϸé, ÄÄÆÄÀÏ ¶§ ¿¡·¯°¡ ¹ß»ýÇÏ¸é¼ º¹»ç »ý¼ºÀÚ³ª ´ëÀÔ
/// ¿¬»êÀÚ¸¦ »ç¿ëÇÒ ¼ö ¾ø´Ù°í ¾Ë·ÁÁØ´Ù.
//////////////////////////////////////////////////////////////////////////////
class Noncopyable
{
protected:
Noncopyable() {}
~Noncopyable() {}
private:
Noncopyable(const Noncopyable&);
const Noncopyable& operator = (const Noncopyable&);
};
#ifdef _MSC_VER
// º¹»ç »ý¼ºÀÚ¸¦ »ý¼ºÇÏÁö ¸øÇß½À´Ï´Ù.
#pragma warning(disable:4511)
// ÄÄÆÄÀÏ·¯¿¡¼ ÁÖ¾îÁø Ŭ·¡½º¿¡ ´ëÇÑ ´ëÀÔ ¿¬»êÀÚ¸¦ »ý¼ºÇÒ ¼ö ¾ø½À´Ï´Ù.
#pragma warning(disable:4512)
#endif
/// »çÁ¤»ó NoncopyableÀ» ¹Ù·Î »ó¼Ó¹ÞÁö ¸øÇϴ Ŭ·¡½º¿¡¼,
/// º¹»ç »ý¼ºÀÚ ¹× ¿¬»êÀÚ¸¦ ¸·±â À§ÇÑ ¸ÅÅ©·Î
#define DECLARE_NONCOPYABLE(NAME) private: \
NAME(const NAME&) {} \
NAME& operator = (const NAME&) { return *this; }
»ç¿ë¿¹
class MustNotCopy1 : private Noncopyable
{
...
};
class MustNotCopy2 : list<SomeThing>
{
DECLARE_NONCOPYABLE(MustNotCopy2)
...
}
3.12 Àӽà º¯¼ö ÇÊ¿ä ¾ø´Â ġȯ ¸ÅÅ©·Î
#define SWAP(A,B) { (A) ^= (B) ^= (A) ^= (B); } º¸´Ù½ÃÇÇ XOR ¿¬»êÀ» ÀÌ¿ëÇϱ⠶§¹®¿¡, ¼ýÀÚ Å¸ÀÔ(int, unsigned int, float µî) º¯¼ö¿¡¸¸ Àû¿ë °¡´ÉÇÏ´Ù. Â÷¶ó¸® std::swap()À» ¾²´Â °ÍÀÌ ³ªÀ» ¼öµµ...
3.13 ¼Ò¼ö üũÇϱâ
bool is_prime(int n)
{
if (n == 2) return true;
if (n == 1 || n % 2 == 0) return false;
int limit = n / 2;
for (int k = 3; k <= limit; k += 2)
if (n % k == 0)
return false;
return true;
}
3.14 2ÀÇ ½Â¼ö üũÇϱâ
¾Æ·¡ÀÇ ÇÔ¼ö´Â ÁÖ¾îÁø Àμö°¡ 2^n ÇüÅÂ, Áï 2ÀÇ ½Â¼öÀÏ ¶§ true¸¦ ¹ÝȯÇÑ´Ù.
bool isPowerOfTwo(int x)
{
return (!(x & (x-1)));
}
SeriousMoin v1 (koMoinMoin 1.0a4 Modified)