Ошибка сегментации для реализации дерева выражений в C

#c #data-structures #segmentation-fault #binary-tree #expression-trees

Вопрос:

С нубом здесь,

Я пытаюсь реализовать программу на языке C для преобразования ПОСТФИКСНОГО выражения в допустимое ПРЕФИКСНОЕ выражение с помощью дерева выражений.

Я создал 2 файла, файл TreeNode.h и основной файл.c

Дерево.h:

 #include <string.h>
#include <stdbool.h>
#include <malloc.h>

typedef char TreeEntry;

typedef struct treenode
{
    char entry;
    struct treenode * left;
    struct treenode * right;
}*TreeNode;


bool isOperator(char c)
{
    if (c == ' ' || c == '-' ||
        c == '*' || c == '/' ||
        c == '^'){
            return true;
        }
    return false;
}


TreeNode newNode(TreeEntry v){
    TreeNode temp;
    temp->left = temp->right = 0;
    temp->entry = v;
    return temp;
}

void inOrder(TreeNode n){
    if(n){
        inOrder(n->left);
        printf("%s",n->entry);
        inOrder(n->right);
    }
}

void preOrder(TreeNode n){
    if(n){
        printf("%s",n->entry);
        preOrder(n->left);
        preOrder(n->right);
    }
}

void postOrder(TreeNode n){
    if(n){
        postOrder(n->left);
        postOrder(n->right);
        printf("%s",n->entry);
    }
}


 

главная.c:

 
#include <stdio.h>
#include "TreeNode.h"

#define MAXSTACK 50

TreeNode stack[MAXSTACK];
int top = -1;

void push(TreeNode n){
    stack[  top] = n;
}

TreeNode pop(){
    TreeNode n = stack[top--];
    return n;
}

TreeNode createExpTree(char postfix[]){
    TreeNode temp,et;
    for (int i = 0; i < strlen(postfix); i  ){
        if(!isOperator(postfix[i])){
            temp = newNode(postfix[i]);
            push(temp);
        }else{
            temp = newNode(postfix[i]);
            temp->right = pop();
            temp->left = pop();
            push(temp);
            printf("%c",temp->entry);
        }
    }

    et = pop();
    return et;
}

int main(void){
    char postfix[] = "ab ";
    TreeNode expTree = createExpTree(postfix);
    inOrder(expTree);
    preOrder(expTree);
    postOrder(expTree);
}
    
 

Я продолжаю получать ошибку сегментации , я не могу понять, что вызывает эту ошибку.
Как мне устранить эту ошибку ? пожалуйста, помогите.

Редактировать:

Сначала я изменил функцию newNode :

 TreeNode * newNode(TreeEntry v){
    TreeNode * temp = (TreeNode *)malloc(sizeof(struct treenode));
    if(temp){
        temp->left = NULL;
        temp->right = NULL;
        temp->entry = v;
    }
    return temp;
}
 

даже после этого изменения я все еще получал ошибку ошибки сегментации.

Мне удалось исправить ошибку , по-видимому, ошибка была в функции inorder в файле TreeNode.h

Я изменил функцию упорядочения на:

 void Inorder(TreeNode *root, void(*Visit)(TreeEntry x))
{
    if (root)
    {
        Inorder(root->left, Visit);
        Visit(root->entry);
        Inorder(root->right, Visit);
    }
}
 

и изменил основной файл.c :

 void printEntry(TreeEntry te){
    printf("%c",te);
}


int main(void){
    char postfix[] = "ab ";
    TreeNode* expTree = createExpTree(postfix);
    Inorder(expTree,printEntry);
    
}
 

Теперь я предполагаю, что предыдущая функция inorder не смогла получить доступ к значениям указателя, который был передан ей, и это было причиной ошибки,

в чем причина этого ? Я был бы благодарен, если бы кто-нибудь смог дать объяснение.

Комментарии:

1. вы должны попытаться выполнить отладку с помощью gdb. Или пройдитесь по программе, используя printf() инструкции, чтобы увидеть, где код прерывается.

2. Можете ли вы описать, что вы пробовали? Компиляция кода с включенными предупреждениями может дать вам полезную информацию, например, вы передаете сообщение char newNode createExpTree вместо TreeNode . Кроме того, я бы рекомендовал посмотреть, как работает управление памятью в C. Объявление указателя не выделяет память. Вам следует обратить внимание на динамическое распределение памяти

3. temp->left = pop(); Я делаю это не c каждый день, но я удивлен, что это даже компилируется, так pop() как возвращает a TreeNode , но TreeNode.left объявляется как struct treenode * left; .

4. недостаточный поток стекового буфера

5. @NeonFire спасибо за ответ. Я использовал инструкции printf для отладки кода, мне удалось исправить (см. Редактирование) ошибку, и теперь программа работает должным образом. Является ли функция inorder неспособной получить доступ к значениям переданного ей указателя. Является ли это причиной ошибки

Ответ №1:

Я думаю, что ошибка кроется в функции newNode. Вы объявляете переменную temp как a TreeNode , которая совпадает с a struct treenode * . Таким образом, это означает, что у вас есть указатель, но вы не установили его равным чему-либо, что означает, что он просто указывает на какую-то случайную точку в памяти. Поэтому, когда вы пытаетесь записать в одну из его переменных, вы, по сути, записываете в память, которая вам не принадлежит, что приводит к ошибке сегментации.

Чтобы исправить это, вам нужно выделить немного памяти для вашего нового узла, как это:

 TreeNode newNode(TreeEntry v){
    TreeNode temp = (TreeNode)malloc(sizeof(struct treenode));
    temp->left = temp->right = 0;
    temp->entry = v;
    return temp;
}
 

Позже вам нужно будет использовать free функцию, чтобы вернуть эту память операционной системе, когда вы закончите с ней.

Комментарии:

1. Спасибо за ответ , я внес изменения, о которых вы упоминали. но я все еще получал сегфо после этого. После этого я изменил функцию inoder, и это исправило ошибку сегментации, и теперь программа работает. Я включил изменения, которые я внес в правку своего оригинального поста. Почему предыдущая функция inoder не может получить доступ к значениям указателя, который был передан ей

2. Я думаю, это произошло потому, что вы используете %s, что означает, что он ожидает строку, заканчивающуюся нулем, но вместо этого вы дали ей символ. Разве ваш компилятор не предупредил вас об этом?