ArkM 1,090 Postaholic

I never used _fseeki64 too. It's declared in VC++ <stdio.h>. It has the same parameters as fseek but offset parameter has long long (64-bit in VC++) type.

You have VC++ 2008 installed. Write _fseeki64, select this id then press F1 ;) or see help on fseek function.

It seems you need a very simple correction:

inline
int fseek32(FILE* stream, unsigned int offset, int origin)
{
    return _fseeki64(stream,offset,SEEK_SET);
}
ArkM 1,090 Postaholic

This fseek32 function is an implementation-dependent nonstandard trick: standard C RTL fseek/ftell expects/returns long int (signed 32-bit for VC++) values only. I think it can't move file pointers over 31-bit boundary (you see that).
Try to rewrite fseek32 with VC++ non-standard _fseeki64 function with long long (64-bit, old typename __int64) offset parameter.

ArkM 1,090 Postaholic

Think about:

/// The last cry container interface.
class MsgSink {
public:
    virtual ~MsgSink() {}
    virtual void saveMessage(const char* pmsg) = 0;
};

class A {
public:
    A():pSink(0) {}
    /// Need explicit to prevent strange casts
    explicit A(MsgSink& sink):pSink(&sink) {}
    explicit A(MsgSink*psink):pSink(psink) {}
    /// It's impossible to initialize array elements
    /// via constructor so we need a special method:
    void bind(MsgSink* psink) { pSink = psink; }
    void bind(MsgSink& sink)  { pSink = &sink; }
    void error(const char* pmsg) {
        if (pmsg && pSink)
            pSink->saveMessage(pmsg);
    }
private:
    MsgSink* pSink;
};
/// A very strange A objects shell
class B: public MsgSink {
public:
    B();
    A   aaa[3];
    const char* getLastMsg() const { return lastMsg.c_str(); }
    void saveMessage(const char* pmsg) {
        if (pmsg)
            lastMsg = pmsg;
        else
            lastMsg.clear();
    }
private:
    /// Think about std::vector to save a log...
    std::string lastMsg;
};

B::B() 
{   // Bind aaa elements to this object.
    for (size_t i = 0; i < sizeof aaa/sizeof*aaa; ++i)
        aaa[i].bind(this);
}
ArkM 1,090 Postaholic

Let's come back to your object model design.

Who is a target of an error message which a class A object setErrorMessage member function registered? If it's this object, where is this message container? No such containers in class A.

Now let's consider class B. Semantically it's a container of three class A objects + a single error message pointer. By the way, the original post title was incorrect: no parent/child relations between your A and B classes. The class B "has" A (parent/child corresponds to "is_a" predicate). Any object of class B contains some objects of class A. No any special mechanics in C++ for such relation: container elements do not have any special info about containers where they exist. An example:

B b1; // have b1.someObject[0..2] - three class A objects
B b2; // have b2.someObject[0..2] - yet another 3 class A objects
A a;	// lonely A object (seventh)

All seven class A objects do not know where they live. Suppose you invent some method to save b1.someObject[0].seErrorMessage("b1.[0]") argument in b1 container object. But where is a target of a.setErrorMessage("for orphans only") message?

I think you need redesign this error message register mechanics. For example, if you want to save container elements error messages in the container, link contained elements with a container explicitly (add a pointer to a container in class A with null pointer for lonely objects - or what else).

ArkM 1,090 Postaholic

What's a problem? Class B must be known before A::setErrorMessage definition - that's all. Collect both class definitions in .h file, include it in .cpp file with class A implementation - or simply move up class B definition in your main module just before A::setErrorMessage definition...

Apropos, you have posted "useless" snippet but on the other hand this code is an excellent example of a very bad class design ;)

ArkM 1,090 Postaholic

1. Move all function definitions to a separate .cpp file (and never, ever include them in .h files, except class templates - but it's the other story).
2. Think about month[i] = !month[i]

hurbano commented: thanks alot +1
ArkM 1,090 Postaholic

You are still mixing declarations and definitions up. Each variable in C++ can have multiple (identical) declarations but should have one and only one definition. This one definition rule was broken.
See http://en.wikipedia.org/wiki/One_Definition_Rule

There are DEFINITIONS of global variables:

CAMERA camera;	// Allocate static memory for these variables
OBJECT *obj;	// and initialize them by default.

There are DECLARATIONS of these variables:

extern CAMERA camera;	// Means: I have two global
extern OBJECT *obj;	// variables defined elsewhere

You place definitions in main.h and now you have these vars definitions in every module included main.h.

Now come back to nucleon's post...

ArkM 1,090 Postaholic
ArkM 1,090 Postaholic

It does not matter what's a name of that array. A function call binds any proper type argument to the correspondent parameter. Try to understand this mechanics.
If you know std::vector standard library containers, better rewrite your code with std::vector<Songs> (instead of Songs[] array).

ArkM 1,090 Postaholic

You must pass real (defined) objects as function arguments, that's a function call:

showSongList(titles,Num_Songs);

A function call is not the same thing as a function declaration. Alas, you ignored one of my question in the previous post, You don't declare array named titles (or what else) in the main function. The construct showSongList(titles,Num_Songs) means: call the function showSongList and pass as the 1st argument of this call the array of Songs named titles and as the 2nd argument a reference to the int variable named Num_Songs. It's impossible: no such array in the main function or in the source text before...

The next error (you will get this diagnostic message after call correction): showSongList wanted a reference to int as the 2nd parameter. You can't pass a reference to const int Num_Songs because it's possible to get const reference to int for a const variable (const means read-only). The function modifies the 2nd argument value via this reference parameter - that's why the language forbids const var to non-const reference conversion.

Yet another defect: suppose you declare an array of Songs in the main, for example:

int main()
{
    ....
    int songcnt; 
    Songs album[100];
    ...
    showSongList(album,songcnt);
    ...

What happens if you have 101 (or more) songs info in the file aPod.txt? Right, you will get "array overflow" - the program overwrite memory allocated for the array album. Pass max number of array elements as the next parameter or use std::vector instead of a plain array...

ArkM 1,090 Postaholic

Well, have you ever compile this source? If so, did you ever read compiler diagnostic messages?

You declare showSongList as a function with two parameters but you are trying to call it without arguments. Where is a definition of an array of Songs? Why you declare TWO different title entities in the function showSongList - the 1st as an array parameter and the 2nd as a local variable of string type?

ArkM 1,090 Postaholic

Don't forget to clear file state if eof was reached:

... read file until eof
    // Now f is in fail() and eof(0 state...
    f.clear(); // Now f is capable to seek...
    f.seekg(0);
... read again ...
ArkM 1,090 Postaholic

Well, we have three defects: the first one is mine, the others are yours ;)
#2: the int array maze is initialized by char data but is printed as int. The 1st 49 is (int)'1' (ASCII code of '1')...
#3: You ignored start this algorithm for every cell of the level 0 phrase...

#1: More seriously (mea culpa;) ) - we must repeat the printing of every cell on every path. For example, at cell i,j we must reprint all previous traversed cells for every downward paths. So we need some kind of path memory to print the path when the lowest level achieved.

That's my alg correction (try to improve it):

void Traverse(const int* pij, int i, int j, int m, int n, int* path)
{
    path[i++] = *pij;   // i => the next level
    if (i == m) {       // lowest level
        for (int k = 0; k < m; ++k) {
            if (k) cout << ' ';
            cout << path[k];
        }
        cout << '\n';   // path printed
    }
    else if (j == 0) {
        Traverse(pij+n,i,j,m,n,path);
        Traverse(pij+(n+1),i,j+1,m,n,path);
    } else if (j == n - 1) {
        Traverse(pij+(n-1),i,j-1,m,n,path);
        Traverse(pij+n,i,j,m,n,path);
    } else {
        Traverse(pij+(n-1),i,j-1,m,n,path);
        Traverse(pij+n,i,j,m,n,path);
        Traverse(pij+(n+1),i,j+1,m,n,path);
    }
}
/// Non-recursive starter (loop for the 1st row):
void TraverseGrid(const int* maze, int m, int n)
{
    if (!maze || m <= 0 || n <= 0)  // sentry
        return;
    int* path = new int[m]; // path trace mem
    for (int j = 0; j < 3; …
ArkM 1,090 Postaholic

What C compiler are you using? What's this pragma format description in the compiler manuals?

ArkM 1,090 Postaholic

Use the classic recursive solution approach.

Suppose you (your traverse algorithm, of course) are standing at the position (i,j) - level i (from 0 to m-1, up to bottom) column j (from 0 to n-1, left to right). That's a current point of your downward traversal, print it. Now you have possible down ways:
- 0 if j == m-1, end of traversal.
- 2 if j == 0 or j == n-1 (n > 1)
- 3 if j > 0 && j < n-2 (n > 2)
Make all possible steps (let the same algorithm continues).

At every point you have selected all possible unique downward ways. Now start this algorithm for every cell of the level 0. All done, you have printed all possible downward grid traversals...

No need in pointers, use a grid matrix directly.

ArkM 1,090 Postaholic

You forgot to add Point() constructor declaration in the class Point definition. Do it.

ArkM 1,090 Postaholic

I see you did not feel the difference ;)...

An assignment operator has a valid, initialized target object. It changes the contents of this object. A copy constructor has raw memory chunk (the same as any other constructor). It must build the object with the same content as its argument from the scratch. Alas, your copy constructor starting from the deallocation of never allocated memory (and the program gets memory exception, of course).

Look at your new copy contructor body. You delete previous contents - but NO any previous contents here! You must allocate memory for this new matrix (see p2dArray(int,int) constructor) then copy argument's data to this allocated 2-d array.

In the new default constructor you forgot to initialize the most sensitive member: the contents pointer. Therefore the constructed (empty) object has garbage valued pointer (instead of the valid null pointer). Now let's look at the class destructor. What happens when it will try to destruct an empty object with unpredictable garbage value of the contents member? Right, it will try to deallocate this "pointer to nowhere"...

It's up to you...

ArkM 1,090 Postaholic

Contrary to your source comments, the class p2dArray has no proper copy constructor(s). You define (wrong) assignment operator but don't define explicit copy constructor. A copy constructor must have (as usually) the signature:

p2dArray::p2dArray(const p2dArray&);

No such member declared in your class but default copy contructor (copy member by member) is inadequate to the dynamic nature of the contents pointer member. However return temp2d; statement in operator+ needed a copy constructor. Inadequate default copy constructor copies temp2d.contents pointer to the result matrix then temp2d object is destructed. Now result object has a pointer to deallocated memory.

That's a brief story.

Yet another remarks:
- The class has inadequate default constructor. It does not initialize members and you get unpredictable pointers and dimensions in constructed objects.
- The operator= does not check target dimensions.

Moral: feel the difference between assignment op and copy constructor...

ArkM 1,090 Postaholic

No, the copy constructor is used only when called explicitly or when an object is being initialized. You could, however, have the assignment operator call your copy constructor.

Yet another context where copy constructor works:

class C {...};
void f(C); // by value
...
C c;
f(c); // <= parameter/argument binding.
ArkM 1,090 Postaholic
#include <iostream>
using namespace std;

struct deneme
{
  int a;
  void (* myFunction)(int a);
  void look4adventures() { myFunction(a); }
};

void function1(int a)
{
  cout << a << endl;
}

void function2(int a)
{
  cout << a + a << endl;
}
int main()
{
   deneme myDeneme[] = {{1,function1},{2,function2}};
  
  myDeneme[0].look4adventures();
  myDeneme[1].look4adventures();
  
  return 0;
}
serkan sendur commented: so smart +3
ArkM 1,090 Postaholic

1. It DOES NOT work because you forgot to double backslashes in the file name string literal (see point #3 example in your snippet).
2. ? No platform-independent solution.
3. ShellExecute is a direct way to do the same job...

ArkM 1,090 Postaholic

You are trying to print an uninitialized and unexistent abc[3] element of abc array of pointers to int...
It's the hexadecimal representation of this value...

ArkM 1,090 Postaholic

The order of evaluation of operands of the operator << is unspecified by the C++ Standard. Therefore both cases in the original snippet are ill-formed. It's another case of the famous bad code example a[i] = ++i; ;)
The order of operands evaluation (from left to right) is defined for comma operator, operator && and operator || only...

Comatose commented: Fantastic Insight +10
ArkM 1,090 Postaholic

So break will break any loop? for, while, do while and swicth case? and then countinue the program from just after the loop?

What's a surprise ;) C++ as a fairy tail...
http://www.learncpp.com/cpp-tutorial/58-break-and-continue/

ArkM 1,090 Postaholic

Obviously you can't get access violation at this statement. Possible cause: stack corruption (for example, overwriting of return address) or bad (uninitialized) pointer in your code (outside of GetCellX function call). Try to go through step by step with debugger.

ArkM 1,090 Postaholic

What do you suggest I do about the gotos? I knew you would't like it,but why?

Look at
http://david.tribble.com/text/goto.html
(not from a mobile device ;) )

ArkM 1,090 Postaholic

Some remark (to the original post).
The Point newPos = myPos + yourPos; construct is not an assignment (that's why you compile w/o errors). It's default copy constructor Point(const Point&) makes an initialization.
Free advice: if you overload an assignment operator then (as usually) you are supposed to define a copy constructor too (and vice versa). It's the other story why...

ArkM 1,090 Postaholic

If the only book you've ever read on C++ is that one, then you're missing out on a wealth of information.

Is it an unsound supposition or a mild form of deliberate insult?
Have you ever seen my home library?

ArkM 1,090 Postaholic

Yet another common and portable approach: use ordinar structures to create BMP info then pack them into the final char buffer (use memcpy(buffer+offset,&member,sizeof member), move offset forward and so on). Of course, it's possible to write data to a file stream directly (no need in current write pos forwarding).
Add some syntax sugar, for example:

struct bmp_header
{
       short BM;
       long size_of_file;
       long reserve;
       long offset_of_pixle_data;
       long size_of_header;
       long width;
       long hight;
       short num_of_colour_plane;
       short num_of_bit_per_pix;
       long compression;
       long size_of_pix_data;
       long h_resolution;
       long v_resolution;
       long num_of_colour_in_palette;
       long important_colours;
    void* pack(void* pbuf) {
        char* p = (char*)pbuf;
        int i = 0;
    # define PACK(member) {memcpy(p+i,&member,sizeof member);i+=sizeof member;}
        PACK(BM)
        PACK(size_of_file)
        ...
        PACK(important_colours)
    # undef PACK
        return pbuf;
    }
       
}
HEADER;
...
   HEADER.pack(buffer)

A nasty thing but it works ;)

ArkM 1,090 Postaholic

Well, you have used a compiled, not interpretive language, so "basically everytime you create an atom object its name (and therefore all your program source text) has to be slightly different to differentiate between all the atoms created in the simulator". In other words, you must recompile, relink and reload all your program "everytime you create an atom object". It's cool! Do you find it funny? I do ;)

Think: no source program names at run-time! There are a sequence of machine instructions. What unexistence entities are you intending to change "everytime you create an atom"?

ArkM 1,090 Postaholic

Have you ever heard about pointers in C and C++?
What's "the name of the object" in your interpretation? There are anonymous objects in C and C++. Can you post pseudocode with desired "changed names"?

ArkM 1,090 Postaholic

Did you want an array of atoms?
Possible answers:
1. I don't understand you.
2. You don't know any arrays of...
?

ArkM 1,090 Postaholic

I'm sorry! Mea culpa: I have initialized that damned tm_mon by 2 (march), not by 1 (february) then seen on mday only (11 - right for march 28) :(
I have wrote lots of sensor data approximation/smoothing codes recently, that's why I prefer direct time arithmetics ;)

ArkM 1,090 Postaholic

I agree that time_t value may be in other units than seconds. It's a very simple task to scale this value because time_t is an arithmetic type capable of representing times. The "implementation-defined encoding" does not bear a relation to this fact (it's about epoch and granularity).

On the other hand a simple addition to tm_mday may produce wrong dates and the real implementation (VC++ 2008) returns a very strange results after mktime of that "new date". For example, for 2009-02-28 (109,2,28 in tm) we have (109,2,42) in tm and have 2009-02-11 after conversion this funny 2009-02-42 date.

That's one of possible scaling (portable) solutions of my previous approach:

/// Get time(0)+Later::days(d) value
class Later
{
public:
    explicit Later(int days = 0);
    static time_t days(double d = 1.0);
private:
    static double scale;
};

namespace {
    tm d1 = { 0 };
    tm d2 = { 0 };
    Later stub;
}

double Later::scale = 0.0;

Later::Later(int days)
{
    if (scale == 0.0) {
        d1.tm_year = d2.tm_year = 2009 - 1900;
        d1.tm_mon  = d2.tm_mon  = 1;
        d1.tm_mday = 1;
        d2.tm_mday = 2;
        time_t t1 = mktime(&d1);
        time_t t2 = mktime(&d2);
        double tpd = difftime(t2,t1);
        scale = tpd / 86400.0;
    }
}

time_t Later::days(double d)
{
    time_t t;
    time(&t);
    return t + static_cast<time_t>(86400.0*d*scale+0.5);
}
// Using:
time_t later14 = Later::days(14);
ArkM 1,090 Postaholic

I have no comments. I think the only good book on C++ is "The C++ Programming Language" by B.Stroustrup ;)...

ArkM 1,090 Postaholic

Well, and what's your problem now? Only inline and template function definitions are placed in .h files.
Look at http://www.daniweb.com/forums/thread165526.html. May be it helps...

ArkM 1,090 Postaholic

I didn't quite understand that. I get the idea of using a common header for system includes. But the rest I wasn't sure of. Am I right in thinking this: include all formal function declarations first, then all their definitions?

I don't understand what's "formal function declaration". Have you ever seen informal function declarations?

ArkM 1,090 Postaholic

After that think again. It seems you have wrote absolutely senseless code with this awkward jumble of std::string and C-string oriented snprintf ;)...

ArkM 1,090 Postaholic
inline time_t addDays(int days)
{
    return time(0)+86400*days;
}
time_t printNewDate(int days)
{
    time_t newtime = addDays(days);
    std::cout << asctime(localtime(&newtime));
    return newtime;
}

The time() function declared in <ctime> header returns current time in seconds.
Seconds per day: 24*60*60 == 86400.
Need more?
;)

ArkM 1,090 Postaholic

Just put all the function definitions in one header file and have all the other headers include it. That way every function knows about every other function.

That's the worst solution. Now you have a huge scrap heap of all possible interfaces. It's hard to maintain such a heap, you have drastically increased compilation time and full project recompilation overheads on every new prototype added.

Look at extremelly rational C library headers structure. Group all your global functions, typedefs and global macros by themes. Place related declarations in correspondent .h files. Include only needed .h files in .c modules. Never mix unrelated function definitions in a single .c file.

If the most of your functions use common (as usually system) headers, place correspondent includes in the single common .h file (common.h, for example). Try to use precompiled headers feature of your compiler. For example, in VC++ place all system header include directives in stdafx.h.

Now your include police looks like:

/* .c file brief description */
#include "common.h"

#include "theme1.h"
#include "utility.h"

/* theme1 function definitions */
ArkM 1,090 Postaholic

altso i never really considered which compilers are better or worse, so does anyone know about code::blocks? im using that :)is it ok?

Code::Blocks is not a compiler, it's a cross-platform Integrated Development Environment (IDE):
http://en.wikipedia.org/wiki/Integrated_development_environment
See also
http://en.wikipedia.org/wiki/Comparison_of_integrated_development_environments#C.2FC.2B.2B
The Code::Blocks IDE supports lots of C++ compilers on Windows, Linux and Mac OS X.

Yes, it's OK, the Code::Blocks is a very good IDE ;)...

ArkM 1,090 Postaholic

...but I don't understand eliminating the #include <string> . Would the preferred practice be a forward declaration of std::string?

Why not? Let a user includes all needed system headers then includes all third-party .h files then its own .h files... It looks like a honest, simple and logical solution: define system environment then define workbench environment then local environment...

That's why I prefer explicit namespace qualification in all user .h files: let this .h-file user makes decision where to place sacramental (and very dangerous) using namespace std; or avoid it.

It's also a pragmatically authorized practice. For example, it's a good practice in MS VC++ to place ALL needed system headers in the project stdafx.h file (MS VC++ pre-compiled headers container). If so, no need to include system headers in user code at all.

Worst case: your template user gets a simple and clear compiler message about std::string error. OK, he/she inserts #include <string> before include_template_definition and gets a wonderful value pair class depended on std::string ;)

ArkM 1,090 Postaholic

The std::getline function wants the 1st parameter of std::istream type so it's OK to pass std::fstream argument. Of course, file var in the snippet may be your infile.

Overloaded input operator >> returns std::istream& value (const reference to the input stream). That's why it's possible to chain input list:

stream >> a >> b; // treated as
// (stream >> a) >> b =>
// (input a then return reference to stream) >> b =>
// (dereference istream& to stream) >> b =>
// (stream) >> b
// stream >> b

There is a conversion from stream to bool (it's the other story what's this conversion mechanism, see http://faqs.cs.uu.nl/na-dir/C++-faq/part07.html, for example). If a stream is in good state then the conversion yields true, bad, eof of fail state returns false. That's why these constructs are valid, clear and simple:

if (infile) { // OK, input possible
...
while (infile >> word) { read word by word
...

There are lots of reasons to fail on file open operation: no such file (file name misprinted, file erased and so on), file access denied, disk error etc...

ArkM 1,090 Postaholic

1. Always test input result, for example:

if (infile >> month) { // that's ok
    ...
} else {
   // Not-a-number, eof or i/o error
}

2. Use code tag to post code snippets:
[code=c++] sources

[/code]
3. Probably more robust text file input method:

std::string line;
std::istringstream is;
while (std::getline(file,line)) { // read a line
    is.str(line);   // attach a line to stringstream
    is.seekg(0); // get from the beginning 
    if (is >> month) ... // read stringstream
    ... // no need to ignore upto '\n'
}
ArkM 1,090 Postaholic

1. Try to avoid exit function in C++ programs. Use return 1; to exit from main on errors.
2. Library names are placed in namespace std. You must open these names visibility by using directive ( using namespace std; ) or using declaration ( using std::ifstream; ).
3.

std::ifstream infile("input.txt");
if (! infile) {
    std::cout << "Can\'t open..." << std::endl;
    return 1;
}

Don't forget to terminate a line (use endl or at least '\n').
4. You have TWO slashes in a date, why you ignore upto slash THREE times?

ArkM 1,090 Postaholic

#1. Version 1.2 means "subversion 2 of version 1", not "version 1 + 2/10". The only reliable floating point "is equal" op is "value == 0.0".
#2. You can't declare type arrays if no accessible default constructor for the type. I can't understand why it's so dangerous to declare arrays of pairs.
#5. You open (at least a part of) outside namespace for user module code. That's obviously undesired side effect of such includes. Use qualified names: std::string, std::ostringstream etc if your template has STL dependencies. Document these dependencies. Let the template user provide all system headers for his code.
>Not sure how to avoid this in a template class?
And what's a problem?

Yet another remark. I think such "pair" templates must have two typename parameters for both members. It's so easy to get a proper template specialization for std::string as the key member type.

Conclusion: a pair of unrelated values template is not an interesting generic class because no non-trivial operations for this type. So it's not so good base to study generic programming in C++.

ArkM 1,090 Postaholic

Alas, my conclusion is: too many defects.
1. I have never seen float type version number. It's cool!
2. I don't understand why nobody can declare arrays of NameValuePair (default constructor is private). Everybody can assign arbitrary values to both pair members via setters but it's impossible to define default member values - a very strange project decision.
3. No need in explicit copy constructor and assignment operator definition: they follows by default copy constructor and assignment operator logics (do it member by member).
4. The toString() member function requires operator<<(string,type) for a template argument type but template class itself does not redefine its own operator<< for std::string. Why?
5. I consider system heaser includes and using directives in user .h files as a very bad and dangerous practice.
6. It's a good practice to place simplest template member function definitions in the class definition or declare them as inline explicitly. Ignored.
7. This class has a virtual destructor (considered as a base of) but it has no protected members: unusual and suspicious symptom.
8. No comments or rudimentary useless comments.

I think it's not a professionally designed class template. I prefer std::pair till now ;)...

ArkM 1,090 Postaholic

Quick pointer answer: you DON'T DEFINE ptr pointer variable but use it.

int *ptr; // Now ptr has a garbage value (points to nowhere)
int var;
ptr = &var; // Now ptr points to var.
*ptr = 5; // Now var has value 5.
ArkM 1,090 Postaholic

1. You forgot that strcat works with c-strings i.e. char arrays with null byte at the end of contents:

void express::parse(){
int i=0,x=0;
char ch; // it's a single char, not char array
while(i<len) {
    if (ch >= '0' && ch <= '9') {
        char* a;
        float f;
        int j=i;
        while (true) { // strcat wants char arrays but...
            strcat_s(a,20,&ch); // *** !!! *** crash

2. The NULL macros is not zero: it's null pointer value (pointer to nowhere):

float getnumber(){ return NULL; } // must be 0.0
...
char getoperator(){ return NULL; } // must be '\0'
ArkM 1,090 Postaholic

Better look at another page of this tutorial (you may change MFC to Forms etc):
http://www.winprog.org/tutorial/apivsmfc.html

No need to study flight dynamics to fly in business class. But if you want to join the F-35 project team...