Created
March 9, 2017 22:50
-
-
Save NatalieWolfe/461ce3805646fac2ecfb0a14335c01b6 to your computer and use it in GitHub Desktop.
Compares strings composed of mixed digits and letters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <cctype> | |
#include <iostream> | |
#include <string> | |
int get_int(const std::string& str, std::size_t& i) { | |
int val = 0; | |
for (; i < str.size() && std::isdigit(str.at(i)); ++i) { | |
val *= 10; | |
val += (int)str.at(i) - (int)'0'; | |
} | |
return val; | |
} | |
/** | |
* @brief Compares composite strings made up of numbers and letters. | |
* | |
* Numeric sections of strings are compared as numbers while alpha sections are | |
* compared as strings. For example, a normal string comparison would put | |
* `"foo2"` after `"foo10"` (the character `'1'` vs `'2'`). This comparitor | |
* would put `"foo2"` _before_ `"foo10"` (the number `10` vs `2`). | |
* | |
* @param a - A string possibly consisting of letters and numbers. | |
* @param b - Another string possibly consisting of letters and numbers. | |
* | |
* @return Less than zero if `a` comes before `b`, greater than zero if `a` | |
* comes after `b`, or zero if they are equal. | |
*/ | |
int smart_compare(const std::string& a, const std::string& b) { | |
std::size_t aI = 0; | |
std::size_t bI = 0; | |
while (aI < a.size() && bI < b.size()) { | |
const int aC = (int)a.at(aI); | |
const int bC = (int)b.at(bI); | |
if (std::isdigit(aC) && std::isdigit(bC)) { | |
int aNum = get_int(a, aI); | |
int bNum = get_int(b, bI); | |
if (aNum != bNum) { | |
return aNum - bNum; | |
} | |
else { | |
continue; | |
} | |
} | |
if (aC != bC) { | |
return aC - bC; | |
} | |
++aI; | |
++bI; | |
} | |
if (aI < a.size()) { | |
return (int)a[aI] - 0; | |
} | |
else if (bI < b.size()) { | |
return 0 - (int)b[bI]; | |
} | |
else { | |
return 0; | |
} | |
} | |
int main() { | |
std::cout << "a vs b: " << smart_compare("a", "b") << std::endl; | |
std::cout << "b vs a: " << smart_compare("b", "a") << std::endl; | |
std::cout << "foo vs bar: " << smart_compare("foo", "bar") << std::endl; | |
std::cout << "4 vs 10: " << smart_compare("4", "10") << std::endl; | |
std::cout << "10 vs 4: " << smart_compare("10", "4") << std::endl; | |
std::cout << "foo4 vs foo10: " << smart_compare("foo4", "foo10") << std::endl; | |
std::cout << "foo10 vs foo4: " << smart_compare("foo10", "foo4") << std::endl; | |
std::cout << "foo10bar vs foo4bar: " << smart_compare("foo10bar", "foo4bar") << std::endl; | |
std::cout << "foo10bar5 vs foo10bar30: " << smart_compare("foo10bar5", "foo10bar30") << std::endl; | |
std::cout << "foo vs foo: " << smart_compare("foo", "foo") << std::endl; | |
std::cout << "foo vs foo6: " << smart_compare("foo", "foo6") << std::endl; | |
std::cout << "foo6 vs foo: " << smart_compare("foo6", "foo") << std::endl; | |
std::cout << "foo6bar vs foobar: " << smart_compare("foo6bar", "foobar") << std::endl; | |
std::cout << "foobar vs foo6bar: " << smart_compare("foobar", "foo6bar") << std::endl; | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment