السلام عليكم و رحمة الله و بركاته
أرجو من أحد المتمرسين في ++C مساعدتي في إيجاد حل لمشكلتي مع هذا الكود
بصفة عامة، هذا الكود يفتح ملف bank.txt و لا يعمل بدونه
و هو برنامج لبنك يقوم بفتح الملف bank.txt و يقرأ ما فيه ثم يضع محتواه في AVLTree و يقوم بزيادة المشتركين و تعديل الإشتراكات الموجودة و طباعتها و إلغائها.
أما ما يحدث أن البرنامج لا يتعامل مع balance على أنه double و يكتبها على الملف على هيئة رقم لا معنى له و كذلك عندما يظهره عند إختيار Update أو print accont.
أرجو المساعدة مأجورين.
وإليكم الكود والمرفق .cpp
اقتباس#include <stdio.h>#include <stdlib.h>
#include<string.h>
FILE *ifpr;
#define LH +1
#define EH 0
#define RH -1
bool fileOpen = false;
bool equal = false;
struct customer
{
public:
int id;
double balance;
char name[10], surname[10], idaccount[10];
customer *left, *right;
int bal;
customer(int x=0)
{
id=x;
balance=x;
left = right = NULL;
bal = EH;
}
};
class AvlTree
{
private:
int count;//,level;
customer *root;
void erase(customer *s);
void preorder(customer *s);
void chkorder(customer *s);
void inorder(customer* s);
void preload (customer* s);
customer* createaccount(customer* s, customer* ptr, bool& taller);
customer* leftBalance(customer *s, bool& taller);
customer* rightBalance(customer *s, bool& taller);
customer* rotateLeft(customer* s);
customer* rotateRight(customer* s);
customer* _delete(customer* root,char idacc[10], bool& shorter, bool& success);
customer* dltLeftBalance (customer *root, bool& smaller);
customer* dltRightBalance (customer *root, bool& shorter);
customer* update(customer* root,char idacc[10], bool& success);
customer* printinfo(customer *root, char idacc[10], bool& sucess);
public:
AvlTree() {root = NULL;count =0;}
~AvlTree() {erase(root);}
bool createaccount(char[10],char[10],char[10], double, int);
bool remove(char [10]);
bool update(char [10]);
bool printinfo(char [10]);
void inorder();
void preorder();
void chkorder();
void preload();
};
void menu()
{
AvlTree A;
char n[10],sn[10],idc[10];
int id,c;
double balance;
bool repeat=true,fileEmpty=true;
ifpr = fopen("bank.txt", "r+");/*here we have to change r with ????*/ /* error*/
fileOpen=true;
fscanf (ifpr,"%s%s%s%f%d",n,sn,idc,&balance,&id);
while( !feof(ifpr) )
{
fileEmpty=false;
A.createaccount(n,sn,idc,balance,id);
fscanf (ifpr,"%s%s%s%f%d",n,sn,idc,&balance,&id);
}
if (!fileEmpty)
A.createaccount(n,sn,idc,balance,id);
fclose(ifpr);
fileOpen=false;
while (repeat)
{
printf("\n\nCHOOSE FROM THE MENU(1-5)\n");
printf("\t1- CREATE ACCOUNTS.\n\t2- UPDATE ACCOUNTS.\n\t3- PRINT ACCOUNTS.\n\t4- DELETE ACCOUNTS\n\t5-EXIT\nYOUR CHOICE: ");
scanf("%d", &c);
switch©
{
case 1:
printf ("\nEnter Name:\t");
scanf ("%s",n);
printf ("\nEnter Surname:\t");
scanf ("%s",sn);
printf ("\nEnter id account:\t");
scanf ("%s",idc);
printf ("\nEnter Balance:\t");
scanf ("%f",&balance);
printf ("\nEnter id number:\t");
scanf ("%d",&id);
A.createaccount(n,sn,idc,balance,id);
break;
case 2:
printf("enter the id of the customer u want to update its information:\n");
scanf("%s", idc);
A.update(idc);
break;
case 3:
printf("enter the id of the customer to get information:\n");
scanf("%s", idc);
A.printinfo(idc);
break;
case 4:
printf("enter the idaccount of the customer u want to delete:\n");
scanf("%s", idc);
if(A.remove (idc))
printf ("\nDelete customer done successfully\n");
else
printf ("\nCustomer not available\n");
break;
case 5:
A.preload();
printf("\nTHANKS BYE\n\n");
repeat=false;
break;
}
}
}
int main()
{
menu();
return 0;
}
bool AvlTree::createaccount(char name[10],char surname[10],char idaccount[10], double balance, int id)
{
equal = false;
customer *ptr;
bool taller;
/*we need to check for dublicate data, before inserting into the customertree*/
ptr=new customer;
strcpy(ptr->name, name);
strcpy(ptr->surname, surname);
strcpy(ptr->idaccount, idaccount);
ptr->balance = balance;
ptr->id = id;
if( root = createaccount( root, ptr, taller ) )
{
if((!fileOpen)&&(!equal))
printf ("\n Customer Added successfully\n");
return true;
}
return false;
}
void AvlTree::inorder() {inorder(root);}
void AvlTree::preorder() {preorder(root);}
void AvlTree::preload()
{
//if(getcount()==0) return;
ifpr = fopen("bank.txt","w");/*here we have to change w with something*/
fileOpen=true; /*error*/
preload(root);
fclose(ifpr);
fileOpen=false;
}
void AvlTree::chkorder()
{// level = 0;
chkorder(root);
}
void AvlTree::erase(customer *s)
{
if ( s != NULL) {
erase(s->left);
erase(s->right);
delete s;
}
}
void AvlTree::preorder(customer *s)
{
if ( s != NULL) {
printf("%s \n", s->idaccount);
preorder(s->left);
preorder(s->right);
}
}
void AvlTree::preload(customer *s)
{
if ( s != NULL) {
fprintf (ifpr,"%s %s %s %f %d\n",s->name,s->surname,s->idaccount,s->balance,s->id);
preload(s->left);
preload(s->right);
}
}
void AvlTree::chkorder(customer *s) {
static level;
level++;
if ( s != NULL) {
for (int i=0; i < level;i++)
printf("\t");
printf("%d. %s\n",level,s->idaccount);
chkorder(s->left);
chkorder(s->right);
}
level--;
}
void AvlTree::inorder(customer* s) {
if ( s != NULL) {
inorder(s->left);
printf("%s ",s->idaccount);
inorder(s->right);
}
}
customer* AvlTree::createaccount(customer* s, customer* ptr, bool& taller) {
/*ptr points to the new customer which will be inserted
s initially will be pointing to the root, at each recursive call
it will point to the root of the subtreetaller is a boolean
operator indicating if the subtree height has increased,
false indicating the subtree has increased in size*/
if(!s)
{
s = ptr;
taller = true;
return s;
}//if root is empty
else if (strcmp(ptr->idaccount,s->idaccount)<0)
{
s->left = createaccount(s->left, ptr, taller);
if (taller) //left subtree is taller, so we have to check wether it is still AVL
switch(s->bal) {
case LH: //Was left high, so we need to rotate
s = leftBalance(s, taller);
break;
case EH://was balanced, now it is left-high
s->bal = LH;
break;
case RH: //was right high, now it is even high
s->bal = EH;
taller = false;
break;
}//switch
}//if less
else if(strcmp(ptr->idaccount, s->idaccount)==0){
equal=true;
printf ("\nCustomer NOT ADDED, The id is used, try again\n");
taller=false;
}
else {
//new customer account number > current customer account number
s->right = createaccount(s->right, ptr, taller);
if (taller)
//right sub tree is taller
switch(s->bal) {
case LH: //Was left high, now EH
s->bal = EH;
taller = false;
break;
case EH: //was balanced, now RH
s->bal = RH;
break;
case RH: //was right high, rotate
s = rightBalance(s, taller);
break;
}//switch
}//else data > s
return s;
}//the private create account member function
customer* AvlTree::leftBalance(customer *s, bool& taller) {
customer *rightTree;
customer *leftTree;
leftTree = s->left;
switch(leftTree->bal) {
case LH: //Left high, Rotate Right
s->bal = EH;
leftTree->bal = EH;
//rotate right
s = rotateRight(s);
taller = false;
break;
case EH: //This is an error
printf("\n\n\aError in left Balance\n\n\n");
exit(100);
case RH: //Right high requires double rotation
//first left, then right
rightTree = leftTree->right;
switch(rightTree->bal) {
case LH:
s->bal = RH;
leftTree->bal = EH;
break;
case EH:
s->bal = EH;
leftTree->bal = EH;
break;
case RH:
s->bal = EH;
leftTree->bal = LH;
break;
}//switch rightTree
rightTree->bal = EH;
//rotate Left
s->left = rotateLeft(leftTree);
//rotate Right
s = rotateRight(s);
taller = false;
}//switch leftTree
return s;
}//leftBalance
customer* AvlTree::rightBalance(customer *s, bool& taller) {
customer *rightTree;
customer *leftTree;
rightTree = s->right;
switch(rightTree->bal) {
case LH: //Left high, requires double rotation
//first right, then left
leftTree= rightTree->left;
switch(leftTree->bal){
case LH:
s->bal = EH;
rightTree->bal = RH;
break;
case EH:
s->bal = EH;
rightTree->bal = EH;
break;
case RH:
s->bal = LH;
rightTree->bal = EH;
break;
}//switch leftTree
leftTree->bal = EH;
//rotateright
s->right = rotateRight(rightTree);
//rotateLeft
s = rotateLeft(s);
taller = false;
break;
case EH://This is an error
printf("\n\n\aError in right Balance\n\n\n");
exit(100);
case RH://Right high, Rotate left
s->bal = EH;
rightTree->bal = EH;
//rotate left
s = rotateLeft(s);
taller = false;
break;
}//switch rightTree*/
return s;
}//rightBalance
customer* AvlTree::rotateLeft(customer* s) {
customer* tmp;
tmp = s->right;
s->right = tmp->left;
tmp->left = s;
return tmp;
}//rotateLeft
customer* AvlTree::rotateRight(customer* s) {
customer* tmp;
tmp = s->left;
s->left = tmp->right;
tmp->right = s;
return tmp;
}//rotateRight
bool AvlTree::remove(char x[10])
// -----------------------------------------------------------------
// Purpose: This function deletes a customer with all its information
// from the AVL tree and rebalances it if necessary. This functions
// true if a customer has been deleted, otherwise false.
// -----------------------------------------------------------------
{
// The following are two objects that are shared through the
// recursive execution of deleting a customer.
bool shorter;
bool success;
customer *newRoot;
// Delete a customer within the tree having the value of dltKey.
newRoot = _delete (root, x, shorter, success);
// If the customer was deleted, the root of the tree may have changed
// requiring that tree be assigned a new address for a root.
if (success)
{
root = newRoot;
count--;
return success;
}
else
{
//printf("SORRY!\nTHE DELETION FAILED\n");
return success;
}
}
customer* AvlTree::_delete(customer* s,char idacc[10], bool& shorter, bool& success)
// -----------------------------------------------------------------
// Purpose: This function deletes a customer from the tree and rebalance
// it if necessary. Returns true if deleted, false if not found.
// -----------------------------------------------------------------
{
// The following are local pointers needed for deletion
// and interchanging of key and data values.
customer *dltPtr;
customer *exchPtr;
customer *news;
if (!s)// If no node to delete, return null.
{
shorter = false;
success = false;
printf ("\nSorry!\n\tThere is no customer");
return NULL;
}
if (strcmp(idacc ,s->idaccount)<0)// Test if need is to delete a customer to the left of the s.
{
s->left = _delete (s->left, idacc, shorter, success);
if (shorter)// Rebalance the tree if the tree has become shorter.
s = dltRightBalance (s, shorter);
}
else if (strcmp(idacc, s->idaccount)>0)// Test if need is to delete a customer to the right of the s.
{
s->right = _delete (s->right, idacc, shorter, success);
if (shorter)// Rebalnce the tree if the tree has become shorter.
s = dltLeftBalance (s, shorter);
}
else//Otherwise the node having the key has been found.
{
dltPtr = s;
if (!s->right)//Check if the node to be deleted has no right child.
{
news = s->left;
success = true;
shorter = true;
delete (dltPtr);
return news;
}
else if (!s->left)// Check if the node to be deleted has no left child.
{
news = s->right;
success = true;
shorter = true;
delete (dltPtr);
return news;
}
else// Otherwise node to be deleted has two children.
{
// Find the right most node from the left child of the
// node ready to be deleted.
exchPtr = s->left;
while (exchPtr->right)
exchPtr = exchPtr->right;
// Exchange data between the right most node and the
// node to be deleted.
strcmp(s->idaccount ,exchPtr->idaccount);
// Delete the leaf node having the key given by exchPtr -> data.key.
s->left = _delete (s->left, exchPtr->idaccount, shorter, success);
if (shorter)// Rebalance the tree if it has become shorter.
s = dltRightBalance (s, shorter);
}
}
return s;
}
customer* AvlTree::dltLeftBalance (customer *s, bool& shorter)
// -----------------------------------------------------------------
// Purpose: This function rebalances the AVL based upon the
// assumption that the tree is shorter after a deletion
// on the right of the s. This function will adjust
// the balance factors and rotate the tree to the right
// if it is necessary. Function returns a potential
// new s.
// -----------------------------------------------------------------
{
// The following are local pointers needed to rebalance the tree.
customer *rightTree;
customer *leftTree;
switch (s->bal)// Determine if the s node is LH, EH, or RH.
{
case RH: // s was RH - now becomes EH.
s->bal = EH;
break;
case EH: // s was EH - now becomes LH.
s->bal = LH;
shorter = false;
break;
case LH: // s was LH - remains LH. Requires rotate right.
leftTree = s->left;
switch (leftTree->bal)
{
case LH:
case EH: // Perform a single rotation to the right.
if (leftTree->bal == EH)
{
s->bal = LH;
leftTree->bal = RH;
shorter = false;
}
else
{
s->bal = EH;
leftTree->bal = EH;
}
s = rotateRight (s);
break;
case RH: // Perform a double rotation.
rightTree = leftTree->right;
switch (rightTree->bal)
{
case LH:
s->bal = RH;
leftTree->bal = EH;
break;
case EH:
s->bal = EH;
leftTree->bal = EH;
break;
case RH:
s->bal = EH;
leftTree->bal = LH;
break;
}
rightTree->bal = EH;
s->left = rotateLeft (leftTree);
s = rotateRight (s);
break;
}
}
return s;
}
customer* AvlTree::dltRightBalance (customer* s, bool& shorter)
// -----------------------------------------------------------------
// Purpose: This function rebalances the AVL based upon the
// assumption that the tree is shorter after a deletion
// on the left of the s. This function will adjust
// the balance factors and rotate the tree to the left
// if it is necessary. Function returns a potential
// new s.
// -----------------------------------------------------------------
{
// The following are local pointers needed to rebalance the tree.
customer *rightTree;
customer *leftTree;
switch (s -> bal) // Determine if the s node is LH, EH, or RH.
{
case LH: // s was LH - now becomes balanced (EH).
s -> bal = EH;
break;
case EH: // s was EH - becomes RH but remains balanced.
s -> bal = RH;
shorter = false;
break;
case RH: // s is RH and remains RH - requires rotate left.
rightTree = s -> right;
if( rightTree -> bal == LH )// Need to perform a double rotation.
{
leftTree = rightTree -> left;
switch (leftTree -> bal)
{
case LH:
rightTree -> bal = RH;
s -> bal = EH;
break;
case EH:
s -> bal = EH;
rightTree -> bal = EH;
break;
case RH:
s -> bal = LH;
rightTree -> bal = EH;
break;
}
leftTree -> bal = EH;
// Rotate right and then left.
s -> right = rotateRight( rightTree );
s = rotateLeft( s );
}
else// Perform a single rotation only.
{
switch (rightTree -> bal)
{
case LH:
case RH:
s -> bal = EH;
rightTree -> bal = EH;
break;
case EH:
s -> bal = RH;
rightTree -> bal = LH;
shorter = false;
break;
}
s = rotateLeft( s );
}
}
return s;
}
bool AvlTree::update(char x[10])
{
// The following are two objects that are shared through the recursive
// execution of updating a customer balance.
bool success;
customer *newRoot;
newRoot = update(root, x, success);
if (success)
return success;
else
{
printf("\n SORRY\n\tUPDATING FAILED\n");
return false;
}
}
customer* AvlTree::update(customer* s,char idacc[10], bool& success)
// -----------------------------------------------------------------
// Purpose: This function update a customer balance.
// Returns true if updated, false if not found.
// -----------------------------------------------------------------
{
// The following is a local pointer needed for updating
// and interchanging of key and data values.
customer *dltptr;
if (!s)// If no node to delete, return null.
{
success = false;
return NULL;
}
if (strcmp(idacc ,s->idaccount)<0)
s->left = update(s->left, idacc, success);
else if (strcmp(idacc, s->idaccount)>0)
s->right = update(s->right, idacc, success);
else// Otherwise the node having the key has been found.
{
dltptr=s;
int choice;
double balance;
printf("choose the data u want to update:\n");
printf("\t1-increase balance\n\t2-decreasing balance\n\t3-cancel\nyour choice:\t");
scanf("%d", &choice);
while((choice!=1)&&(choice!=2)&&(choice!=3))
{
printf("YOUR CHOICE MUST BE BETWEEN (1-3)\n");
scanf("%d", &choice);
}
if(choice==1)
{
printf("ENTER THE AMOUNT YOU WANT TO ADD\n");
scanf("%f", &balance);
dltptr->balance+=balance;
}
else if(choice==2)
{
printf("ENTER THE AMOUNT YOU WANT TO DRAW\n");
scanf("%f", &balance);
while(balance > s->balance)
{
printf("\nSORRY!\nNOT REQUIRED\nYOUR BALANCE IS %d", s->balance);
printf("ENTER ANOTHER AMOUNT:\t");
scanf("%f", &balance);
}
dltptr->balance-=balance;
}
else
{
printf("\nNO CHANGE IN BALANCE\n");
}
}
return s;
}
bool AvlTree::printinfo(char x[10])
{
// The following are two objects that are shared through the recursive
// execution of printing information to a customer.
bool success;
customer *newRoot;
if (newRoot = printinfo(root, x, success))
return success;
else
{
printf("\nSORRY!\n\tTHE CUSTOMER IS NOT AVAILABLE\n");
return false;
}
}
customer* AvlTree::printinfo(customer* s,char idacc[10], bool& success)
// -----------------------------------------------------------------
// Purpose: This function print information
// Returns true if printed, false if not found.
// -----------------------------------------------------------------
{
if (!s)// If no node to delete, return null.
{
success = false;
printf ("\n There is no customer\n");
return NULL;
}
if (strcmp(idacc ,s->idaccount)<0)// Test if need is to print informationa to the left customer of the s.
s->left = printinfo(s->left, idacc, success);
else if (strcmp(idacc, s->idaccount)>0)// Test if need is to print information to the right customer of the s.
s->right = printinfo(s->right, idacc, success);
else// Otherwise the node having the key has been found.
{
printf("\nTHE INFORMATION FOR CUSTOMER %s:\n", s->idaccount);
printf("\tNAME:\t%s\n\tSURNAME\t%s\n\tACCOUNT NUMBER \t%s\n\tBALANCE:\t%f\n\tIDNUMBERE\t%d\n", s->name, s->surname, s->idaccount, s->balance, s->id);
}
return s;
}