大一C语言栈应用项目:输出乱码与pop函数合并优化求助
栈应用项目问题解决方案
项目背景与问题描述
我正在完成大一课程的栈应用小项目,实现以下功能:
- 后缀(postfix)与前缀(prefix)表达式求值
- 字符串反转
- 括号匹配校验
- 十进制转二进制
- 中缀转后缀表达式转换
遇到两个核心问题:
- 输出存在多余字符(如特殊符号),比如十进制转二进制输出、括号匹配提示时的多余左括号;
- 代码中存在两个返回类型分别为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")会读取之前输入的换行符,导致表达式读取失败。
修复步骤
- 重写
pop()函数,移除内部打印逻辑,仅负责弹栈并返回值:
int pop() { if (top == -1) { printf("Stack underflow!\n"); return -1; } return stack[top--]; }
- 修正
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; } }
- 替换
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';
- 修正
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即可。
实现方案
- 删除原
pop1()函数,统一使用修正后的pop(); - 在需要字符的场景强转返回值:
// 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
相关产品推荐
相关产品推荐

