扫描堆栈中的字符时遇到错误

Encountering error in scanning a character in stacks

本文关键字:遇到 错误 字符 堆栈 扫描      更新时间:2023-10-16
#include <stdio.h>
#define MAXLEN 100
typedef struct
    {
     char element[MAXLEN];
     int top;
    } stack;
stack init(stack s)
{
     s.top=-1;
     return s;
}
int isEmpty(stack s){
     return(s.top==-1);
}
int isFull(stack s){
    return (s.top==MAXLEN-1);
}
stack push(stack s,char ch){
  if(s.top==MAXLEN-1){
     printf("n the stack is fulln");
     return s;
  }
  else{
     ++s.top;
     s.element[s.top]=ch;
     return s;
  }  
}
stack pop(stack s){
    if(s.top==-1){
       printf("n the stack is empty");
       return s;
    }
    else{
       --s.top;
       return s;
    }
}
void top(stack s){
    if(s.top==-1){
        printf("n empty stack");
    }
    else
        printf("%c",s.element[s.top]);
    }
void print(stack s){
    int i;
    printf(" serial no         character   ");
    for(i=0;i<s.top;++i){
       printf("   %d                %c n",i,s.element[i]);
    }
}
int main(){
       stack s; 
       s.top=-1; 
       init(s);
       char e; 
       int n,j=1,k;
       while(j==1){
           printf("n enter your choice 1.push 2.pop 3.top 4.print 5.exit:");
           scanf("%d",&n);
      switch(n)
        {
        case 1:
            printf("n enter the element to be pushed:  ");
            scanf("%ch",&e);
            s=push(s,e);
            break;
        case 2:
            s=pop(s);
            break;
        case 3:
           top(s);
           break;
        case 4:
          print(s);
          break;
        case 5:
          j=0;
          break;   
        default:      
          printf("n wrong choice entered enter correct one ");
          break;
         }
    }
}

错误发生在我编译并运行它并扫描了一个字符之后;它从开关中出来,没有连续扫描n的值,只是使用预先分配的值进入开关,它从开关出来并要求n输入t。通过这种方式,我在堆栈元素中自动遇到空间作为字符,并且顶部加倍。请帮我解决这个问题。您可以编译一次并自行检查。

更改

 scanf("%ch",&e); /* %ch ? */

 scanf(" %c",&e); // notice a whitespace in the format string

scanf("%c",&e);离开换行符时,该换行符再次被消耗。

这告诉 scanf 忽略空格。

if (scanf(" %c",&e) != 1)
        //Print error

使代码正常工作并不需要很多。 在下面的固定代码中,由于我使用的编译器选项,我预先声明了函数。 另一种方法是将函数定义为 static

#include <stdio.h>
#define MAXLEN 100
typedef struct
{
    char element[MAXLEN];
    int top;
} stack;
int isEmpty(stack s);
int isFull(stack s);
stack init(stack s);
stack pop(stack s);
stack push(stack s, char ch);
void print(stack s);
void top(stack s);
stack init(stack s)
{
    s.top = -1;
    return s;
}
int isEmpty(stack s)
{
    return(s.top == -1);
}
int isFull(stack s)
{
    return(s.top == MAXLEN - 1);
}
stack push(stack s, char ch)
{
    if (s.top == MAXLEN - 1)
    {
        printf("the stack is fulln");
    }
    else
    {
        ++s.top;
        s.element[s.top] = ch;
    }
    return s;
}
stack pop(stack s)
{
    if (s.top == -1)
    {
        printf("the stack is emptyn");
    }
    else
    {
        --s.top;
    }
    return s;
}
void top(stack s)
{
    if (s.top == -1)
        printf("empty stackn");
    else
        printf("TOS: %cn", s.element[s.top]);
}
void print(stack s)
{
    int i;
    printf("serial no   charactern");
    for (i = 0; i <= s.top; ++i)
    {
        printf("  %3d       %cn", i, s.element[i]);
    }
}
int main(void)
{
    stack s;
    s.top = -1;
    init(s);
    char e;
    int n, j = 1;
    while (j == 1)
    {
        printf("nenter your choice 1.push 2.pop 3.top 4.print 5.exit: ");
        if (scanf("%d", &n) != 1)
        {
            fprintf(stderr, "Failed to read a number.n");
            return 1;
        }
        switch (n)
        {
        case 1:
            printf("nenter the element to be pushed: ");
            if (scanf(" %c", &e) != 1)
            {
                fprintf(stderr, "Failed to read a character.n");
                return 1;
            }
            s = push(s, e);
            break;
        case 2:
            s = pop(s);
            break;
        case 3:
            top(s);
            break;
        case 4:
            print(s);
            break;
        case 5:
            j = 0;
            break;
        default:
            printf("incorrect choice (%d not in range 1-5); enter correct onen", n);
            break;
        }
    }
    return 0;
}

除了使缩进保持一致(我使用 uncrustify ,但还有其他工具也可以完成这项工作),我在 scanf() 语句中添加了错误检查,修复了"%ch"格式字符串(h是多余的,尽管大部分是无害的),从打印中删除尾随空格,在非提示printf()语句末尾使用换行符。

您的打印代码打印不够;由于您运行堆栈指针的方式,您需要使用 <= 而不是 < 打印for (i = 0; i <= s.top; i++)。 一种更正统的使用方式top让它显示要使用的下一个空间(因此数字从零开始并上升到 MAXLEN)。 需要进行许多相应的更改。

但是,还有一些主要的好奇心。 您继续按值传递堆栈并按值返回它们,而不是通过指针传递它们。 因此,您将 104 个字节传入和传出函数,这是相当多的。 在这个代码中,效率不是一个大问题,但风格是非正统的,我们可以说。 main()中的初始化节也有问题:

stack s;
s.top = -1;
init(s);

第一行很好。 第二行设置top,并且在"它工作"方面是可以的,但违反了封装。 下一行有多个问题。 它获取已初始化堆栈的副本,将top设置为 -1 ,并返回修改后的值。 但是,调用代码会忽略返回的值。

如果将指针传递给函数,则应使用:

void init(stack *s)
{
    s->top = -1;
}

然后:

stack s;
init(&s);

如果传递值,则可以使用:

stack s;
s = init(s);

虽然这有点毫无意义,你可以使用:

stack init(void)
{
    stack s;
    s.top = -1;
    return s;
}

然后调用:

stack s = init();

其中,通过指针传递是 largish 结构的正常机制(如果要求指定 'largish',我会说"16 字节或更多")。 您可以在知情的基础上进行例外,但要注意按值传递大型结构的隐性成本。 此外,对按值传递的结构所做的更改不会反映在调用函数中。 您可以通过返回修改后的值来规避这一点,但要小心。