Hi!
I'm making a graph generator.
Most is done but the only problem is that when i'm doing the 2nd or 3rd graph in the same session, the graph collapses . and after the end of execution of the program, i get "Null pointer assignment"

I tried debugging but i have only found out that the functions calculating the functional value start giving zero at a certain point.
That point is different for different inputs.

If i close the program after the first graph, the error is not returned and after starting it again it works again for atleast the first time.
If it helps, I am posting the two functions responsible for function solving.

Screenshots below code

int eqn::valuefinder(double v,int two)
{
	if(two)
		strcpy(eqan2,seceqan);
	if(two==0)
		strcpy(eqan2,eqan);
	
	char xchar[10];
	sprintf ( xchar, "%.3f", v );
	for(int i=0;i<strlen(eqan2); i++)
	{
		if (eqan2[i]=='x' || eqan2[i]=='X')
		{
			replacer(eqan2,xchar,i,i);
		}
	}

	int val=manager_eqn(eqan2);
	return(val);
}

void eqn::replacer(char* a,char* b,int m,int n)                  //inserts b inside a from index m to n
{
	int j=0,k,i,l,size=(strlen(a)-n);
	char *sub=new char[size];

	for(i=n+1; a[i]!='\0' ;i++)
	{
		sub[j]=a[i];
		j++;
	}
	sub[j]='\0';

	for (i=m,j=0; b[j]!='\0' ; i++,j++,k=i)
		a[i]=b[j];

	for (i=k,j=0; sub[j]!='\0'; i++,j++)
		a[i]=sub[j];
	a[i]='\0';
}

Recommended Answers

All 5 Replies

Its very possible that on line 25 the value of size will be 0. new can handle that ok but will return a pointer to a zero length string and line 25 will trash memory when that happens.

>>//inserts b inside a from index m to n

I don't think that's going to happen because m and n are the same value according to line 14.

> I don't think that's going to happen because m and n are the same

It starts copying from n+1 and is working alright.

for(i=n+1; a[i]!='\0' ;i++)
{
sub[j]=a[i];
j++;
}

If i write cout<<eqan2<<val in line 19 before reyurning, the eqan2 is what it should be all the time(ex-56*sin56) while val gets screwed up somewhere on the way.

The error seems to be non logical, because the same graph is generated OK the first time but the second tome things get screwed up.

Frankly I have no clue looking at the amount of code you've posted.
Two things I can say:
1. On my laptop std::numeric_limits<double>::max() is "1.79769e+308". Don't know but would this cause any issues with your sprintf() call on line 9?
2. In general when I reuse instance of some class, I put a "clean()" method, which I call before reusing the instance, to cleanup state of the instance. If possible do that to be sure.

Alright, i'm posting the entire code this time. Its the second class eqn that does the graphs, first one(expsolver) is a calculator.
Its written for ancient Turbo C++ that our school uses so it might cause a few problems with new compilers.

>when I reuse instance of some class, I put a "clean()" method
No clue about that. Google gives nothing too. Could you explain a bit.

#include <fstream.h>
#include <conio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <graphics.h>

class expsolver
{
	char inputstring[50],str[50],exp[50], prec[5],subexp[15];
	char operat[15];
	int pos[15],posl, no[5], neighbours[2], step,pass,neg, no_ops;
	double t1,t2,ta;

	public:
	expsolver()
	{
		strcpy(prec,"^/*+-");
		step=0;
		pass=1;
		neg=0;
		no_ops=0;

	}

	void display();
	void manager();
	void master();
	void neighbourset(int);
	void pos_setter();
	void copier(char*,char*,int ,int);
	void convertno(char*,double &t);
	void operation(double,double,int);
	void convertalpha(double);
	void replacer(char*,char*,int,int);
	void endcopier(char*,char*,int);
	void negbugfix();
	void operationname(int,int);

	double manager_eqn(char*);
	void master_eqn();

};

void expsolver::display()
{
	char cho;
	do
	{
	clrscr();
	cout<<"\n\t\tEnter the expression to be evaluated\n\t\t";
	gets(inputstring);
	strcpy(str,inputstring);
	manager();
	cout<<"\n\t\tWant to try again ? ";
	cin>>cho;
	}
	while(cho!='n');
}

void expsolver::manager()
{
	int i,lcount=0,rcount=0,li=0,ri=0;
	pass=1;
	for (i=0; i<strlen(str); i++)
	{
		if(str[i]=='(')
			lcount+=1;
		if(str[i]==')')
			rcount+=1;
	}
	for(int j=0;j<lcount;j++)
	{
	if (lcount==rcount)
	{
		for (i=0; i<strlen(str); i++)
		{
			if (str[i]=='(')
			{
				li=i;
			}
			if (str[i]==')')
			{
				ri=i;
				break;
			}
		}
	}
	copier(exp,str,li+1,ri-1);

	cout<<"\nBracket no "<<pass;
	master();
	replacer(str,exp,li,ri);
	cout<<"\nAfter solving bracket "<<pass<<", result is "<<str<<"\n\n";
	pass++;
	}
	cout<<"\nResult- "<<str;
}

void expsolver::master()
{

	for (int i=0; i<4; i++)
	{
		no[i]=0;
		for (int j=1; j<(strlen(exp)); j++)
			if (exp[j]==prec[i])
			{			
				no[i]+=1;
				no_ops++;
			}
	}

	if(no_ops==0)
	{
		convertno(exp,ta);
		convertalpha(ta);
		replacer(exp,subexp,0,strlen(exp));
	}			

	for(i=0; i<4; i++)
	{
		if(i==3)
			negbugfix();
		for (int j=0; j<no[i]; j++)
		{
		pos_setter();
			
		if(pos[0]!=32767)
			for (int k=1; k<(strlen(exp)); k++)
				{
					if (exp[k]==prec[i])
					{
					neighbourset(k);
					char *a =new char [k-neighbours[0]];
					char *b =new char [neighbours[1]-k];
					copier (a,exp,neighbours[0],(k-1));
					copier (b,exp,(k+1),neighbours[1]);
						
					convertno (a,t1);
					convertno (b,t2);
					operation (t1,t2,i);
					convertalpha (ta);
					operationname(i,0);
					cout<<"\nStep "<<++step<<": "<<operat<<t1;
					operationname(i,1);
					cout<<operat<<t2<<"\n\t"<<exp;
					replacer (exp,subexp,neighbours[0],neighbours[1]);
					break;
					}
				}

		}

	}
}

void expsolver::pos_setter()
{
	unsigned int i=1,j=0;
	for (;exp[i]!='\0';i++)
	{
		if((exp[i]=='^')||(exp[i]=='/')||(exp[i]=='*')||(exp[i]=='+')||((exp[i]=='-')&&(neg)))
		{
				pos[j]=i;
				j++;
		}
		pos[j]=32767;
		posl=j;
	}
}

void expsolver::neighbourset (int k)
{
	for (int i=0; pos[i]!=32767; i++)
	{
		if (k==pos[i])
		{
			neighbours[0]=pos[i-1]+1;
			neighbours[1]=pos[i+1]-1;
			if (i==0)
				neighbours[0]=0;
			if(i==posl-1)
				neighbours[1]=((strlen(exp))-1);
		}
	}
}

void expsolver::copier(char* a,char* b,int m,int n)
{
	int i,j;
	for(i=m,j=0;i<=n ;i++,j++)
	{a[j]=b[i];
		}
	a[j]='\0';
}

void expsolver::endcopier(char* x,char* y,int start)
{
	int i,j;
	for (i=start,j=0;x[i]!='\0' ;i++,j++ )
		y[j]=x[i];
	y[j]='\0';
}

void expsolver::convertno(char* a,double &t)
{
	char input[20], *endptr;
	double inputval;

	if((strncmpi(a,"sin",3)==0)||(strncmpi(a,"cos",3)==0)||(strncmpi(a,"tan",3)==0)||(strncmpi(a,"log",3)==0))
	{
		if(strncmpi(a,"sin",3)==0)
		{
			endcopier(a,input,3);
			inputval=strtod(input,&endptr);
			t=sin(inputval*(3.1415926535/180));
		}
		if(strncmpi(a,"cos",3)==0)
		{
			endcopier(a,input,3);
			inputval=strtod(input,&endptr);
			t=cos(inputval*(3.1415926535/180));
		}
		if(strncmpi(a,"tan",3)==0)
		{
			endcopier(a,input,3);
			inputval=strtod(input,&endptr);
			t=tan(inputval*(3.1415926535/180));
		}
		if(strncmpi(a,"log",3)==0)
		{
			endcopier(a,input,3);
			inputval=strtod(input,&endptr);
			t=log(inputval);
		}
	}
	else
		t=strtod(a,&endptr);
}

void expsolver::operation(double x,double y,int i)
{
	if (i==0)
		ta=pow(x,y);
	if (i==1)
		ta=x/y;
	if (i==2)
		ta=x*y;
	if (i==3)
		ta=x+y;
	if (i==4)
		ta=x-y;
}

void expsolver::replacer(char* a,char* b,int m,int n)
{
	int j=0,k,i,l,size=(strlen(a)-n);
	char *sub=new char[size];

	for(i=n+1; a[i]!='\0' ;i++)
	{
		sub[j]=a[i];
		j++;
	}
	sub[j]='\0';

	for (i=m,j=0; b[j]!='\0' ; i++,j++,k=i)
		a[i]=b[j];

	for (i=k,j=0; sub[j]!='\0'; i++,j++)
		a[i]=sub[j];
	a[i]='\0';
}

void expsolver::convertalpha(double x)
{
   sprintf ( subexp, "%.3f", x );
}

void expsolver::negbugfix ()
{
	for(int i=1; i<strlen(exp); i++)
		if(exp[i]=='-')
		{
			replacer(exp,"+",i,i-1);
			i++;

			no[3]++;
		}
}

void expsolver::operationname(int p,int q)
{
	if(p==0)
	{
		if(q==0)
			strcpy(operat,"Raise ");
		if(q==1)
			strcpy(operat," to the power ");
	}

	if(p==1)
	{
		if(q==0)
			strcpy(operat,"Divide ");
		if(q==1)
			strcpy(operat," by ");
	}

	if(p==2)
	{
		if(q==0)
			strcpy(operat,"Multiply ");
		if(q==1)
			strcpy(operat," with ");
	}

	if(p==3)
	{
		if(q==0)
			strcpy(operat,"Add ");
		if(q==1)
			strcpy(operat," to ");
	}
}

double expsolver::manager_eqn(char* arg)
{
	strcpy(str,arg);
	int i,lcount=0,rcount=0,li=0,ri=0;
	for (i=0; i<strlen(str); i++)
	{
		if(str[i]=='(')
			lcount+=1;
		if(str[i]==')')
			rcount+=1;
	}
	for(int j=0;j<lcount;j++)
	{
	if (lcount==rcount)
	{
		for (i=0; i<strlen(str); i++)
		{
			if (str[i]=='(')
			{
				li=i;
			}
			if (str[i]==')')
			{
				ri=i;
				break;
			}
		}
	}
	copier(exp,str,li+1,ri-1);

	master_eqn();
	replacer(str,exp,li,ri);
	}
	return(ta);
}

void expsolver::master_eqn()
{

	for (int i=0; i<4; i++)
	{
		no[i]=0;
		for (int j=1; j<(strlen(exp)); j++)
			if (exp[j]==prec[i])
			{			
				no[i]+=1;
				no_ops++;
			}
	}

	if(no_ops==0)
	{
		convertno(exp,ta);
		convertalpha(ta);
		replacer(exp,subexp,0,strlen(exp));
	}			

	for(i=0; i<4; i++)
	{
		if(i==3)
			negbugfix();		
		for (int j=0; j<no[i]; j++)
		{
		pos_setter();
			
		if(pos[0]!=32767)
			for (int k=1; k<(strlen(exp)); k++)
				{
					if (exp[k]==prec[i])
					{
					neighbourset(k);
					char *a =new char [k-neighbours[0]];
					char *b =new char [neighbours[1]-k];
					copier (a,exp,neighbours[0],(k-1));
					copier (b,exp,(k+1),neighbours[1]);
						
					convertno (a,t1);
					convertno (b,t2);
					operation (t1,t2,i);
					convertalpha (ta);
						
					replacer (exp,subexp,neighbours[0],neighbours[1]);
					break;
					}
				}

		}

	}
}


class eqn:public expsolver
{
	char eqan[40],eqan2[40],seceqan[40];
	int xorig,yorig,action,second;
	double xscalefac,yscalefac,xneg,xplus;


	public:
	eqn()
	{
		xorig=320;
		yorig=240;
		xscalefac=1;
		yscalefac=1;
		second=0;
	}
	int valuefinder(double,int);
	void replacer(char* a,char* b,int m,int n);
	void geteq();
	void grapher();
	void eqmenu();
};

void eqn::grapher()
{
	int gdriver = DETECT, gmode, errorcode;
	char msg[80];

	initgraph(&gdriver, &gmode, "");


	errorcode = graphresult();
	if (errorcode != grOk)
	{
		printf("Graphics error: %s\n", grapherrormsg(errorcode));
		printf("Press any key to halt:");
		getch();
		exit(1);
	}

	int maxx=getmaxx();
	int maxy=getmaxy();

	clrscr();
	cleardevice();

	xneg=-(xorig*xscalefac);
	xplus=(maxx-xorig)*xscalefac;
	moveto(xorig+xneg,yorig);
	lineto(maxx,yorig);
	moveto(xorig,maxy);
	lineto(xorig,0);
	moveto(xorig+xneg,yorig);
	int xpos=0;
	double x;

	for(x=xneg;x<=xplus;x+=xscalefac,xpos++)
	{
	       lineto (xpos,yorig-(valuefinder(x,0)*yscalefac));

	}
	if(second)
	{
		moveto(xorig+xneg,yorig);
		int xpos=0;

		for(x=xneg;x<=xplus;x+=xscalefac,xpos++)
		{
			lineto (xpos,yorig-(valuefinder(x,1)*yscalefac));
		}
	}
	action=getch();
	closegraph();
}

void eqn::geteq()
{
	clrscr();
	cout<<"\t\tEnter the Equation : Y = ";
	gets(eqan);

	cout<<"\n\t\tX Scale Factor ";
	cin>>xscalefac;
	cout<<"\n\t\tY Scale Factor ";
	cin>>yscalefac;

	if (second)
	{
		cout<<"\t\tEnter second equation : Y = ";
		gets(seceqan);
	}
	    grapher();

	    cout<<"\tDo you want to save this graph? (y/n)";
	    char ch;
	    cin>>ch;
	    if(ch=='y')
	    {
		cout<<"\nEnter target file name :";
		char targetfile[20];
		cin>>targetfile;
		fstream ofile("cubic.txt", ios::out);
		if(!ofile)
			cout<<"\nCannot Open file";
		ofile<<eqan;
		cout<<"\n\tFile saved";
		ofile.close();
	     }


}

int eqn::valuefinder(double v,int two)
{
	if(two)
		strcpy(eqan2,seceqan);
	if(two==0)
		strcpy(eqan2,eqan);
	
	char xchar[10];
	sprintf ( xchar, "%.3f", v );
	for(int i=0;i<strlen(eqan2); i++)
	{
		if (eqan2[i]=='x' || eqan2[i]=='X')
		{
			replacer(eqan2,xchar,i,i);
		}
	}

	int val=manager_eqn(eqan2);
	return(val);
}

void eqn::replacer(char* a,char* b,int m,int n)
{
	int j=0,k,i,l,size=(strlen(a)-n);
	char *sub=new char[size];

	for(i=n+1; a[i]!='\0' ;i++)
	{
		sub[j]=a[i];
		j++;
	}
	sub[j]='\0';

	for (i=m,j=0; b[j]!='\0' ; i++,j++,k=i)
		a[i]=b[j];

	for (i=k,j=0; sub[j]!='\0'; i++,j++)
		a[i]=sub[j];
	a[i]='\0';
}

void eqn::eqmenu()
{
	clrscr();
	cout<<"\t\t\tGraph-ite v0.1\n\n";
	cout<<"\t\t\t1. Create new graph\n";
	cout<<"\t\t\t2. Load graph from file\n";
	cout<<"\t\t\t3. Compare two graphs\n";
	cout<<"\t\t\tEnter Choice : ";
	int ch;
	cin>>ch;
	switch(ch)
	{
		case 1: geteq();
			break;
		case 2: char targetfile[20];
			cout<<"Enter target file name :";
			cin>>targetfile;
			fstream ifile("cubic.txt",ios::in);
			if(!ifile)
				cout<<"\nCannot open file";
			ifile.getline(eqan,80);

			grapher();
			ifile.close();
			break;
		case 3: second=1;
			geteq();
	}


}

int main()
{

   int gdriver = DETECT, gmode, errorcode;
   int style, midx, midy;

   initgraph(&gdriver, &gmode, "");

   errorcode = graphresult();
   if (errorcode != grOk)
   {
      printf("Graphics error: %s\n", grapherrormsg(errorcode));
      printf("Press any key to halt:");
      getch();
      exit(1);
   }

	midx = getmaxx() / 2;
	midy = getmaxy() / 2;

	settextstyle(4, HORIZ_DIR, 6);

	clrscr();
	settextjustify(CENTER_TEXT, TOP_TEXT);
	outtextxy(midx,midy-150,"Computer Science Project\n");

	settextstyle(1, HORIZ_DIR, 4);
	outtextxy(midx,midy+40,"\nScientific calculator & Graph Generator\n");

	settextstyle(3, HORIZ_DIR, 2);
	outtextxy(midx,midy+100,"\nAuthor: Chetan Kushwaha\n");
	outtextxy(midx,midy+120,"\nFor the academic year 2009-10");

	getch();
	closegraph();
	int i;
	do
	{
	initgraph(&gdriver, &gmode, "");
	settextjustify(CENTER_TEXT, TOP_TEXT);

	clrscr();
	settextstyle(1, HORIZ_DIR, 4);
	outtextxy(midx,midy,"1.Calculator    2.Graph generator\n");

	settextstyle(3, HORIZ_DIR, 2);
	outtextxy(midx,midy+40,"Press the required option, Escape to quit");

	i=getch();
	cleardevice();
	 closegraph();
	switch(i)
	{
		case 49:
		case 79: expsolver obj;
			obj.display();
			break;

		case 50:
		case 80:eqn objeq;
			objeq.eqmenu();
			break;
		case 27: exit(0);
			break;
	}

	}while(i!=27
	);
	return(0);
}

Since it is a null pointer assignment, you might be able to start finding out the cause(s) of the crash using assert() .
So, for all your pointers wherever used, do: assert( the_pointer != NULL ); Likewise, add sanity checks, so that you will not allocate zero-length strings, i.e. assert( size_to_alloc > 0); (also remember to delete [] the memory you allocate).
Then switch the usage of sprintf() to snprintf() AND check whether the data was truncated or not.

One thing to fix for sure is the first strcpy() you have there ( strcpy(prec,"^/*+-") ), it is a guaranteed buffer overflow, you need a larger buffer there.

Maybe the above helps to track down the problems.


However, I'd suggest that you completely switch from C to C++, i.e. use string, stringstream, getline() et al, everywhere. It would be could practise for you, I think.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.