Consider the following program and input file:
#include <algorithm>
#include <cstdlib>
#include <ctime>
#include <functional>
#include <fstream>
#include <iostream>
#include <iterator>
#include <string>
#include <vector>
#include "natural_compare.h"
struct natural_less: std::binary_function<std::string, std::string, bool> {
bool operator()(const std::string& a, const std::string& b)
{
return natural_compare(a, b) < 0;
}
};
std::vector<std::string> get_lines(std::istream& in)
{
std::vector<std::string> v;
std::string line;
while (std::getline(in, line)) {
if (line[0] != '#')
v.push_back(line);
}
return v;
}
int main()
{
std::srand((unsigned)std::time(0));
std::ifstream in("test.txt");
if (in) {
std::vector<std::string> v = get_lines(in);
std::random_shuffle(v.begin(), v.end());
std::sort(v.begin(), v.end(), natural_less());
std::vector<std::string>::const_iterator it = v.begin();
std::vector<std::string>::const_iterator end = v.end();
while (it != end)
std::cout<<'>'<< *it++ <<"<\n";
}
}
# Basic tests
a1
a2
a3
a10
a11
a12
# Matching value tests
b5
b 5
b05
b 5
b 05
b005
b 5
b 05
b 005
b0005
b 5
b 05
b 005
b 0005
b00005
# Second tier matching value tests
c 1 5
c 1 5
c 1 05
c 1 5
c 1 05
c 1 005
c 1 5
c 1 05
c 1 005
c 1 0005
c 1 5
c 1 05
c 1 005
c 1 0005
c 1 00005
The code obviously won't compile because the natural_compare function isn't implemented (we'll get to that shortly). But with a basic call to std::sort using the normal character ordering rules, the output would look something like this:
>a1<
>a10<
>a11<
>a12<
>a2<
>a3<
>b 5<
>b 5 <
>b 05<
>b 5<
>b 5 <
>b 005<
>b 05<
>b 5<
>b 5 <
>b 0005<
>b 005<
>b 05<
>b 5<
>b 5 <
>b00005<
>b0005<
>b005<
>b05<
>b5<
>b5 <
>c 1 5<
>c 1 5 <
>c 1 05<
>c 1 5<
>c 1 5 <
>c 1 005<
>c 1 05<
>c 1 5<
>c 1 5 <
>c 1 0005<
>c 1 005<
>c 1 05<
>c 1 5<
>c 1 5 <
>c 1 00005<
>c 1 0005<
>c 1 005<
>c 1 05<
>c 1 5<
>c 1 5 <
Not exactly intuitive unless you're a computer. Because the value of each individual character is used unconditionally in the comparison, the result is less than desirable. A more natural ordering would take numeric values into account like so:
>a1<
>a2<
>a3<
>a10<
>a11<
>a12<
>b5<
>b5 <
>b 5<
>b 5 <
>b05<
>b 5<
>b 5 <
>b 05<
>b005<
>b 5<
>b 5 <
>b 05<
>b 005<
>b0005<
>b 5<
>b 5 <
>b 05<
>b 005<
>b 0005<
>b00005<
>c 1 5<
>c 1 5 <
>c 1 5<
>c 1 5 <
>c 1 05<
>c 1 5<
>c 1 5 <
>c 1 05<
>c 1 005<
>c 1 5<
>c 1 5 <
>c 1 05<
>c 1 005<
>c 1 0005<
>c 1 5<
>c 1 5 <
>c 1 05<
>c 1 005<
>c 1 0005<
>c 1 00005<
Your challenge, should you choose to accept it, is to fill in the blanks (write the natural_compare.h header and all implementation files) such that the natural_compare function exists and can produce the naturally sorted output.
This is a software engineering problem, so there's no right answer as long as the function works as intended. You're welcome to add functionality once the basic functionality required to produce the second output has been completed. If you choose to give up and see my attempt, I'll be happy to send it to you, but give it an honest try first. There are a number of ways to solve the problem.