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

I agree, the tic tac toe game is pretty trivial to solve. The set of possible situations a player can face is very limited. And, as firstPerson mentioned, if you write a decision tree for the optimal strategy, it is very simple and unbeatable, that's too easy. Typically, to really be able to test any kind of AI, you need a scenario in which there are no unbeatable strategies, where even the stupidest strategy (usually random decisions) is expected to win at least some of the times, and where no simple strategy is optimal (in AI terms, the value-function is far from simple).

There are several such open-ended problems that could be fun to tackle. For instance, a while ago I took a machine learning course and people had all sorts of diverse AI projects to present at the end. The problem I did my class project on was a Pursuit-Evasion game. This is very simple to set-up, you just simulate a fast-moving, slow-turning pursuer and a slow-moving, highly-maneuverable evader in a 2D or 3D environment (just empty-space environments). Then you just get the pursuer to catch the evader, each starting at random points, and train both AIs to learn their respective optimal strategies, then count to number of successes of each party (if evader is still alive after X period of time, he wins, otherwise, well.. he's dead). I personally tested several AI algorithms on a slightly more complex scenario, and it isn't easy to solve (but luckily, …

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

As Narue said, the top-level cv-qualifier is discarded in function calls. This is simply because, like in your example, when you pass-by-value, the top-level cv-qualifier of the original value doesn't and shouldn't matter, because it is copied to the function anyways.

To fix the problem, simply make the parameter to print() a reference to T instead of T, as so:

#include <iostream>

template <typename T>
struct IsConst{
	enum {isConst = 0};
};

template <typename T>
struct IsConst<const T>{
	enum {isConst = 1};
};

template <typename T>
void print(T& val){ //notice the & here.
	std::cout << IsConst<T>::isConst << std::endl; //prints 1.. hurray!!
}
int main() {

	const int x = 10;

	print(x); //x will be implicitly transformed to 'const int&'

	std::cout << IsConst<const int>::isConst << std::endl; //prints 1

	return 0;
}
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Consider this simple example:

class Foo {
  public:
    virtual void f();     //one virtual function
    virtual void g() = 0; //one pure-virtual function
};

class Bar : public Foo {
  public:
    virtual void f(); //overridden 
    virtual void g(); //overridden
    virtual void h(); //one additional virtual function
};

Now, class Foo will have a virtual table that looks like this (lets assume all the function pointers are stored as void*, to make it simple):

void* Foo_vtable[] = {&Foo::f, //pointer to member function f() in Foo.
                      NULL};   //null-pointer since g() is pure-virtual.

And the virtual table for Bar will look like this:

void* Bar_vtable[] = {&Bar::f, //pointer to member function f() in Bar
                      &Bar::g, //pointer to member function g() in Bar
                      &Bar::h}; //pointer to member function h() in Bar

Notice how the additional entry (function h()) is simply appended to the list, this way, the start of the table looks exactly like the vtable of Foo and can be interpreted as such.

Also, since the virtual table is the same for all objects of one class, there is only one virtual table per class (well, multiple inheritance can complicate things a bit more, but that's the gist of it).

When writing a derived class, the compiler will generate the correct virtual table for it. If there are functions which are pure-virtual, they will have a null-entry and also make the class "abstract" which means an object cannot be created from that class directly since it would mean a …

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

The "initialization list" is what you need. This should, in fact, be used to initialize all your data members and base-classes, if possible. Here is a simple example:

mem_data::mem_data(int a,int b,std::string c) : mem_store(a), complete(b), date_file(c) { };

That's it. What is between the colon and the opening { is called the initialization list and it lists constructor calls to all the data members. If you omit a data member from that list, its default constructor is called implicitly (this is why you should prefer to initialize everything in there, because otherwise you get data members to be default-initialized, and then you give them a value, that is redundant and inefficient).

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

Install the newest version of Code::Blocks (with MinGW), a fresh install.
Other than that, I cannot help you fix problems on your computer / OS / compiler / IDE / OpenGL setup.

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

You can get MinGW from here. And you simply extract the MinGW where it was originally installed by your Code::Blocks IDE (probably within the CB install folder). It should work.

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

Redownload everything fresh. Don't try to piece stuff together. Make sure you have a recent compiler.

I mean, I am confused now, you seem to be using Windows (based on some posted code), but you have .a extensions to link libraries (indicating MinGW or Cygwin). I would not recommend trying to use OpenGL through Cygwin, if that is what you are trying to do. If using MinGW, make sure you have the latest version installed (GCC 4.5.x) (which should come with the latest OpenGL headers and libs).

For extensions, I would recommend you either use gl3w (you need Python 2.6+ installed) or glew.

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

The library for glext.h is, for microsoft, the same opengl32.lib. See here for FAQs. And here for general FAQs.

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

The math is very simple. Take the difference between two pair of points (like pt2 - pt1, and pt3 - pt1) to get two vectors, take the cross-product of the vectors, and normalize it. That's it. In other words:

void GenerateNormal(float x[3], float y[3], float z[3], float &ox, float &oy, float &oz)
{
    //get difference vectors:
    float dx1 = x[1] - x[0]; float dy1 = y[1] - y[0]; float dz1 = z[1] - z[0];
    float dx2 = x[2] - x[0]; float dy2 = y[2] - y[0]; float dz2 = z[2] - z[0];
    //cross-product:
    ox = dy1 * dz2 - dz1 * dy2;
    oy = dz1 * dx2 - dx1 * dz2;
    oz = dx1 * dy2 - dy1 * dx2;
    //normalize:
    float mag = sqrt( ox * ox + oy * oy + oz * oz );
    ox /= mag;
    oy /= mag;
    oz /= mag;
}
mrnutty commented: vedy vedy niceeee +13
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

You should try this code verbatim, it is the simplest working example, the corresponding tutorial is here. It requires GLUT and GLEW which are pretty useful utility libraries. Note also, that it is required that the "windows.h" be #included before any OpenGL headers.

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

VBOs are essentially the only drawing method that is viable and not deprecated (display lists and glBegin/glEnd are both deprecated). If you do not have glGenBuffers, glBindBuffer, and other related functions, then your OpenGL version must be either very old (more than 8 years old) or you didn't include the right headers. Make sure you have the latest OpenGL install, and that your header files and link libraries for OpenGL are also up-to-date. These functions are standard functions, if they are not there, then there is something wrong with your installation.

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

Don't use the ARB versions for GenBuffers, BindBuffer, etc. They are now part of standard OpenGL (since version 1.5, which is ancient now). Use glGenBuffers() and related functions.

The kind of hack that you are doing at the start is not recommended at all.

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

Check your version of OpenGL and the headers you have. Functions marked with the letters ARB (or EXT, or many others) are extensions to OpenGL which don't exist on older versions, and might have been promoted to official functions in newer versions. Make sure you are up-to-date and that the tutorial code you are using is also up-to-date.

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

Of course, VBOs include all the data you like, vertices, texcoords, normals, colors, and more.

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

The only things that matter between glNewList and glEndList are the OpenGL calls, and they get "frozen" (because they are compiled on the GPU). Any logic conditional statements or whatever can be used to create the OpenGL calls, but once they are created, that's it. DisplayLists themselves cannot record any logic, only the results of the logic, when applied at the construction of the List, it is fixed after that. DisplayLists are also deprecated, so I wouldn't spend much time worrying about those, better concentrate on VBOs and pixel shaders.

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

The assign function is used to completely overwrite the entire content of the vector. The overload that you are using (with an integer first and an element value second) is the overload that interprets the first parameter as the number of elements in the new vector content, and the second parameter as the value that should fill the vector. With your use, you are simply setting the vector to have 0 elements.

To read/write a particular value in a vector, you do like with a normal array, with []. As so:

bag.potions[0] = &energy_potion;
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

You are right. A typedef is nothing more than a new name for a type, in that sense, it is an alias. And, it really is just a new name for a type, not a new type in and of itself. It serves the purpose of shortening names to make the code more readable, and to associate types as nested in a class declaration (see STL containers for examples). Typedefs are especially useful in generic programming and template meta-programming, because the names of the types tend to get very long (with many template arguments). They are also useful in template meta-programming to declare the results of meta-functions. But still, typedefs are just an alias for a type. In fact, this is what they are now referred to as in the new C++ standard, as type aliases, with a new syntax:

typedef std::size_t size_type; //old syntax (still valid in C++11, of course)

using size_type = std::size_t; //new syntax.

template <typename T>
using vect_type = std::vector<T>; //new syntax allows template aliases too.
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

I think the problem is that you are looking at this problem with an oversimplified model of what a computer does and how memory is fetched. I cannot claim to be an expert, but I can try to explain my understanding of it in general terms.

What you are saying is perfectly logical when you think of memory fetching as "send a guy to the warehouse to fetch a collection of bits for you". In that very simple model, it makes sense that alignment should not matter. But, this simple model is flawed and impractical in so many ways.

Obviously, for speed, it makes no sense to "send a guy to fetch", then wait for the data to come back, and send him again on another fetch or deposit "mission". What you want, for speed, is a continuous flow of data in and out of the warehouse. So, for that, you would try to look-ahead in time to see what data items you might want in the near future and start asking for it right away (just like a restaurant doesn't wait until it runs out of food to order more from their suppliers). To perform the look-ahead at future instructions, the CPU uses an "instruction pipeline" (so it is not one instruction executing at a time, it is a whole series of instructions continuously flowing through that pipeline, where one instruction is executed, but many before and after that one are being decoded, inspected, fetched, and finalized). …

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

The "natural word size" is the 32bit in "32bit architectures" or the 64bit in "64bit architectures". It is just the size of normal integral types which are used all over the place in a program (e.g. pointers and integers).

>>i still wish i knew why about odd address's and why they cause unaligned memory accesses

It's the other way around. Misaligned memory cause "odd" addresses. Normally, compilers will align the memory to avoid "odd" addresses (and by "odd", it is meant as a non-integral multiple of the natural word size of the architecture, of course, not the regular meaning of "odd numbers"). For example, consider this class:

class Foo {
  char c;
  short s;
  int i;
};

On a 32bit architecture, the int type will normally be of 4 bytes, the short type of 2 bytes and the char type of 1 byte. So, one could expect that the above class would take 7 bytes of memory. However, the compiler is allowed to take the architecture of the computer into account and decide to align the memory on 4 bytes intervals, leading to a total size for this class of 12 bytes (5 of which are not used). This will avoid any "odd" addressing, and will generally be more efficient. There are a few ways to force a compiler not to do this alignment, but these are complicated and should not be used unless you have a really good reason to do so. And some compilers won't …

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

Your use of exception specifications is well intended, but impractical, especially for a generic class. In Herb Sutter's words, "Don't bother. Even experts don't bother.". The same goes for Boost developers. Here is an in-depth look at this issue. Just don't do it.

Second, whenever making generic types, you should use nested typedefs for just about any type used in your class. This avoids the maintainability nightmare of having to go through your entire code if you suddenly decide to change one of the types.

Finally, if you are going to be diligent and write good comments for each function, you might as well use doxygen tags (they are more descriptive, standard, used to generate automatic documentation of your code, and supported by most IDE for documentation and code highlighting).

With there recommendations, your list.h file could look like this:

#ifndef LIST_H
#define LIST_H

#include "ListOutOfExceptedRange.h"
#include "ListException.h"

//#pragma once //don't use non-standard compiler extensions.

// declaration of the class
template <typename T>
class list
{
public:
   typedef T value_type;
   typedef T& reference;
   typedef const T& const_reference;
   typedef std::size_t size_type;
   typedef std::ptrdiff_t difference_type;

   /// Default constructor.
   list();
   
   /**
    * Determines whether a list is empty.
    * \pre None.
    * \post Returns true if the list is empty,
    *       otherwise returns false.
    * \return True if the list is empty, false otherwise.
    * \throw None.
    */
   bool isEmpty() const;

   /**
    * Returns the number of elements currently stored in the list. …
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

That's just how processors are built. When one talks about the "natural word size" of an architecture, it relates to the size of the registers and the granularity of memory addressing. CPUs are expected to spend the greatest part of their time doing operations on numbers of the natural word size, it is normal to expect that they will be optimized in some way to read/write and operate on those data elements faster than any other "more unusual" data elements. This is why it is always recommended to use the natural word size (int) even if a char or short would be enough to store your largest number, because you will get a performance penalty in memory alignment, conversion, and addressing.

Think of memory alignment as if you had a big warehouse full of boxes that are all of the same "standard" size. If you didn't store things in boxes, it would be hard to find anything in the mess of all things. If you have boxes, you can assign an address to each of them and put them in order in the warehouse, so it is easy to find. Say you want to store things that are each smaller than the standard box size (say you have a bunch of jelly beans, a bunch of raisins and a bunch of M&Ms). Without memory alignment (i.e. a very stupid compiler), this would mean that you put all the jelly beans in box 1, then fill the remaining space with …

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

Your error doesn't say that NumericOperation does not exist. The error says that, at line 47, there is an "illegal use of an incomplete type". Forward declarations don't allow you to use the type/class directly, it allows you to use complete types which are related to that forward-declared type. Pointers and references are complete types, so you can use a pointer or reference to an object of the forward-declared type, but not an object of the forward-declared type because that type is not complete yet. That's just the way it is, you need to redesign such that you either don't need the forward-declaration or that have a data member of type NumericOperation in your other class (or store it via a pointer to a dynamically allocated object). From the looks of your code, I see no reason why the declaration of NumericOperation cannot be put before the declaration of CMySkaiciuokle.

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

I think you are asking the wrong question. Programming is a tool. Asking if people get bored of programming is like asking a plumber if he gets bored of using a wrench, he would probably tell you that his job is not about using a wrench but about helping people with their plumbing problems and that is what he is motivated and proud to do.

Of course, programming takes a lot more time to learn how to do well. So, during that time, it does require an eagerness to learn and general interest for programming. With that, I don't think it gets boring, unless you picked the wrong projects for you. It does get frustrating from time to time during the learning phase because nothing seem to work as you wish and you are constantly stumbling on bugs or problems that you don't know how to solve (yet). But the sooner you can start focusing on problems that you want to solve, the more motivation you have to fight through these difficulties, and if you love to solve tough problems, there are plenty of those in various applications of computer programming.

Of course, the "job" can get repetitive and boring for time to time, but what job isn't? You have to look at the bigger picture to remind yourself why you are going through this less exciting part (like refactoring a large piece of code).

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

First of all, you should only seed the random number generator once, not everytime you call rand(). So, you should seed the RNG in the constructor of randomInteger.

Second, to obtain a random number between 0 and some max-value, you can just use the modulus operator %. As so:

#ifndef RANDOMINTEGER_H
#define RANDOMINTEGER_H

#include<iostream>
using namespace std;

class randomInteger{
public:
        randomInteger();
	unsigned int operator() (unsigned int);
	unsigned time_seed();
};
#endif // RANDOMINTEGER_H

#include<iostream>
#include<time.h>
#include"randominteger.h"

using namespace std;

randomInteger::randomInteger() { 
  srand(time_seed()); 
};

unsigned int randomInteger::operator () (unsigned int max_value){
		// QUESTION: Why is Max always 2?  Or at least the times when I   run/debug it.
  return rand() % max_value;
}

unsigned randomInteger::time_seed() {
  time_t now = time ( 0 );
  unsigned char *p = (unsigned char *)&now;
  unsigned seed = 0;
  size_t i;
  
  for ( i = 0; i < sizeof(now); i++ )
    seed = seed * ( UCHAR_MAX + 2U ) + p[i];
 
  return seed;
}

Finally, I think your time_seed() function is much more complicated than it needs to be, but it should work still.

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

You need to put those #include statements for winsock and win2bth into the .c file. This is because you are going to need to #include your header file into your MinGW project, which will drag along the bluetooth windows includes that are causing problems with GCC. You don't need those includes to create your header file, so just put them in the .c file.

Second, you need to declare your functions in your header file with the extern "C" as well (in fact, that's where it matters the most).

Third, you probably want to compile this as a small DLL, so you also need to declare those functions as exported/imported, as so:

#ifdef COMPILING_DLL_MODULE
#define DLLFUNCTION __declspec(dllexport)
#else
#define DLLFUNCTION __declspec(dllimport)
#endif

extern "C" int DLLFUNCTION CreateSocket();

So that when you compile the DLL, you set the #define COMPILING_DLL_MODULE, and when you use your DLL, you use the same header, but without defining COMPILING_DLL_MODULE (thus, causing the functions to be imported).

To know if your code is working, you should first use this code with a simple main() function to test that you can connect / read / write / close successfully. Do that test on MSVC without compiling this into a DLL, that will be easier for debugging if there are any trouble. Once you know that your code works, compile it as a DLL and import it to your MinGW project.

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

A DLL is a Dynamic Link Library. It is essentially a collection of compiled functions that can be called from another executable (or another DLL). So, instead of compiling your C++ code into a executable, you compile it into a DLL with a set of functions that you want to call from your other non-C++ executable. There are some restrictions when dealing with another programming language. Essentially, all programming languages can pretty much deal with a DLL whose functions are C functions. So, you need to make all your functions that you "export" from the DLL into C functions. That means, you are confined to the rules and types of C for that function's prototype (return type and parameter types). This doesn't mean that your entire DLL needs to be in C, just the prototype of your exported functions. Moreover, you need to harmonize the "calling convention", which means your exported DLL functions should be of a standard calling convention, the safest bet is "stdcall". So, depending on your OS and compiler, the usual declaration of a DLL exported function is:

extern "C" int __attribute(__dllexport) __stdcall add(int a, int b) {
  return a + b;
};

The extern "C" tells the compiler to make this function look like a C function to the outside world (even though it is compiled in C++). The __attribute(__dllexport) tells the compiler that this function should be exported from the DLL (visible to another application to call it). And the __stdcall tells the compiler …

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

Well, obviously, your example is a straw-man, you would not want to upcast in that case.

One of the main points of Object-Oriented Programming is the concept of Polymorphism, which entirely relies on upcasting and virtual member functions. If you are not familiar with virtual functions, it is almost pointless to convince you of the purpose of upcasting. In your example, you could have:

class shape {
  public:
    virtual double getArea() const = 0; //virtual function to compute the area.
    virtual ~shape() { }; //don't forget to make the destructor virtual in the base class.
};

class rectangle : public shape {
  private:
    double width, length;
  public:
    virtual double getArea() const { return width * height; };
};

class circle : public shape {
  private:
    double radius;
  public:
    virtual double getArea() const { return 3.14159 * radius * radius; };
};

int main() {
  std::vector< shape* > v;
  v.push_back(new rectangle());
  v.push_back(new rectangle());
  v.push_back(new rectangle());
  v.push_back(new rectangle());
  v.push_back(new circle());
  v.push_back(new circle());
  v.push_back(new circle());
  v.push_back(new circle());
  
  double totalArea = 0;
  for(std::vector< shape* >::iterator it = v.begin(); it != v.end(); ++it)
    totalArea += (*it)->getArea();
  std::cout << "total area of all shapes is " << totalArea << std::endl;

  for(std::vector< shape* >::iterator it = v.begin(); it != v.end(); ++it)
    delete *it;
  return 0;
};

The point in the above example is that the vector of shapes can hold any kind of shapes (rectangles, circles, what have you), and not care of what kind of class they are, because all that is needed is …

Aranarth commented: Good post, as always +7
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

>>So the compiler does not do a typechecking seeing that the address offset is zero.
No, the C++ compiler follows strict rules, the standard is clear and will not be broken for this kind of trivial issues. Basically, since there are cases where this kind of cast would not be valid, it is simply forbidden.

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

Well, plotting a graph implies a GUI, and most GUI tools have at least basic plotting tools. One that can easily be advocated is the used Qt for the GUI and Qwt for the scientific plotting tools.

If you just want to have a plot, no GUI, I would suggest you just save the data to a ascii file (with data elements separated by spaces or tabs or commas) and use any software for plotting it, like Excel, OpenOffice-Spreadsheet, Matlab or Octave.

none of the above suggestions are "untrustworthy", you can use them without fear that they will blow up your computer!

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

>>But I cannot get hold of how OGL maps its coordinates system with respect to the screen of the computer.

This is done via something called the Projection Matrix. It is quite a simple transformation from 3D cartesian coordinates to a 3D projective geometry (which produces 2D screen coordinates and 1 depth-value). The x-y coordinates are used to place the pixels on the screen and the depth value is tested against the pixel that is already there (see glDepthTest) to determine if that new pixel should be drawn or not.

For the 3D cartesian transformations, they are obtained via homogeneous transformation matrices (well.. the projection matrix is also a homogeneous transformation matrix). The matrix that does that is called the ModelView Matrix. To understand the transformations, the main thing is to understand 3D rotations (which is not as trivial as it looks).

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

A pointer to a derived class and a pointer to a base class, for the same object, are not guaranteed to hold the same address in memory. Often, they do, but sometimes they don't. For example, when using virtual inheritance and/or multiple inheritance, then, for the same object, the pointers to different classes in the hierarchy are not the same. In that sense, an implicit cast from a derived class to a base class does not just "reinterpret" the address value as being an address to the base class, it also applies an offset to that address value. So, because the actual address value can be required to change between Derived* and Base*, to do the conversion, it creates a new pointer of type Base*, and since it is a temporary (if you don't assign it to a variable), its address cannot be taken. That is why a conversion from Derived** to Base** is impossible, you need, as Narue posted, an intermediate variable of type Base* whose address can be taken (lvalue).

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

>>Please tell me why loading textures is messing with my colours and if possible how to fix it?

The colors and texture pixels get blended together, that's just how it works. But normally, setting the color to white should leave the texture intact (e.g. setting the color to red should give a red tint to the texture, and so on).

Your problem is not with OpenGL, it is with the loading of the texture from the file and with the transferring of the image to the graphics card (with glTexImage2D). Try using another method for loading the texture, like following the NeHe's method of loading the texture, exactly.

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

First things first, don't store matrices as arrays of arrays. You need to store them contiguously, i.e., you make one big linear array and store either one column after another (column-major) or one row after another (row-major). Storing arrays of arrays is very inefficient in general.

Second, save yourself the trouble and get an off-the-shelf library for doing this. There are tons of those, from very old but significantly tested and robust (like LAPACK), to very new and sophisticated programming-wise (like Blitz++), to architecturally optimized, to GPU-based, to parallel computation-based. There are also libraries that specialize for sparse matrices or very large matrices (and btw, your matrices wouldn't really qualify as "huge", more like "not small"). Pick your choice.

Finally, if all you need is to multiply / add / subtract matrices, then these functions are really simple (like the code by monjed above), it's a trivial matter of a few nested for-loops to implement those operations.

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

>>When we use a table's name as a parameter the table is used as an address (the address of its first element)

Correct.

>>then &tab is a pointer to tab's first element address?

Correct. &tab is a pointer to the pointer to the first element in the table.

>>What does this really mean?

It means that tab is really just a pointer (if it is not a static array), and & operator takes its address (that is why it is called the address-of operator).

>>If i use new in order to create a dynamic array without deallocating the previous chunk of memory then will that lead to a problem?

Yes. This problem is called a "memory leak". The problem is not so much about allocating new memory before deallocating the previous memory (which is the correct way to do it), the problem is with overwriting the pointer value (tab) with the new address to the new memory. When overwriting, you loose the address of the previously allocated chunk of memory, since you don't have its address anymore, that memory is unreachable and thus, cannot be deallocated. The idiomatic way to reallocate memory is as such:

int* ptr = new int[10]; //original memory
  for(int i = 0; i < 10; ++i) ptr[i] = i;

  //allocating new memory:
  int* temp = new int[20]; //new memory.
  for(int i = 0; i < 10; ++i) temp[i] = ptr[i]; //copy old memory
  delete[] ptr; //delete old memory. …
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Was I right in believe that thisMyClass was out of scope in myFunction()?

No, the object was created before the function call and gets deleted after the function returns. So, unless your myFunction() does something unholy, the passed object is in scope and the pointer is valid. Of course, if the myFunction() ends up saving that pointer somewhere else (like a global variable), then you might be in trouble and should avoid doing that.

Am I right in passing by reference in this case where I am expecting thisMyClass to be changed by myFunction() ?

In general yes, prefer passing by reference when possible (which is the vast majority of the time). References are safer because they cannot be reseated, meaning that you cannot accidentally invalidate the pointer by altering its address, or easily copy the reference to a persistent (global) variable and thus keeping a reference to the object beyond the scope of myFunction(). They are also preferred because they act as aliases for a variable and thus, the syntax is cleaner and more readable when using references, which is also less error-prone.

@firstPerson:

because reference needs to be pointing to a valid object
That is not strictly true. References can point to invalid objects (or deleted objects). But it is true that it is much harder to make that bug happen with references, while it is a lot easier to make that error with a pointer.

Should I be using delete anywhere …

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

Your average computation:

average =(num1 + num2 + num3 + num4)/4;

Will not output floating-point values (i.e. with decimals), this is because the rhs (right-hand side) of the expression involves only integer values (i.e. num1-2-3-4 are integers and the literal value 4 is also interpreted as an integer value). The compiler will interpret this whole expression using "integer arithmetic". Basically, integer arithmetic performs regular math except for the division operations, because it must always yield an integer value. So, an integer division will discard the remainder of the division, for example, 4 / 3 gives 1 because 3 fits only 1 time in 4 with a remainder of 1/3 which is discarded. Integer arithmetic also include the modulus operator % (percent sign) which gives you the remainder (without the division), so 4 % 3 gives 1.

The fix is very simple. You just need to tell the compiler to switch to floating-point arithmetic (which is "normal math", as your pocket calculator would to, as in, 5 / 2 = 2.5). You can do that by adding a 0 decimal to the literal 4, as so:

average =(num1 + num2 + num3 + num4) / 4.0; //notice the .0

This makes the compiler interpret the 4 as a floating-point value, and by the rules of C/C++, the division gets "promoted" to a floating-point division instead of an integer division (i.e. the rule is essentially that for any expression, the most "sophisticated" type determines the arithmetic used for the …

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

You misplaced the parentheses on your print line. It should be:

printf("((%d / %d) + %d) * %d is %d\n\n", num1, num2, num3, num4, result); //notice ) at the end and not after the last \n".

If you are wondering why your code still compiled with the misplaced parenthesis, well, that is too long to explain. Long story short: don't use antiquated C functions like scanf/printf. Use IOstreams instead.

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

>>Are my answers correct?

Not quite. Without giving anything away..

a)
Think a bit more about what happens at "step 4: fix(q1, 2-1)". This is a recursive call (a function calling itself again, usually with different parameters, in this case, n-1 instead of n).

b)
Already, with your current answer to (a), your answer to (b) is incorrect. Once you have worked out the correct answer to (a), this should be pretty easy to answer.

c)
A precondition for fix() is: The queue exists, it is not empty, and... it has at least (blank) elements.

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

There are a few problems with your code. Let's go through them in order of importance.

First, lines 1 to 3 are called "function prototypes". These are announcing to the rest of the program that there will be three functions named "add", "output" and "input", respectively. And, it announces what parameters (how many and their types) they will take and what type of result value they yield. Later, you have the implementation (often called "definition") of the functions (with the actual code that they execute when called). It is necessary that the prototype and the definition match exactly. So, in this case, you need the following prototypes (instead of lines 1 to 3):

float add(float a, float b);
void output(float sum);        //notice the 'void' here.
void input(float a, float b);  //notice the parameters.

The error message you are getting is due to the fact that when you call the functions (or when the compiler sees the calls to your functions), the compiler only knows about the prototypes that you declared at the start, because it hasn't reached the definitions yet. So, it expects different functions from what the definitions are (different parameters and/or return type), so, the compiler gets confused and throws a compilation error.

Second, in your function "input", you pass two parameters "a" and "b" to the function. The problem is that you need to understand that these parameters are "passed-by-value", which is a one-way street. By passing parameters, you can only give values to …

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

void : is a type that acts as a place-holder for "nothing".

>>I don't understand where you get the value for "A", "C" or "rad" when it's not given a value anywhere in the code.

"A" "C" and "rad" are function parameters. A declaration like float add(float a, float b); declares a function which returns a float , the function is called "add", and it takes two parameters "a" and "b" which are each of type float . When you call the function "add", you pass a value for each parameter, then the execution enters the body of the function and, at that point, the variables "a" and "b" will have the values that were passed by the "caller". When the function is finished it returns a value using a statement like return some_value; (where "some_value" is either a variable holding a value or the result of some expression). In your sample code, the lines 14 to 16 are calling the various functions, giving them the values for the parameters "A", "C" and "rad".

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

An unsigned char is just a regular unsigned integer going from 0 to 255. Just interpret it as a regular "number" and map 0 to -1.0 and 255 to 1.0 with a simple linear mapping:

unsigned char u;
  float f;
  f = float(u) / 127.5 - 1.0;
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

Narue's answer is good, of course. But on a less formal basis, I see encapsulation and abstraction as sort of two sides of the same coin. In both cases, you usually hide away the details that the user of your library or class doesn't need to know about (hiding data and/or implementation details (like helper functions)). In a sense, encapsulation is asking yourself: What are the things the user shouldn't see? and abstraction is asking yourself: What are the only things the user should see? Most software components have things the user really shouldn't see (e.g. see the PImpl idiom) and things that are part of the interface of this software component (see "programming by contract in OOP"). In an ideal world, the split is clear, in the real world, the line is blurred, so it makes sense to think of both sides of the question (should this thing be hidden? is this thing part of the (abstract) interface?).

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

>>what is a namespace

A namespace is literally a "name-space". When programming large libraries, you need names for everything (e.g. data-types, variables, constants, classes, functions, parameters, etc., etc.). How do you make sure that the names that you pick will not conflict (or "clash") with other names in other libraries that a programmer might be using at the same time as yours? The answer is: you put it in a namespace. A namespace creates a little private world (or space) where you can name things the way you want to without fear that it will clash with other names, because those other names will be in other namespaces. It is also a way to "hide" parts of your library by putting it in another sub-namespace that is not published (often that "hiden" namespace is called "detail", by convention). For example, if I wanted to make my own version of std::vector, but I didn't want it to be confused with std::vector, but still enjoy the nice and intuitive name "vector" for the class, I could do this as so:

namespace my_lib { //this puts all the stuff between { } into namespace 'my_lib'

template <typename T>
class vector {
  //....
};

};

//The user can now use both, without conflict:
int main() {
  std::vector<int> v1; //using the standard version
  my_lib::vector<int> v2; //using my library's version.
};

The statement "using namespace std;" or "using namespace my_lib;" means that you "import" all the names that are defined in the std namespace …

Ancient Dragon commented: great :) +17
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

The right combination is:

//constructor:
Node(Expression* left, Operator op, Expression* right) {

//use:
  Value v1(3), v2(4);
  Node n(&v1, ADD, &v2);
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

You need to give pointers to the constructor, not objects. So, line 48 could be replaced by:

Value v1(3), v2(4);
  Node n(&v1, ADD, &v2);
mike_2000_17 2,669 21st Century Viking Team Colleague Featured Poster

I don't know much about BITMAP, but the info is on msdn. I usually use other more transparent and cross-platform libraries (like FreeImage for simple image IO).

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

>>Does anybody know what is causing the colour mix up?

The pixel transfer/storage. Clearly, the image is correctly loaded from the file (since you can see an undistorted NeHe icon). The problem must be with the format of the BITMAP image. I would guess that your format "GL_BGR_EXT" and "GL_UNSIGNED_BYTE" is not correct (and usually bitmap images are either GL_COLOR_INDEX or GL_RGB). Make sure that this format info matches that of the BITMAP information structure (bmBitsPixel, bmPlanes, etc.).

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

Aaargh! Microsoft strikes again!

You did things correctly. The problem with all those things (many of which start with double underscore) is that Microsoft cannot restrain themselves from using non-standard, MSVC-specific language extensions even in their SDK headers.

In this case, I would recommend that you do wrap your bluetooth calls in a piece of code that you compile with MSVC. But, that piece of code doesn't need to be a dll (could be a .lib and using the same process to link it in MinGW). Remember to expose only a C interface (extern "C").

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

As far as I know, under windows, bluetooth is provided by native OS APIs (either Bluetooth-specific functions, or through Windows Sockets). Of course, it requires that you link against "Bthprops.lib". MinGW and GCC have work-arounds to be able to link to libraries not compiled with GCC, but it is most likely that this library is a C library and linking to it should be a breeze (otherwise, look up "linking MSVC .lib in MinGW", there are tutorials on the subject).

Making your own little wrapper in MSVC, and putting it into a dll is not going to be any easier than linking with Bthprops.lib in your MinGW/GCC project directly. You shouldn't need to "transform" the .lib into a dll. I have done this in the past (but can't exactly remember how) but it is very easy (just a linker flag to set, or a simple command-line to run).

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

>>Should u not decrement objectCount in Destroy function?

The OP does not require that. If you were to assign a new Student ID for every new student, you probably don't want to decrement the counter on destruction (e.g. you create two students, with ID 1 and 2, then delete Student 1, and create a third Student, which will result in two Students with the ID 2). But, of course, for counting existing instances or reference counting of an object (e.g. in a smart pointer), then, yes, you should decrement the counter on destruction, which results in the following:

class People {
  private:
    People() { }; //constructible only from factory Create().
    ~People() { }; //destructible only from factory Destroy().
    People(const People); //non-copyable.
    People& operator=(const People&); //non-assignable.
    static int& getActivePeopleCount_impl() { 
      static int objectCount = 0;
      return objectCount;
    };
  public:
    static int getActivePeopleCount() { return getActivePeopleCount_impl(); };
    static People* Create() {
      ++getActivePeopleCount_impl();
      return new People();
    };
    static void Destroy(People* p) {
      --getActivePeopleCount_impl(); 
      delete p; 
    };
};

int main() {
  People p1 = People::Create();
  std::cout << "There are " << People::getActivePeopleCount() << " active people, now." << std::endl;
  People::Destroy(p1);
  std::cout << "There are " << People::getActivePeopleCount() << " active people, now." << std::endl;
  return 0;
};