首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >一个C语言编程实践问题的反馈

一个C语言编程实践问题的反馈
EN

Code Review用户
提问于 2014-02-17 02:58:15
回答 8查看 4.8K关注 0票数 25

这是我们老师给我们的编程实践,如果有人能看一下我的程序,告诉我我是否做得很好,我会很感激。

基本上,我加入了一家公司,用C编写了一个程序,它需要三个输入(英尺钢、滚珠轴承和铜磅),并返回第二天可以做多少个钟声和口哨。

吹口哨需要0.5英尺的钢和一个滚珠轴承。制作钟需要1.10磅青铜(.75磅青铜和1克拉珀(.35磅青铜))。

这是我写的程序。如果看起来乱七八糟,我很抱歉。

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

void PrintLine();
int CalculateWhistles(int steel, int bearings);
int CalculateBells(int bronze);

int main() {
    bool runProgram = true;
    int runAgain = 0;

    while (runProgram == true) {
        int ftSteelIn = 0;
        int numBallBearingIn = 0;
        int ibsBronzeIn = 0;

        printf("\n\n"); // Formatting...
        PrintLine();

        printf("    How many feet of steel was received today:               "); // Steel received
        scanf("%d", &ftSteelIn);
        printf("    How many ball bearings were received today:              "); // Ball bearings received
        scanf("%d", &numBallBearingIn);
        printf("    How many pounds of bronze was received today:            "); // Bronze received
        scanf("%d", &ibsBronzeIn);

        PrintLine(); // Print line

        PrintLine(); // Print line

        // Print company logo and program title
        printf("                                Acme Corporation\n");
        printf("                                Product Report\n");

        PrintLine();// Print line

        // Print number of bells and whistles
        printf("    Number of Bells                                                      %d\n", CalculateBells(ibsBronzeIn));
        printf("    Number of Whistles                                                   %d\n", CalculateWhistles(ftSteelIn, numBallBearingIn));

        PrintLine(); // Print line
        PrintLine();

        printf("\n\n");
        PrintLine();

        // Ask the user if they would like to run the program again
        printf("    Would you like to run the program again? ('1' for yes, '2' for no): ");
        scanf("%d", &runAgain);
        PrintLine();

        // If user does not say 'yes', end the program and say goodbye
        if (runAgain != 1) {
            printf("\n    Exitting the program. Have a good day.\n\n");
            PrintLine();
            runProgram = false;
        }
    }

    return 0;
}

void PrintLine() {
    int i = 0;
    printf("    ");
    while (i <= 70) {
        printf("-");
        i++;
    }
    printf("\n");
}

int CalculateWhistles(int steel, int bearings) {
    steel = steel / 0.5;
    if (steel < bearings) {
        return steel;
    }
    else if (bearings < steel) {
        return bearings;
    }
}

int CalculateBells(int bronze) {
    int bells = bronze / 1.1;
    return bells;
}

它运行良好,没有任何错误。还有第二部分,我计算剩余部分,但我想要一些反馈,然后再讨论这个部分。

任何建议都会很感激,如何使它更有效率或类似的东西(我只是在学习C)。

EN

回答 8

Code Review用户

回答已采纳

发布于 2014-02-17 03:29:47

大约50%的编程是关于处理错误的。您说您的代码工作,但它不处理错误,因此无法工作。

示例1

代码语言:javascript
运行
复制
How many feet of steel was received today:  four

程序没有说“错误,再试一次”。相反,它显示所有提示,而不等待任何用户输入和退出。

示例2

代码语言:javascript
运行
复制
How many feet of steel was received today:  3.7

程序没有说“错误,再试一次”。相反,它显示所有提示,而不等待任何用户输入和退出。

示例3

代码语言:javascript
运行
复制
How many feet of steel was received today:  3 4

程序没有说“错误,再试一次”。相反,它假设3英尺的钢,显示“多少球轴承”,不等待用户输入,并假设4个球轴承。

示例4

代码语言:javascript
运行
复制
Would you like to run the program again? ('1' for yes, '2' for no): yes

程序没有说“错误,再试一次”。相反,它退出了。

示例5

代码语言:javascript
运行
复制
How many feet of steel was received today:               -99
How many ball bearings were received today:              -99
How many pounds of bronze was received today:            -99

程序决定了你可以做-89铃铛和-198口哨。

示例6

代码语言:javascript
运行
复制
How many feet of steel was received today:               999999999999999999
How many ball bearings were received today:              999999999999999999
How many pounds of bronze was received today:            999999999999999999

程序决定了你可以做-1351471477铃铛和-2147483648口哨。

示例7

代码语言:javascript
运行
复制
How many feet of steel was received today:               200
How many ball bearings were received today:              100

程序决定了你可以做0口哨。注意:与前面的例子不同,这不是一个“检查无效输入失败”的问题。

票数 30
EN

Code Review用户

发布于 2014-02-17 04:35:59

我不知道你在班上有多远,但这里有一些我在其他答案中没有看到的笔记:

  • 您的CalculateWhistles()方法可能会失败if条件测试,并到达非void方法的末尾。对于每一种情况,您的方法都应该有一个返回语句,即使您必须不返回任何东西。例如,如果steel等于bearings,您的代码将做什么?int CalculateWhistles(int钢,int轴承){ steel = steel / 0.5;if (钢<轴承){返回钢;}否则如果(轴承<钢){返回轴承;}由于此方法在测试条件失败时无法返回值,因此它不会在我的系统上编译。我有一个比大多数编译器都更严格的编译器,因此这告诉我,您在编译时没有启用警告,而您应该打开警告。我重写了这个方法,以便它能够在我的系统上正确编译。int ( int calculateWhistles,int轴承){ /= 0.5钢;if (钢<=轴承)返回钢;否则返回轴承;}
  • for方法中使用PrintLine()循环。PrintLine() { int i= 0;printf(“");while (i <= 70) { printf("-");i++;} printf("\n");}但是,在检查for循环时,它所做的只是打印出一些空格和一串破折号。printf()语句在系统上可能很昂贵,因此要最大限度地提高效率,您应该尽可能少地使用它们。void printLine() { printf(“------------------------------------------\n");}),但是这里我们可以真正提高效率,因为您的老师需要使用这种方法:在函数上使用inline关键字。创建函数inline的目的是向编译器提示,值得做出某种形式的额外努力,以比其他方式更快地调用该函数--通常将函数的代码替换为其调用方。除了不需要调用和返回序列之外,它还允许编译器在两个函数的主体之间执行某些优化。这并不意味着您应该inline所有的东西。使用inline
    • 而不是#define
    • 使用非常小的函数是inline的好选择:更快的代码和更小的可执行文件(更多的机会留在代码缓存中)
    • 当函数很小并且经常被调用时

不要使用inline

代码语言:javascript
运行
复制
- with large functions: leads to larger executables, which significantly impairs performance regardless of the faster execution that results from the calling overhead
- when the function is seldom used

但是,对于您的函数来说,使用它们是正常的。内联printLine() {printLine}

  • 您不需要方法bells中的CalculateBells()变量。int CalculateBells(int青铜器){ int贝尔斯=青铜/ 1.1;返回铃铛;}您只需将所做的数学操作返回给参数,用圆括号括起来。int calculateBells(int青铜){int(青铜/ 1.1);}
  • 你的一些评论我觉得没必要。printLine();//打印行
  • 可以在一行中初始化一种类型的所有变量。这将有助于以后组织更大的项目。int ftSteelIn = 0;int numBallBearingIn = 0;int ibsBronzeIn = 0;这也会减少代码行的数量。int ftSteelIn = 0,numBallBearingIn = 0,ibsBronzeIn = 0;
  • 如果将所有方法都放在main()之前,就不必事先对它们进行原型化。但是,由于我们使用的是__inline__,所以我们必须使用原型。
  • 如果用户想再次运行这个程序,我会让用户输入一个"y“或"n”的char,也许是在do-while循环中。
  • 在某些地方,您可以使用函数puts()而不是printf()
  • 就我个人而言,我觉得你的“报告”有太多的篇幅。打印(“Acme Corporation\n");但这是你的酌处权。

最终代码(已更改的实现):

代码语言:javascript
运行
复制
#include <stdio.h>
#include <stdbool.h>
#include <ctype.h>

void printLine();
int calculateWhistles(int steel, int bearings);
int calculateBells(int bronze);

inline void printLine()
{
    puts("----------------------------------------------------");
}

inline int calculateWhistles(int steel, int bearings)
{
    steel /= 0.5;
    if (steel <= bearings) return steel;
    else return bearings;
}

inline int calculateBells(int bronze)
{
    return (bronze / 1.1);
}

int main()
{
    bool isRunning = true;
    char runAgain = 'n'; // default to no

    do
    {
        int ftSteelIn = 0, numBallBearingIn = 0, ibsBronzeIn = 0;

        printf("How many feet of steel was received today? ");
        scanf("%d", &ftSteelIn);
        printf("How many ball bearings were received today? ");
        scanf("%d", &numBallBearingIn);
        printf("How many pounds of bronze was received today? ");
        scanf("%d", &ibsBronzeIn);
        for(; getchar() != '\n'; getchar())
        {
        } // eat superfluous input, including the newline

        // Print company logo and program title
        puts("\nAcme Corporation: Product Report");
        printLine();

        // Print number of bells and whistles
        printf("Number of Bells: %d\n", calculateBells(ibsBronzeIn));
        printf("Number of Whistles: %d\n", calculateWhistles(ftSteelIn, numBallBearingIn));

        // Ask the user if they would like to run the program again
        printf("Would you like to run the program again? (y/N) "); // capital 'N' to suggest it is default
        scanf("%c", &runAgain);

        if (tolower(runAgain) != 'y') isRunning = false;
    } while (isRunning);

    puts("Exitting the program. Have a good day.");
    return 0;
}
票数 16
EN

Code Review用户

发布于 2014-02-17 06:15:40

这里的其他答案都很好,尤其是布兰登接受的答案。我想补充一点意见。你写道:

任何建议都会很感激,如何提高效率.

我想通过一个简单的评论来谈谈你关于让它“更有效率”的评论:不要。写你的代码,让它工作。代码要干净,做一些有意义的事情来保持设计的直截了当。记录您的代码,考虑其他可能查看或使用它的人,并考虑自己将来回到代码中,而不记得您在编写代码时在想什么。

一旦你的程序写好了,然后问问自己:它不符合我设定的硬性能要求吗?UI太慢了吗?是不是有些算法花费的时间太长,实际上影响了我的程序的使用,以一种明显和消极的方式?我有什么地方没记忆了吗?如果是这样的话,那么首先集中精力在更高的层次上改进任何算法或逻辑;例如,您可能正在对大量数据进行排序,而且它显然过于缓慢或资源密集型--首先考虑另一种排序算法。在您对此感到满意之后,如果有必要,您可以继续添加进一步的微观优化,但前提是您已经清楚地确定了实际瓶颈所在的位置(例如,分析,或测量功能时间,而不仅仅是盲目猜测)。

不要担心在这里或那里浪费几个CPU周期,如果这会导致干净、可维护、清晰的代码,特别是在初始开发期间,您可能会意外地更改一些东西。您希望避免过早的优化,这种优化既会分散您对实际目标的注意力,又会将您锁定在某个实现中,如果需要的话,这些实现是很难更改的。

新程序员一开始就想要进行不必要的微观优化是很常见的,特别是在那些并不重要的领域(例如编写一个程序,比如生成图像文件,但试图优化代码,以检查输出文件名字符串是否有效)。别走那条路!设计->实现-> Test -> Profile ->优化->测试,并且只有在性能要求未满足的情况下才进行最后3次测试。

我知道这可能是一个一般性的建议,有点为时过早,但如果你记住这一点(以及其他伟大答案中的所有信息),你将为一个顺利和富有成效的体验做好准备。

票数 13
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

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

复制
相关文章

相似问题

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