C语言 无法识别代码中的内存访问错误,不断给出分段错误

tvz2xvvm  于 2023-01-01  发布在  其他
关注(0)|答案(2)|浏览(214)

我试过创建一个程序,它使用简单的堆栈函数(如push)将语句的内容添加到堆栈中,然后从堆栈中打印出每个字符,然后反转语句。我使用“.”和“-〉”成员访问变量来更改基于结构体的堆栈的内容。编译时,它打印出原始语句,但之后它会给出分段错误。说我正在尝试解引用一个未初始化的指针。有人能指导我如何解决这个问题吗?因为它也没有说明我产生问题的行。

#include <stdio.h>
#define MAX 1000
#define FULL (MAX - 1)
#define EMPTY -1

typedef struct stack {char s[MAX]; int top;} stack;
int top = EMPTY;

int isFull()
{
  if(top == FULL)
    return 1;
  else
    return 0;
}

int isEmpty()
{
  if(top == EMPTY)
    return 1;
  else
    return 0;
}

void reset(stack *stk)
{
  stk -> top = EMPTY;
}

void push(char c, stack *stk)
{
  stk -> top++;
  (*stk).s[(*stk).top] = c;
}

char pop(stack *stk)
{
  return (*stk).s[(*stk).top--];
}

void print(stack *stk)
{
  int i;
  while(1)
  {
    if(isEmpty())
    {
      printf("Stack underflow\n");
      break;
    }
    for(i = 0; i <= top; i++)
    {
      printf("%c\n", (*stk).s[i]);
    }
    printf("\n");
    return;
  }
}

void reverse(stack *stk)
{
  int i;
  while(1)
  {
    if(isEmpty())
    {
      printf("Stack underflow\n");
      break;
    }
    for(i = top; i >= 0; i--)
    {
      printf("%c", (*stk).s[i]);
    }
    printf("\n");
    return;
  }
}

char peek(const stack *stk)
{
  while(1)
  {
    if(isEmpty())
    {
      printf("Stack underflow\n");
      break;
    }
    return (*stk).s[(*stk).top];
  }
}

int main()
{
  stack stack_of_char;
  char *str = "i am otto am i";
  int i;
  reset(&stack_of_char);
  printf("original is: %s\n", str);
  while(str[i] != '\0')
  {
    push(str[i++], &stack_of_char);
  }
  print(&stack_of_char);
  reverse(&stack_of_char);
  return 0;
}
5rgfhyps

5rgfhyps1#

你的程序有几个问题,让我们从全局变量top开始,这是因为一方面你有一个stack结构体负责维护栈,它有它自己的top,但是你有一个全局变量,你甚至没有用到它,就好像你加了它来避开你不理解的编译错误;)
所以让我们抛弃它,修复你的堆栈函数,我重新排列push函数的参数,使堆栈成为第一个参数,这是一个更传统的方法。

typedef struct stack {
    char s[MAX];
    int top;
} stack;

int isFull(stack *stk)
{
    return stk->top == FULL;
}

int isEmpty(stack *stk)
{
    return stk->top == EMPTY;
}

void reset(stack *stk)
{
    stk->top = EMPTY;
}

void push(stack *stk, char c)
{
    if (isFull(stk))
        return;
    stk->s[++stk->top] = c;
}

char pop(stack *stk)
{
    if (isEmpty(stk))
        return '\0';
    return stk->s[stk->top--];
}

对于pop函数,如果堆栈为空,我就任意返回一个NUL字符,因为必须返回 something,但实际上,如果堆栈为空,就不应该调用这个函数。
现在让我们看看你的显示功能。我注意到的第一件事是这些功能真的很复杂。没有必要这么复杂。看这里:

void print(stack *stk)
{
    for(int i = 0; i <= stk->top; i++)
    {
        printf("%c\n", stk->s[i]);
    }
    printf("\n");
}

void reverse(stack *stk)
{
    for(int i = stk->top; i >= 0; i--)
    {
        printf("%c", (*stk).s[i]);
    }
    printf("\n");
}

char peek(const stack *stk)
{
    if (isEmpty(stk))
    {
        printf("Stack empty!\n");
        return '\0';
    }
    return stk->s[stk->top];
}

因此,剩下的工作就是稍微整理一下主函数,并调整push的参数顺序。

int main()
{
    const char *str = "i am otto am i";
    printf("original is: %s\n", str);

    stack stack_of_char;
    reset(&stack_of_char);
    for (int i = 0; str[i]; i++)
    {
        push(&stack_of_char, str[i]);
    }

    print(&stack_of_char);
    reverse(&stack_of_char);
}

还要注意的是,你不应该用这些函数遍历你的堆栈,你使用堆栈反转的典型方式是将值压入堆栈,然后再将它们弹出,所以,你可以像这样反向打印字符串:

// Pop characters from stack to print in reverse
    while (!isEmpty(&stack_of_char))
    {
        char c = pop(&stack_of_char);
        putc(c, stdout);
    }
    putc('\n', stdout);
az31mfrm

az31mfrm2#

没有初始化,整数将是一个随机值。这是内存访问错误的根本原因。
您需要正确初始化变量。在主函数中,而不是
int i;
您应该使用
int i = 0;.
假设您计划访问从索引0开始的值。

相关问题