c - 如何制作一个接受 C 中两位整数或字符的菜单界面?
问题描述
在过去的几个小时里,我一直在摸索这个程序,我似乎找不到让这个程序工作的方法。我从一个 switch 语句样式菜单开始,但后来我遇到了一个问题,菜单会通过并退出,我无法弄清楚,所以我只是将我的代码切换到基于 if else 的菜单。该程序背后的想法如下:
编写并测试实现基于堆栈的整数计算器的 C 程序。程序接受输入,直到输入 q。然而,我的困难在于让菜单接受大于 10 的数字。
我的程序中的每个函数都可以正常工作,除非我输入一个两位数的整数,它会分别存储这两个数字。我知道这是因为我有菜单设置来读取和使用字符,但我无法弄清楚如何让一组字符工作。我以前从未在 C 中编程过,所以动态内存分配的想法暗示了我,因为我不完全确定何时需要。到目前为止,这是我为该程序提供的源代码:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <ctype.h>
#define SIZE 6
int stack[SIZE]; //stack size
int top = 0; //top of stack
void pop();
void clear();
void display();
void top_element();
void add();
void multiply();
void subtract();
void division();
void power();
int main()
{
char input;
int flag = 1;
while(flag == 1)
{
printf(": ");
scanf(" %c",&input);
if(isdigit(input))
{
if(top < SIZE)
{
stack[top] = input - '0';
top++;
}
else
printf("Error: stack overflow\n");
}
else if(input=='p')
pop();
else if(input=='c')
clear();
else if(input=='d')
display();
else if(input=='=')
top_element();
else if(input=='+')
add();
else if(input=='*')
multiply();
else if(input=='-')
subtract();
else if(input=='/')
division();
else if(input=='^')
power();
else if(input=='q')
flag = 0;
else
printf("Error: invalid command\n");
}
printf("Goodbye!\n");
return 0;
}
void pop()
{
if(top==0)
printf("Error: stack is empty\n");
else
top--;
}
void clear()
{
top=0;
}
void display()
{
int i;
if(top == 0)
printf("Error: stack is empty\n");
else
{
for(i = top - 1; i >= 0; i--)
printf("%d\n",stack[i] );
}
}
void top_element()
{
printf("%d\n",stack[top-1] );
}
void add()
{
if(top<2)
printf("Error: not enough operands for the requested operation\n");
else
{
int ans=stack[top-1]+stack[top-2];
stack[top-2]=ans;
top--;
}
}
void multiply()
{
int ans=stack[top-1]*stack[top-2];
stack[top-2]=ans;
top--;
}
void subtract()
{
if(top < 2)
printf("Error: not enough operands for the requested operation\n");
else
{
int ans = (stack[top-2] - stack[top-1]);
stack[top-2]=ans;
top--;
}
}
void division()
{
if(top < 2)
printf("Error: not enough operands for the requested operation\n");
else
{
if(stack[top-1]==0)
printf("Error: attempt to divide by 0\n");
else
{
int ans = (stack[top-2]/stack[top-1]);
stack[top-2]=ans;
top--;
}
}
}
void power()
{
if(top < 2)
printf("Error: not enough operands for the requested operation\n");
else
{
int ans = pow(stack[top - 2], stack[top - 1]);
stack[top - 2] = ans;
top--;
}
}
解决方案
我有几件事要注意,不想把它变成 TLDR,所以我会尽量把每个问题放在单独的段落中。你可以对这一切持保留态度;毕竟,这只是建议。
- 您正在寻找的格式指令是
%2[0123456789]
. 将指针传递到一个适当大小的位置以存储三个字符(即char something[3]
,空字符的第三个字节)并检查返回值。该指令需要单独调用scanf
它,否则您可能会在稍后调试与空字段相关的问题,因此“绿灯”返回值表明您的程序正在成功处理良好的scanf("%2[0123456789]", ptr_into_array_of_char)
输入返回 1. 任何其他返回值表示发生了琥珀色或红色灯。请注意,我在这里非常严格地解释您的规格(不完整)......实际上我只是使用%d
并很高兴我的用户通过输入将患关节炎的机会减半1
而不是01
(而且您在不处理时也不太可能患动脉瘤%[
)。 - 当我们犯一些语法错误时,我们的编译器通常会发出错误消息并中止编译,但这个要求违背了这一原则:“程序接受输入直到输入 q。” 我希望您的完整规范能够解释当用户偏离预期时会发生什么。我想你可以发出一个错误,清除堆栈,读到行尾,就像程序重新启动一样操作......像
scanf("%*[^\n]"); getchar(); puts("Error message here"); top = 0;
?我们通常使用一些组合键,如 CTRL+d(在 Linux 上)或 CTRL+Z(在 Windows 上)来关闭,stdin
从而表示输入终止。 - “动态内存分配的想法暗示了我” ,所以你会很高兴知道你可能不应该在这里使用动态内存分配,除非你希望你的堆栈超过你设置的硬编码 6 个插槽,也许...
- 我认为这个问题的标题混淆了;您不是在设计菜单,而是在实施语法。看看
gcc
这里的“菜单”是如何设计灵感的。如果您曾经想设计一个菜单stdin
,请停下来;也许您真正想要的是一个指向和单击的 GUI,因为这不是 Unix 倾向于工作的方式。 void fubar(void);
由于某些技术历史文物,随后声明void fubar() { /* SNIP */ }
是未定义的行为,同样适用int main()
......这就是为什么你最好选择一本专门教授 C 的书,由有名望的人写的,来学习 C。有很多微妙的细微差别会困住你。- 关于函数原型等,考虑堆栈是一种通用数据结构。作为一个替代的思想实验,考虑一下
strcpy
如果它只对声明为文件范围的数组进行操作会很痛苦。从逻辑上讲,它的所有外部数据需求都应该来自它的参数,而不是来自一个变量,即stack
用文件范围声明的变量。 - 我们被教导要谨慎地使用记忆,在我看来,像这样仅将变量用作控制表达式似乎违反了这些教训。在诸如 和 之类的结构
break
存在continue
的goto
情况下,没有变量声明的更简洁的替代方案是可能的(因此有一个额外的免费寄存器用于其他用途)。
推荐阅读
- python - 使用 PyQt5 QtWebEngineWidgets 打开 PDF 文件
- windows - 递归子文件夹并移动所有带有扩展名的文件
- .net - MS Bot Framework:如何在仅通知机器人中获取用户的语言环境?
- python - 如何更改在 Matplotlib 绘图/图形中创建的子图的大小?
- python - 在生产中使用服务器端firebase-admin(实时数据库)允许所有读/写权限是否安全?
- r - 后续:泛化一个data.frame子集函数2
- python - 如何增加子图文本大小并添加自定义条形图注释
- sharepoint-2013 - 将自定义 Web 部件添加到页面 SharePoint 2013 c# csom
- python - python-nmap 报告缺失模块源
- linux - 如何切换到当前窗口而不是在 GTK 中创建新实例?