使用堆栈作为C语言中的链接列表的中缀到postfix

时间:2013-08-31 06:33:51

标签: c

我已经编写了一个程序,使用UBUNTU中的C语言将中缀转换为后缀...但是我的程序无法正常工作可以帮助吗? 我的计划如下:

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

char op[50];

struct node
{
    char data;
    struct node *next;
} *l1=NULL;

void push(char x)         // pushes char into the linkedlist
{
    if(l1==NULL)
    {
        l1=(struct node *)malloc(sizeof(struct node));
        l1->data=x;
        l1->next=NULL;
    }
    else
    {
        struct node *p;
        p=(struct node *)malloc(sizeof(struct node));
        p->data=x;
        p->next=l1;
        l1=p;
    }
}

char pop()           // pops char outof linkedlist
{
    char c;
    struct node *p;
    if (l1==NULL)
    {
        printf("the stack is empty\n");
        // exit(1);
    }
    else
    {
        c=l1->data;
        p=l1->next;
        free (l1);
        l1=p;
    }
    return c;
}

void display(struct node *start)
{
    {
        int i=0;
        struct node *p;
        p=start;
        if(p==NULL)
            printf("Empty list");
        else
        {
            while(p!=NULL)
            {
                printf("%c->",p->data);
                p=p->next;
            }
            printf("NULL\n");
        }
    }
}


int prior(char s, char c)
{
    if ( c=='^' && s=='+' || s=='-' ||s=='/' || s=='*')
        return 1;
    else if( c=='*' || c=='/')
    {
        if(s=='+' || s=='-' )
            return 1;
        else
            return 0;
    }
    else if( c=='+' || c=='-' )
        return 0;
}

void cnvrt(char s[], int n)       // convert infix to postfix
{
    char g;
    int i,j,x;
    for(i=0,j=0;i<n;i++)
    {

        if (s[i]>='0'&&s[i]<='9' || s[i]>='a' && s[i]<='z'|| s[i]>='A' && s[i]<='Z')
        {
            op[j]=s[i];
            j++;
        }
        else if(s[i]=='(')
        {
            push(s[i]);
        }
        else if (s[i]=='+' || s[i]=='/' || s[i]=='-' || s[i]=='*' || s[i]=='^')
        {

            if( l1==NULL)
                push(s[i]);
            else if(l1->data=='(')
                push(s[i]);
            else if(prior(l1->data, s[i] )!=1)
                push(s[i]);
            else
            { op[j]=pop();
                j++;
                push(s[i]);
            }
        }
        else if(s[i]==')')
        {
            while(l1!=NULL && l1->data!='(')
            {
                op[j]=pop();
                j++;
            }
            g=pop();
        }
    }
    while(l1!=NULL)
    {
        op[j]=pop();
        j++;
        l1=l1->next;
    }
}


void main()
{
    int i,n;
    char c[50];
    printf(" enter the no of characters in infix string\n ");
    scanf("%d",&n);
    printf(" enter the infix string\n");
    //for(i=0;i<n;i++)
    scanf("%s",c);

    cnvrt(c,n);
    printf("the postfix string is \n");
    for(i=0;i<n;i++)
    {
        printf("%c",op[i]);
    }
}

答案中始终缺少其中一个运算符...而且它有时会将CORE DUMPED作为输出,如果infix包含'('ot')'那么它会在堆栈为空时给出输出...... 请帮助我,我是一名学生,所以他们可能在我的课程中出错。

2 个答案:

答案 0 :(得分:4)

此代码中存在许多问题,一些是次要问题,一些主要

MAJOR: pop()如果列表为空,将返回一个不确定的字符(即未定义的行为)。

MINOR:display()

中无用的块范围

MINOR:i

中未使用的变量display()

MAJOR:prior()开头if条款错误。它看起来像这样:

if  ( c=='^' && s=='+' || s=='-' ||s=='/' || s=='*')

它应该是这样的:

if  ( c=='^' && (s=='+' || s=='-' ||s=='/' || s=='*'))

MAJOR :在prior()中存在一个没有建立返回值的控制路径,因此该函数具有未定义的行为。见下文

int prior(char s, char c)
{
    if ( c=='^' && (s=='+' || s=='-' ||s=='/' || s=='*'))
        return 1;
    else if( c=='*' || c=='/')
    {
        if(s=='+' || s=='-' )
            return 1;
        else
            return 0;
    }
    else if( c=='+' || c=='-' )
        return 0;

    // ELSE NO RETURN VALUE SET; UNDEFINED BEHAVIOR
}

MINOR:在cnvrt()中,第一个if子句接近加密要理解。它看起来像这样:

(s[i]>='0'&&s[i]<='9' || s[i]>='a' && s[i]<='z'|| s[i]>='A' && s[i]<='Z')

考虑将其更新为:

((s[i]>='0'&&s[i]<='9') || (s[i]>='a' && s[i]<='z') || (s[i]>='A' && s[i]<='Z'))

并感谢@cHao对运算符优先级的轻推。

MINOR:cnvrt()变量x未使用。

非标准: void不是main()的有效返回类型。根据标准,main() 必须返回int。虽然这可能适用于您的平台,但它不符合标准。

这些只是我在阅读代码时发现的内容,我猜测修复它们将极大地帮助修复程序,尤其是标记为 MAJOR 的项目。如上所述,我不能这样做,所以我只能希望是这种情况。

答案 1 :(得分:3)

以下是工作修改:

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

char op[50];

struct node
{
    char data;
    struct node *next;
} *l1=NULL;

void push(char x)         // pushes char into the linkedlist
{
    if(l1==NULL)
    {
        l1=(struct node *)malloc(sizeof(struct node));
        l1->data=x;
        l1->next=NULL;
    }
    else
    {
        struct node *p;
        p=(struct node *)malloc(sizeof(struct node));
        p->data=x;
        p->next=l1;
        l1=p;
    }
}

char pop()           // pops char outof linkedlist
{
    char c;
    struct node *p;
    if (l1==NULL)
    {
        printf("the stack is empty\n");
        // exit(1);
    }
    else
    {
        c=l1->data;
        p=l1->next;
        free (l1);
        l1=p;
    }
    return c;
}

void display(struct node *start)
{
    {
        //int i=0;
        struct node *p;
        p=start;
        if(p==NULL)
            printf("Empty list");
        else
        {
            while(p!=NULL)
            {
                printf("%c->",p->data);
                p=p->next;
            }
            printf("NULL\n");
        }
    }
}


int prior(char s, char c)
{
    if ( (c=='^' && s=='+') || s=='-' ||s=='/' || s=='*')
        return 1;
    else if( c=='*' || c=='/')
    {
        if(s=='+' || s=='-' )
            return 1;
        else
            return 0;
    }
    else if( c=='+' || c=='-' )
        return 0;
  return -1;
}

void cnvrt(char s[], int n)       // convert infix to postfix
{
    //char g;
    int i,j;//,x;
    for(i=0,j=0;i<n;i++)
    {

        if ((s[i]>='0'&&s[i]<='9') || (s[i]>='a' && s[i]<='z')|| (s[i]>='A' && s[i]<='Z'))
        {
            op[j]=s[i];
            j++;
        }
        else if(s[i]=='(')
        {
            push(s[i]);
        }
        else if (s[i]=='+' || s[i]=='/' || s[i]=='-' || s[i]=='*' || s[i]=='^')
        {

            if( l1==NULL)
                push(s[i]);
            else if(l1->data=='(')
                push(s[i]);
            else if(prior(l1->data, s[i] )!=1)
                push(s[i]);
            else
            { op[j]=pop();
                j++;
                push(s[i]);
            }
        }
        else if(s[i]==')')
        {
            while(l1!=NULL && l1->data!='(')
            {
                op[j]=pop();
                j++;
            }
            pop();
        }
    }
    while(l1!=NULL)
    {
        op[j]=pop();
        j++;
    }
}


int main()
{
    int i,n;
    char c[50];
    printf(" enter the no of characters in infix string\n ");
    scanf("%d",&n);
    printf(" enter the infix string\n");
    //for(i=0;i<n;i++)
    scanf("%s",c);

    cnvrt(c,n);
    printf("the postfix string is \n");
    for(i=0;i<n;i++)
    {
        printf("%c",op[i]);
    }

    return 0;
}

您可以diff代码并查找修改,或查看@WhozCraig答案。那里有一些小错误,但导致内存错误的错误就是这个部分:

    //127-132
    while(l1!=NULL)
    {
        op[j]=pop();
        j++;
        l1=l1->next;
    }
调试器中的

> gcc code.c -Wall -g

> gdb -q a.exe
Reading symbols from a.exe...done.
(gdb) run
Starting program: a.exe
[New Thread 4000.0x524]
 enter the no of characters in infix string
 3
 enter the infix string
1+2

Program received signal SIGSEGV, Segmentation fault.
0x004016f9 in cnvrt (s=0x22fee6 "1+2", n=3) at code.c:131
131             l1=l1->next;
(gdb)
(gdb) p l1
$1 = (struct node *) 0x0
(gdb)

l1NULL,因此l1->next将失败。你需要做到:

    while(l1!=NULL)
    {
        op[j]=pop();
        j++;
    }

pop()负责更改l1的指针,然后当它从最后一项完成时,它将指向NULL,然后访问l1->next将失败。

现在几乎没有测试:

> a.exe
 enter the no of characters in infix string
 3
 enter the infix string
1+2
the postfix string is
12+
> a.exe
 enter the no of characters in infix string
 7
 enter the infix string
(1+3)*4
the postfix string is
13+4*
>