Skip to content

Instantly share code, notes, and snippets.

@NatalieWolfe
Created March 9, 2017 22:50
Show Gist options
  • Save NatalieWolfe/461ce3805646fac2ecfb0a14335c01b6 to your computer and use it in GitHub Desktop.
Save NatalieWolfe/461ce3805646fac2ecfb0a14335c01b6 to your computer and use it in GitHub Desktop.
Compares strings composed of mixed digits and letters
#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