You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

大一C语言栈应用项目:输出乱码与pop函数合并优化求助

栈应用项目问题解决方案

项目背景与问题描述

我正在完成大一课程的栈应用小项目,实现以下功能:

  • 后缀(postfix)与前缀(prefix)表达式求值
  • 字符串反转
  • 括号匹配校验
  • 十进制转二进制
  • 中缀转后缀表达式转换

遇到两个核心问题:

  1. 输出存在多余字符(如特殊符号),比如十进制转二进制输出、括号匹配提示时的多余左括号;
  2. 代码中存在两个返回类型分别为int和char的pop函数,希望合并为单个函数。

项目原代码如下:

#include <stdio.h>
#include <ctype.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#define MAX 20
int stack[MAX], opp1, opp2, top = -1;

struct stack
{
    char stck[20];
    int top;
}
s;
void push(int x)
{
    top++;
    stack[top] = x;
}
int pop()
{
    char c;
    c = stack[top];
    top = top - 1;
    printf("%c", c);
}
char pop1()
{
    if (top == -1)
        return -1;
    else
        return stack[top--];
}
void postfixeval()
{
    char postfix[20];
    int res, i;
    gets(postfix);
    for (i = 0; postfix[i] != '\0'; i++)
    {
        if (isdigit(postfix[i]))
        {
            push(postfix[i] - 48);
        }
        else
        {
            opp2 = pop();
            opp1 = pop();
            switch (postfix[i])
            {
                case '+':
                    push(opp1 + opp2);
                    break;
                case '-':
                    push(opp1 - opp2);
                    break;
                case '*':
                    push(opp1 *opp2);
                    break;
                case '/':
                    push(opp1 / opp2);
                    break;
                case '^':
                    res = pow(opp1, opp2);
                    break;
            }
        }
    }
    printf("result is %d \n", pop());
}
void prefixeval()
{
    int len;
    char prefix[20];
    int res, i;
    gets(prefix);
    len = strlen(prefix);
    for (i = len - 1; i >= 0; i--)
    {
        if (isdigit(prefix[i]))
        {
            push(prefix[i] - 48);
        }
        else
        {
            opp1 = pop();
            opp2 = pop();
            switch (prefix[i])
            {
                case '+':
                    push(opp1 + opp2);
                    break;
                case '-':
                    push(opp1 - opp2);
                    break;
                case '*':
                    push(opp1 *opp2);
                    break;
                case '/':
                    push(opp1 / opp2);
                    break;
                case '^':
                    res = pow(opp1, opp2);
                    push(res);
                    break;
            }
        }
    }
    printf("result is %d \n", pop());
}

int match(char a, char b)
{
    if (a == '[' && b == ']')
        return 1;
    if (a == '{' && b == '}')
        return 1;
    if (a == '(' && b == ')')
        return 1;
}
int check(char exp[])
{
    int i;
    char temp;
    for (i = 0; i < strlen(exp); i++)
    {
        if (exp[i] == '(' || exp[i] == '{' || exp[i] == '[')
            push(exp[i]);
        if (exp[i] == ')' || exp[i] == '}' || exp[i] == ']')
            if (top == -1)
            {
                return 0;
            }
        else
        {
            temp = pop();
            if (!match(temp, exp[i]))
            {
                printf("Mismatched parentheses are : ");
                printf("%c and %c\n", temp, exp[i]);
                return 0;
            }
        }
    }
    if (top == -1)
    {
        printf("Balanced Parentheses\n");
        return 1;
    }
    else
    {
        return 0;
    }
}
void dectobin(int n)
{
    while (n != 0)
    {
        push(n % 2);
        n = n / 2;
    }
    while (top != -1)
    {
        printf("%d", pop());
    }
}
int priority(char x)
{
    if (x == '(')
        return 0;
    if (x == '+' || x == '-')
        return 1;
    if (x == '*' || x == '/')
        return 2;
}
void intopost()
{
    char exp[100];
    char *e, x;
    printf("Enter the expression : \n");
    scanf("%s", exp);
    printf("\n");
    e = exp;

    while (*e != '\0')
    {
        if (isalnum(*e))
            printf("%c ", *e);
        else if (*e == '(')
            push(*e);
        else if (*e == ')')
        {
            while ((x = pop1()) != '(')
                printf("%c ", x);
        }
        else
        {
            while (priority(stack[top]) >= priority(*e))
                printf("%c ", pop1());
            push(*e);
        }
        e++;
    }

    while (top != -1)
    {
        printf("%c ", pop1());
    }
}

int main()
{
    int ch, i, len;
    char postfix[20], prefix[20], str[30];
    do {
        printf("\n----STACK APPLICATIONS----\n");
        printf("1.postfix expression evaluation\n2.prefix expression evaluation\n3.reverse a string\n4.paranthesis balancing\n5.decimal to binary\n6.infix to postfix\n7.exit\n");
        printf("enter choice");
        scanf("%d", &ch);
        switch (ch)
        {
            case 1:
                {
                    printf("enter postfix expression\n");
                    scanf("%c", &postfix);
                    postfixeval();
                    break;
                }
            case 2:
                {

                    printf("enter prefix expression\n");
                    scanf("%c", prefix);
                    prefixeval();
                    break;
                }
            case 3:
                {
                    printf("enter string\n");
                    scanf("%s", str);
                    len = strlen(str);
                    for (i = 0; i < len; i++)
                    {
                        push(str[i]);
                    }
                    printf("reversed string is:");
                    for (i = 0; i < len; i++)
                    {
                        pop();
                    }
                    break;
                }
            case 4:
                {

                    char exp[20];
                    int valid;
                    printf("Enter an algebraic expression : \n");
                    scanf("%s", exp);
                    valid = check(exp);
                    if (valid == 1)
                    {
                        printf("Valid expression\n");
                    }
                    else
                    {
                        printf("Invalid expression\n");
                    }
                    break;
                }
            case 5:
                {
                    int dec;
                    printf("enter decimal number\n");
                    scanf("%d", &dec);
                    dectobin(dec);
                    break;
                }
            case 6:
                {
                    intopost();
                    break;
                }
            case 7:
                {
                    exit(0);
                }
            default:
                printf("invalid choice\n");
        }
    } while (ch != 7);
}

问题一:输出多余字符的修复

核心原因

  • pop()函数内部冗余了printf("%c", c);语句,导致每次弹栈都额外输出字符;
  • check()函数的if-else缩进错误,导致右括号处理逻辑异常;
  • gets()与scanf()混用导致输入残留,且gets()存在缓冲区溢出风险;
  • main()中case1、case2的scanf("%c")会读取之前输入的换行符,导致表达式读取失败。

修复步骤

  1. 重写pop()函数,移除内部打印逻辑,仅负责弹栈并返回值:
int pop() {
    if (top == -1) {
        printf("Stack underflow!\n");
        return -1;
    }
    return stack[top--];
}
  1. 修正check()函数的缩进问题,确保右括号处理逻辑正确嵌套:
int check(char exp[]) {
    int i;
    char temp;
    top = -1; // 每次检查前重置栈
    for (i = 0; i < strlen(exp); i++) {
        if (exp[i] == '(' || exp[i] == '{' || exp[i] == '[')
            push(exp[i]);
        else if (exp[i] == ')' || exp[i] == '}' || exp[i] == ']') {
            if (top == -1) {
                printf("Unbalanced Parentheses: extra right bracket\n");
                return 0;
            } else {
                temp = (char)pop();
                if (!match(temp, exp[i])) {
                    printf("Mismatched parentheses are : %c and %c\n", temp, exp[i]);
                    return 0;
                }
            }
        }
    }
    if (top == -1) {
        printf("Balanced Parentheses\n");
        return 1;
    } else {
        printf("Unbalanced Parentheses: remaining left brackets\n");
        return 0;
    }
}
  1. 替换gets()为fgets()并处理换行符,同时清除scanf()残留的换行符:
// postfixeval中的输入处理
fgets(postfix, sizeof(postfix), stdin);
postfix[strcspn(postfix, "\n")] = '\0';

// main中case1的输入修正
printf("Enter postfix expression: ");
getchar(); // 清除换行符
fgets(postfix, sizeof(postfix), stdin);
postfix[strcspn(postfix, "\n")] = '\0';
  1. 修正dectobin()的打印逻辑,处理0的特殊情况:
void dectobin(int n) {
    top = -1;
    if (n == 0) {
        printf("0");
        return;
    }
    while (n != 0) {
        push(n % 2);
        n = n / 2;
    }
    while (top != -1) {
        printf("%d", pop());
    }
}

问题二:合并两个pop函数

核心思路

C语言中字符本质是ASCII码整数,栈存储的int类型可以兼容字符存储。统一使用返回int的pop()函数,在需要字符的场景中将返回值强转为char即可。

实现方案

  1. 删除原pop1()函数,统一使用修正后的pop();
  2. 在需要字符的场景强转返回值:
// intopost中的弹栈处理
while ((x = (char)pop()) != '(')
    printf("%c ", x);

// check中的弹栈处理
temp = (char)pop();

完整修正后的代码

#include <stdio.h>
#include <ctype.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#define MAX 20
int stack[MAX], opp1, opp2, top = -1;

void push(int x) {
    if (top >= MAX - 1) {
        printf("Stack overflow!\n");
        return;
    }
    top++;
    stack[top] = x;
}

int pop() {
    if (top == -1) {
        printf("Stack underflow!\n");
        return -1;
    }
    return stack[top--];
}

void postfixeval() {
    char postfix[20];
    int res, i;
    fgets(postfix, sizeof(postfix), stdin);
    postfix[strcspn(postfix, "\n")] = '\0';

    for (i = 0; postfix[i] != '\0'; i++) {
        if (isdigit(postfix[i])) {
            push(postfix[i] - '0');
        } else {
            opp2 = pop();
            opp1 = pop();
            switch (postfix[i]) {
                case '+':
                    push(opp1 + opp2);
                    break;
                case '-':
                    push(opp1 - opp2);
                    break;
                case '*':
                    push(opp1 * opp2);
                    break;
                case '/':
                    if (opp2 == 0) {
                        printf("Division by zero error!\n");
                        return;
                    }
                    push(opp1 / opp2);
                    break;
                case '^':
                    res = pow(opp1, opp2);
                    push(res);
                    break;
                default:
                    printf("Invalid operator: %c\n", postfix[i]);
                    return;
            }
        }
    }
    printf("result is %d\n", pop());
}

void prefixeval() {
    int len;
    char prefix[20];
    int res, i;
    fgets(prefix, sizeof(prefix), stdin);
    prefix[strcspn(prefix, "\n")] = '\0';

    len = strlen(prefix);
    for (i = len - 1; i >= 0; i--) {
        if (isdigit(prefix[i])) {
            push(prefix[i] - '0');
        } else {
            opp1 = pop();
            opp2 = pop();
            switch (prefix[i]) {
                case '+':
                    push(opp1 + opp2);
                    break;
                case '-':
                    push(opp1 - opp2);
                    break;
                case '*':
                    push(opp1 * opp2);
                    break;
                case '/':
                    if (opp2 == 0) {
                        printf("Division by zero error!\n");
                        return;
                    }
                    push(opp1 / opp2);
                    break;
                case '^':
                    res = pow(opp1, opp2);
                    push(res);
                    break;
                default:
                    printf("Invalid operator: %c\n", prefix[i]);
                    return;
            }
        }
    }
    printf("result is %d\n", pop());
}

int match(char a, char b) {
    return ((a == '[' && b == ']') || (a == '{' && b == '}') || (a == '(' && b == ')'));
}

int check(char exp[]) {
    int i;
    char temp;
    top = -1;
    for (i = 0; i < strlen(exp); i++) {
        if (exp[i] == '(' || exp[i] == '{' || exp[i] == '[')
            push(exp[i]);
        else if (exp[i] == ')' || exp[i] == '}' || exp[i] == ']') {
            if (top == -1) {
                printf("Unbalanced Parentheses: extra right bracket\n");
                return 0;
            } else {
                temp = (char)pop();
                if (!match(temp, exp[i])) {
                    printf("Mismatched parentheses are : %c and %c\n", temp, exp[i]);
                    return 0;
                }
            }
        }
    }
    if (top == -1) {
        printf("Balanced Parentheses\n");
        return 1;
    } else {
        printf("Unbalanced Parentheses: remaining left brackets\n");
        return 0;
    }
}

void dectobin(int n) {
    top = -1;
    if (n == 0) {
        printf("0");
        return;
    }
    while (n != 0) {
        push(n % 2);
        n = n / 2;
    }
    printf("Binary: ");
    while (top != -1) {
        printf("%d", pop());
    }
    printf("\n");
}

int priority(char x) {
    if (x == '(')
        return 0;
    if (x == '+' || x == '-')
        return 1;
    if (x == '*' || x == '/')
        return 2;
    return -1;
}

void intopost() {
    char exp
相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 05:24:17