Duoas 1,025 Postaholic Featured Poster

Thanks Ed. I'm glad you've got such a sharp eye. I didn't even think of that...

Duoas 1,025 Postaholic Featured Poster

Ah. This is called an "associative list", which is a degenerate form of S-expression.

Remember that a binary tree is nothing more than a collection of nodes where each node links to two other nodes (a left node and a right node) and optionally contains a value. In a true binary tree, a value would be a leaf node itself, and branch nodes would not contain anything but links.

The best way I can answer your question without just giving you the answer is that you should get out a piece of paper and draw your binary tree. Forgive the ASCII art, but this is what I drew:

word 1-------------------------------line 1--END
  |                                    |
word 2----------------line 1--END    line 2--END
  |                     |              |
word 3--line 1--END   line 2--END    line 3--END
  |       |             |              |
 END    line 2--END    END           line 4--END
          |                            |
        line 3                        END
          |
         END

For word nodes, in each case the left branch leads to the next word, while the right branch leads to line number nodes. And again, for line number nodes, each left branch leads to the next line number and the right branch is unused.

Hope this helps.

Duoas 1,025 Postaholic Featured Poster

Your Vector3 is missing the appropriate copy constructor.

A good rule of thumb is if you use any one of copy constructor, assignment operator, or virtual destructor, then you need all three. (Not always, but usually.)

Hope this helps.

Duoas 1,025 Postaholic Featured Poster

It depends on the atom.

Carbon is a tetravalent element, so all you have to do is check to see that all four links are not NULL.

For example:
[edit] good grief, sometimes editing is such a pain...

struct atom_t
  {
  std::string   name;
  double        weight;
  vector <atom_t*> bonds;

  atom_t( const std::string& name, double weight, int valence ):
    name( name ), weight( weight ), bonds( valence )
    { }
  };

atom_t* carbon()   { return new atom_t( "carbon",   12.0107, 4 ); }
atom_t* hydrogen() { return new atom_t( "hydrogen", 1.00794, 1 ); }

...
Duoas 1,025 Postaholic Featured Poster

I'm sorry, but I'm really tired right now and maybe I'm just missing something.

It looks to me like all you have is an ordered list.

Do you mean to have just a simple form of associative container, for example:

type
  p_integer   = ^integer;
  p_word_node = ^t_word_node;
  t_word_node = record
    word_key:   string;
    word_value: p_integer;
    next_node:  p_word_node
    end;

This is basically a degenerate tree, which is semantically the same as a single-linked list:

p_word_node = ^t_word_node;
  t_word_node = record
    word_key:   string;
    word_value: integer;  // the value is now part of the node, instead of a child
    next_node:  p_word_node
    end;

Did that make sense?

Duoas 1,025 Postaholic Featured Poster

It depends on how you plan to form the bonds.

If you just want to "shake the box" and let atoms connect, then you'll have to use a loop to look through what kinds of atoms you have and connect them by linking nodes.

For example, if one of the nodes identifies itself as a carbon atom, and you can find another four hydrogen atoms, then you can bind them together by linking the carbon node's four links/pointers to a hydrogen node each, and linking each hydrogen node's link/pointer to the carbon node.

Thereafter, examining any one of the linked atoms leads to the entire covalent molecule, and only encountering different atom(s) in the box that could combine for in a more convenient bond would be reason to break up the methane molecule.

Hope this helps.

Duoas 1,025 Postaholic Featured Poster

Heh, that was an interesting thread...

Yes, there is a simple, one-shot way to do it using the STL, but it is fairly advanced stuff (though I don't know why) :twisted:
Here's a little program to demonstrate it.

#include <algorithm>  // for copy()
#include <iostream>   // cin, cout
#include <iterator>   // all the funky iterators
#include <sstream>    // stringstream
#include <string>
#include <vector>

using namespace std;

//--------------------------------------
// This is the type of my polynomial in one variable.
//
struct term_t
  {
  int coefficient;  // (these could be doubles, you know)
  int exponent;
  };
typedef vector <term_t> polynomial1v_t;

//--------------------------------------
// Overload the input operator to read a term
//
istream& operator >> ( istream& ins, term_t& term )
  {
  ins >> term.coefficient >> term.exponent;
  return ins;
  }

//--------------------------------------
// Here is the one-line magic:
// This function reads a polynomial from a stream
// The stream is assumed to contain nothing but the poly's terms
//
polynomial1v_t read_polynomial1v( istream& ins )
  {
  polynomial1v_t result;
  copy(
    istream_iterator <term_t> ( ins ),
    istream_iterator <term_t> (),
    back_insert_iterator <polynomial1v_t> ( result )
    );
  return result;
  }

//--------------------------------------
int main()
  {
  string line;

  // get the terms from the user
  cout << "Please enter your polynomial terms> ";
  getline( cin, line );

  // convert them into a poly of one var
  istringstream iss( line );
  polynomial1v_t poly = read_polynomial1v( iss );

  // pretty-print the poly wanna cracker
  for (unsigned i = 0; i < poly.size(); i++)
    {
    if ((poly[ i ].coefficient >= …
Duoas 1,025 Postaholic Featured Poster

Google "linked list".

I presume each node represents a single atom?

Duoas 1,025 Postaholic Featured Poster

I'm really not sure I understand the question, but as it has been five days I figure I'll give it a shot... :-/

If it is just a matter of mixing whole games and half games, convert to the lowest common denominator: half games.

So for every whole game from the old system, just treat it as two half-games and divide the rating between them. (If the rating is just some number of points, give half to one and half to the other. If it is a statistical average or something, just factor in 2/2. Etc.)

In other words, if you get data from an old game, convert it to equivalent data for the new game and use the new game's code to manage it.

Hope this helps.

Duoas 1,025 Postaholic Featured Poster

Here's a link all about it:
Tutorial: Handling Dates and Time in Delphi.

For D5 all the date-time stuff is in the System unit. The DateUtils unit first appeared in D6. While there are some extra-friendly functions there, it isn't anything you really can't do without.

You can either write your own routines to make up the difference, or I'm sure that if you search the web you can find the DateUtils.pas unit.

Things like IncMinute are really simple. For example:

function IncMinute(
  const aDateTime:        tDateTime;
  const aNumberOfMinutes: int64
  ):                      tDateTime;
  begin
  result := ((aDateTime *MinsPerDay) +aNumberOfMinutes) /MinsPerDay
  end;

Where MinsPerDay = MSecsPerDay *60 *60; Hope this helps.
Good luck.

Duoas 1,025 Postaholic Featured Poster

The code looks fine to me.

Are you sure there isn't an extraneous #0 at the end of U?

Duoas 1,025 Postaholic Featured Poster

I don't understand why you would need a binary tree to store an ordered list of words.

Can you give a short example of what you are trying to do?

Duoas 1,025 Postaholic Featured Poster

Are you using Delphi or Pascal? (It makes a difference.)

All binary trees are just a fancy form of linked-list, so there is no reason why you can't include a string in your node record.

In Delphi:

type
  pNode = ^tNode;
  tNode = record
    word: string;
    left, right: pNode
    end;

In Pascal, I'd use a Schema type:

type
  pNode = ^tNode;
  tNode( wordsize: integer ) = record
    word: string( wordsize );
    left, right: pNode
    end;

If you can't use Schemata, then just make a simple character array:

type
  pNode = ^tNode;
  tNode = record
    word: array[ 1..80 ] of char;
    left, right: pNode
    end;

Hope this helps.

Duoas 1,025 Postaholic Featured Poster

You'll want to play with MASM32. It has everything you need.

Good luck!

Duoas 1,025 Postaholic Featured Poster

Eh, I understand. You solved it.

Your makefile looks fine to me. I usually write my makefiles by hand as well.

However, for large projects people will tend to some sort of program like automake or scons or some other like tool to manage all the dependencies in your project and automatically generate the build process for you.

Hope this helps.

Duoas 1,025 Postaholic Featured Poster

Two things:

1) char is not the same as char*. The first is a single character. The second is an address to one or more characters (like an array). Your function should take the second as argument.

2) The function prototype lists an argument, but the function itself never names it. Hence it cannot be used (and I would imagine that your compiler would complain about the mismatched prototypes anyway.)

int request( const char* );

int main()
  {
  ...
  }

int request( const char* filename )
  {
  ofstream Asker( filename, ios::trunc );
  ...
  }

Hope this helps. :)

Duoas 1,025 Postaholic Featured Poster

I'm not sure I understand your question. OpenGL programs only have one screen/view. Do you mean that you want to draw to someplace other than the OGL window?

Duoas 1,025 Postaholic Featured Poster

Yoinks! Good catch.

Line 6 should read [b]while[/b] (getline( datestream, s, '/' )) Sorry about that.

Duoas 1,025 Postaholic Featured Poster

I disagree. I think that getline() is one of those under-valued little functions that make simple parsing like this a breeze.

But like VD said, you must use it on a stream. You actually almost have it already.

vector <int> parse_date( string date )
  {
  vector <int> result;
  stringstream datestream( date );
  string s;
  while (getline( datestream, s ))
    {
    int i;
    if ((result.size() > 3) or (!(stringstream( s ) >> i)))
      {
      // invalid date
      result.clear();
      break;
      }
    result.push_back( i );
    }
  return result;
  }

int main()
  {
  vector <int> date;
  string user_input;
  cout << "Please enter a date as Y/M/D> ";
  getline( cin, user_input );
  date = parse_date( user_input );

  if (date.empty())
    cout << "That wasn't a date!\n";
  else
    cout << "The Americans would say: "
         << date[1] << '/' << date[2] << '/' << date[0] << endl;

  return 0;
  }

If you use STL algorithms you can reduce all that to four or five lines of code.

Duoas 1,025 Postaholic Featured Poster

I don't want to obnoxiously barge-in to this thread, but the STL allows you to do a lot of this stuff automatically.

#include <algorithm>
#include <iostream>
#include <iterator>
#include <limits>
#include <deque>
#include <string>

using namespace std;

int main()
  {
  deque <double> numbers;

  // Use the STL to read the list of numbers from the user
  //
  cout << "Enter the numbers you wish to sort.\n"
       << "Enter 'stop' to stop." << endl;

  copy(
    istream_iterator <double> ( cin ),
    istream_iterator <double> (),
    back_insert_iterator <deque <double> > ( numbers )
    );
  cin.clear();
  cin.ignore( numeric_limits<streamsize>::max(), '\n' );

  // Use the STL to sort them in non-descending order
  //
  sort( numbers.begin(), numbers.end() );

  // Use the STL to write them back out to the user, one per line
  //
  copy(
    numbers.begin(),
    numbers.end(),
    ostream_iterator <double> ( cout, "\n" )
    );

  // Better than pause
  //
  cout << "Press ENTER to continue...";
  cin.ignore( numeric_limits<streamsize>::max(), '\n' );

  return 0;
  }

It stops reading input as soon as the failbit is set in cin (because the user entered something other than a number on input).

If you want to sort on different criteria, you can always provide a function to compare two elements as the third argument of sort().

Everything else should be fairly self-explanatory.

Hope this was interesting.

Duoas 1,025 Postaholic Featured Poster

Do you mean you have something like this:

class Foo
  {
  private:
    Baz* baz;  // <-- This gets shared between instances.
               //     It will cause problems... (See the destructor!)
  public:
    Foo(): baz( new Baz ) { }
    Foo( const Foo& foo ): baz( foo.baz ) { }
    ~Foo() { delete baz; }
    ...
  };

And when you try to sort your program crashes?

Standard containers are notorious for copying stuff, even if you don't think you are doing something that would cause it to happen. (Of course, it is in their specification that they are allowed to do this.)

Likewise, the standard algorithms will crash and burn with a class like the one above, since you are almost guaranteed for copies to be created.

The best thing to do is either a deep copy or implement some form of reference counter. If you Google that, stay away from auto_ptr. It cannot be safely used with any STL container.

Duoas 1,025 Postaholic Featured Poster

(Sorry, I've got a splitting headache so I haven't really looked at your code...)

For a CSV file you know that the headers are there. If you load all lines into the vector then it is easy to delete them before saving again. (While a vector works fine for this, a better choice would be to use a deque. It looks exactly like a vector but it is better for handling insertions and deletions at both front and back of the list.)

// Load my list of records from the CSV file
deque <record_t> csv_data = read_csv_file( ... );
...
// Get rid of those two header records at the front of the array...
csv_data.erase( csv_data.begin(), csv_data.begin() +2 );
// ...and write what is left back to file.
write_csv_file( csv_data, ... );

Hope this helps.

Duoas 1,025 Postaholic Featured Poster

I know next to nothing about databases (because I really don't like messing with them).

But I wonder, being separate forms, are you using a separate connection to the database in each form?

It sounds to me like the second form is trying to modify something that is locked by the first form.

That's my wild stab in the dark.

Duoas 1,025 Postaholic Featured Poster

You are close, but there are a couple of things you need to fix before it will work right.

The main problem is that you forgot to adjust for the random function. You'll get a number from 0 to 44 inclusive from random( 45 ) , so you can't forget to add one to it.

Calling randomize should occur only once in the code, otherwise you are defeating the random number generator's randomness. Good places to put it are: in the DPR, in the main form constructor/OnCreate event, and in the main form's initialization section.

Finally, you forgot to free your TStringList. Typically, whenever I create a new string list I automatically add a try..finally block like:

sl := tStringList.create;
try
finally sl.free end;

This guarantees your memory not to leak from the string list.


The use of the string list to track which numbers you already have is a good idea. I also like the use of TMemo in your OnClick handler. It demonstrates good thinking.

Hope this helps.

Duoas 1,025 Postaholic Featured Poster

Sorry, haven't rebooted into Linux yet (I will before the night is through).

The way you are mixing standard I/O and curses is not very stable. In each case you must be certain to completely flush your output before doing anything else. And even then it is not guaranteed to behave perfectly on all combinations of hardware and terminfo definitions.

All things considered, why don't you just use curses for all your console I/O? Why keep switching back and forth?

If it makes a difference, you can wrap existing calls to printf() in a variadic macro. Just make sure it is included after <stdio.h>:

// cursed_printf.h

#ifndef CURSED_PRINTF_H
#define CURSED_PRINTF_H

#define printf( fmt, ... ) printw( fmt, __VA_ARGS__ )

#endif

// end cursed_printf.h

Its a kludge, to be sure, but if that's the thing holding you back...

Duoas 1,025 Postaholic Featured Poster

I think your professor means he wants you to search the array with 100 randomly generated numbers (a new random number to find for each search).

The only meaning I can get out of sequential search is just what you'd expect an unordered search to look like:
does elt 0 match? no... does elt 1 match? no... does elt 2 match? ...

You could always ask your professor for clarification.

Hope this helps.

Duoas 1,025 Postaholic Featured Poster

For all those graphic characters you are completely at the mercy of the terminfo database, which is often enough incomplete in that respect.

I typically just set the graphic characters to a nice combination of minus, pipe, and plus (-, |, +) in my initialization code.

Duoas 1,025 Postaholic Featured Poster

Alas, my first answer was a wild stab in the dark. You've done everything else I could think of.

As I know nothing more it might be worth investigating over at the codegear support forums.

Sorry I couldn't be of help.

Duoas 1,025 Postaholic Featured Poster

Yep, it works perfectly for me.

Give me a little time to switch over to my Kubuntu partition and try it there.

[edit]
Before I get that far though, if your problem is just that you aren't seeing updates right away it is because you haven't refreshed.

After line 18 should be a refresh() Hope this helps.

Duoas 1,025 Postaholic Featured Poster

It works fine for me.

BTW, you should #include <curses.h>, not <ncurses.h>, unless you have special needs on a Solaris system.

I compiled using the GCC on Windows XP and PDCurses: gcc a.cpp -lpdcurses and I tried both cases of the line 21 branch.

What OS and hardware are you using?

Duoas 1,025 Postaholic Featured Poster

x86: CMP, Jxx, JMP

MIPS: b, bne, etc.

Duoas 1,025 Postaholic Featured Poster

Actually it does have it backwards... foo = [B]this[/B]->foo; != [B]this[/B]->foo = foo; ?

Ancient Dragon commented: you are right, I should have seen that too +30
Duoas 1,025 Postaholic Featured Poster

I've not had that problem. I also don't see how you can get it when I look through Variants.pas. Are you sure the file isn't damaged in some way? (Like missing an end or somesuch?)

Duoas 1,025 Postaholic Featured Poster

Ah, you are mixing classes.

The class LeeXML has a member function named leerEntrada(), but xmlDoc does not.

You need to create a reader object first, then use it to read the document object.

xmlDocPtr doc = xmlParseFile(argv[1]);
LeeXML leador;
leador.leerEntrada( doc );

Hope this helps.

Duoas 1,025 Postaholic Featured Poster

No offense, but he already addressed that in his first post. ;) Wake up! heh heh heh

/me runs off to eat

[edit] man, too slow again... :S

Duoas 1,025 Postaholic Featured Poster

This is the reason I think making typedefs to pointers is a bad idea...

It looks like you did the right thing, but the compiler is saying that the xmlDoc class does not publish a method named leerEntrada(). It looks like you are including the correct files (since the compiler can complain about the struct _xmlDoc), so you should look in the "leeXML.h" file and check that it really does have something like the following in it.

typedef struct _xmlDoc
  {
  ...
  public:
    void leerEntrada();
    ...
  };

Is it possible that you have mis-capitalized the name of the function? LeerEntrada() Or perhaps the function is named something else? You can look through the header file to see if there is anything named to suggest reading the XML header (I presume by "entrada" it means the XML header.)

Hope this helps.

Oh, yeah, please post your code in code tags:
[[B][/B]code[B][/B]]
Code goes here
[[B][/B]/code[B][/B]]


[edit] Is the library publicly available? If it is I'll see if I can find it.

Duoas 1,025 Postaholic Featured Poster

Depending on how the data is packed.

If it is packed (MSB...LSB) ARGB then

int alpha = (color >> (3 * 8)) & 0xFF;
int red   = (color >> (2 * 8)) & 0xFF;
int green = (color >> (1 * 8)) & 0xFF;
int blue  = (color >> (0 * 8)) & 0xFF;

If it is packed in the Windows order: ABGR

int alpha = (color >> (3 * 8)) & 0xFF;
int blue  = (color >> (2 * 8)) & 0xFF;
int green = (color >> (1 * 8)) & 0xFF;
int red   = (color >> (0 * 8)) & 0xFF;

etc.

You can put these into a function for each component.

Or better yet, an ARGB_t class. You might find my response in this thread at cplusplus.com useful for some ideas. (It would be very simple to extend the RGB_t class to an ARGB_t or ABGR_t or whatever you need class.)

Hope this helps.

VernonDozier commented: Great link. +3
Duoas 1,025 Postaholic Featured Poster

I'm not sure I understand your requirements.

Is this a homework assignment to use lists?

Or is this work-work?
Do you have an existing database or do you have to design it?
How does the database update (synchronize with warehouse stock)?
What do lists have to do with it?
Is the list homogeneous or heterogeneous?
Does this have to work over a network?

Duoas 1,025 Postaholic Featured Poster

Without a working (or failing, as it were) example I don't know what to say.

If you want to use the standard I/O again you need to do as explained:

endwin();  // leave curses mode
printf( "%s\n", "Hello world! );
sleep( 2000 );
refresh();  // return to curses mode

The curses library is pretty well tested and standardized, and by no less than esr himself (who is a pretty strict coder --he's famous for good reasons), so I suspect it is something you are doing either strange with curses or something else is failing.

[edit]
Sorry, accidentally hit Post when I meant to get back into the edit window...

Also, from your last post... yes, you can do that. Either way works.

Sorry I can't be of more help without more info.
You should see who you can get to take a look over your code. A second pair of eyeballs often solves problems.

Duoas 1,025 Postaholic Featured Poster

Frankly, you've confused me a little about how you are using curses. I don't know what is causing your error, but typically a curses program will work something like:

int main()
  {
  initialize_curses_my_way();
  while (!done())
    do_stuff();
  endwin();
  return 0;
  }

If you do call endwin(), you only need to call [[B]w[/B]]refresh() to return to curses mode. I'm not sure you ever need to quit it though...

If that doesn't help, can you post a complete code snippit that I can compile and see misbehaving?

Duoas 1,025 Postaholic Featured Poster

You'll need to use the modulo (or remainder) operator: % It does what it says: cout << (123 % 10); Hope this helps.

Duoas 1,025 Postaholic Featured Poster

There are only a couple that I'd recommend.

First, straight from esr himself:
http://web.cs.mun.ca/~rod/ncurses/ncurses.html

And another very good one, replete with great examples:
http://tldp.org/HOWTO/NCURSES-Programming-HOWTO/

PDCurses is really a port of NCurses for non-POSIX platforms like Windows and the Amiga and the like. There are a few differences but those generally stem from really unportable stuff where one or the other will explicitly say YRMV.

Have fun! (And be sure to post if you get lost. A few of us here know our way around ncurses pretty well.)

Ancient Dragon commented: nice links to curses lib and tutorials :) +29
Duoas 1,025 Postaholic Featured Poster

That makes it considerably easier. Just set your dialogues to center themselves on the screen or above their parent window.

You can set this several ways:
1. Set the Position property in the Object Inspector.
2. Position the form in the dialog constructor.
3. Override ShowModal as something like the following:

int TForm1::ShowModal()
  {
  // set form position here
  ...
  // pass off to inherited
  return TForm::ShowModal();
  }

(I just typed this in off the top of my head. Some adjustments may be necessary, since I tend to use Delphi more than C++Builder for Windows GUI development).

Hope this helps.

Duoas 1,025 Postaholic Featured Poster

DialogA is in a separate exe than DialogB?

You will need to play with the STARTUPINFO structure when you call CreateProcess().

Either that or just set both dialogs to center themselves on the screen or on their parent when they are used.

Hope this helps.

Duoas 1,025 Postaholic Featured Poster

std::sort and functors
Things like std::sort() are template functions. They don't exist until you try to use them with a specific type.

What follows is functional programming concepts.

The sort algorithm takes as a third argument a binary predicate, which is a function taking two arguments and returning true or false.

In the case of the sort algorithm, the predicate returns true if the first argument is strictly less-than the second argument. For integers, such a predicate might look like:

bool int_pred( int a, int b )
  {
  return (a < b);
  }

And you can sort a list of integers with it:

// This code assumes you compile with writable constants.
int ints[ 6 ] = { 1, -7, 54, 12, 519, 42 };
sort( ints, ints +6, int_pred );

The predicate need not be an actual function (like int_pred()). It can be a function object, or what is commonly called a functor.
An int_pred functor looks much the same as the function did:

struct int_pred2
  {
  bool operator () ( int a, int b )
    {
    return (a < b);
    }
  };

The only difference now is that the function is wrapped up into an object type (or class), with the () operator properly overloaded. You could use it normally, except that you must first instantiate an object of type int_pred2 before you can use it.

if (int_pred( 10, 20 )) cout << "yeah!\n";
if (int_pred2()( 10, …
Duoas 1,025 Postaholic Featured Poster

But for whole libraries (particularly conio.h) remember jephthah's words of wisdom.

If you think your program will do very much non-C-standard stuff with the console you should look at NCurses (*nix, OS X) or PDCurses (DOS, Win, OS/2, X11, SDL, etc.).

Duoas 1,025 Postaholic Featured Poster

CLR code doesn't like it if you stick your own types into something it wants to manipulate exclusively.

Just stick the struct definition somewhere else (outside the CLR class). It won't hurt anything...

Hope this helps... (hope that works, I've never played with .NET). If worse comes to worse, you can just convert it into a regular function:

bool mysort( const std::string&a, const std:string& b )
  {
  ...
  }

and call the sort with

std::sort( myvect.begin(), myvect.end(), mysort );

Hope this helps.

Duoas 1,025 Postaholic Featured Poster

While the libraries are non-portable, don't worry too much about using _kbhit() or some other like function. If you do need to port someday, it is trivial to implement it in terms of the new platform.

While jephthah is correct that you are better off just learning to do it multi-threaded, you can multitask it yourself (particularly if you expect to run on really old hardware).

The trick is to structure your sort algorithm so that it can be called as part of a multitasking solution. This involves three things:
1. you need to write yourself an event loop
2. you need to watch the clock
3. you need to keep state between calls to your sort and read input functions

The simplest variation (and what AD was probably thinking of) would be to just check _kbhit() every now and then while sorting, and if true, store the current state of the sorting and return to the caller to get the user's input, and continue sorting after dealing with it.

Good luck.

Duoas 1,025 Postaholic Featured Poster

The best way to deal with console text alignment issues is to get out a piece of graph paper and a stylus and draw what you want it to look like. Then you can count things out so that they always match.

As for the CSV stuff, give me a day or three to finish my CSV library (since the need seems to pop up regularly). CSV files are deceptively simple, so that caveats always catch people. The C++ version is pretty much done (it needs more testing still), but the C-version is a headache to deal with variable-length strings gracefully...

(You'll like the C++ version. It is all standard containers and can even translate data types for you using the standard stream operators... Its only about 300 lines of code total not counting boilerplate.)

Duoas 1,025 Postaholic Featured Poster

You need to write the comparitor.

#include <sstream>
#include <string>

struct mysort
  {
  bool operator () ( const std::string& a, const std::string& b )
    {
    std::stringstream as( a );
    std::stringstream bs( b );
    double ad, bd;
    as >> ad;
    bs >> bd;
    return ad < bd;
    }
  };

Now you can use it with the sort() algorithm.

#include <algorithm>
#include <vector>

...

int main()
  {
  using namespace std;

  vector<string> v;
  v.push_back( "3.1,there" );
  v.push_back( "-0.7,hello" );
  v.push_back( "10.0,friend" );
  v.push_back( "3.2,my" );

  sort( v.begin(), v.end(), mysort() );

  for (unsigned i = 0; i < v.size(); i++)
    cout << v[ i ] << endl;

  return 0;
  }

Hope this helps.