mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Well from my understanding, you are sharing the objects between your different objects, i.e. the Graph and Edge objects contain pointers to shared Nodes. In this case, of course storing the objects directly is out of the question, or at least one of the two objects that hold the shared Node, must store it as a pointer, otherwise the instance of Node that is shared will not be the same (i.e. copies of each other).

So you're right to use pointers. But watch out! Typically in a graph architecture, you need to define rules of ownership (i.e. who is responsible for destroying the instance of a Node to which several other objects (Graph, Edge, Node) hold a pointer to). Then, you have to worry about the order of destruction, such that an object which holds a pointer to a Node for which he doesn't have ownership, should not access it after the owner has destroyed it. This can become quite tricky. Then, you have cycles or semi-cycles to worry about as well.

Luckily, Boost Smart Pointers give you a nice trio of smart pointers that can really help in graph-like object hierarchies: shared_ptr, weak_ptr, unique_ptr (all now part of TR1 standard library, i.e. tentative release 1). A shared_ptr is a reference-counted pointer, meaning that it will automatically destroy only when all copies of that shared_ptr are deleted or gone out-of-scope. This can allow you to make sure no pointers to a Node will suddenly point to the freed …

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

In this case, if the two objects are of the same class, then you can fairly easily just pass one object to a method called on the other and act on both objects in that method. In code:

class player {
  .. all the stuff you posted ..
  public:
    void fight(player& opponent) {
      hp -= opponent.atk;
      opponent.hp -= atk;
    };
};

int main() {
  .. all the stuff you posted ..
  one.fight(two);
  ..
};

I assumed that atk means attack (power) and hp means health points. On that, I would recommend that you try and use more complete names rather than acronyms for variable names, this will help you in the long-run for debugging and understanding your own code (and for us to understand better too).

>>not sure about inheritance...new to classes :-D
Well, if you don't feel ready to tackle inheritance just yet, and that's understandable, just know that you shouldn't try to program anything too big in object-oriented programming before reaching the point of being able to use inheritance and all the advantages of it (it's essential in OOP). It's ok to start step by step, but you might want to get into inheritance soon rather than later.

Anyway, putting inheritance aside, one thing you could do in this case, that is typical of games or simulators, is to use a managing class. In your battle scenario, I would suggest you make a class called "battle" whose data members are the players and other …

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

These messages are useless, what are the "error" messages? the "in member.." just tells you where the erroneous code was called from. You should have later on some messages saying "error" and giving the file and line, e.g. "my_header.h(42)" for an error in my_header.h at line 42.

Generally, you should literally copy-paste the error messages and Google them, and you will find solutions for your problems.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

And you should probably also make the operator == constant as well:

bool operator==(const Node &) const;

//.cpp
bool Node::operator ==(const Node& node) const {
  return node.getName() == getName();
};
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

On the main() function, see this SO-thread. Your prof is wrong on this matter. Even the original C standards have always defined main as returning an int, although the old standards allowed to omit the return type, in which case the int type was implied. This was changed in C99 standard and is no longer allowed. Also, it is possible that compilers accept a non-standard void main(). Finally, some C compilers may not complain if you don't give a value to return. Thus, in some weird old-standard inspired, but non-standard C compiler, this would be possible:

main() { //here return type is omitted but implied as int, not void.
  ...
  return; //or no return statement at all. All compilers I know would not allow this.
};

You are right about the wide-chars, they occupy two bytes of memory but represent one character. I don't know exactly how you write a literal wchar_t that has a non-ASCII value (> 0xFF), but still, it's not with 'ab' for sure.


Instead of arguing with your prof. Put him in front of a computer with C / C++ compilers (which are strictly compliant with the latest standard C99 and C++03 or C++0x-draft) and ask him to compile his own code snippets.

nbaztec commented: Thank you. +1
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

I think arkoenigs answers makes a lot of sense, and I trust that he's right.

By opposition to C and C++, look at Pascal and Object Pascal (or Delphi). Delphi has nested functions because it was extended from Pascal that already had those too. It's a matter of linking strategies and other compiler intricacies (like arkoenig mentioned), which are quite different in C++ and Delphi (I know, I started in Delphi, and it took me a while to move from the Smart Linker of Delphi to the so-called Stupid Linker of C++, which is arguably better, or worse, opinions are quite evenly split on that, as far as I know). There are obviously more issues than just "Is it a nice feature? Yes! then we'll add it!" I think none could argue that nested functions are useless, but are they worth the trouble? Especially based on C, it's quite a hassle to add that feature, as arkoenig said.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Well first, you need types for "position,item,success" unless these are types already, but I doubt it from the names. Intuitively I can guess it should be "(int position, aDataType item, bool& success)". Then, "List" here is repetitive, I would take it out. As in:

class List {
  public:
    bool Insert(int position, aDataType item); //just return success? as bool return value.
    bool Remove(int position); //same here... try not to use delete.
    int Length(); //return the length as int, and no need for (void)
    bool IsEmpty(); //return the state as bool, and no need for (void)
};
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

I don't know of any way to do this... try iostreams in this case, they allow you to set precision formats as functions like setprecision(3) or whatever, this will allow a variable number.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

@Garrett: >>there's no way to do it without using a pointer vector
For the record, Nothing is impossible in C++:

class SuperClass {
  public:
    class Impl {
      public:
        virtual void someMethod() = 0;
        virtual Impl* clone() throw() = 0;
        virtual ~Impl() throw() { };
        SuperClass Encapsulate() throw() { return this; };
    };
  private:
    Impl* pImpl;
    SuperClass(SuperClass::Impl* aImpl = NULL) throw() : pImpl(aImpl) { };
  public:
    void someMethod() { pImpl->someMethod(); };
    ~SuperClass() throw() { delete pImpl; };
    SuperClass(const SuperClass& aObj) throw() : pImpl(aObj.pImpl->clone()) { };
    SuperClass& operator =(const SuperClass& aObj) throw() { pImpl = aObj.pImpl->clone(); return *this; };
};

class SubClass1 : public SuperClass::Impl {
  public:
    virtual void someMethod() { .. };
    virtual Impl* clone() throw() { return new SubClass1(*this); };
    SubClass1(const SubClass1& aObj) throw() : ... { ... };
    ...
};

int main() {
  std::vector<SuperClass> objects;
  objects.push_back((new SubClass1)->Encapsulate());
  ...
};
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

If you want to modify the pointer primary (which was in either primary->left or primary->right in the recursive caller), you need to pass the pointer by reference. Because modifying primary in the above code snippet is not going to affect the original tree that you pass to Merge. So, simply change the prototype of your Merge function to something like this:

void Merge(node* &primary,node* &secondary)

For the rest, I can't really tell if your function will work before you explain further how your tree is structured.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Well this is not the first time on this forum that people have posted weird problems while using Windows Vista / 7 and Dev-C++ (a combination that has many known issues). I recommend you try another IDE, like Code::Blocks and see if the problem persists.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

>>My class (or should I use struct?)
Well classes and structs are essentially the same in C++, the only difference really is that by default all data members declared in a class are private, while the default for struct is public. So in your code, you won't be able to access the members of Inventory, you need to do either one of these options:

class Inventory {
  public: //make data members public.
    string ItemName;
    int ItemQty;
    float ItemPrice;
};

struct Inventory { //change to struct, and data members will be public by default.
    string ItemName;
    int ItemQty;
    float ItemPrice;
};

Then as sfuo said, pass the vector by reference and not by pointer, that should get you going further towards solving your problems with this code.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

There is a another, a bit twisted way of achieving the lookup table without having to implement a lookup table: using a shared library (.so) and linking dynamically to it. This way you can use dlsym(handle, some_null_terminated_string_command_name) to get the function pointer for your command. Then all you need to do is put all your command functions inside a shared library and export them with their proper name.

To pass multiple parameters, take example of the main(int argc, char** argv) prototype. If you make all your command functions with the same format as that. You can parse the command-file just like the linux terminal parses them before launching the executable (space-separated arguments with special handling of double-quotes) and send the list of arguments to your commands and allow them to parse them internally for what ever data they need.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

@AD: <string> is technically part of the C++ standard library, not the C++ standard template library (STL), these are two distinct libraries.

Ancient Dragon commented: right +31
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

>> >>I can't use iostream (not linux compatible)
>>How the hell told you that lie?
It may not be a lie.. I suspect that the OP is running this code on a very peculiar platform (e.g. micro-controller) that could have a very non-standard implementation of Linux, because otherwise why would he not be able to use C++ libraries?

>>That leaves only one other alternative -- a series of if statements.
Lets not give up so fast.. object-oriented programming still has plenty of tricks that could help in this case, if we only knew enough about the case.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

>>I can only use C library functions
Well in the posted examples, you can reasonably easily replace <string> with <string.h> and <iostream> with <stdio.h> and <stdlib.h>. And then the functionality is similar but you need to deal with char* instead of std::string and printf / scanf instead of std::cout and std::cin. That's no big deal, but a little more work of course, but you have no choice. The only problem is in my example where a std::map is used as a lookup-table. For that you can make your own lookup-table like in the first post from Ketsuekiame. But I don't understand why the <map> header cannot be included in your code because it's STL, which only needs you to have the headers (there are essentially no pre-compiled code attached to it) so if you can use C++ syntax, but no C++ standard library, well.. <map> is not, strictly-speaking, part of the "standard library", it's part of "standard TEMPLATE library" (a headers-only library that can compile on any naked environment with a C++ compiler and the STL headers).

>>I've been advised not to use lookup tables.
How else are you going to find the command that corresponds to a string? Unless you want to shackle yourself in the rigid format of a switch statement. The only better way than a naive lookup table is a hash table, and that is what std::map implements. Lookup tables are not recommended in the sense that they are usually not the nicest …

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

@SkyDiploma: Man.. you are evil!
@racoon: Stay away from the evil temptation of making your own class named string in the std namespace.. if there is a Hell for programmers this will certainly send you there.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

First of all, the memory leak comes from this line:

m_pText = new char[nTotLen + 1];

Because before this line, m_pText already points to allocated memory, so you need to add a delete statement before:

if(m_pText)
  delete[] m_pText;
m_pText = new char[nTotLen + 1];

If you have also a similar delete statement in the destructor of String, then you don't need that "delete[] Stemp.m_pText" statement in this function, because when the function scope ends, the Stemp.m_pText will be deleted. That brings me to the heap memory exception you are getting. If you delete Stemp.m_pText and don't set it to NULL, when the destructor of Stemp executes (as the function scope ends) it will try to delete memory that has already been delete which will throw a heap memory exception, or worse, will corrupt the heap.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

@firstPerson: That's just because <string> is probably included by <iostream>.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

NO

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

The output is not exactly 0.0 because floating-point values on a computer can NEVER be exact. You can format the output such that it doesn't display in scientific notation (like with a big negative exponent, as I assume it does now).

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

For any platform, you can use Boost Date_Time library to do anything you want, and you can even get time in MICROSECONDS.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

>>its like having 2 classes derived from logger that implement the virtual functions(one in this case) differently?

Exactly.

In this case it is very trivial because it's only one line of code different. You could just as well have a bool data member in your class Logger and it would work fine too:

/* logger.h */
class Logger
{
  public:
    bool CreateLog(const std::string &name, bool overwrite = true);
    void Write(const std::stringstream& stream);
    void CloseLog(void);
    Logger(bool aIsSync = true) : log(), IsSync(aIsSync) { };
    virtual ~Logger() { };
  protected:
    std::ofstream log;
    bool IsSync;
};

/* logger.cpp*/
void Logger::Write(const std::stringstream &stream)
{
	log<<stream;
        if(IsSync)
	  log.flush();
}
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Your problem is that a function pointer is essentially a C feature and does not support methods (that is a function acting on an object). So you can only make function pointers to static class methods or global (or namespaced) functions.

>>As i think you can see i basically want the logger to be able to be set in either mode (at any time but i only intend to use it once at the start)
Why not use polymorphism? Try something like this:

/* logger.h */
class Logger
{
  public:
    bool CreateLog(const std::string &name, bool overwrite = true);
    void Write(const std::stringstream& stream);
    void CloseLog(void);
    virtual ~Logger() { };
  protected:
    virtual void WriteLog(const std::stringstream &stream) = 0;
    std::ofstream log;
};

class SyncLogger : public Logger {
  protected:
    void WriteLog(const std::stringstream& stream);
};
class AsyncLogger : public Logger {
  protected:
    void WriteLog(const std::stringstream& stream);
};
/* logger.cpp*/
void Logger::Write(const std::stringstream &stream)
{
	WriteLog(stream);
}

void AsyncLogger::WriteLog(const std::stringstream &stream)
{
	log<<stream;
}

void SyncLogger::WriteLog(const std::stringstream &stream)
{
	log<<stream;
	log.flush();
}

Then at the start, you create either a SyncLogger or a AsyncLogger depending on the case.

There are many other solutions also, that I'm sure will come up on this thread. But function pointers is really not a particularly good one (I would say the worst.. function pointers are deprecated in C++ as far as I'm concerned).

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

I agree with Narue, I have never heard of legitimate certifications for C/C++. In my experience, only experience rings well in employers ears. But personal experience counts too, don't be satisfied with the exercises from a course or book, take some initiative to start your own projects and get experience that way. Then, you may join some open-source projects to gain more professional experience while you are still at school or looking for a job. If you came out of school and have no experience outside of coursework, then it looks pretty bad.. I hope that's not your situation. On the other end, if you have no academic background or "certification" in C++, but have a lot of experience, then don't worry about a "certification" or something, the experience will be impressive enough to possible employers (unless they are brain-dead!), at least that's from my experience and the people I know. For example, in the 3D game industry (which is almost exclusively in C++), in many places, not even half of the people have a computer science degree of some sort, let alone "certifications", many are just talented programmers, sometimes even coming straight out of high-school. If you prove you are talented and experienced by your record of past projects it will far surpass any "certification" or amount of exams you passed and what grades you got.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

OP>>I would like to avoid using atoi function.
You can use stringstream for converting between strings and other types, in the same way you take input from cin and output to cout.

For the rest, I think AD answered pretty well.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Well basically, for rendering it (displaying it) there are two main libraries, OpenGL and Direct3D. I am familiar with OpenGL, which also has a few possibly useful utility tools like GLUT (some extra functions, and cross-platform windows), GLUI (some functions for User Interfaces), and OpenInventor (for some tools to load models, display simple 3D objects and their 3D transformations). Basic tutorials for OpenGL from NEHE are very helpful to start, and it has example code mainly in C++, but also in about two dozen other programming languages.. it's all pretty much the same anyway. They will also show how to apply the translation and rotation transformations.

For moving 3D objects, there are two things to handle, translation and rotation. The former is a piece of cake, the latter can be a real nightmare. All renderers use homogeneous transformation matrices for both modelview (the motion of the 3D models) and projection (project models onto a 2D screen with a 3D look). So to learn about it, you should look into "representation of 3D rotations" and "the homogeneous transformation matrix", but I warn you, it's a bit of mathematics and geometry. I personally rely almost exclusively on quaternions for rotation, but there are options like the rotation matrix or Euler angles or Euler axis/angle which are also possible. It depends on what you want to do. For static pose of models, they are all pretty OK. If you want to do some movement (time integration of 3D rotational motion), …

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

What you need to include is <ctime>.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

I think the size (as in gradeCount, which is a more obvious name of the variable btw) NEEDS to be in the Student class because the Student holds the list of grades, so it has to know how many there are. Additionally, gradeCount SHALL be in the class Class also because all students in the Class have the same number of grades.

As for get/set methods, it's not a great idea. The gradeCount is attached to the size of this "grade" array, so changing it means changing the amount of grades too (size of the grade array). So get() is fine, but a simple set() would be wrong. If you want to change the number of grades, which I don't think you need to do, then you should have a more obvious special function like a resize() or something.

I suggest strongly, that you hold the gradeCount in the class Class and pass it to the constructor of every new student (like you have done already), to initialize the grade array to its required size and then provide no means of changing the number of grades for a student by NOT providing a setGradeCount() or resizeGrades() or any similar method in Student.

..unless your prof requires it, of course, in that case, I can't do anything about your prof's poor judgment, and you will have to implement a resize method, probably with a re-prompt for the user to enter the new grade list again.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

You can reinterpret_cast your char pointer to an int pointer or void pointer to print out its address.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

@StuXYZ.. just a little important correction, the OP should add:

virtual ~baseClass() {}; //notice the ~ for destructor

check also this thread on a very similar topic.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

This building tool is "autoconf", which is really bad compared to cmake.. but if you don't have a choice. I have worked a little with this, but not so much. The file you are looking to modify has the name "Makefile.in" in the folder where your additional source code is (along with other source code that is already properly compiled). Open that file, find a place where there is a list of other .cpp files and add your new one there. That's what I did in a similar situation and it worked, but I don't know much more about how to use autoconf.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Sure, you can use a dynamic array. I could say you can use a linked-list too, but that may be to big a step. So, yeah, if you didn't get to std::vector in your class, then I guess you should use a dynamic array, but it will be a bit more work for allocating and reallocating new memory for each add student. But if he didn't forbid you to use vectors, then maybe it's worth a look.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

@Kanoisa:
What function did you use to obtain the total memory allocated on the process heap? I used to use AllocMemSize / AllocMemCount back in my days of Delphi programming, but I have never found one for C++, so I would like to know, even if it's just for windows. (You didn't include the main source file in your zip, memoryDealloc.cpp is missing from it)

@arkoenig:
Also, for the two examples you gave. First of all, if you are going to repopulate the vector myVec after the clear(), then who cares if the clearing method used actually frees the memory or not? Second, in the example 2, the "big memory" of the original myVec will not be destroyed until temp goes out of scope, at the final } in this example, as opposed to example 1 where the "big memory" will be destroyed at the semi-colon of the same line, i.e. the end of the expression's evaluation. That's all the difference I can see. But again, both examples are ridiculous because of my first point.

Finally,
@onako:
If you are really concerned about making sure that that vector is freed exactly when you "command" it to free and for some reason you cannot make your vector go out of scope when you want it to. I see an obvious solution:

Hold your vector as a pointer and allocate it with new and then delete it when you want to fully clear it. I …

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

>>But what of constructors and get/set?
Well of course, constructors/destructors too, I didn't mention them because they are implied and I generally don't include them under "functionality" per se, they are more a part of "data" because they generally just initialize and clean up the data. As for get/set functionalities, well sure you can put them, but ask yourself, do you really need them? Often, as in your case, the data members can just be made public because they can be considered as part of the "interface" of the class. But either way you like is fine, public data members, or private data with get/set methods, or just private data with no get/set, doesn't make much of a difference in this case, IMO. If you ask me I use, most of the time, private/protected data with no get/set, in the spirit of the RAII idiom, i.e., Resource Allocation Is Initialization, but you don't need to worry about that at this point, do as you like.

>>Also, what of the function addStudent? Is that supposed to work somewhat like a resize function for students
YES, just like the push_back function in std::vector. Just adds a student to the list of students that belong to one Class, and probably calls the Student::promptUser() function to fill the data for the student at the same time.

>>why would it be located in the class Class?
This is called "ownership", a Student is owned by a Class, because a Class …

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Don't be discouraged, your code is quite good!

One mistake that solves the problems with option 2 and 3: in several places, when dealing with the marks array, you do the following for example:

for(int i=0;i<5;i++,average+=marks[i]);

Putting the "average += marks" within the for-statement's third section is not good. The problem is, first this statement does not execute on the first iteration, while i is 0, so you miss the first mark. Then, after at the last iteration, i is incremented to 5, then "average += marks[5]" is done, which reads a corrupt value from beyond the end of the array and corrupts "average", and finally i<5 evaluates to false and the loop is exited. So it should be in the loop as simply, for that example (but a similar thing is done for lines 27, 39, and 52):


for(int i=0;i<5;i++) average+=marks[i];

Finally, your name searching loop should be:

while(i<n&&(!found))
	{
                if(strcmp(nm,a[i].name)==0)
		{
			found=1;
                        break; //notice here, break out of the loop and preserve value of i.
		}
		i++;
	}
	if(found) a[i].display(); //display student i.
	else cout<<"NOT FOUND\n\n";
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Narue is right, the clear() function is not specifically guaranteed to free all the memory because for memory-optimization purposes, in general, the vector class can keep a large amount of allocated memory in anticipation of future reuse of the memory. So calling clear(), does call all destructors of the elements it contains, but it does not necessarily free the memory allocated. Narue's method will accomplish that (well I assume it will, taking Narue's word for it). Look at the difference between std::vector::size() and std::vector::capacity().

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

I prefer spaghetti bolognese to spaghetti code... boy, isn't this a mess! I think you will have to start from the start again. This is object-oriented programming. So first of all, you need to decide what data and functionality go together. In this case, it's not a very tough software design problem, you obviously have two classes to make: Class and Student. So lets examine each of them:

Class:
Data:
- should store the list of students in the class, i.e. std::vector<Student>
- should store the name of the Class, i.e. std::string (for "first grade" or else)
- should store the number of grades in the Class, since all students have equal number of grades.
Functionality (Methods):
- should be able to prompt the user for the name of the Class, the number of grades, the number students, and the students themselves.
- should be able to save all its data to a file.
- should be able to load all its data from a file.
- should be able to display the entire class on screen (std::cout).
- should be able to calculate statistics such number of girls and boys, class average for each grade, etc.

So the above is pretty much exactly how you class Class should be made. And you already have most of the code to do this, but you need to structure it properly because now all you have is spaghetti. For the …

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

The problem is that calling "cin >> ch;" will wait for the enter to be pressed, then will read the first char. This will leave the newline or '\n' character on the input stream, so the next time you do gets() to read the line, it will grab the '\n' on the input stream and assume a line was entered. Since the str is empty (or only \n), it will output an extra newline before asking to continue, and again the same cycle repeats. You should use something that will get the '\n' character in the "Continue?" prompt, not a single char. For example, this will work (I don't have conio.h so I have removed those, and you probably should too because it is not standard or portable):

char str[80];
    do
    {
      cout<<"\nEnter The String\n";
      cin.getline(str,80);
      int len=strlen(str);   // ----
      for(int i=0;i<len;i++) // these lines are useless, you can print the string back with just "cout << str;"
        cout<<str[i];        // ----
      cout<<"\nContinue?\n";
      //cin>>ch;
      cin.getline(str,80);
   }
    while(str[0]=='y' || str[0]=='Y');
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

You need to make the destructor in the base class as virtual (otherwise the base class destructor will be called directly). Try this code:

#include <iostream>

class base1 {
  public:
    virtual ~base1() { //notice virtual keyword here
      std::cout << "base1 destructor called!" << std::endl;
    };
};

class derived1 : public base1 {
  public:
    ~derived1() {
      std::cout << "derived1 destructor called!" << std::endl;
    };
};


class base2 {
  public:
    ~base2() { //notice NO virtual keyword here
      std::cout << "base2 destructor called!" << std::endl;
    };
};

class derived2 : public base2 {
  public:
    ~derived2() {
      std::cout << "derived2 destructor called!" << std::endl;
    };
};

int main() {
  base1* b1 = new derived1;
  base2* b2 = new derived2;

  std::cout << "now deleting b1 and then b2..." << std::endl;

  delete b1;
  delete b2;
};

This will output:
now deleting b1 and then b2...
derived1 destructor called!
base1 destructor called!
base2 destructor called!

I think that should answer your question. So, general rule, always make the base class destructor virtual.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

>> >>it[switch statements] doesn't make the slightest difference at the end

>>On the contrary it does. Switch statements are easier to read, cleaner, and faster
>>than ifs/else's.

OK well, to me that's a matter of opinion.. frankly I have never understood the purpose of switch statements in an object-oriented software design, and I (almost) never use them. So, I never liked them, never got used to them, and never found them easier to read or cleaner, I just find them useless and cumbersome. But you're right, they are faster, for contiguous integer case-values (or enums, of course), but not for strings (like in the OP) and most other types.

>> >>But, to be even more on the C++ side, you can use function objects

>>And to be even more more towards C++ side, you can ditch the new and delete command
>>for now, and let smart pointers handle it.

Sure that's a good point, and "delete" statements are a very rare occurrence in modern C++ code with smart pointers (in mine also, of course). But I omitted that point for a good reason: I like to preach awareness of memory management issues as a vital part of the understanding of computer programming, before giving more advanced tips. Crawl -> Walk -> Run.

Aranarth commented: Agree +1
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

I am using a switch statement, so they must be constant

Then don't use a switch statement. The switch statement is just shorter (a bit) to write then "if () {} else if () {} ...", but it's fundamentally the same. So if it is not convenient for you, don't use it, it doesn't make the slightest difference at the end.

I don't recommend you use the code from Ketsuekiame (for many reasons I won't get into). But if you want to implement a similar strategy and I understand you are allowed to use some C++ constructs, then use "std::map" in the standard header "#include <map>". You can make it as this (in the flavor of Ketsuekiame):

#include <iostream>
#include <string>

bool FunctionOne() {
   cout << "Function One Called" << endl;
};

bool FunctionTwo() {
   cout << "Function Two Called" << endl;
};

typedef (bool)(*commandFnPtr)();

std::map< std::string, commandFnPtr > lookUpTable;

bool ExecCommand(const std::string& functionName) {
  std::map< std::string, commandFnPtr >::iterator iter = lookUpTable.find(functionName);
  if(iter != lookUpTable.end())
    return (*(iter->second))();
  return false;
};

int main(int argc, char** argv)
{
  lookUpTable["command_string1"] = &FunctionOne;
  lookUpTable["command_string2"] = &FunctionTwo;

  for(int i=1;i<argc;++i) {
    if(!ExecCommand(argv[i])) {
      std::cout << "An error occurred during command '" << argv[i] << "'. Terminating application..." << std::endl;
      return 1;
    };
  };
  return 0;
};

But, to be even more on the C++ side, you can use function objects (because function pointers are essentially deprecated in C++). And you will get nice additional benefits with it such as data members that can be …

StuXYZ commented: Clearly explained. +3
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Line 17, 24, 33 are all the same and they are all wrong for one very important reason. "post_evaluation *t;" declares a pointer to a post_evaluation object, but it is not initialized. So "t" points nowhere or anywhere, which is really the same thing. You cannot use t if it was not initialized or you will get a "segmentation fault" which means you are trying to access memory that was never allocated (this will happen if you dereference a NULL pointer or a pointer that is uninitialized and thus, whose value is outside the chunks of memory that are allocated for you).

So you need to create an object, dynamically, and get its address into t. This is how:

post_evaluation *t = new post_evaluation();

You will also need to write a destructor for your class in order to free all this memory of the linked-list. Such as:

post_evaluation::~post_evaluation() {
  if( nxt != NULL )
    delete nxt;
}
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

First of all, for any type (string or other), the statement "if ( a = b )" does not check whether a is equal to b, it assigns the value of b to a, and returns the final value a (which is also the value of b). The single = sign is an assignment operator, not a comparison operator. The comparison for equality is ==, i.e. double equal sign.

Second, the strings that you are using are so-called C-strings (kept for legacy support of C code in C++). The proper string to use is the class "std::string" (in the "#include <string>" header. Using these, your code will work (with the double equal sign instead of single equal sign for comparisons).

Third, if you have to use "char *", i.e. C-strings, then there is no equality operator for it, so "a == "yes"" will not work. The proper function to compare two C-strings is strcmp(), which will return 0 if they are equal. Thus:

if( strcmp(a,"yes") == 0 )

Finally, and most importantly, having "char* a;" does not initialize "a". "a" is a pointer to an array of characters (char). By not initializing it, you have a pointer that points nowhere (well it points somewhere, but not somewhere that it should point to, because the memory at that address will be used for something else and using "a" uninitialized will corrupt your program). So, you need to initialize it by giving some space for it. Since you are …

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Well, I think tesuji answered pretty well, but if I may add something to answer your original question:

>>should I use some RDBMS or should I just write some stucts or better yet classes that relate to each other through some methods and then write them to a binary file?

Why not both? I mean using a RDBMS does not substitute for the OOD of the software. You don't want to have a software full of random spaghetti-like database calls everywhere. You should still make those fancy structs and classes to best represent and work with your data structures, then just implement them such that they store their information on the database (and you probably also want to buffer the data temporarily in the structs/classes to limit the data-traffic). That is the fundamental idea of encapsulation.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

>>anyway, is a move-constructor just copy-and-delete-constructor?
when you have a class like handlerthread which, I assume, has an internal handle to the thread that it is running (windows HANDLE or posix pthread* or boost::thread), you don't want to copy it naively (default copy-constructor), because it makes no sense to have two handlerthread objects referencing the same thread of execution. So a move-constructor, is just a copy-constructor (with a non-const reference as parameter) that copies the content of its parameter and sets the parameter into a null state (like making the internal handle = NULL). In other words, the ownership of the resources is transfered (or moved) from one object to the other during the "copy" operation. Otherwise, if an object owns resources (like a thread handle) it should not be copyable if it's not movable instead. So a move-constructor is not a "copy-and-delete-constructor", but more a "ownership-transfer-constructor", such that ownership of a resource is always unique (the "owner" is, simply put, the object that is responsible for cleaning-up the resource, and you don't want to ever have more than one).

Anyways, glad to see you found the solution to your problem!

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

First, I want to say that the little method I posted earlier is only working is some cases like the one you posted and that I tested on. I don't think it works in all cases.

So, to avoid the stride problem, I don't see how that can possibly be done. There is an inherent mismatch in the indices from the nature of the transpose operation itself. If you read in order (incrementing index by one for each read), you have to write in disorder, and vice-versa. In the bigger scheme of things, sometimes people who are really concerned with efficiency and know they will use transpose a lot, will put a flag (enum) in the matrix class to tell whether it is row-major (as for your implementation) or column-major. Effectively, you can transpose the matrix by switching the flag value, but then all algorithms using the matrix will have to be implemented for all possible cases, which is a real pain in the ass, so I don't do that.

So, all in all, I think I will not be able to help more. But this wiki might be a good source to start from, if you didn't get there already.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Your problem is with handlerthread. Are you sure that once a thread is started that it remains valid when going back to idle or when it is initially at idle? This seems to mean that the handlerthread pointer is destroyed, or its internal handle to the actual OS thread (pthread or whatever) goes invalid (i.e. terminates). So, the code of your handlerthread would be more relevant to the problem you are getting, because there is (almost) nothing wrong with your vector implementation (and vector<handlerthread*> is correct, as long as you have the code which deletes all the threads before _pool gets deleted, that would be in the destructor of threadpool).

The one thing that could possibly also cause the trouble, depending on the code that uses threadpool (which I assume is a singleton), is that you are not protecting _pool with a mutex. Look up what a mutex is and why it is almost indispensable in multi-threaded code.

BTW, vector<handlerthread> is also possible to avoid dealing to much with pointers, but you need to write a proper copy-constructor (which needs to be a move-constructor) for your handlerthread class.

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Well "master mike" is back to quote tesuji...

Your program crashes because of this portion of the code (line 40 to 52):

//For each i > j: row i - (Cij/Cjj)* row j
        i = j++;
        for(int row_i = i; row_i < N; row_i++)
        {
            for(int row_j = j; row_j <= N; row_j++)
            {
                C[row_i][row_j] = C[row_i][row_j] - ((C[i][j]/C[j][j]) * C[j][row_j]);
                cout.precision(2);
                cout.width(10);
                cout << C[row_i][row_j];
            }
            cout << endl;
        }

The problem is that you say, correctly, for each i > j, but the first line "i = j++;" will return the initial value of j and increment j. So you are starting from i = j" not "i = j + 1", this causes the first iteration to eliminate the row that is used to cancel the other rows (row j) and thus, for all other row elimination after that, you get a divide-by-zero and it crashes on an exception, I presume. (I think I actually pointed that out in your previous thread too, this is not a mistake that would go unseen by my C++ eagle eye) So replace "i = j++;" by "i = j + 1;" and it should work (not ++j because you already increment j in the outermost for-statement).

mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

>> what is the difference between (i) *p++ & ++*p

++*p : reads as follows: pointer p is dereferenced to give the variable that it points to, then this variable is incremented and its final value is returned.

*p++ : reads as follows: since postfix increment has priority over dereferencing, the pointer p is incremented by one sizeof(variable_type) step, its original value is dereferenced and the variable value at the original pointer location is returned.