#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()
как возвращает aTreeNode
, но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, что означает, что он ожидает строку, заканчивающуюся нулем, но вместо этого вы дали ей символ. Разве ваш компилятор не предупредил вас об этом?