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 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
|
/// CharToNum.h ; 1/22/2011
/// Rafael Perez-Santana (C) 2011
/// mr.rafael.ps@gmail.com
// THIS TOOK ME 1 WEEK TO DESIGN AND DEBUG. PLEASE APPRECIATE MY
// LACK OF SLEEP AND COUNTLESS NIGHTS & MORNINGS I STAYED UP CREATING
// CharToNum, IF YOU USE IT, HIT ME UP WITH AN E-MAIL!
// ALSO, IF YOU FIND A WAY TO IMPROVE IT, LET ME KNOW! THANKS!
// NOTE: THE ONLY INCLUDES SHOULD BE <cctype> & <cstring> ANY MORE WOULD
// VOID THE IDEA OF IMPROVING THE class & templates.
// ALSO: I KNOW ABOUT THE C++ <sstream> THAT CAN CONVERT A STRING TO
// A NUMBER. HOWEVER, AT THE COST OF INCREASING THE SIZE OF YOUR
// COMPILED PROGRAM! THIS IS WHY I CREATED CharToNum, TO AVOID
// USING <sstream> FOR CONVERSION & REDUCE COMPILE SIZE.
/// CharToNum ALSO PARSES THE <CHAR STRING> (I.E "a4556@#!!78!!2") WILL
/// CONVERT TO "4556782" GIVEN THE TYPE SUPPORTS THE SIZE OF THE OUTPUT.
/// IF YOU GET A PLAIN 0 DURING CONVERSION, TWO EVENTS MAY HAVE OCCURED;
/// 1. YOU CONVERTED A <char string> 0 TO A 0.
/// 2. THE OPERATION WAS ABORTED DUE A TYPE NOT SUPPORTED BY CharToNum.
/// SEE --> @@
#ifndef CHARTONUM_H
#define CHARTONUM_H
#include <cctype> // FOR; isdigit()
#include <cstring> // FOR; strlen(),strcat()
class CharToNum
/// CONVERTS A <char string> TO A NUMBER YOU CAN STORE IN TYPES; SHORT,
/// INT, UNSIGNED INT, LONG, UNSIGNED LONG, LONG LONG & UNSIGNED LONG LONG.
/// :: UNSIGNED SHORT IS RETARDED & NOT RECOMMENDED TO USE WITH CharToNum!!
{
private:
class SupportedTypes
// THIS CLASS HELPS TO IDENTIFY DIFFERENT TYPES.
{ public: /// IF THE TYPE IS NOT SUPPORTED; 0.
operator int() { return 1; }
operator long() { return 1; }
operator short() { return 1; }
operator long long() { return 1; }
operator unsigned int() { return 1; }
operator unsigned long() { return 1; }
operator unsigned long long() { return 1; }
/// THE FOLLOWING TYPES ARE NOT SUPPORTED BY CharToNum.
operator unsigned short() { return 0; }
operator double long() { return 0; }
operator double() { return 0; }
operator float() { return 0; }
} TypeSupport;
char*pNumStr; /// USE .c_str() FOR C++ STRINGS.
unsigned int iMemAlloc; // AMOUNT OF MEMORY TO ALLOCATE.
public:
CharToNum() // :: CONSTRUCTOR.
/// ALLOCATES MEMORY TO STORE THE <char string> THIS WAS DONE SO THAT
/// STRINGS ARE CONCATENATED WHEN THE << OPERATOR IS USED.
{
iMemAlloc=128; // SHOULD BE ENOUGH.
pNumStr=new char[iMemAlloc]; // ALLOCATE THE MEMORY.
if(pNumStr)*pNumStr='0'; // SET FIRST ENTRY TO 0.
}
~CharToNum() // :: DESTRUCTOR.
/// FREES THE ALLOCATED MEMORY.
{
if(pNumStr)delete[]pNumStr; // ONLY FREE IF NOT NULL!
}
// OVERLOAD OPERATOR << TO GET POINTER TO <char string>.
// USAGE: CharToNum YourObject; YourObject<<ACharString; (^_^)
CharToNum&operator<<(const char*pNumStr_)
/// GETS POINTER TO <char string> & STORES LOCATION IN pNumStr.
// IF YOU USE; YourObject<<"123"<<"679"; THE RESULT IS "123679".
{
if(strlen(pNumStr)<iMemAlloc) /// DO NOT EXCEED ALLOCATED MEMORY!
strcat(pNumStr,pNumStr_); // APPEND NEW <char string>
return*this;
}
/// NOTE: EVEN THOUGH << CONCATENATES THE <char strings> TOGETHER, IF THE
/// CONVERSION OUTPUT EXCEEDS THE TYPE MAX LIMIT, YOU MAY NOT GET ALL THE NUMBERS!
// OVERLOAD OPERATOR >> TO INVOKE TYPE CONVERSION TEMPLATE FUNCTION;
// USAGE: int iSomeNumber; YourObject>>iSomeNumber; LOOKS NICER!! (^_^)
template<typename T>CharToNum&operator>>(T&xData)
/// THIS CREATES A TEMPLATE THAT INVOKES YET ANOTHER TEMPLATE, LOL!!
/// IF pNumStr IS NULL, NOTHING HAPPENS, ELSE THE TYPE CONVERSION TO T().
{
if(pNumStr)xData=this->operator T(); // INVOKE TEMPLATE FOR; operator T().
return*this;
}
/// NOTE: IF THE >> OPERATOR IS USED MULTIPLE TIMES;
/// YourObject>>Number1>>Number2>>Number3; THE CONVERSION IS STORED IN
/// Number1 & THEN Number2 EQUALS Number1 & Number3 EQUALS Number2.
// INTERNAL TYPE CONVERSION TEMPLATE FUNCTION; THE HEART OF CharToNum!
template<typename T>operator T()
/// IF THE CONVERSION EXCEEDS THE MAXIMUM ALLOWED MAX LIMIT FOR A TYPE, THE
/// TYPE REVERTS TO 0 OR NEGATIVE, IF THAT HAPPENS, THE CONVERSION OPERATION IS
/// ABORTED AND THE FUNCTION RETURNS THE LAST CONVERSION OPERATION. SEE --> ##
{ T iGetNum=0,iBuffer=0; // TEMPORARY VARIABLES.
T iTYPE=TypeSupport;if(!iTYPE)return iTYPE; /// IF 0 ; TYPE IS NOT SUPPORTED. @@
for(int i=0;*(pNumStr+i)!='\0';i++) // LOOP UNTIL NULL IS FOUND.
{
/// *(NumStr+i) IS CAST TO THE TYPE (T) THE RESULT IS THE char CODE FOR
/// THE NUMBER; char(48 TO 57) REPRESENTS 0,1,2,3,4,5,6,7,8,9. BY SUBRACTING
/// 48 FROM THE char CODE, WE CAN OBTAIN THE ACTUAL NUMBER.
iGetNum=*(pNumStr+i)-48; // CONVERT char CODE TO ACTUAL NUMBER.
if(!isdigit(*(pNumStr+i)))continue; // IGNORE IF NOT A DIGIT.
if(!iBuffer){iBuffer=iGetNum;continue;} // SET TO iGetNum ON FIRST PASS.
// WE MUST CAST THE CONDITION (iBuffer*10+iGetNum) TO THE TYPE (T)!
if(T(iBuffer*10+iGetNum)<iBuffer)break; /// MUST NOT BE LESS, ABORT IF SO! ##
iBuffer=iBuffer*10+iGetNum; // MULTIPLY BY 10 & ADD iGetNum.
/// WARNING! iBuffer=iBuffer*10+iGetNum; MUST BE UNCHANGED!!
/// iBuffer*=10+iGetNum WILL CAUSE 10+iGetNum to EXECUTE FIRST!!
/// YOU DO NOT WANT THAT, iBuffer MUST BE MULTIPLIED BY 10 FIRST
/// BEFORE ADDING iGetNum!!
}
return iBuffer; // iBuffer HAS CONVERSION.
}
};
/// PS: SORRY FOR THE CAPS, IT HELPED TO SEE THE COMMENTS BETTER WHEN THE LACK
/// OF SLEEP STARTED TO KICKED IN! THIS PROJECT WAS LOTS OF FUN!! (^_^)
/// AND NO, I AM NOT JAPANESE! I JUST LIKE TO USE IT --> (^_^) LOL!
#endif // CHARTONUM_H
|