연습의 일부로 프로그래밍을 배우려고 노력하면서 을 사용하는 프로그램을 만들도록 요청되었습니다. 1. 구조체 2. 두 배로 연결된 목록 3. 이진 검색 트리이진 검색 트리 문제
고객의 데이터베이스를 만들려면 .. 노드를 목록에 추가하고 검색하는 것이 좋습니다. 그러나 고객을 삭제하려고 할 때 프로그램이 작동하지 않아 충돌이 발생합니다. 문제점을 추적하여 BST_delete 함수이 86 행부터 시작됩니다. 왜냐하면이 함수를 실행하지 않으면 프로그램이 훨씬 효과적입니다. 구체적으로 내가이 날 미치게됩니다
내가 이진 트리의 가장 최근의 노드 수 있어야 올바르게 기능 BST_email_root을 .. 업데이트하고 있지 않다라고 생각! 나는 그것이 가장 우아한 코드는 아니지만 나는 여전히 배우려고 노력하고 있다는 것을 압니다! 감사합니다
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_STRING 250
void myflush();
// Defining a customer structure.
struct customer {
char *name;
char *address;
char *email;
};
// A double linked list. The data field points to a customer struct.
struct double_linked_list {
struct customer *data;
struct double_linked_list *previous;
struct double_linked_list *next;
};
// Defining a pointer for the first one of the customers in the double linked list.
struct double_linked_list *customers_head=0;
// A node for a Binary Search Tree (BST).
struct BST_node {
struct double_linked_list *data;
struct BST_node *left;
struct BST_node *right;
};
// Defining a variable for the root of the BST that is indexed by the email.
struct BST_node *BST_email_root = 0;
// Looking for a node with a specific email in the BST.
struct BST_node *BST_find_customer(struct BST_node *root, char *email) {
if (root==NULL)
return NULL;
if (strcmp(email,root->data->data->email)==0)
return root;
else
{
if (strcmp(email,root->data->data->email)==-1)
return BST_find_customer(root->left,email);
else
return BST_find_customer(root->right,email);
}
}
// A procedure to finding a customer according to his email.
void find_customer() {
char email[MAX_STRING];
struct double_linked_list *l;
struct BST_node *b;
printf("Give the email of the customer (up to %d characters) : ", MAX_STRING-1);
gets(email);
b = BST_find_customer(BST_email_root, email);
if (b==0)
printf("There is no customer with this email.\n");
else
{
l = b->data;
printf("Customer found! \n");
printf("Name : %s\n", l->data->name);
printf("Address : %s\n", l->data->address);
printf("Email : %s\n", l->data->email);
}
}
struct BST_node *findMaxNode(struct BST_node *root)
{
if(root->right == NULL) return root;
findMaxNode(root->right);
}
// Deleting a node in the BST, according to a given email.
// The function returns the (new?) root of the BST, which might have been changed or not.
struct BST_node *BST_delete(struct BST_node *root, char *email)
{
if (root==NULL)
return root;
struct BST_node *father=NULL;
char which_son;
while (strcmp(email,root->data->data->email)!=0){ //first, finding root and remembering who's root father
if(root==NULL) {
return root;
} else if (strcmp(email,root->data->data->email) <0){
father = root;
root = root->left;
if(root==NULL)
return;
else which_son = 'l';
} else {
father = root;
root = root->right;
if(root==NULL)
return;
else which_son = 'r';
}
}
// now you have both the root node, and its father
if ((root->right == NULL) && (root->left == NULL)){ //case 1, if it's a leaf
free(root);
} else if (root->left == NULL) { //case 2
if (which_son == 'l') {
father->left = root->right;
} else {
father->right = root->right;
}
} else { //case 3 : here i get the "rightest" son of root's left son
struct BST_node *replacing_node = root->left;
while (replacing_node->right != NULL) {
replacing_node = replacing_node->right;
} //now replacing_node is a leaf, and can replace root
if (which_son == 'l') {
father->left = replacing_node;
replacing_node->left = root->left;
replacing_node->right = root->right;
} else {
father->right = replacing_node;
replacing_node->left = root->left;
replacing_node->right = root->right;
}
}
return root;
}
// This function adds a new node in the Binary Search Tree (BST) rooted by *root,
struct BST_node *new_BST_node(struct BST_node *root, struct double_linked_list *l)
{
if (root==NULL)
{
root= (struct BST_node *)malloc(sizeof(struct BST_node));
if (root==NULL)
{
printf("Out of Memory!");
exit(1);
}
root->data=l;
root->left=NULL;
root->right=NULL;
return root;
}
if ((strcmp(l->data->email,root->data->data->email))<0)
root->left =new_BST_node(root->left,l);
else
root->right =new_BST_node(root->right,l);
};
// A procedure to modify the data concerning an existing customer
void modify_customer() {
char old_email[MAX_STRING];
char new_email[MAX_STRING];
char new_name[MAX_STRING];
char new_address[MAX_STRING];
char ans;
struct BST_node *ind;
struct double_linked_list *l;
printf("Give the email of the customer you want to modify: ");
gets(old_email);
ind = BST_find_customer(BST_email_root, old_email);
if (ind == 0)
{
printf("There is no customer with this email.\n");
return;
}
l = ind->data; // The node in the double linked list for the customer
printf("Old name: %s\n", l->data->name);
printf("Give the new name (up to %d characters, <Enter> if it does not change): ", MAX_STRING - 1);
gets(new_name);
if (new_name[0] == 0)
strcpy(new_name, l->data->name);
printf("Old address: %s\n", l->data->address);
printf("Give the new address (up to %d characters, <Enter> if it does not change): ", MAX_STRING - 1);
gets(new_address);
if (new_address[0] == 0)
strcpy(new_address, l->data->address);
printf("Old email: %s\n", l->data->email);
printf("Give the new email (up to %d characters, <Enter> if it does not change): ", MAX_STRING-1);
gets(new_email);
if (new_email[0] == 0)
strcpy(new_email, l->data->email);
if (strcmp(l->data->email, new_email))
{
if (BST_find_customer(BST_email_root, new_email))
{
printf("New email already exists. Modification aborted.\n");
return;
}
}
printf("\n\n");
printf("REPLACE:\n");
printf("Name : %s\n", l->data->name);
printf("Address : %s\n", l->data->address);
printf("Email : %s\n", l->data->email);
printf("WITH:\n");
printf("Name : %s\n", new_name);
printf("Address : %s\n", new_address);
printf("Email : %s\n\n", new_email);
printf("Are you sure? (Y)es/(N)o\n");
scanf(" %c", &ans);
myflush();
if (ans == 'Y' || ans == 'y')
{
free(l->data->name);
l->data->name = strdup(new_name);
free(l->data->address);
l->data->address = strdup(new_address);
if (strcmp(l->data->email, new_email) != 0)
// Only in case the email has been changed, we have to maintain the BST
{
BST_email_root=BST_delete(BST_email_root, l->data->email);
free(l->data->email);
l->data->email = strdup(new_email);
BST_email_root=new_BST_node(BST_email_root, l);
}
}
}
// add a new customer
struct double_linked_list *new_customer()
{
char name[MAX_STRING], address[MAX_STRING], email[MAX_STRING];
struct BST_node *b;
struct double_linked_list *l;
struct customer *c;
printf("\nADDING A CUSTOMER\n\n\n");
printf("Give the name (up to %d characters): ", MAX_STRING-1);
gets(name);
printf("Give the address (up to %d characters): ", MAX_STRING - 1);
gets(address);
printf("Give the email (up to %d characters): ", MAX_STRING - 1);
gets(email);
// check for duplicate email
b = BST_find_customer(BST_email_root, email);
if (b)
{
printf("Duplicate email. Customer aborted.\n");
return 0;
}
c = (struct customer *) malloc(sizeof(struct customer));
if (c == 0)
{
printf("Not enough memory.\n");
return 0;
}
c->name = strdup(name); // check for memory allocation problem
if (c->name == 0) return 0;
c->address = strdup(address); // check for memory allocation problem
if (c->address == 0) return 0;
c->email = strdup(email); // check for memory allocation problem
if (c->email == 0) return 0;
l = (struct double_linked_list*) malloc(sizeof(struct double_linked_list));
if (l == 0)
{
printf("Not enough memory.\n");
free(c->name);
free(c->address);
free(c->email);
free(c);
return 0;
}
l->data = c;
l->previous = 0;
l->next = customers_head;
if (customers_head)
customers_head->previous = l;
customers_head = l;
BST_email_root = new_BST_node(BST_email_root, l);
return l;
}
// This function deletes a customer, based on its email
void delete_customer() {
char email[MAX_STRING];
struct BST_node *n_del;
printf("Give the email of the customer you want to delete(up to %d characters) : ", MAX_STRING-1);
gets(email);
n_del = BST_find_customer(BST_email_root, email);
if (n_del==0)
printf("There is no customer with this email.\n");
else
{
struct double_linked_list *current = n_del->data;
//struct double_linked_list *temp;
//struct double_linked_list *prev = customers_head;
if (current->next==NULL &¤t->previous==NULL)
{
free(current);
customers_head=0;
}
else if (current->next==NULL) //TA EXOUN ANAPODA??i oxi..Den exw katalaveiNEXT=0 EINAI GIA TO PROTO STOIXEIO pou vazw. An exw mono ena stoixeio ti ginete? prepei na to dw..
{
printf("1");
current->previous->next=NULL;
free(current);
}
else if (current->previous==NULL)
{ printf("2");
current->next->previous=NULL; //Apla kane to previous tou proigoumenou apo ton teleytaio pou thes na kaneis na mi deixnei pouthena..
customers_head=current->next;
free(current);
}
else
{
printf("3");
current->next->previous = current->previous; //vle ton proigoumeno komvo na deixnei ston epomeno kai ton epomeno ston proigoumeno
current->previous->next = current->next; //Ftiakse to customer's head na deixnei sto proigoumeno pou einai pleon to pio prosfato sti lista
}
}
BST_email_root=BST_delete(BST_email_root, email);
}
void displaymenu() {
printf("\n\n");
printf("1. New customer\n");
printf("2. Find customer using email\n");
printf("3. Modify customer\n");
printf("4. Delete customer\n");
printf("0. Exit\n\n");
printf("Give a choice (0-6) : ");
}
// This function empties the buffer of the standard input (stdin), that is, of the keyboard
void myflush()
{
char ch;
while ((ch = getchar()) != '\n' && ch != EOF);
}
// The main function
int main() {
int choice;
do {
displaymenu();
scanf("%d", &choice);
myflush();
switch (choice) {
case 1:
new_customer();
break;
case 2:
find_customer();
break;
case 3:
modify_customer();
break;
case 4:
delete_customer();
break;
default:
printf("Wrong selection.\n\n");
}
} while (choice != 0);
return 0;
}
세상에 나! 당신은리스트와 트리를 연결했고 데이터는 할당 된 메모리 포인터로 구조화되어 있습니다. 대답은 한 가지 문제를 발견했습니다. 그 동안 디버거로 바쁘다. BTW는 프로그램 단계를 작은 단계로 구성했는지 확인하고 스트레칭을 진행하거나 거대한 밤새 코딩 작업을 수행 한 후에 넘어 졌습니까? –
대답은 아니지만 가능한 버그 관찰 :'BST_delete'에서 두번째'if (root == NULL)'체크는'return;'으로 이어진다. 그것은 일종의'struct BST_node *'를 반환해야합니다. 포인터가 'NULL'일지라도 명시 적으로 말해야합니다. (들여 쓰기도 그 줄에서 이상하게 보입니다 ... 잘라 내기 및 붙여 넣기 오류, 아마도?) –
하나의 오류가 발견되었습니다 ... 디버거를 사용 중입니다! 'while (strcmp (email, root-> data-> data-> email)! = 0)'루핑 할 때'BST_delete()'함수에서'if (root == NULL)'을 체크하지 않는다. 'root = root-> left; 또는'root = root-> right; 그리고'root-> data'는 실패했습니다 !!! –