0

我正在尝试编写一个使用函数来计算水费的程序。它从文件中读取有关用水量的信息,然后计算税后水费。

这是文件:

g 5000
B 1250
M 50

这就是输出应该是什么:

Type  Water usage  Cost including tax($)
g     5000              194.30
B        1250              93.89
Wrong user type

这是我的输出:

Type  Water usage  Cost including taxWrong user type.
g     5000          0.000000
B     1250          18.750750
Wrong user type.

我不确定问题出在我的公式还是其他问题上。函数中的 if else 语句显然存在问题,因为它一直在不应该的地方打印“错误的用户类型”。

这是我的代码:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <math.h>

double water_billcalculation(char user_type, double water_use, double bft, double at);

int main(void) {
    FILE* water;
    water = fopen("water_usage.txt", "r");

    char user_type;
    int cf;
    double bft = 0, at = 0, water_use = 0;

    printf("Type  Water usage  Cost including tax");

    while (fscanf(water, "%c%d ", &user_type, &cf) != EOF) {
        //water_billcalculation(user_type, water_use, bft, at);
        printf("%c     %d          %lf\n", user_type, cf, water_billcalculation(user_type, water_use, bft, at));
    }

    return(0);
}

double water_billcalculation(char user_type, double water_use, double bft, double at) {
    if (user_type == 'G') { 
        bft = (water_use * 0.035) + 3.75;
        at = bft + (bft * .087);
    }
    else if (user_type == 'B') { 
        bft = (water_use * .0553) + 17.25;
        at = bft + (bft * .087);
    }
    else if (user_type == 'R') { 
        if (water_use <= 400) {
            bft = (water_use * .04) + 13.5;
            at = bft + (bft * .087);
        }
        else if (water_use > 400 && water_use <= 700) {
            bft = (water_use * .062) + 13.5;
            at = bft + (bft * .087);
            
        }
        else {
            bft = (water_use * .12) + 13.5;
            at = bft + (bft * .087);
        }
    }
    else { 
        printf("Wrong user type.\n");
    }
    return(at);
}
4

2 回答 2

4

问题

您以错误的方式“阅读”您的文件。更改此行:

    while (fscanf(water, "%c%d ", &user_type, &cf) != EOF) {

对此(注意第二个参数的区别fsanf):

    while (fscanf(water, " %c%d", &user_type, &cf) == 2) {

water_billcalculation也错了:你正在照顾 user_type GB并且R根据你的代码,但你实际上正在照顾g,BM! 所以你需要改变这部分:

    if (user_type == 'G') { 
        bft = (water_use * 0.035) + 3.75;
        at = bft + (bft * .087);
    }
    else if (user_type == 'B') { 
        bft = (water_use * .0553) + 17.25;
        at = bft + (bft * .087);
    }
    else if (user_type == 'R') { 

对此:

    if (user_type == 'g') { 
        bft = (water_use * 0.035) + 3.75;
        at = bft + (bft * .087);
    }
    else if (user_type == 'B') { 
        bft = (water_use * .0553) + 17.25;
        at = bft + (bft * .087);
    } else if (user_type == 'M') { 

在此之后,您将获得以下输出:

Type  Water usage  Cost including taxg     5000          4.076250
B     1250          18.750750
M     50          14.674500

我有点不确定,如果这是你想要的输出,因为根据你的帖子说,你想要这个输出:

Type  Water usage  Cost including tax($)

g     5000              194.30

B        1250              93.89
 
Wrong user type

让我想到:

  • 您实际上不想“解析” type M。如果是,则删除函数中的else if (user_type == 'M')条件。water_billcalculation
  • 计算不正确,或者我的代码中没有看到另一个错误(尽管我什至使用 valgrind 运行它,它没有抱怨任何无效操作)。

代码审查

当我阅读您的代码时,我想到了一些改进的想法。所以这里有一些建议。如果你对它们不感兴趣,你可以跳过这个。

调用后检查返回值fopen

fopenFILE *一切正常时才返回您!所以请确保添加一个查找部分:

    FILE * water;
    water = fopen("water_usage.txt", "r");

    if (water == NULL) {
        // Thanks to @William Pursell for pointing out to use stderr for error messages, I forget that pretty often
        perror("Houston, we've got a problem: The file couldn't be opened :(\n");
        // or use the `exit()` function here (but you'd need to include stdlib.h)
        return 1;
    }

字符串格式

我建议使用\t而不是计算你的空间。这将使您产生更好的输出。\n如果您在新的上下文中打印某些内容,也不要忘记添加。

一开始我有这个输出:

Type  Water usage  Cost including taxg     5000          4.076250
B     1250          18.750750
M     50          14.674500

我先是有点恼火,因为我没有看到与g类型的线。

将输出更改为以下内容:

    printf("Type\tWater usage\tCost including tax\n");

    while (fscanf(water, "%c %d\n\n", &user_type, &cf) != EOF) {
        printf("%c\t%d\t\t%lf\n", user_type, cf, water_billcalculation(user_type, water_use, bft, at));
    }

这给了我以下输出:

Type    Water usage     Cost including tax
g       5000            4.076250
B       1250            18.750750
M       50              0.000000

哪个更好读(在我看来)。

(可选)使用 switch-case

water_billicalculation可以包含一个 switch-case 语句而不是嵌套的 if-else 语句。

我将编写函数如下:

double water_billcalculation(char user_type, double water_use, double bft, double at) {

    switch (user_type) {
        case 'g':
            bft = (water_use * 0.035) + 3.75;
            at = bft + (bft * .087);
            break;
        case 'B':
            bft = (water_use * .0553) + 17.25;
            at = bft + (bft * .087);
            break;
        case 'M':
            if (water_use <= 400) {
                bft = (water_use * .04) + 13.5;
                at = bft + (bft * .087);
            }
            else if (water_use > 400 && water_use <= 700) {
                bft = (water_use * .062) + 13.5;
                at = bft + (bft * .087);
                
            }
            else {
                bft = (water_use * .12) + 13.5;
                at = bft + (bft * .087);
            }
            break;
        defaut:
            fprintf(stderr, "Wrong user type: '%c'\n", user_type);
            break;
    }
    return at;
}

而不是这个:

    if (user_type == 'g') { 
        bft = (water_use * 0.035) + 3.75;
        at = bft + (bft * .087);
    }
    else if (user_type == 'B') { 
        bft = (water_use * .0553) + 17.25;
        at = bft + (bft * .087);
    }
    else if (user_type == 'M') { 
       // and so on...

但这可能是非常个人的,所以请将此视为意见。

于 2021-10-04T22:50:26.390 回答
1

虽然@TornaxO7 回答了您的字面问题,但您可以通过调试程序轻松确定问题所在:

如何调试 C 程序

具体来说,

  • 通过在扫描后步进或中断程序,您会注意到您user_typecf.
  • 通过逐步完成 中的比较water_billcalculation(),您会注意到您期望的比较成功和失败 - 这会导致您注意到您正在与 进行'g'比较'G'

此外,或替代地,向您的程序添加一些“调试打印”或日志类型打印,至少在开发它时,即使在没有调试的常规运行中也能提供一些相同的信息。

于 2021-10-06T16:33:14.913 回答