在KNK的C编程中运行示例代码时的错误函数第10章

uinbv5nw  于 2023-05-16  发布在  其他
关注(0)|答案(1)|浏览(101)

我对我的代码有疑问。这是我对KNK的C Programming a Modern Approach(第2版)第10章中的项目1的回答。
这个问题要求我们写一个堆栈来查看一系列括号和/或大括号是否正确嵌套。这个问题明确地要求学生修改10.2中的代码-这是本章的前一部分。我的编译器给了我错误warning control may not reach end of non-void function。编译器引用char pop(void)函数的调用。
我唯一的问题是我看不出有什么不对

char pop(void)
{
  if (is_empty())
     stack_underflow();
  else
    return contents[--top];
}

如果堆栈指针返回到零,则程序终止,如果不是,则返回一个字符,即contents[--top]。不仅如此-这正是10.2节中的示例指导学生编写pop函数的方式。因此,这似乎表明KNK弄错了,除非这是一个新版本的C(这本书使用C99)的问题。很明显我漏掉了什么。
因此,我甚至不确定我现在的代码是否正确,因为我甚至不能首先运行它。
如果你能告诉我哪里做错了,我会很感激的。

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

#define STACK_SIZE 100

/* function declarations */
bool is_empty(void);
bool is_full(void);
void push(char);
char pop(void);
void stack_overflow();
void stack_underflow();

/* external variables */
char contents[STACK_SIZE] = {0};
int top = 0;

int main(void)
{ 
  char ch;
  
  printf("Enter parentheses and/or braces: ");
  scanf("%c", &ch);
  
  while(ch != '\n')
  { 
    if(ch == '{' || ch == '(')  push(ch);
    else if(ch == '}' && pop() != '{')
    { 
      printf("Parentheses/braces are not nested properly\n");
      return 0;
    }
    else if(ch == ')' && pop() != '(')
    { 
      printf("Parentheses/braces are not nested properly\n");
      return 0;
    }
    scanf("%c", &ch);
  }
  
  if(is_empty())
    printf("Parentheses/braces are nested properly\n");
  else
    printf("Parentheses/braces are not nested properly\n");

  return 0;
}

bool is_empty(void)
{
  return top == 0;
}

bool is_full(void)
{
  return top == STACK_SIZE;
}

void push(char ch)
{
  if (is_full())
    stack_overflow();
  else
    contents[top++] = ch;
}

char pop(void)
{
  if (is_empty())
     stack_underflow();
  else
    return contents[--top];
}

void stack_overflow(void)
{
  printf("Stack overflow\n");
  exit(0);
}

void stack_underflow(void)
{
  printf("Parentheses/braces are not nested properly\n");
  exit(0);
}
km0tfn4u

km0tfn4u1#

这个函数说它返回一个char,但是如果是is_empty(),那么你什么也不返回。以下是几个选项:
1.返回一个从未达到的虚拟值:

char pop(void) {
  if (is_empty()) {
     stack_underflow();
     return '\0'; // silence warning; never reached
  }
  return contents[--top];
}

1.更改接口,以便您可以告诉调用者错误而不是现有错误:

typedef enum stack_error {
     STACK_OK,
     STACK_OVERFLOW,
     STACK_UNDERFLOW
} stack_error;

stack_error pop(char *output);

如果你不喜欢现在的样子:

char ch;
if(pop(&ch != OK) {
    // ...
}

你可以把它 Package 在一个宏中,但它给了调用者选择他们想要的行为的自由。

  1. gcc支持一个扩展来告诉编译器stack_overflow()不返回,并且它会像这样用你的代码静默警告:
void stack_underflow() __attribute__ ((noreturn));

1.在C 2017中,您可以使用_Noreturn函数说明符,如果包含<stdnoreturn.h>noreturn,它也会使警告静音。这将是我在这个时候的首选。

_Noreturn stack_underflow();

1.在即将到来的C 2023中,_Noreturn是过时的功能(6.7.12.6),您可以使用以下语法:

[[noreturn]] stack_underflow();

顺便说一句,我会避免全局变量,并将其存储在struct中。甚至可能采取额外的步骤,完全隐藏实现。我还建议你使用“stack_”命名空间前缀:

#include <stdlib.h>

typedef struct stack stack;
stack *create_stack(size_t size);
char stack_pop(stack *s);
// ...

相关问题