الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

أين الخطأ

مغلق
بدأه maro009 في 16 مايو 2005 · 5 رد · 571 مشاهدة · في الأسئلة المجابة
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

بسم الله الرحمن الرحيم

لقد قمت بتكملة هذا البرنامج وهو عبارة عن آله حاسبه

ال compiler لا يعطى error

ولكن البرنامج يتوقف

أرجو المساعدة

1-calcCommand.h

 #ifndef CALCCOMMANDH
#define CALCCOMMANDH

#include <string>
using std::string;

/**
This class implements a CalcCommand. A CalcCommand object can be used to store
an operation that was done on a calculator. CalcCommand objects can be linked
togheter in a LinkedList by means of their getNext () and setNext () methods.
This class is fully implemented and can be used as is.

@author Tom Artoos.
*/

class CalcCommand
{
    private:
  //MyRef string doesn't support white space??!!! 
        string fOperand;            //125...etc
        string fOperation;          // +,-,*,..etc
        string fDescription;        // messege
        CalcCommand* fNext;
        
    public:
        CalcCommand ();
        CalcCommand (string operand, string operation, string description);
        CalcCommand (const CalcCommand& cmd); //MyRef;copy constructor
        
        string getOperand () const;
        string getOperation () const;
        string getDescription () const;
        string toString ();// ???

        //MyRef:the seter will pass the argument by refrence
        void setOperand (const string& operand);
        void setOperation (const string& operation);
        void setDescription (const string& description);
        
        // Members that allow CalcCommands to be in a LinkedList
  //MyRef: they are the seter and the geter of "fNext"
        CalcCommand* getNext () const;
        void setNext (CalcCommand* next);
};
#endif

2-linkedlist.h

#ifndef LINKEDLISTH
#define LINKEDLISTH

#include "calccommand.h"

/**
Implement this LinkedList as a list of CalcCommands. Provide the necessary
constructor, destructor, etc... The List has three methods:

void push (CalcCommand* cmd): adds a dynamically allocated CalcCommand object
    to the end of the list.
CalcCommand getFirst (): returns a reference to the first CalcCommand object
    in the list.
void clear (): removes all CalcCommand objects from the list and frees their
    memory
bool isEmpty (): returns true when the list is empty

The methods in the list should be sufficient for the application at hand. A
typical code snippet that retrieves all elements in the list looks like this:
    
    if (!list -> isEmpty ())
    {
        CalcCommand* iter = list -> getFirst ();
        while (iter != 0)
        {
            cout << iter -> toString ();
            iter = iter -> getNext ();
        }
    }

@author Tom Artoos
*/

class LinkedList
{
    private:
        CalcCommand* fFirst;
        
    public:
        LinkedList ();
        LinkedList (LinkedList& list);
        ~LinkedList ();
        LinkedList& operator= (LinkedList& list);
        
        void push_back (CalcCommand* data);
        void clear ();
        
        CalcCommand* getFirst () const;
        bool isEmpty () const;
};
#endif

3 - calculator.h

#ifndef CALCULATORH
#define CALCULATORH
#include "utils.h"
#include "linkedlist.h"
#include <string>
using std::string;

/**
This class represents a basic calculator. It contains a number of methods that
represent the supported operations (add, subtract, etc...). Each of these 
operations take one operand and they all work on the internally stored subresult
the following is an example:
    
    calc -> add ("125");
    
    1. convert string 125 to double
    2. take fSubResult and do fSubResult += 125
    3. log the operation with the logCommand method
        - operation = +
        - operand = 125
        - description = free to choose
    4. if all went well return true, else return false
    5. log an error when the operation failed (logCommand)
        - operation = ERROR
        - operand = operand that was given
        - description = error description

The following are special methods:
    
    reset: reset the internal subresult to 0 and clear the command history
    getResult: return the current subresult
    getHistory: returns a pointer to the internal command history list
    logCommand: adds a CalcCommand object to the internal command history list
    
@author Tom Artoos
*/

class Calculator
{
    private:
        LinkedList* fCommandHistory;
        double fSubResult;
        
    protected:
        void logCommand (string operation, string operand, string description);
    
    public:
        Calculator ();
        ~Calculator ();
        
        bool add (const string& operand);
        bool subtract (const string& operand);
        bool divide (const string& operand);
        bool multiply (const string& operand);
        bool sqrtC (const string& operand);
        bool powC (const string& operand);
        void reset ();
        
  void setStart(const string subResult);
        string getResult ();
        LinkedList* getCommandHistory () const;
};
#endif

4 - utils.h // help functions

#ifndef UTILSH
#define UTILSH

#include <string>
#include <sstream>
#include <cstdlib>
#include <cctype>
using namespace std;

bool isValidDouble (string data);
double stringToDouble (string data);
string doubleToString (double data);

#endif

5 - calccommand.cpp

#include "calccommand.h"
#include <cstdio>
#include <string>

CalcCommand::CalcCommand ()//waseem;default constructor 
{fNext = 0;}

CalcCommand::CalcCommand (string operand, string operation, string description)
{
    fOperand = operand;
    fOperation = operation;
    fDescription = description;
    fNext = 0; // set the pointer to 0
}

CalcCommand::CalcCommand (const CalcCommand& cmd)//copy constructor
{
	fNext = 0;
    fOperand = cmd.getOperand ();
    fOperation = cmd.getOperation ();
    fDescription = cmd.getDescription ();
    fNext = cmd.getNext ();
}

string CalcCommand::getOperand () const
{
    return fOperand;
}

string CalcCommand::getOperation () const
{
    return fOperation;
}

string CalcCommand::getDescription () const
{
    return fDescription;
}


string CalcCommand::toString ()
{
    int bufsize = fOperation.size() + fOperand.size() + fDescription.size() + 3;
    char* buffer = new char [bufsize];
    sprintf (buffer, "%s\t%s\t%s\n", fOperation.c_str(), fOperand.c_str(), 
        fDescription.c_str()); //myref C_str() will return the string that passed into it
    string str (buffer);
    delete buffer;
    return str;
}

void CalcCommand::setOperand (const string& operand)
{
    fOperand = operand;
}

void CalcCommand::setOperation (const string& operation)
{
    fOperation = operation;
}

void CalcCommand::setDescription (const string& description)
{
    fDescription = description;
}

void CalcCommand::setNext (CalcCommand* next)
{
    fNext = next;
}

CalcCommand* CalcCommand::getNext () const
{
    return fNext;
}

6 - linkedlist.cpp

#include "linkedlist.h"

LinkedList::LinkedList ():fFirst(0){} // default constructor 
LinkedList::~LinkedList (){clear ();} // destructor

//copy constructor
LinkedList::LinkedList (LinkedList& list)
{
    CalcCommand* end = 0;
	CalcCommand* temp = list.fFirst;
	/**
	list.fFirst still not assigned to any value ...
	list.fFirst i think it's one number 
	CalcComand * end or *temp is pointing to one number also */
	while (temp) 
    {
  //in the example "CalcCommand* el = new CalcCommand (temp)" this didn't work here
  CalcCommand* el = new CalcCommand (*temp); 
  
  el -> setNext (0); 
  if (!fFirst) fFirst = el; // if there is no item in the list
  // el will poit to the first node
  else end -> setNext(el);
  end = el;
  temp = temp -> getNext();
    }  
}

//Assignment operator 
LinkedList& LinkedList::operator= (LinkedList& list)
{
    clear ();

	CalcCommand* end = 0;
	CalcCommand* temp = list.fFirst;
	while (temp) 
    {
  CalcCommand* el = new CalcCommand (*temp);
  
  el -> setNext (0);
  if (!fFirst) fFirst = el;
  else end -> setNext(el);
  end = el;
  temp = temp -> getNext();
	}
	return *this;
} 

//Returns the first element
CalcCommand* LinkedList::getFirst () const {return fFirst;}

//Pushes an element in the back of the list.
void LinkedList::push_back (CalcCommand* data)
{

	CalcCommand* temp = fFirst;
    while (temp -> getNext () != 0)
    {
        temp = temp -> getNext ();
    }
    
	temp -> setNext (data);//this will add data to the end of the list
	data -> setNext (0); //and this will set the one after the end of the list to NULL
}

void LinkedList::clear ()
{
	CalcCommand* temp = 0;
	while (fFirst) 
    {
  temp = fFirst;
  fFirst = fFirst -> getNext();
  delete temp;
	}
	fFirst = 0;
}

bool LinkedList::isEmpty () const
{
	if (!fFirst) return true;
	else return false;
}

7- calculator.cpp


Code:
#include "calculator.h"
#include <math.h>
#include <iostream>
using namespace std;

Calculator:: Calculator ():fCommandHistory(0) , fSubResult(0){} //DEFAULT CONSTRUCTOR
Calculator::~Calculator (){reset ();} //Calculator Destructor

// How can i use this (LinkedList* fCommandHistory) ?
// i can't call the seter functions of CalcComand "they are public"??

//log command mesthod 
void Calculator::logCommand (string operation, string operand, string description)
{
	fCommandHistory->push_back(new CalcCommand (operand,operation,description));
}

//Calculation Methods
bool Calculator::add (const string& operand)
{
	if (isValidDouble (operand))
	{
  fSubResult += stringToDouble (operand);
  logCommand ("+",operand,"Add ");
  return true;
	}
	else logCommand ("Adding number",operand,"Faild"); 
	return false;
}

bool Calculator::subtract (const string& operand)
{
	if (isValidDouble (operand))
	{
  fSubResult -= stringToDouble (operand);
  logCommand ("-",operand,"subtract");
  return true;
	}
	else logCommand ("Subtraction number",operand,"faild"); 
	return false;
}

bool Calculator::divide (const string& operand)
{
	if (isValidDouble (operand))
	{
  fSubResult /= stringToDouble (operand);
  logCommand ("/",operand,"divide");
  return true;
	}
	else logCommand ("dividing number",operand,"Faild"); 
	return false;
}

bool Calculator::multiply (const string& operand)
{
	if (isValidDouble (operand))
	{
  fSubResult *= stringToDouble (operand);
  logCommand ("*",operand,"multiply");
  return true;
	}
	else logCommand ("multiplay number",operand,"Faild"); 
	return false;
}
bool Calculator::sqrtC (const string& operand)
{
	if (isValidDouble (operand))
	{
  fSubResult =sqrt( stringToDouble (operand));
  logCommand ("sqrt",operand,"sqrt");
  return true;
	}
	else  logCommand ("sqrt",operand,"Faild");
	return false;
}
bool Calculator::powC (const string& operand)
{
	if (isValidDouble (operand))
	{
  fSubResult = pow(fSubResult,stringToDouble (operand));
  logCommand ("+",operand,"pow");
  return true;
	}
	else logCommand ("pow",operand,"Faild"); 
	return false;
}

void Calculator::setStart(const string subResult)
{
	if (isValidDouble (subResult))
	{
  fSubResult = stringToDouble (subResult);
	}
	else cout<<"error input , input wil be set to 0"<<endl; 
	fSubResult=0;
}

LinkedList* Calculator:: getCommandHistory () const {return fCommandHistory;}

string Calculator::getResult () 
{
	return doubleToString (fSubResult);
	reset ();
}

void Calculator::reset ()
{
	fSubResult = 0;
	fCommandHistory= 0;
}

8 - utils.cpp

#include "utils.h"

/**
This method runs a simple check on the string data to verify that it is a valid
double number.
*/

bool isValidDouble (string data)
{
    bool decpointcnt = 0;
    for (int i = 0; i < data.size(); i++)
    {
        if (isdigit(data) == 0)
        {
            // if the char is no digit...
            if (data != '.' && data != '-') return false; // '.' the point od decimal
            else if (data == '-' && i != 0) return false;//'-' for min numbers
            else if (data == '.' && decpointcnt > 0) return false; //'.' can be only once
            
            if (data == '.' && decpointcnt == 0) ++decpointcnt;
        }
    }
                    
    return true;
}

/**
Converts a string into a double value. This function only produces reliable
results if data contains a valid double number. Use isValidDouble to verify
this.
*/
double stringToDouble (string data)
{
    return atof (data.c_str());  /*MyRef atof is a function included in <cstdlib> 
       & it take a parameter whitch is a pointer to string and it returns double **/ 
}

/**
Converts any double number into a string.
*/
string doubleToString (double data)
{
    stringstream stream;
    stream << data;
    string result;
    stream>>result;
    stream.clear ();
    return result;
}

9 - main.cpp

#include <iostream>
#include <stdlib.h>
#include "Calculator.h"
using std::string;

using namespace std;

int main ()
{
	string operand;
	string start  ;
	char operation ='?';
	bool finish = true;
	Calculator cal;

	cout<<"\t\t\tCalculator\n"<<endl;

	cout<<"\tEnter White space Between numbers and Operations!!\n"<<endl;

	cout<<" \t --------------------------------------  "<<endl;
	cout<<" \t| [+] Add number  [-] Substruct Number |"<<endl;
	cout<<" \t| Multiply    [/] Divide           |"<<endl;
	cout<<" \t| [§] Sqrt        [^] Power            |"<<endl;
	cout<<" \t| [=] Show result                      |"<<endl;
	cout<<" \t -------------------------------------- "<<endl;
	cout<<"\n\nYour Calulation = ";


	cin>>start;
	cal.setStart(start);

	do
	{
  finish = true;
  cin>>operation;
  switch (operation)
  {
 	 case '+' :	
      cin>>operand;
      cal.add(operand);
      break;
 	 case '-':	
      cin>>operand;
      cal.subtract(operand);
      break;
 	 case '*' :
      cin>>operand;
      cal.multiply(operand);
      break;
 	 case '/' :	
      cin>>operand;
      cal.divide(operand);
      break;
 	 case '§' : 
      cin>>operand;
      cal.sqrtC(operand);
      break;
 	 case '^' :
      cin>>operand;
      cal.powC(operand);
      break;
 	 case '=' :
      finish =false;
      cout<<"Result = "<<cal.getResult();
      break;
 	 default :
      finish =false;
      cout<<"Unknow input"<<endl;
  }
	}while (finish = true);



	return 0;
}
#2

هل تتوقع من احد ان يقرأ كل هذا الكود ليعرف اين الخطأ

اشرح المشكلة

Sr. Software Development Engineer
Hulu, LLC
My Blogs

#3

والله أخي عندك حق

لكنى توقعت أن يضعه أحد في برنامج

المهم المشكلة باختصار أن البرنامج يتوقف فى المنتصف

البرنامج هو عمل آله حاسبه

وتخزين العمليات الحسابيه فى linkedlist

خطوات العمل :

1- يقوم المستخدم بادخال عمليه حسابيه عن طريق calculator.cpp يستطيع المستخدم ان يضيف عمليه اخرى الى الناتج

2 – اذا اراد المستخدم أن يرى الناتج عن طريق getResult () نقوم بعمل calcommand object هذا ال object ثم نقوم بتخزينها فى linkedlist عن طريق push_back (CalcCommand* data); " وهنا هى المشكله "

3- اذا اراد المستخدم أن يدخل عمليه جديده نقوم بنفس الخطوات السابقه ,

سوف أضع البرنامج فى المرفقات ,

شكرا

calculator.zip

#4

باستخدام الـ debugger في الـ Visual Studio ظهرت المشكلة هنا:

void LinkedList::push_back (CalcCommand* data)

الظاهر ان هناك مشكلة مع الـ pointers, ربما شي متعلق بكون fFirst يحمل قيمة غير معرفة (اظن انه يشير الى الموقع 0, يعني NULL pointer)

#5

نعم اخى فى هذا السطر CalcCommand* temp =fFirst;

اقتباس
الظاهر ان هناك مشكلة مع الـ pointers, ربما شي متعلق بكون fFirst يحمل قيمة غير معرفة (اظن انه يشير الى الموقع 0, يعني NULL pointer)

لكنى حاولت طريقة أخرى لكن لا أعرف ماذا هناك

void LinkedList::push_back (CalcCommand* data)
{

	if (!getFirst ())
	{
  fFirst->setNext(data);
	}
	else
	{
  CalcCommand* temp =fFirst;

  while (temp->getNext() != 0)
  {
      temp = temp -> getNext ();//to let temp point to the last node in the list
  }
  
  temp -> setNext (data);//this will add data to the end of the list
  data -> setNext (0); //and this will set the one after the end of the list to NULL
	}
}
#6

نفس الشي ..

fFirst->setNext(data);

لا تستطيع استدعاء اي شي على fFirst مادامت null.

.. لحظة لحظة ......

اصلا المشكلة هنا:

void Calculator::logCommand (string operation, string operand, string description)
{
	fCommandHistory->push_back(new CalcCommand (operand,operation,description));
}

fCommandHistory هو اللي لا يشير الى شيء, لذلك اول ما تدخل في push_back تحصل على خطأ !!

حاول تغيير الكونستركتر تبع Calculator الى:

Calculator:: Calculator ():fCommandHistory(0) , fSubResult(0)
{
	fCommandHistory = new LinkedList();
}

تم تعديل هذه المشاركة بواسطة hasan_aljudy في 17 مايو 2005 في 20:54

هذا الموضوع مغلق.

مواضيع مشابهة