我是C编程新手,我以前学过Python。下面是我在C的第一年的项目。
我的项目名为“高级计算器”,它是一个菜单驱动的计算器应用程序,有几个操作,从第一个菜单中可以看到:
Which mode do you want to use?
[1] Normal maths operations
[2] Special Functions
[3] Fibonacci Series
[4] Random Mathematical Question
[5] Exit
Your input:虽然到目前为止计算器还能工作,所有的操作都已经完成,但是我觉得这个程序缺少一些在任何计算器中都能找到的特性和功能。我计划在其中添加sinh、tanh和cosh,但还有什么?任何想法都是值得赞赏的!
#include <stdio.h>
#include <stdlib.h> //For functions like system() and exit()
#include <windows.h> //For function Sleep()
#include <math.h> //For functions like pow(), sin(), cos(), tan()
#include <time.h> //For time based modules and functions
#include <conio.h> //For kbhit, input detector
#define PI 3.14159265358979323846
load(); //Function Prototype
main(void)
{
int i = 1; /* */
double x, xy, y; /* */
char Opt; /* Declaring the type variables */
int Numbering; /* */
int N, F, Oof, Check; /* */
int a, b, Choice; /* */
int c, d, K; /* */
float Num1, Num2 ,ans, CheckF; /* */
char oper, H; /* */
system("cls"); //Clears terminal screen
printf("Welcome to our calculator.\n");
while (1){ //While loop that never ends, unless exit(0) is used
printf("\n\nWhich mode do you want to use?\n[1] Normal maths operations\n[2] Special Functions\n[3] Fibonacci Series\n[4] Random Mathematical Question\n[5] Exit\n\nYour input: ");
scanf(" %c", &Opt);
if (Opt == '1'){
printf("Welcome to Normal maths operation Mode.\n\nYour two numbers: ");
scanf("%f%f", &Num1, &Num2);
printf("\nAVAILABLE SYMBOLS:\n\n+ for Addition\n- for Subtraction\n/ for Division\n* for Multiplication\n^ for Power function\n\\ for Rooting\nYour input: ");
scanf(" %c", &oper);
if (oper == '+'){
ans = (Num1 + Num2);
printf("Here is your answer:\n%f %c %f = %.5f (To 5 decimal places)\n\n", Num1, oper, Num2, ans);
Sleep(245);
} else if (oper == '-'){
ans = (Num1 - Num2);
printf("Here is your answer:\n%f %c %f = %.5f (to 5 decimal places)\n\n", Num1, oper, Num2, ans);
Sleep(245);
} else if (oper == '/'){
ans = (Num1 / Num2);
printf("Here is your answer:\n%f %c %f = %.5f (to 5 decimal places)\n\n", Num1, oper, Num2, ans);
Sleep(245);
} else if (oper == '*'){
ans = (Num1 * Num2);
printf("Here is your answer:\n%f %c %f = %.5f (to 5 decimal places)\n\n", Num1, oper, Num2, ans);
Sleep(245);
} else if (oper == '^'){
ans = (pow (Num1 , Num2));
printf("Here is your answer:\n%f %c %f = %.5f (to 5 decimal places)\n\n", Num1, oper, Num2, ans);
Sleep(245);
} else if (oper == '\\'){
ans = pow(Num2 , 1/Num1);
Check = Num1;
Oof = Check % 2;
if (Num2 < 0){
printf("Cannot root a negative number; ERROR 1 Sintek\a\n");
system("pause");
system("cls");
} else if (Oof == 0){
printf("Here is your answer:\n%f root(%f) = - %.5f or + %.5f (to 5 decimal places)\n\n", Num1, Num2, ans, ans);
Sleep(245);
} else if (!Oof == 0){
printf("Here is your answer:\n%f root(%f) = + %.5f (to 5 decimal places)\n\n", Num1, Num2, ans);
Sleep(245);
}
} else {
printf("\n\nYour input operator is incorrect; ERROR 1 Sintek\n");
printf("\a\n");
system("pause");
system("cls");
}
}
if (Opt == '2'){
printf("Welcome to Special Functions Mode.\n\n[1] Sine Function\n[2] Cosine Function\n[3] Tangent Function\n[4] Log (With base 10)\n[5] Log (With base e)\n[6] Log (With user defined base)\n[7] Sine Inverse Function\n[8] Cosine Inverse Function\n[9] Tangent Inverse Function\n\nWhich mode do you want: ");
scanf("%d", &N);
if (N == 1){
printf("Your angle: ");
scanf("%f", &Num1);
ans = (sin ( Num1 * PI/180 ));
printf("\nHere is your answer:\nSine(%f) = %.5f (to 5 decimal places)\n\n", Num1, ans);
Sleep(245);
} else if (N == 2){
printf("Your angle: ");
scanf("%f", &Num1);
ans = (cos ( Num1 * PI/180 ));
printf("Here is your answer:\nCosine(%f) = %.5f (to 5 decimal places)\n\n", Num1, ans);
Sleep(245);
} else if (N == 3){
printf("Your angle: ");
scanf("%f", &Num1);
ans = (tan ( Num1 * PI/180 ));
printf("Here is your answer:\nTangent(%f) = %.5f (to 5 decimal places)\n\n", Num1, ans);
Sleep(245);
} else if (N == 4){
printf("Your number: ");
scanf("%f", &Num1);
ans = log10(Num1);
if (Num1 < 0){
printf("Cannot log a negative number; ERROR 1 Sintek\a\n");
system("pause");
system("cls");
} else if (Num1 == 0){
printf("Cannot log(0); ERROR 1 Sintek\a\n");
system("pause");
system("cls");
} else if (Num1 > 0){
printf("Here is your answer:\nLg(%f) = %.5f (to 5 decimal places)\n\n", Num1, ans);
Sleep(245);
}
} else if (N == 5){
printf("Your number: ");
scanf("%f", &Num1);
ans = log(Num1);
if (Num1 < 0){
printf("Cannot ln a negative number; ERROR 1 Sintek\n\a");
system("pause");
system("cls");
} else if (Num1 == 0){
printf("Cannot ln(0); Error 1 Sintek\n\a");
system("pause");
system("cls");
} else if (Num1 > 0){
printf("Here is your answer:\nLn(%f) = %.5f (to 5 decimal places)\n\n", Num1, ans);
Sleep(245);
}
} else if (N == 6){
printf("Enter the base number, followed by the number: ");
scanf("%f%f", &Num1, &Num2);
ans = ( log(Num2) / log(Num1));
if (Num1 <= 0 || Num2 <=0){
printf("Cannot log a negative/zero base/number; ERROR 1 Sintek\n\a");
system("pause");
system("cls");
} else if (Num1 > 0 && Num2 > 0){
printf("Here is your answer:\nLog[base %f]%f = %.5f (to 5 decimal places)\n\n", Num1, Num2, ans);
Sleep(245);
}
} else if (N == 7){
printf("[1] Entering hypotenuse and opposite of triangle\n[2] Entering the value directly\n\nYour option: ");
scanf("%d", &K);
if (K == 1){
printf("Enter hypotenuse and opposite sides of the triangle: ");
scanf("%f%f", &Num1, &Num2);
CheckF = Num2 / Num1;
if (CheckF < -1 || CheckF > 1){
printf("The opposite side should not be larger than the hypotenuse side. Please recheck your values!\nERROR 1 Sintek\n\a");
system("pause");
system("cls");
} else {
ans = (asin ( CheckF ));
printf("Sine inverse %f/%f =\n%f (In radians)", Num2, Num1, ans);
ans = ans * 180/PI;
printf("\n%f (In degrees)", ans);
Sleep(250);
}
} else if (K == 2){
printf("Enter your value: ");
scanf("%f", &CheckF);
if (CheckF < -1 || CheckF > 1){
printf("Value cannot be higher than 1/lower than -1. Please recheck your input!\nERROR 1 Sintek\n\a");
system("pause");
system("cls");
} else {
ans = (asin ( CheckF ));
printf("Sine inverse %f =\n%f (In radians)", CheckF, ans);
ans = ans * 180/PI;
printf("\n%f (In degrees)", ans);
Sleep(250);
}
} else if (K != 1 || K != 2) {
printf("Your input option is not found! ERROR 404\a\n");
system("pause");
system("cls");
}
} else if (N == 8){
printf("[1] Entering adjacent and hypotenuse of triangle\n[2] Entering the value directly\n\nYour option: ");
scanf("%d", &K);
if (K == 1){
printf("Enter adjacent and hypotenuse sides of the triangle: ");
scanf("%f%f", &Num1, &Num2);
CheckF = Num1 / Num2;
if (CheckF < -1 || CheckF > 1){
printf("The adjacent side should not be larger than the hypotenuse side. Please reckeck your values!\nERROR 1 Sintek\n\a");
system("pause");
system("cls");
} else {
ans = (acos ( CheckF ));
printf("Cosine inverse %f/%f =\n%f (In radians)", Num1, Num2, ans);
ans = ans * 180/PI;
printf("\n%f (In degrees)", ans);
Sleep(250);
}
} else if (K == 2){
printf("Enter your value: ");
scanf("%f", &CheckF);
if (CheckF < -1 || CheckF > 1){
printf("Value cannot be higher than 1/lower than -1. Please recheck your input!\nERROR 1 Sintek\n\a");
system("pause");
system("cls");
} else {
ans = (acos ( CheckF ));
printf("Cosine inverse %f = \n%f (In radians)", CheckF, ans);
ans = ans * 180/PI;
printf("\n%f (In degrees)", ans);
Sleep(250);
}
} else if (K != 1 || K != 2) {
printf("Your input option is not found! Error 404\a\n");
system("pause");
system("cls");
}
} else if (N == 9){
printf("[1] Entering opposite and adjacent of triangle\n[2] Entering the value directly\n\nYour option: ");
scanf("%d", &K);
if (K == 1){
printf("Enter opposite and adjacent sides of the triangle: ");
scanf("%f%f", &Num1, &Num2);
CheckF = Num1 / Num2;
ans = (atan ( CheckF ));
printf("Tangent inverse %f/%f =\n%f (In radians)", Num1, Num2, ans);
ans = ans * 180/PI;
printf("\n%f (In degrees)", ans);
Sleep(250);
} else if (K == 2){
printf("Enter your value: ");
scanf("%f", &CheckF);
if (CheckF < -1 || CheckF > 1){
printf("Value cannot be higher than 1/lower than -1. Please recheck your input!\nERROR 1 Sintek\n\a");
system("pause");
system("cls");
} else {
ans = (atan ( CheckF ));
printf("Tangent inverse %f =\n%f (In radians)", CheckF, ans);
ans *= 180/PI;
printf("\n%f (In degrees)", ans);
Sleep(250);
}
} else if (K != 1 || K != 2) {
printf("Your input option is not found! ERROR 404\a\n");
system("pause");
system("cls");
}
} else {
printf("Your input option is not found! ERROR 404\a\n");
system("pause");
system("cls");
}
}
if (Opt == '3'){
printf("Welcome to Fibonacci Series Mode.\n\nPress any key to stop while printing the numbers, to pause.\nEnter how many numbers do you want from the series, from the start: ");
scanf("%d", &N);
x = 0;
y = 1;
F = 3;
Numbering = 3;
printf("Here is Your Series:\n\n");
if (N == 1){
printf("[1] 0\n");
Sleep(1000);
}
if (N == 2){
printf("[1] 0\n");
Sleep(75);
printf("[2] 1\n");
Sleep(1075);
}
if (N == 3){
printf("[1] 0\n");
Sleep(75);
printf("[2] 1\n");
Sleep(75);
printf("[3] 1\n");
Sleep(1075);
}
if (N > 3){
printf("[1] 0\n");
Sleep(75);
printf("[2] 1\n");
Sleep(75);
}
while ( N > 3 && F <= N ){
xy = x + y;
printf("[%.0d] %.5g\n", Numbering, xy);
Sleep(75);
x = y;
y = xy;
F++;
Numbering++;
while (kbhit()){
printf("\n\n[+] Interrupted\n\nE to exit\nC to continue printing\n\nOption: ");
scanf(" %c", &H);
if (H == 'E'){
printf("Exiting in 3 seconds. Goodbye!");
Sleep(3000);
exit(0);
} else if (H == 'C'){
continue;
}
}
}
Sleep(1000);
}
if (Opt == '4'){
srand(time(NULL));
Choice = rand()%3;
if (Choice == 0){
a = rand()%5001;
b = rand()%5001;
c = a + b;
printf("What is %d + %d?\nYour answer: ", a, b);
scanf("%d", &d);
if (d == c){
printf("Yes. You are right; Congratulations\n\n");
system("pause");
} else {
printf("No. The correct answer is %.0d. Need to practice more!\n\n", c);
system("pause");
system("cls");
}
}
if (Choice == 1){
a = rand()%5001;
b = rand()%5001;
c = a - b;
printf("What is %d - %d?\nYour answer: ", a, b);
scanf("%d", &d);
if (d == c){
printf("Yes. You are right; Congratulations\n\n");
system("pause");
} else {
printf("No. The correct answer is %.0d. Need to practice more!\n\n", c);
system("pause");
system("cls");
}
}
if (Choice == 2){
a = rand()%20;
b = rand()%20;
c = a * b;
printf("What is %d times %d?\nYour answer: ", a, b);
scanf("%d", &d);
if (d == c){
printf("Yes. You are right; Congratulations\n\n");
system("pause");
} else {
printf("No. The correct answer is %.0d. Need to practice more!\n\n", c);
system("pause");
system("cls");
}
}
}
if (Opt == '5'){
printf("Thank you for using my calculator. Hope to see you again!!");
Sleep(1250);
system("cls");
exit(0);
}
if (Opt < '1' || Opt > '5'){
printf("Your option is not found! ERROR 404");
printf("\a\n");
system("pause");
system("cls");
}
}
}发布于 2020-06-29 14:26:32
欢迎来到代码评论,我们祝您一切顺利。
一般性意见
恭喜你让它工作了,一个长356行,文本几乎17K的函数有点大,很难编码和调试。
复杂性
函数main()太复杂,应该分解为函数。在所有编程中,一个普遍的经验法则是,函数应该只有一个大小的编辑屏幕,因为很难跟踪所有正在发生的事情。典型的软件/程序设计包括将问题分解成越来越小的部分,以便更容易理解。例如,有不同的函数处理菜单中列出的每种模式,一个用于Special Functions,一个用于Fibonacci Series,一个用于Normal maths operations,另一个用于Random Mathematical Question。这些顶级函数中的每一个都可以调用子函数。
这里涉及到几个软件原则:
在大型函数(如main )中,会有代码在不同的地方重复自己,而不是重复代码--将代码放入函数并调用该函数是必要的,这允许代码编写和调试一次,从而加快开发和维护速度。
单一责任原则
这里也有一个叫做单一责任原则的编程原则。单一责任原则指出:
每个模块、类或函数都应该对软件提供的功能的单个部分负责,而该责任应该完全由该模块、类或函数封装。
接吻校长,保持它的简单性
这是相当不言自明的,使代码尽可能简单的小块。
总体设计原则是自上而下设计或逐步求精,一般应用于过程语言,自顶向下和自下而上的设计可用于面向对象的设计。
一个函数的例子可以是print_menu_return_option()。
char print_menu_return_option()
{
char Opt; /* Declaring the type variables */
int input_check = 0;
while (input_check == 0)
{
printf("\n\nWhich mode do you want to use?\n[1] Normal maths operations\n[2] Special Functions\n[3] Fibonacci Series\n[4] Random Mathematical Question\n[5] Exit\n\nYour input: ");
input_check = scanf(" %c", &Opt);
}
return Opt;
}在上面的代码中,您应该使用scanf()的返回值来检查用户输入中的错误。
发布于 2020-06-30 00:47:26
许多评论,所以一些额外的想法。
与其硬编码5,不如使用一个灵活的变量.也许以后的代码可能会允许用户调整宽度。
// printf("Here is your answer:\nLg(%f) = %.5f (to 5 decimal places)\n\n", Num1, ans);
int prec = 5;
printf("Here is your answer:\nLg(%.*f) = %.*f (to %d decimal places)\n\n",
prec, Num1, prec, ans, prec);另外,考虑一下"*.g",它提供了更多的信息,包括小值和大值。
float诉double没有什么理由使用float,特别是因为代码调用了这么多double函数。在C中,double是默认的浮点类型.保存float,以便代码在空间上或性能上受到限制。
if (Num1 < 0){是个好主意,但值得在ans = log(Num1);面前出现
在划分之前考虑一次测试:
if (Num2 == 0.0) Handle_div_by_zero();
else ans = (Num1 / Num2);虽然OP至少为pi提供了17位数字,但更多的位数并不会造成伤害。对于此类常用常量,建议在可用时使用预期数字需求的两倍或通用define。当FLT_VAL_METHOD == 2 (使用long double的double数学)时,会使用更高的精度。
#ifdef M_PI
#define PI M_PI
#else
#define PI 3.1415926535897932384626433832795
#endifTrig函数,尤其是大角度的功能,首先以度的方式减少范围。
// ans = (cos ( Num1 * PI/180 ));
ans = (cos ( fmod(Num1,360) * PI/180 ));发布于 2020-06-29 21:54:34
尽管@pacmaninbw提供了一些优秀的通用策略,但让我们看看一些特定的语法。
这是一些争论的一点,但是--库定义了M_PI --我倾向于使用它。由于您包含了windows.h,所以很可能您正在使用MSVC。在这种情况下,如果使用它给出了数学常量配置编译器,则为_USE_MATH_DEFINES。
我的观点是,这是一个预编译器指令,而预编译器是构建可配置的,所以在构建中配置它。如果您需要将其移植到Linux,支持M_PI所需的预编译器配置将发生变化,但当您到达时,您可以跨过这座桥。
load(); //Function Prototype它是?为了什么功能?我在任何地方都没有看到这个定义。
自C99以来,在函数顶部预先声明所有变量都是不必要的,而且,我发现,这是不正确的。您可以在使用它们的地方声明和初始化它们。还有,你的名字(Oof?)需要一点爱。
把它分开:
printf("\n\nWhich mode do you want to use?\n[1] Normal maths operations\n[2] Special Functions\n[3] Fibonacci Series\n[4] Random Mathematical Question\n[5] Exit\n\nYour input: ");转到
printf(
"\n\n"
"Which mode do you want to use?\n"
"[1] Normal maths operations\n"
"[2] Special Functions\n"
"[3] Fibonacci Series\n"
"[4] Random Mathematical Question\n"
"[5] Exit\n\n"
"Your input: "
);switch这一点及其相关的比较:
if (Opt == '1'){应该使用交换机。
ans = ( log(Num2) / log(Num1));不需要外胎。
https://codereview.stackexchange.com/questions/244710
复制相似问题