Dialogue class code for RPG

This is a discussion on Dialogue class code for RPG within the Game Programming forums, part of the General Programming Boards category; The following code draws a dialogue box on the screen with an image for the character you are talking to. ...

  1. #1
    Registered User ~Kyo~'s Avatar
    Join Date
    Jun 2004
    Posts
    320

    Dialogue class code for RPG

    The following code draws a dialogue box on the screen with an image for the character you are talking to. It has no errors and compiles fine using allegro and MSVC++ .net. Feel free to use it or mod it some and if you mod it much toss me a copy so I can see what yea did. Feedback is welcome as well.

    Special notes for this class:
    It will hold the game up ex. a fireball is about to incinerate the player the player runs to a NPC and talks - he is safe untill he is done talking.

    if BIG_FONT is not defined everything will be drawn in the small default font.
    to see the dialogue class in action check out these screen shots (bottom two):
    http://www.geocities.com/meanguy76012/PASss.html

    Dialogue.h
    Code:
    #ifndef DIALOGUE_H
    #define DIALOGUE_H
    #include <allegro.h>
    #include <fstream>
    
    #include <string.h>
    class Dialogue
    {
    	public:
    		 Dialogue();
    	void Initalize(int x,int y,char* Dia, char* Picture);
    	void DrawDialogue(BITMAP *BUFFER,FONT *big_font,RGB *PICPAL);
    	     ~Dialogue();
    	private:
    	int x;
    	int y;
    	char* Dial;
    	char* PicPath;
    };
    #endif
    Dialogue.cpp
    Code:
    #include "dialogue.h"
    
    #include <allegro.h>
    //#include <winalleg.h>
    #include <fstream>
    
    #include <string.h>
    #include <math.h>
    
    using namespace std;
    //default constructor 
    Dialogue::Dialogue()
    {
    	PicPath = NULL;
    	Dial = NULL;
    }
    //Setting the top x,y coord, and the text to display pointer, and the picture pointer.
    void Dialogue::Initalize(int xx,int yy,char* Dia, char* Picture)
    {
    	if(PicPath)delete PicPath;
    	PicPath = NULL;
    	if(Picture != NULL)	//NULL is valid it just says we have no picture to display.
    	{
    		PicPath = new char [strlen(Picture)+1];
    		strcpy(PicPath,Picture);	//save us a copy of the picture's path from the exe
    	}
    	if(Dial)delete Dial;
    	Dial = new char [strlen(Dia)+1];	
    	strcpy(Dial,Dia);			//save us a copy of the dialogue text
    	x = xx;						//set coords
    	y = yy;
    }
    //The actual drawing of the dialogue all it uses is the pointer to a surface a font pointer, and a pointer to a RGB struct.
    void Dialogue::DrawDialogue(BITMAP *BUFFER,FONT *big_font,RGB *PICPAL)
    {
    	const int maxlngth = 35;	//the number of characters per line in the dialogue
    	BITMAP *PIC;				//making a local bitmap for the dialogue
    	int col;
    	int r1,r2,b1,b2,g1,g2;		//vars used in the blend
    	char *path;					//the path to the picture
    	path = NULL;				//set to NULL for now in case there is no PIC
    	if(PicPath != NULL)			//if we have no picpath we dont need to copy into path
    	{
    		path = new char[strlen(PicPath)+1];
    		strcpy(path,PicPath);	//copy into path
    		path[strlen(PicPath)] = '\0';
    	}
    	r1 = 45;					//Just choosing the rgb values for the dialogue background
    	b1 = 70;					//Alpha blending might look better I may test that later
    	g1 = 45;
    	if(PicPath != NULL)			//dont try to load without a picpath
    	{
    		PIC = load_bitmap(path,PICPAL);	//load the picture for the dialogue
    	}
    	for(int yy = y;yy < y+160;yy++)			//the actual draw part
    	{
    		for(int xx = x;xx < x+512; xx++)
    		{
    			col = getpixel(BUFFER,xx,yy);
    			r2 = getr32(col);
    			g2 = getg32(col);
    			b2 = getb32(col);
    			r2 += r1;
    			r2  = r2/2;	//get avg red
    			g2 += g1;
    			g2  = g2/2; //get avg green
    			b2 += b1;
    			b2  = b2/2; //get avg blue
    			col = makecol(r2,r2,r2);  //get the avg color
    			putpixel(BUFFER,xx,yy,col);
    		}
    	}
    	if(PicPath != NULL && PIC)blit(PIC,BUFFER,0,0,x,y,96,96);		//draw the picture onto the buffer if there is one to draw
    	//textouts here 160 high with 20 pixels per line so thats 7 lines 8th is for Press Enter 
    	text_mode(-1);	//to make the color around the textout transparent
    	//new line every maxlngth chars
    	int length = strlen(Dial);
    	if(length > maxlngth)
    	{
    		double bla=(length / maxlngth);
    		int linenum = 1 + ceil(bla);
    		char templine[maxlngth+1];
    		templine[maxlngth] = '\0';
    		for(int za = 0;za < linenum;za++)
    		{
    			for(int ca = 0;ca < maxlngth;ca++)
    			{	
    				templine[ca] = Dial[(za*maxlngth)+ca];
    				templine[maxlngth] = '\0';
    			}
    			try	//try to output with our font 
    			{
    				textout(BUFFER,big_font,templine,x+105,y+(20*za),makecol(255,255,255));
    			}
    			catch(...)	//if we can't we will use the default
    			{
    				textout(BUFFER,font,templine,x+105,y+(20*za),makecol(255,255,255));
    			}
    		}
    	}
    	else
    	{
    		try
    		{
    			textout(BUFFER,big_font,Dial,x+105,y,makecol(255,255,255));
    		}
    		catch(...)
    		{
    			textout(BUFFER,font,Dial,x+105,y,makecol(255,255,255));
    		}
    	}
    	try
    	{
    		textout(BUFFER,big_font,"PRESS ENTER TO CONTINUE",x+105,y+140,makecol(255,255,255));
    	}
    	catch(...)
    	{
    		textout(BUFFER,font,"PRESS ENTER TO CONTINUE",x+105,y+140,makecol(255,255,255));
    	}
    	while(!key[KEY_ENTER])blit(BUFFER,screen,0,0,0,0,1024,768);	//wait on enter we need to redraw this is in case they alt+tab
    	while(key[KEY_ENTER]);
    	if(path != NULL)delete[] path;	// destroy only if we need to 
    	if(PicPath != NULL)destroy_bitmap(PIC);	//although we aren't looking at pic to delete we are looking at if it would have been loaded earlier
    }
    Dialogue::~Dialogue()
    {
    	
    	try	//for some reason MSVC++ doesn't like deleting an already deleted pointer so this code is quick way to identify the problem
    	{
    		if(PicPath)delete[] PicPath;
    		if(Dial)delete[] Dial;
    	}
    	catch(...)
    	{
    		ofstream errorlog;
    		errorlog.open("ERROR.txt");
    		allegro_message("An error was encountered and saved to ERROR.txt");
    		errorlog<<"An error was encountered during the destructor of the Dialogue class."<<endl<<"Dumping relevant data"<<endl;
    		errorlog<<"PicPath: "<<&PicPath<<endl;
    		errorlog<<"Dial: "<<&Dial<<endl;
    		errorlog.close();
    		exit(2);
    	}
    }

  2. #2
    Registered User ~Kyo~'s Avatar
    Join Date
    Jun 2004
    Posts
    320

    Updated code

    NOTE: ADD int textcolor in the header so this will compile!!!!

    Started dinking around with old code so I wrote a couple helpful things into this class and figured I would share it.

    basicly if you pass something like

    #255000000 <text> it will draw it in red
    #000255000 <text> is blue.... etc

    Also fixed word wrapping issue where it would break words on new line.

    Enjoy.

    No idea how I used it before with no word wrap code >_>...
    Code:
    #include "Dialogue.h"
    
    #include <allegro.h>
    #include <winalleg.h>
    #include <fstream>
    
    #include <conio.h>
    #include <string.h>
    #include <math.h>
    using namespace std;
    Dialogue::Dialogue()
    {
    	PicPath = NULL;
    	Dial = NULL;
    }
    void Dialogue::Initalize(int xx,int yy,char* Dia, char* Picture)
    {
        int mr=255,mg=255,mb=255;
    	if(PicPath)delete PicPath;
    	PicPath = new char [strlen(Picture)+1];
    	strcpy(PicPath,Picture);
    	if(Dial)delete Dial;
    	if(Dia[0] == '#')   //first 10 digits are a color code!
    	{ //#255255255 Text out here.
    	    mr = ((Dia[1]-'0')*100)+((Dia[2]-'0')*10)+(Dia[3]-'0');
    	    mg = ((Dia[4]-'0')*100)+((Dia[5]-'0')*10)+(Dia[6]-'0');
    	    mb = ((Dia[7]-'0')*100)+((Dia[8]-'0')*10)+(Dia[9]-'0');
    	    Dial = new char [strlen(Dia)-10];
    	    int mx;
    	    for(mx = 11;mx < strlen(Dia);mx++)
    	    {
    	       Dial[mx-11] = Dia[mx];
    	    }
    	    Dial[strlen(Dia)-11] = '\0';
    	}else
    	{
    	   Dial = new char [strlen(Dia)+1];
    	   strcpy(Dial,Dia);
        }
    	x = xx;
    	y = yy;
    	textcolor = makecol(mr,mg,mb);
    }
    void Dialogue::DrawDialogue(BITMAP *BUFFER,FONT *big_font,RGB *PICPAL)
    {
    	const int maxlngth = 45;
    	BITMAP *PIC;
    	int col;
    	int r1,r2,b1,b2,g1,g2;
    	char *path;
    	path = new char[strlen(PicPath)+1];
    	strcpy(path,PicPath);
    	path[strlen(PicPath)] = '\0';
    	r1 = 45;
    	b1 = 70;
    	g1 = 45;
    	PIC = load_bitmap(path,PICPAL);
    	if(!PIC)
    	{
    		char *errormsg;
    		errormsg = new char[24 + strlen(path)*2];
    		strcpy(errormsg,"PICTURE WAS NOT LOADED ");
    		strcat(errormsg,path);
    		allegro_message(errormsg);
    		allegro_message(path);
    		delete[] errormsg;
    	}
    	for(int yy = y;yy < y+160;yy++)
    	{
    		for(int xx = x;xx < x+512; xx++)
    		{
    			col = getpixel(BUFFER,xx,yy);
    			r2 = getr32(col);
    			g2 = getg32(col);
    			b2 = getb32(col);
    			r2 += r1;
    			r2  = r2/2;	//get avg red
    			g2 += g1;
    			g2  = g2/2; //get avg green
    			b2 += b1;
    			b2  = b2/2; //get avg blue
    			col = makecol(r2,r2,r2);  //get the avg color
    			putpixel(BUFFER,xx,yy,col);
    		}
    	}
    	if(PIC)blit(PIC,BUFFER,0,0,x,y,96,96);
    	//textouts here 160 high with 20 pixels per line so thats 7 lines 8th is for Press Enter blah
    
    	//new line every maxlngth chars
    	int length = strlen(Dial);
    	if(length > maxlngth)
    	{
    		double bla=(length / maxlngth);
    		int correction = 0;
    		int linenum = (int)(1 + ceil(bla));
    		char templine[maxlngth+1];
    		templine[maxlngth] = '\0';
    		for(int za = 0;za < linenum;za++)
    		{
    			for(int ca = 0;ca < maxlngth;ca++)
    			{
    				templine[ca] = Dial[(za*maxlngth)+ca-correction];
    
    				if(maxlngth-ca < 6 && (Dial[(za*maxlngth)+ca-correction] == ' ' || Dial[(za*maxlngth)+ca-correction] == '\0'))
    				{  //if we are in the last 6 chars and it is the end or a space term line and goto next.
                       //this is just to avoid words breaking over the next line as it looks funky
                       correction += maxlngth-ca-1;  //-1 to eliminate starting new line with a space that looks weird too
                       templine[ca] = '\0';     //terminate line prematurely
                       break;
    				}
    				templine[maxlngth] = '\0';  //normal termination of line probably more of an exception now.
    			}
    			try
    			{
    				textout_ex(BUFFER,big_font,templine,x+105,y+(20*za),textcolor,-1);
    			}
    			catch(...)
    			{
    				textout_ex(BUFFER,font,templine,x+105,y+(20*za),textcolor,-1);
    			}
    		}
    	}
    	else
    	{
    		try
    		{
    			textout_ex(BUFFER,big_font,Dial,x+105,y,textcolor,-1);
    		}
    		catch(...)
    		{
    			textout_ex(BUFFER,font,Dial,x+105,y,textcolor,-1);
    		}
    	}
    	try
    	{
    		textout_ex(BUFFER,big_font,"PRESS ENTER TO CONTINUE",x+105,y+140,makecol(255,255,255),-1);
    	}
    	catch(...)
    	{
    		textout_ex(BUFFER,font,"PRESS ENTER TO CONTINUE",x+105,y+140,makecol(255,255,255),-1);
    	}
    	while(!key[KEY_ENTER])blit(BUFFER,screen,0,0,0,0,1024,768);
    	while(key[KEY_ENTER]);
    	delete[] path;
    	if(PIC)destroy_bitmap(PIC);
    }
    Dialogue::~Dialogue()
    {
    	ofstream errorlog;
    	errorlog.open("ERROR.txt");
    	try
    	{
    		if(PicPath)delete[] PicPath;
    		if(Dial)delete[] Dial;
    	}
    	catch(...)
    	{
    		allegro_message("An error was encountered and saved to ERROR.txt");
    		errorlog<<"An error was encountered during the destructor of the NPC class."<<endl<<"Dumping relevant data"<<endl;
    		errorlog<<"PicPath: "<<&PicPath<<endl;
    		errorlog<<"Dial: "<<&Dial<<endl;
    		errorlog.close();
    		exit(2);
    	}
    }

  3. #3
    C++まいる!Cをこわせ! Elysia's Avatar
    Join Date
    Oct 2007
    Posts
    22,543
    Two initial suggestions:
    Use std::string instead of char*. Saves you a lot of trouble.
    Move Initialize into the constructor. Saves you checks to see if the object is initialized or face the consequences.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  4. #4
    Registered User ~Kyo~'s Avatar
    Join Date
    Jun 2004
    Posts
    320
    Quote Originally Posted by Elysia View Post
    Two initial suggestions:
    Use std::string instead of char*. Saves you a lot of trouble.
    Move Initialize into the constructor. Saves you checks to see if the object is initialized or face the consequences.
    char * or string really has no impact both work in very similar ways. In my code I like char* I have used it for years and haven't had issues yes it is depreciated, that does not mean it will not work. Another point would be found here http://www.allegro.cc/manual/api/text-output/textout_ex it calls for a char * not string.

    Class was made implementaion specifc. Also this post was more for a refferance so people can use the code at will and was not ment to be asking how to improve it more of a I wonder how people will use it.

    If you are writing code and know specificly to use an initalize funtion there is no reason that you should ever have an uninitalized class. My structure is _GENERALLY_

    Code:
    //define vars
    //code
    not something like the following that makes you look in two or possibly more spots to see the declaration of the variable.

    Code:
    //define some local vars
    //code some load stuff
    //make some more vars and use loaded info to populate the new vars
    //code more stuff
    Last edited by ~Kyo~; 07-02-2010 at 01:12 PM. Reason: more info

  5. #5
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    21,636
    Quote Originally Posted by ~Kyo~
    char * or string really has no impact both work in very similar ways.
    The impact is that with std::string, or other string classes, you no longer need to do manual memory management. This can be of tremendous benefit, especially in the face of the possible throwing or propagating of exceptions in C++.

    Quote Originally Posted by ~Kyo~
    Another point would be found here textout_ex it calls for a char * not string.
    The parameter that you have in mind is of type const char*, which you can obtain by calling the c_str() member function of std::string.

    Quote Originally Posted by ~Kyo~
    If you are writing code and know specificly to use an initalize funtion there is no reason that you should ever have an uninitalized class.
    If you can eliminate the possibility of using an uninitialised object, or attempting to initialise the same object twice, then you might as well do so instead of using two phase construction.

    Quote Originally Posted by ~Kyo~
    My structure is _GENERALLY_
    Code:
    //define vars
    //code
    That does explain your preference for two phase construction. However, if you make full use of your constructors to perform initialisation (as you should), you can then declare (and define) variables near first use. This helps in maintenance by keeping variables in as small a scope as feasible, while potentially improving performance by avoiding unnecessary work. Of course, there is also the benefit of correctness as has been mentioned, i.e., an object is always in a valid, initialised state.
    C + C++ Compiler: MinGW port of GCC
    Version Control System: Bazaar

    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  6. #6
    Registered User ~Kyo~'s Avatar
    Join Date
    Jun 2004
    Posts
    320
    Quote Originally Posted by laserlight View Post
    The impact is that with std::string, or other string classes, you no longer need to do manual memory management. This can be of tremendous benefit, especially in the face of the possible throwing or propagating of exceptions in C++.


    The parameter that you have in mind is of type const char*, which you can obtain by calling the c_str() member function of std::string.


    If you can eliminate the possibility of using an uninitialised object, or attempting to initialise the same object twice, then you might as well do so instead of using two phase construction.


    That does explain your preference for two phase construction. However, if you make full use of your constructors to perform initialisation (as you should), you can then declare (and define) variables near first use. This helps in maintenance by keeping variables in as small a scope as feasible, while potentially improving performance by avoiding unnecessary work. Of course, there is also the benefit of correctness as has been mentioned, i.e., an object is always in a valid, initialised state.
    You mention scope of variable which lies with implementation and the method of implementation.

    Code:
    if(strncmp(temp, "DisplayMessage",14) == 0)
         {
            int lcv;
            char *mypicpath;
            char *mytext;
            Dialogue tdia;
            BITMAP *temp;
            
            mytext = new char[255];
            mypicpath = new char[255];
            for(lcv = 15;lcv < strlen(temp);lcv++)
            {
               if('&' == temp[lcv]){mytext[lcv-15] = '\0';break;}
               mytext[lcv-15] = temp[lcv];
            }
            lcv+=2;
            int lock = lcv;
            for(lcv;lcv < strlen(temp);lcv++)
            {
               mypicpath[lcv-lock] = temp[lcv];
            }
            mypicpath[lcv-lock] = '\0';
            tdia.Initalize(25,25,mytext,mypicpath);
            if(intest)log<<"   mytext: "<<mytext<<endl;
            if(intest)log<<"   mypicpath: "<<mypicpath<<endl;
            
            temp = create_bitmap(1024,768);
            blit(MYBUFFER,temp,0,0,0,0,1024,768);
            tdia.DrawDialogue(MYBUFFER,MYFONT,APAL);
            blit(temp,MYBUFFER,0,0,0,0,1024,768);
            destroy_bitmap(temp);
            if(intest)log<<"   END "<<endl<<endl;
         }
    This is the main block that uses this class the dialogue class is more for doing the draw routine than it is for a long term storage type class. While yes I could use it as a global function the class works better in terms of portability. Perhaps everyone thought it was used as a long term storage and rendoring situation which is not the case. I would think another option would be to overload the constructor, but as it stands with my current implementation it would be wasted code. The only difference I see is it would be in existance a split second less if I implement it the way that was offered - maybe in other situations it would help with memory management, but in this situation we are talking about <1k of memory that exists for the amount of time it takes for the person to read the text and hit enter which is still in an endless loop.

    You say string would be a safer way to store data compared to a char * or even a char []. It also limits the data manipulation without calling your other class funtions. If you know you will NEED to do data manipulation on a structure why not leave it in a form that provides you with the access you need to begin with? The most common arguement is so that things don't "accidentally" get changed how do you have an accident in code you type do x then y then z the computer then performs x then y then z if it does something wrong your code is illogical you should not be manipulating data structures if you are reading them and if you really want to make it so people can not break it - assuming portability which is relevant in this case let us use const so no one screws the data up - which could also be placed into the class, but the class is tested and known to work which would mean it is not a requirement because we know the data doesn't get changed.

  7. #7
    C++まいる!Cをこわせ! Elysia's Avatar
    Join Date
    Oct 2007
    Posts
    22,543
    C++ version:
    Code:
    if (temp == "DisplayMessage")
         {
            Dialogue tdia;
            BITMAP* temp;
    
            std::size_t npos = temp.find("&");
            if (npos == std::string::npos)
                    npos = temp.size();
            std::string mytext = temp.substr(15, npos);
            
            int lcv = 17;
    
            std::string mypicpath(temp);
    
            tdia.Initalize(25,25,mytext,mypicpath);
            if(intest)log<<"   mytext: "<<mytext<<endl;
            if(intest)log<<"   mypicpath: "<<mypicpath<<endl;
            
            temp = create_bitmap(1024,768);
            blit(MYBUFFER,temp,0,0,0,0,1024,768);
            tdia.DrawDialogue(MYBUFFER,MYFONT,APAL);
            blit(temp,MYBUFFER,0,0,0,0,1024,768);
            destroy_bitmap(temp);
            if(intest)log<<"   END "<<endl<<endl;
         }
    Note how you don't have to bother with freeing the memory, which you don't anyway. Less code, as well. Less clutter. Easier to read. Exception safe.

    For the first statement, I have no idea what you mean. All we suggested is that instead of creating the object and then call Initialize, you simply call the constructor with the same arguments as Initialize, and then the object is ready to use.

    And for the second... look at the code above. Much easier to understand and maintain. It is also exception safe. You don't have to free. Etc, etc.
    You seem to have a C background. Not to tell you what to do, but you really should embrace what is already there for you. Why roll out your own solution? Using facilities brings down bugs and decreases security risks, so you can spend more time on implementing features rather than hunting down bugs. What is not to like?
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  8. #8
    Super Moderator VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,596
    I'm not sure how valuable a modal dialog is in the context of a game other than for a pause menu and/or the main menu.

  9. #9
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    21,636
    Quote Originally Posted by ~Kyo~
    You say string would be a safer way to store data compared to a char * or even a char []. It also limits the data manipulation without calling your other class funtions.
    It does not limit the data manipulation that you can do.

    I do not think that Elysia's code accurately copies what your code does. Assuming that temp is changed to a std::string, that Dialogue has a constructor that appropriately performs initialisation (i.e., it does the work that the Initialize member function currently does, with const std::string& parameters), and that an appropriate using declaration or using directive is in scope:
    Code:
    if (temp.substr(0, 14) == "DisplayMessage")
    {
        const string::pos = temp.find('&', 15);
        if (pos == string::npos || pos + 2 >= temp.length())
        {
            // assertion? throw an exception?
        }
    
        const string mytext(temp.substr(15, pos - 15);
        const string mypicpath(temp.substr(pos + 2));
        if (intest)
        {
            log << "   mytext: " << mytext << endl
                << "   mypicpath: " << mypicpath << endl;
        }
    
        Dialogue tdia(25, 25, mytext, mypicpath);
        BITMAP* temp_bitmap = create_bitmap(1024, 768);
        blit(MYBUFFER, temp_bitmap, 0, 0, 0, 0, 1024, 768);
        tdia.DrawDialogue(MYBUFFER, MYFONT, APAL);
        blit(temp_bitmap, MYBUFFER, 0, 0, 0, 0, 1024, 768);
        destroy_bitmap(temp_bitmap);
    
        if (intest) log << "   END \n" << endl;
    }
    C + C++ Compiler: MinGW port of GCC
    Version Control System: Bazaar

    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  10. #10
    C++まいる!Cをこわせ! Elysia's Avatar
    Join Date
    Oct 2007
    Posts
    22,543
    Though I did translate the code 1-to-1, as best I could. I did find some problems, though, such as uninitialized pointers and overwritten pointers. It was used to serve an example, not a working piece of code.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Mixing C++ class and non-class code?
    By Depthcharge101 in forum C++ Programming
    Replies: 1
    Last Post: 05-27-2009, 12:11 AM
  2. Replies: 2
    Last Post: 05-14-2009, 04:13 PM
  3. Class design problem
    By h3ro in forum C++ Programming
    Replies: 10
    Last Post: 12-19-2008, 08:10 AM
  4. Default class template problem
    By Elysia in forum C++ Programming
    Replies: 5
    Last Post: 07-11-2008, 08:44 AM
  5. Screwy Linker Error - VC2005
    By Tonto in forum C++ Programming
    Replies: 5
    Last Post: 06-19-2007, 02:39 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21