c - 我在 C 程序中遇到运行时错误,该错误应该从中缀表示法转换为后缀表示法

标签 c data-structures linked-list stack

我正在编写一个程序,该程序应该从 txt 文件中读取方程式并将其填充到链接列表中,检查其有效性,然后将每个有效方程式转换为后修复符号并计算最终结果。然后将它们写入文件或在控制台上打印它们取决于用户的选择。以下是我已经完成的操作,我知道我的代码非常长,但我将其全部发布是为了使我的问题更清楚:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct node *ptr;
struct node
{
char eq[100];
char pstfix[100];
double result;
ptr next;
int topPST;
int topOP;
int validity;
};
typedef ptr list;
typedef ptr position;

list l;

void menu(); // prints the menu
void readFile(list l); //reads data from a file
int opPriority(char operators[],char operation,int top) ; // check the     priority of a given operation
void isValid(position p);//Function to check the validity of each equation.
void convert(list l);  // to convert from infix to postfix
void getResult(list l);  // to calculate the result of an equation
double calculate(char operation, int op1,int op2);//To return the value in each step when getting the result
void showValidity(list l); // print the equations and show the ones that have errors
void acceptEq(list l); // Let the user enter equations on the console screen
void fillInfix(position p, char c[]);//A function to fill the array of infix in the node.
int isNum(char val);//returns if the value passed to it is a number or character.
void writeToFile(list l);//Write to the file
void showConsole(list l);//Show the final results on the console


int main()
{
printf("\t\t\t*Data Structure\tSecond project*\n\n\t\t\t*Convert from infix to postfix*\n\n");
menu();
l=(list)malloc(sizeof(struct node));
return 0;
}

//Function to print the menu and let the program work depending on the choice.
void menu()
{
system("cls");
int choice;
printf("\t\t\t\tMenu\n\n\t\t\t1.Read equations from file.\n\t\t\t2.Check validity.\n\t\t\t3.Convert to postfix.\n\t\t\t4.Add more equations to the file.\n\t\t\t\n\t\t\t5.Calculate Results.\n\t\t\t6.Write results to file.\n\t\t\t7.Show results on the console.\n\t\t\t8.End.\n\n\t\t\tEnter Your choice number please\n\t\t\t");
scanf("%d",&choice);
switch (choice)
{
    case 1: readFile(l);
    break;
    case 2: isValid(l);
    break;
    case 3: convert(l);
    break;
    case 4: acceptEq(l);
    break;
    case 5: getResult(l);
    break;
    case 6: writeToFile(l);
    break;
    case 7: showConsole(l);
    break;
    case 8: exit(0);
}

}

//The following function should read equations from a file specified by the user
void readFile(list l)
{
system("cls");
char fileName[50];
FILE *eqFile;
printf("\t\t\tEnter the title of the file please\n\t\t\t");
scanf("\t\t\t%s",fileName);
eqFile=fopen(fileName,"r");

//To ensure the existence of the requested file.
while (eqFile == NULL)
{
    printf("\t\t\tThe file you asked for does not exist. Enter another name or enter 'back' to return to menu\n\t\t\t");
    scanf("\t\t\t%s",fileName);
    if(strcmp(fileName,"back")==0) menu();
    else eqFile=fopen(fileName,"r");
}
(l)->next=(position)malloc(sizeof (struct node));
position temp=(l)->next;
char line[100];
while (temp != NULL){
while (fgets(line,sizeof line, eqFile) != NULL)
{
    isValid(temp);
    if ((temp)->validity) fillInfix(temp,line);
    temp=(temp)->next;
    (temp)->next=NULL;
}
}
fclose(eqFile);
int choice;
printf("\t\t\tData Read Successfully\n\t\t\tEnter 0 to exit or 1 to return to menu\n\t\t\t");
scanf("%d",&choice);
if (choice) menu();
else exit(0);

}


void isValid(list l)
{
system("cls");
position temp;
temp=l;
int i,count=0;
while((temp)->next!=NULL)
{
    for (i=0;i<100;i++)
    {
        if (((l)->eq[i]=='+' && (l)->eq[i+1]=='*') || ((l)->eq[i]=='-' && (l)->eq[i+1]=='*')|| ((l)->eq[i]=='*' && (l)->eq[i+1]=='/') || ((l)->eq[i]=='/' && (l)->eq[i+1]=='+')|| ((l)->eq[i]=='/' && (l)->eq[i+1]=='-') || (l)->eq[i]==' ')
            count++;
    }
    if (count!=0) (temp)->validity=0;
    temp=(temp)->next;
}
int choice;
printf("\t\t\tChecking validity is done enter 0 to quite or 1 to return to menu\n\t\t\t");
scanf("%d",&choice);
if(choice) menu();
else exit(0);

}

void fillInfix(position p, char line[])
{
int i;
for (i=0;i<100;i++)
{
    while (line[i]!='\0')
    {
        (p)->eq[i]=line[i];
    }
}
}
void push(char st[],char element, int top)
{
++top;
st[top]=element;
}

char pop(char st[],int top)
{
 char elemnt=st[top];
 --top;
 return elemnt;
 }

int opPriority(char operators[], char operation, int top)
{
if ((operation=='*' && operators[top]=='-') || (operation=='*' && operators[top]=='+') || (operation=='*' && operators[top]=='/') || (operation=='/' && operators[top]=='-')|| (operation=='/' && operators[top]=='+') || (operation=='+' && operators[top]=='-')) return 0;
else
    if ((operation=='(' && operators[top]=='*') || (operation=='(' && operators[top]=='/') || (operation=='(' && operators[top]=='+') || (operation=='(' && operators[top]=='-')) return 0;
else if (operation==')') return 2;
else
    return 1;
}

int isNum(char val)
{
if (val!='+' && val!='-' && val!='*' && val!='/') return 1;
else return 0;
}

void convert(list l)
{
position temp=l;
int i;
char operators[100];
while ((temp)->next != NULL)
{
    temp=(temp)->next;
    if ((temp)->validity)
    {
       for (i=0;i<100;i++)
       {
           if (isNum((temp)->eq[i])) push((temp)->pstfix,(temp)->eq[i],(temp)->topPST);
           else
           {
               int priority=opPriority(operators,(temp)->eq[i],(temp)->topOP);
               if (priority==1)
               {
                   push((temp)->pstfix,pop(operators,(temp)->topOP),(temp)->topPST);
                   push(operators,(temp)->eq[i],(temp)->topOP);
               }
               else
                    if (priority ==0) push(operators,(temp)->eq[i],(temp)->topOP);
               else
               if (priority==2)
               {
                   while (operators[(temp)->topOP]!='(')
                   {
                       push((temp)->pstfix,pop(operators,(temp)->topOP),(temp)->topPST);
                   }
                   char trash=pop(operators,(temp)->topOP);//Unwanted closed bracket
               }
           }

       }

    }

    }
    int choice;
    printf("\t\t\tConversion Done successfully. Enter 0 to quite or 1 to return to menu\n\t\t\t");
    scanf("%d",&choice);
    if(choice) menu();
    else exit(0);
}

void acceptEq(list l)
{
system("cls");
char newEq[100];
printf("\t\t\t Enter your equation please. Note that your equation must not exceed the 100 characters length.\n\t\t\t");
scanf("\t\t\t%s",newEq);
position temp=l;
position p=(position)malloc(sizeof (struct node));
while ((temp)->next!=NULL)
{
    temp=(temp)->next;
}
(temp)->next=p;
isValid(p);
if ((p)->validity)
{
    fillInfix(p,newEq);
    convert(p);
}

}

void getResult(list l)
{
system("cls");
position temp=l;
while ((temp)->next != NULL)
{
    temp=(temp)->next;
    int i=0;
    while ((temp)->pstfix[i]!= '\0')
    {
        if ((temp)->pstfix[i]=='+' || (temp)->pstfix[i]=='-' || (temp)->pstfix[i]=='*' || (temp)->pstfix[i]=='/')
        (temp)->result = calculate((temp)->pstfix[i],(temp)->pstfix[i-2],(temp)->pstfix[i-1]);
        push((temp)->pstfix,(temp)->result,(temp)->topPST);
        printf("\n\t\t\t%c",(temp)->pstfix[i]);
        i++;
    }
    printf("=%f",(temp)->result);
}
}

double calculate (char operation,int op1,int op2)
{
double result;
if (operation=='+') result=op1+op2;
if (operation=='-') result=op1-op2;
if (operation=='*') result=op1*op2;
if (operation=='/') result=op1/op2;

return result;
}

void writeToFile(list l)
{
system("cls");
char fileWName[50];
printf("\n\t\t\tEnter the name of the file you want to print on please\n\t\t\t");
scanf("\t\t\t%s",fileWName);
FILE* resultFile;
resultFile=fopen(fileWName,"w");
position temp=l;
fprintf(resultFile,"Infix Notation:\t\t");
fprintf(resultFile,"Validity:\t\t");
fprintf(resultFile,"Postfix Notation:\t\t");
fprintf(resultFile,"Value:\t\t\n");
while ((temp)->next != NULL)
{
    temp=(temp)->next;
    int i=0;
    while ((temp)->eq[i]!='/0')
    {
        fprintf(resultFile,"%c",(temp)->eq[i]);
        i++;
    }
    fprintf(resultFile,"\t\t");
    i=0;
    while ((temp)->pstfix[i]!='/0')
    {
        fprintf(resultFile,"%c",(temp)->pstfix[i]);
        i++;
    }
    fprintf(resultFile,"\t\t");
    if ((temp)->validity == 0) fprintf(resultFile,"INVALID");
    else
    {
        fprintf(resultFile,"VALID\t\t");
        fprintf(resultFile,"%f",(temp)->result);
    }
}

fclose(resultFile);
int choice;
printf("\t\t\tDATA WRITTEN TO FILE SUCCESSFULLY. Press 1 to return to menu or 0 to quite\n\t\t\t");
scanf("%d",&choice);
if (choice) menu(l);
else exit(0);
}

void showConsole(list l)
{
system("cls");
position temp=l;
printf("Infix Notation:\t\t");
printf("Validity:\t\t");
printf("Postfix Notation:\t\t");
printf("Value:\t\t\n");
while ((temp)->next != NULL)
{
    temp=(temp)->next;
    int i=0;
    while ((temp)->eq[i]!='/0')
    {
        printf("%c",(temp)->eq[i]);
        i++;
    }
    printf("\t\t");
    i=0;
    while ((temp)->pstfix[i]!='/0')
    {
        printf("%c",(temp)->pstfix[i]);
        i++;
    }
    printf("\t\t");
    if ((temp)->validity == 0) printf("INVALID");
    else
    {
        printf("VALID\t\t");
        printf("%f",(temp)->result);
    }
}

int choice;
printf("\t\t\tDATA WRITTEN SUCCESSFULLY. Press 1 to return to menu or 0 to quite\n\t\t\t");
scanf("%d",&choice);
if (choice) menu();
else exit(0);
}

我已经使用调试器来找出问题所在。现在我知道这个语句中有一个编译错误:

(l)->next=(position)malloc(sizeof (struct node));

我想知道这个说法有什么问题吗?我正在尝试为节点分配空间,以便能够为每行(方程)创建更多节点。

最佳答案

在这种情况下,很容易看出问题所在:您尝试取消引用 NULL 指针。

要理解原因,您应该知道所有全局变量(例如程序中的变量 l)都是零初始化的。这基本上意味着指针 l 被初始化为 NULL

问题的出现是因为l的内存在调用menu函数之后才被分配。因此,从 menu 调用的任何函数的 l 都将等于 NULL

<小时/>

您的代码还存在一些其他问题。一是您使用 malloc 分配的内 stub 本没有初始化,因此,例如,当您稍后在 readFile 函数中使用新的值调用 isValid 时,分配的节点,并且在 isValid 取消引用 temp->next 指针时,该 next 指针的值不确定 (实际上看起来是随机的)。访问这样的未初始化数据将导致undefined behavior 。这当然适用于结构内的所有数据,而不仅仅是指针。

您似乎也没有在任何地方将 temp->validity 设置为非零。

关于c - 我在 C 程序中遇到运行时错误,该错误应该从中缀表示法转换为后缀表示法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29457947/

相关文章:

c - 使用按位运算符,找到一个逻辑不等价

将 C 代码转换为 MIPS 汇编 - 使用递归的组合函数

c - 这个问题来 self 最近做的一道算法题,但我无法得到正确的答案

带有 : : (double colon) syntax? 的 C 函数

c - 递归 - 数据结构类(class) - 打印所有可能的系列

c - 链接列表和 fscanf

c - 在数组 (C) 中搜索最大的开放空间?

java - 实现集合及其顺序时使用的实际数据结构是什么?

c - C 中的链表迭代

java - 如何将代码拆分为同一目录中的两个 .java 文件(使用类)?