首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C++清理优化代码,计算器

C++清理优化代码,计算器
EN

Code Review用户
提问于 2019-12-22 11:36:08
回答 2查看 796关注 0票数 4

这段代码目前正在工作,我想知道我是否可以做任何优化或任何事情,以使代码看起来更干净使用函数或诸如此类的,建议是受欢迎的!

代码语言:javascript
复制
#include <cmath>
#include <cstdio>

int prompt(const char* name) 
{
printf("%s", name);
int value;
scanf("%d", &value);
return value;
}

int main()
{   
    int mod, a, b, zbroj, razlika, umnozak, kolicnik;
    printf("Mod 1 je za zbrajanje \n");
    printf("Mod 2 je za oduzimanje \n");
    printf("Mod 3 je za mnozenje \n");
    printf("Mod 4 je za dijeljenje \n");
    printf("U kojem modu zelis biti: \n");
    std::scanf("%d", &mod);

    switch (mod)
    {
        case 1:
            printf("Odabrali ste zbrajanje! \n");
            a = prompt("a: ");
            b = prompt("b: ");
            zbroj = a + b;
            printf("%d + %d = %d", a, b, zbroj);
            break;
        case 2: 
            printf("Odabrali ste oduzimanje! \n");
            a = prompt("a: ");
            b = prompt("b: ");
            razlika = a - b;
            printf("%d - %d = %d", a, b, razlika);
            break;
        case 3: 
            printf("Odabrali ste mnozennje! \n");
            a = prompt("a: ");
            b = prompt("b: ");
            if(a == 0 or b==0){
                printf("Mnozite s nulom, a kad se mnozi s nulom rezultat je uvijek 0: \n");
                umnozak = 0;
            }
            else
            {
                umnozak = a * b;
            }
            printf("%d * %d = %d", a, b, umnozak);
            break;
        case 4: 
            printf("Odabrali ste dijeljenje! \n");
            a = prompt("a: ");
            b = prompt("b: ");
            if(a == 0 or b==0){
                printf("Dijelite s nulom, a kad se dijeli s nulom rezultat je uvijek 0: \n");
                kolicnik = 0;
            }
            else
            {
                kolicnik = a / b;
            }
            printf("%d / %d = %d", a, b, kolicnik);
            break;
        default:
            printf("Nemamo tu opciju trenutno, prcekajte za nadogradnju programa, ili se javite developeru! \n");
    }
    return 0;
}
EN

回答 2

Code Review用户

回答已采纳

发布于 2019-12-22 15:41:22

以下是一些可以帮助您改进代码的东西。

检查错误的返回值

调用scanf可能失败。您必须检查返回值,以确保没有返回值,或者当给定格式错误的输入或系统资源不足时,程序可能会崩溃(或更糟)。严格的错误处理是大多数工作软件和无错误软件之间的区别。你应该为后者而奋斗。

将程序分解为函数

这里几乎所有的逻辑都是在一个相当长且密集的代码块中的main中。最好将其分解为不同的函数。

不要滥用using namespace std

using namespace std放在每个程序的顶端是您最好避免的坏习惯。知道什么时候使用它,什么时候不使用它(就像写包含标题的时候一样)。在这个特殊的例子中,我碰巧认为它是非常合适的,因为它是一个短程序,而不是头。有些人似乎认为在任何情况下都不应该使用它,但我的看法是,只要是负责任和充分了解其后果,就可以使用它。

使用<cstdio>而不是<stdio.h>

这两种表单的不同之处在于前者定义了std::命名空间中的东西,而不是全局命名空间中的东西。语言律师对此有很多乐趣,但对于日常使用,我建议使用<cstdio>。详情请参见这个问题

更喜欢iostream而不是老式的printf

iostream库是更现代的C++实现I/O的方式。更喜欢它而不是printfscanf。所以,不是这样的:

代码语言:javascript
复制
printf("%d + %d = %d", a, b, zbroj);

写这个:

代码语言:javascript
复制
std::cout << a << " + " << b << " = " << zbroj << '\n';;

详情请参见SL.io.3

在使用

之前初始化变量

在将mod变量设置为任何值之前将其打印出来。这不太可能有用。更好的做法是始终确保所有变量在使用前都已初始化。

使用常量字符串串联

该代码目前包括以下几行:

代码语言:javascript
复制
cout << "U kojem modu kalkulatora zelis biti? \n" << mod;
cout << "Mod 1 je za zbrajanje \n";
cout << "Mod 2 je za oduzimanje \n";
cout << "Mod 3 je za mnozenje \n";
cout << "Mod 4 je za dijeljenje \n";

我建议把它写成这样:

代码语言:javascript
复制
std::cout << 
    "U kojem modu kalkulatora zelis biti? \n" 
    "Mod 1 je za zbrajanje \n"
    "Mod 2 je za oduzimanje \n"
    "Mod 3 je za mnozenje \n"
    "Mod 4 je za dijeljenje \n";

由于下一行恰好是scanf,我建议您使用prompt函数。

考虑使用更惯用的C++

虽然您对andnot的使用在技术上并没有错,但是您应该注意到,许多经验丰富的C++程序员将不熟悉这些操作符替代方案,因此如果其他人阅读了您的代码,这可能会妨碍他们对代码的理解。

消除冗余变量

我不会说克罗地亚语,但变量名很好,因为它们准确地描述了程序上下文中变量的含义。但是,我建议您可以使用一个变量zbroj, razlika, umnozak, kolicnik来代替rezultat

不要重复你自己(干)

case语句中的数学操作都包含非常相似的重复代码。与其重复代码,通常更好的做法是将通用代码转换为函数。唯一变化的是提示符、数学运算和打印结果的方式。一种先进的技术是将它们汇集到一个数据结构中。如果你才刚开始,如果你还不明白,就别担心。它使用lambda表达式和C++17 std::string_view等。我把它放在这里是为了展示C++有多强大:

代码语言:javascript
复制
#include <cmath>
#include <iostream>
#include <string_view>
#include <array>

int prompt(const char* name) 
{
    std::cout << name;
    int value;
    std::cin >> value;
    return value;
}

int main()
{   

    struct MathOp {
        std::string_view opname;
        int (*operate)(int a, int b);
        std::string_view opsymbol;

        void operator()() const {
            std::cout << "Odabrali ste " << opname << "!\n";
            int a = prompt("a: ");
            int b = prompt("b: ");
            int rezultat = operate(a, b);
            std::cout << a << opsymbol << b << " = " << rezultat << '\n';
        }

    };

    constexpr std::array<MathOp, 4> op{{
        { "zbrajanje", [](int a, int b){ return a+b; }, " + " },
        { "oduzimanje", [](int a, int b){ return a-b; }, " - " },
        { "mnozenje", [](int a, int b){ return a*b; }, " * " },
        { "dijeljenje", [](int a, int b){ 
                if (b == 0) {         
                    std::cout << "dijeljenje s nulom \n";
                    return 0;
                } 
                return a/b;
            }, " / " },
    }};

    std::cout << "U kojem modu kalkulatora zelis biti? \n";
    for (std::size_t i{0}; i < op.size(); ++i) {
        std::cout << "Mod " << i+1 << " je za " << op[i].opname << "\n";
    }
    unsigned mod;
    std::cin >> mod;

    if (mod > 0 && mod <= op.size()) {
        op[mod-1]();
    } else {
        std::cout << "Nemamo tu opciju trenutno, prcekajte za nadogradnju programa, ili se javite developeru! \n";
    }
}

例如,如果我们想要添加指数,我们所需要做的就是向op数组中添加一行:

代码语言:javascript
复制
{ "eksponenciju", [](int a, int b){ return static_cast<int>(std::pow(a,b)); }, " ** " },
票数 7
EN

Code Review用户

发布于 2019-12-22 18:12:16

( 1)放置支架时应保持一致。未寄出下列文件:

代码语言:javascript
复制
if(a == 0 or b==0){
    printf("Mnozite s nulom, a kad se mnozi s nulom rezultat je uvijek 0: \n");
    umnozak = 0;
}
else
{
    umnozak = a * b;
}

要么写成这样:

代码语言:javascript
复制
if (a == 0 or b==0) {
    printf("Mnozite s nulom, a kad se mnozi s nulom rezultat je uvijek 0: \n");
    umnozak = 0;
} else {
    umnozak = a * b;
}

或作为

代码语言:javascript
复制
if (a == 0 or b==0)
{
    printf("Mnozite s nulom, a kad se mnozi s nulom rezultat je uvijek 0: \n");
    umnozak = 0;
}
else
{
    umnozak = a * b;
}

你可以选择任何你最喜欢的风格,但你应该坚持它。

2)在使用变量之前不要声明变量。延迟声明变量,直到您真正需要它们。所以而不是

代码语言:javascript
复制
int umnozak;
... some code here ...
umnozak = a * b;

你写

代码语言:javascript
复制
int umnozak = a * b;

这会导致switch语句的子句中的范围问题,因此它们现在必须被大括号包围。

3)把除法处理得更好。假设4/0= 0,结果是未定义的,这是不正确的。

4)变量zbrojrazlika只使用过一次。大多数情况下,这类变量可以而且应该被消除,这里也是如此。

最后的代码以紧凑的大括号样式格式化,如下所示:

代码语言:javascript
复制
#include <stdio.h>

int prompt(const char* name) {
    printf("%s", name);
    int value;
    scanf("%d", &value);
    return value;
}

int main() {
    printf("Mod 1 je za zbrajanje\n");
    printf("Mod 2 je za oduzimanje\n");
    printf("Mod 3 je za mnozenje\n");
    printf("Mod 4 je za dijeljenje\n");
    printf("U kojem modu zelis biti:\n");
    int mod;
    scanf("%d", &mod);

    switch (mod)
    {
    case 1: {
        printf("Odabrali ste zbrajanje!\n");
        int a = prompt("a: ");
        int b = prompt("b: ");
        printf("%d + %d = %d\n", a, b, a + b);
        break;
    }
    case 2: {
        printf("Odabrali ste oduzimanje!\n");
        int a = prompt("a: ");
        int b = prompt("b: ");
        printf("%d - %d = %d\n", a, b, a - b);
        break;
    }
    case 3: {
        printf("Odabrali ste mnozennje!\n");
        int a = prompt("a: ");
        int b = prompt("b: ");
        printf("%d * %d = %d\n", a, b, a * b);
        break;
    }
    case 4: {
        printf("Odabrali ste dijeljenje! \n");
        int a = prompt("a: ");
        int b = prompt("b: ");
        if (b == 0) {
            printf("%d / %d = undefined (divison by zero)\n", a, b);
        } else {
            printf("%d / %d = %d\n", a, b, a / b);
        }
        break;
    }
    default:
        printf("Nemamo tu opciju trenutno, prcekajte za nadogradnju programa, ili se javite developeru! \n");
    }
    return 0;
}
票数 2
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/234477

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档