I'm having some trouble with sorting a vector that I have. That is to say, I've managed to sort it using std::sort, but I actually need it to be sorted in a more human-friendly fashion.
Basically, I have strings in my vector that are similar to the following:
IDS_STRING3
IDS_STRING10
IDS_STRING1
IDS_STRING20
etc.
And when using sort they come out as follows:
IDS_STRING1
IDS_STRING10
IDS_STRING20
IDS_STRING3
I understand why this happens, but it's not what I want. I need it so the output would be IDS_STRING1, 3, 10, 20.
You can make completely different sorting rules by using predicates.
A predicate is a function that takes two elements and returns a boolean. For example, if you have a list of 10 students (numbered 1->10) that each have a grade (student 1's grade is located in grades[0], student10's grade is located in grades[9]), you could sort it this way:
The sad thing is that your predicate function can't take any other parameters and you can't (?) define local functions, so you'll have to find a way to keep your predicate generic enough to keep it global.
In your case, your predicate will need to be able to find the numerical part of string and compare those.
[edit]
Actually, in this case, it might be sufficient to sort twice: once on number (like now) and once on string length. I think the std::sort guarantees a stable sort [i.e. the order of 'equal' elements is maintained]. As a result, the second sort (on str length) will put 100 after 10, but will keep it before 200 because they have the same str length but 200 was after 100 after the first sort.
I was using those IDS_STRING's as a test for my code. I will actually end up with strings in the following format:
IDS_STRING3 "Actuator"
IDS_STRING10 "On/Off"
IDS_STRING1 "Service"
IDS_STRING2 "some other sentence..."
etc.
So each string has the ids_string identifier and then a command. Now, if I sort this by length my results could end up incorrect. Is there a way I can split the id apart from the command and then sort?
Those ID's are just names which don't exist anymore at runtime. I honestly don't get why you'd want to sort them by the name you've given them - if you want them to be in a particular order, just insert them in that order. Other than that you COULD also define an own predicate, specifically one that maps each of your strings to a corresponding ID nr:
You could use that for comparisons (insert the strings and the corresponding ID's into the map first, of course).
A cleaner way to do this would be with a functor (avoids the global variable), or, even better, a lambda if your compiler supports them. Other than that, you don't have too many choices here.
Oh, and by the way - why do you mix C and C++ that much? IMHO: Either use C++ I/O, OR use C I/O. Not both.
Sorry, I should have explained what i'm trying to achieve in more detail.
I basically have an application that is used for translating files into other languages (i.e. chinese, romanian etc). The files that are being translated are for a program that one of our customers has been issued with by us previously and contain all commands, menu items, messages etc.
The application will be used by a translator where they select a resource id number (the IDS_STRING value) and the english string for that id is displayed. They then type out the translation and it gets stored in the equivalent language file. This all sounds straightforward so far..
However, the translated files may already contain a translation that has been inputted previously. if this is the case then that translation must be displayed to show the translator that someone has already done it. BUT the translator has the ability to correct any incorrect translations that have been inserted at a prior moment in time.
Also, the translations can be written in any order (i.e. they may choose to start from the last id and work their way backwards).
These are the reasons for needing the IDS_STRINGS to be in order.
So, it looks like defining my own predicate is the way to go then? I'll have a deeper look into that now.
And my apologies, I don't usually work in c++ so that's why it's a bit mixed up, but i'll work on sorting that out :)
I'm still not sure why you require sorting. As long as they have the ID, they can look up any IDS/command pair. Let the data structure determine how to organize them; as long as it can store and access them easily, why would you care about the order they're saved in?
Maybe it's just the technique i'm using that's wrong then, but the files are actually text files (they get converted to rc files at a later stage), so at the moment when the user selects a resource number from a numeric up and down box, the ids_string is displayed from pulling the equivalent line from the text file (so if the user selects resource id 5, the 5th line is read from the text file). That's why I require them to be stored in the correct order.
I'd happily use another way of doing it, but after researching I couldn't find anything, hence using my own make-shift (and perhaps shoddy) technique.