【问题标题】:Arrange the code to separate functions in C安排代码以分离 C 中的函数
【发布时间】:2020-02-13 12:15:26
【问题描述】:

我在大学做我的练习,这里是:“输入方程,检查是否有括号。如果它正在打开 - 推入堆栈。如果它正在关闭 - 检查堆栈的头部元素是左括号/括号。如果堆栈为空,则等式是正确的“。我编写了代码在 main() 函数中检查它。但需要检查方程的元素是否是第一个函数中的括号/括号,并与下一个括号/括号进行比较。

如果你能帮助我,非常感谢)。代码如下:

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

#define STACK_SIZE 20
#define OVERFLOW -100
#define UNDERFLOW -101

///BEGIN DEFINING
typedef char C;
typedef struct Stack_tag {
    C data[STACK_SIZE];
    size_t size;
} Stack;
///END DEFINING

///BEGIN STACK FUNCTIONS
void Push(Stack* stack, const C value) {
    if (stack->size >= STACK_SIZE) exit(OVERFLOW);

    stack->data[stack->size] = value;
    stack->size++;
}

C Pop(Stack* stack) {
    if (stack->size == 0) exit(UNDERFLOW);

    stack->size--;
    return stack->data[stack->size];
}

C Peek(const Stack* stack) {
    if (stack->size <= 0) exit(UNDERFLOW);
    return stack->data[stack->size - 1];
}

void PrintStackValue(const C value) {
    printf("%c", value);
}

void PrintStack(const Stack* stack, void(*PrintStackValue)(const C)) {
    int i, len = stack->size - 1;
    printf("\nStack %d", stack->size);
    for (i = 0; i < len; i++) {
        PrintStackValue(stack->data[i]);
        printf(" | ");
    }
    if (stack->size != 0) {
        PrintStackValue(stack->data[i]);
    }
    printf("\n");
}
///END STACK FUNCTIONS

///BEGIN OTHER FUNCTIONS
char isBr(char item) {
    switch (item) {
    case '(': return '(';
    case ')': return ')';
    case '[': return '[';
    case ']': return ']';
    case '{': return '{';
    case '}': return '}';
    default: return NULL;
    }
}
void Check(char item, Stack stack) {
    switch (item) {
    case '(': Push(&stack, item);
    case '[': Push(&stack, item);
    case '{': Push(&stack, item);
    case ')': if (Peek(&stack) == '(') Pop(&stack);
    case ']': if (Peek(&stack) == ']') Pop(&stack);
    case '}': if (Peek(&stack) == '}') Pop(&stack);
    }
}
///END OTHER FUNCTIONS
int main()
{
    Stack stack;
    stack.size = 0;
    ///EQUATION
    char* equation;
    int i;
    equation = (char*)malloc(100 * sizeof(char));
    printf("Enter the Equation: \n");
    gets(equation);
    ///CHECKING PROCESS
    ///TODO:
    ///1) SEPARATE FUNCTIONS
    for (i = 0; i < strlen(equation); i++) {
        /*
        if (equation[i] == '(' || equation[i] == '{' || equation[i] == '[') {
            Push(&stack, equation[i]);
        }
        if (equation[i] == ')') {
            if (Peek(&stack) == '(') Pop(&stack);
        }
        if (equation[i] == '}') {
            if (Peek(&stack) == '{') Pop(&stack);
        }
        if (equation[i] == ']') {
            if (Peek(&stack) == '[') Pop(&stack);
        }
        */
        char p = isBr(equation[i]);
        Check(p, stack);

    }



    ///PRINT THE RESULT
    puts(stack.size == 0 ? "FINE" : "NOOPE!!!");
    //PrintStack(&stack, PrintStackValue);

    return 0;
}

【问题讨论】:

  • [Tangent] 不要使用gets。它已被弃用,并已从 C 和 C++ 中删除。

标签: c stack parentheses brackets


【解决方案1】:

这里有两个问题:

  • 当您将堆栈结构传递给Check 时,该函数会看到堆栈的副本。因此,您所做的更改会丢失在main 中——它们只是对副本进行的。传递一个指向结构的指针,就像您为堆栈操作的函数所做的那样。 (由于变量stack 将成为Check 中的指针,因此您应该将stack 而不是&amp;stack 传递给堆栈函数。)

  • C 中 switch 语句中的情况不是孤立的。如果您不以breakreturn 结束代码,则执行将“失败”到下一个案例。

您的检查功能可能如下所示:

void Check(char item, Stack *stack) {
    switch (item) {
    case '(': Push(stack, item); break;
    case '[': Push(stack, item); break;
    case '{': Push(stack, item); break;
    case ')': if (Peek(stack) == '(') Pop(stack); break;
    case ']': if (Peek(stack) == ']') Pop(stack); break;
    case '}': if (Peek(stack) == '}') Pop(stack); break;
    }
}

然后你像这样从 main 调用它:

Check(p, &stack);

进一步观察:

  • 堆栈下溢不应导致程序立即退出。相反,它应该会导致一条消息指出方程式格式错误。
  • 如 cmets 中所述,请勿使用不安全且已弃用的函数 gets。请改用fgets
  • 真的没有必要用malloc在堆上分配一个100个字符的缓冲区。只需使用自动数组:char equation[100];。如果您使用malloc,则在从main返回之前,您还必须使用free

【讨论】:

  • 如果 OP 使用malloc(),那么在程序退出之前释放内存真的有好处吗?
  • 嗯,系统当然应该清理资源,但在我看来,这是不好的做法。我认为学习者应该养成freeing 分配的内存、fcloseing 打开文件等的习惯。在 C 中,你必须自己管理资源,所以最好习惯它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-05-12
  • 1970-01-01
  • 1970-01-01
  • 2012-06-03
  • 1970-01-01
  • 1970-01-01
  • 2011-03-19
相关资源
最近更新 更多