字符串在C输出时成为符号

Kad*_*ama -1 c string gets data-structures

我在代码中输出一些字符串时遇到问题.当我输入1个字符串然后输出它时,根本没有问题.但是,当我输入至少2个字符串时,它就失败了.字符串成为符号,除了最后一个.这是截图:

在此输入图像描述

我一直在使用fflush(stdin)和fflush(stdout),但问题仍然存在.所以我该怎么做?我需要你的建议.

这是我的完整代码:

#include <stdio.h>
#include <stdlib.h>

void menu();
void entry();
void search();
void PrintSingle();
void PrintComplete();
float TotalUsed(int i);
float RegularCost(int i);
float tax(int i);
float discount(int i);
float TotalPayment(int i);

#define NMaks 101

typedef enum {false=0,true=1} boolean;
typedef struct {int BillNumber,BillClass;float LastMeter,CurrentMeter;char name[];} BillDatabase;
BillDatabase bill[NMaks];

int DataAmount=0;

int main() {

    menu();
    return 0;
}

void menu() {

    int i;

    repeat:
    system("cls");
    printf("\t\t.: Electric Billing System :.\n\n");
    printf("[1] Entries customer information\n");
    printf("[2] Search customer\n");
    printf("[3] Print single bill\n");
    printf("[4] Print complete billing report\n");
    printf("[5] Exit\n\n");
    printf("Select the menu[1..5]: ");scanf("%d",&i);

    switch (i) {
        case 1  :   entry();break;
        case 2  :   search();break;
        case 3  :   PrintSingle();break;
        case 4  :   PrintComplete();break;
        case 5  :   {
                    printf("\n\nGoodbye!");
                    getch();
                    break;
        }
        default :   {
                    printf("\n\nWrong menu!");
                    goto repeat;
        }
    }
}

void entry() {

    char repeat;

    do {
        system("cls");
        printf("\t\t.: Electric Billing System :.\n\n");
        printf("[1] Entries customer information\n\n");
        DataAmount++;
        printf("Bill number: ");scanf("%d",&bill[DataAmount].BillNumber);
        printf("Customer name: ");fflush(stdin);fflush(stdout);gets(bill[DataAmount].name);
        printf("Class[1..3]: ");scanf("%d",&bill[DataAmount].BillClass);
        printf("Last meter: ");scanf("%f",&bill[DataAmount].LastMeter);
        printf("Current meter: ");scanf("%f",&bill[DataAmount].CurrentMeter);
        printf("\nEntry again[y/n]: ");repeat=getche();
    } while (tolower(repeat)=='y');
    menu();
}

void search() {

    int i,BN;
    boolean found;
    char repeat;

    do {
        system("cls");
        printf("\t\t.: Electric Billing System :.\n\n");
        printf("[2] Search customer\n\n");
        printf("Enter the bill number: ");scanf("%d",&BN);
        found=false;
        for (i=1;i<=DataAmount;i++)
            if (BN==bill[i].BillNumber) {
                found=true;
                break;
            }
        if (found) {
            printf("\nCustomer found!\n\n");
            printf("Bill number\tN   a    m    e Class\t\tLast meter\tCurrent meter\n");
            fflush(stdin);fflush(stdout);
            printf("%d\t\t%15.15s\t%d\t\t%.2f kWh\t%.2f kWh\n",bill[i].BillNumber,bill[i].name,bill[i].BillClass,bill[i].LastMeter,bill[i].CurrentMeter);
        }
        else
            printf("\nCustomer not found!\n");
        printf("\nSearch again[y/n]: ");repeat=getche();
    } while (tolower(repeat)=='y');
    menu();
}

void PrintSingle() {

    int i,BN;
    boolean found;
    char repeat;

    do {
        system("cls");
        printf("\t\t.: Electric Billing System :.\n\n");
        printf("[3] Print single bill\n\n");
        printf("Enter the bill number: ");scanf("%d",&BN);
        found=false;
        for (i=1;i<=DataAmount;i++)
            if (BN==bill[i].BillNumber) {
                found=true;
                break;
            }
        if (found) {
            printf("\nCustomer found!\n\n");
            printf("Bill number\tN   a    m    e Class\t\tLast meter\tCurrent meter\n");
            fflush(stdin);fflush(stdout);
            printf("%d\t\t%15.15s\t%d\t\t%.2f kWh\t%.2f kWh\n",bill[i].BillNumber,bill[i].name,bill[i].BillClass,bill[i].LastMeter,bill[i].CurrentMeter);
            printf("Total used\tRegular cost\tTax\t\tDiscount\tTotal Payment\n");
            printf("%.2f kWh\t$%7.2f\t$%7.2f\t$%7.2f\t$%7.2f\n",TotalUsed(i),RegularCost(i),tax(i),discount(i),TotalPayment(i));
        }
        else
            printf("\nCustomer not found!\n");
        printf("\nPrint again[y/n]: ");repeat=getche();
    } while (tolower(repeat)=='y');
    menu();
}

void PrintComplete() {

    int i;

    system("cls");
    printf("\t\t.: Electric Billing System :.\n\n");
    printf("[4] Print complete billing report\n\n");
    printf("Bill number\tN   a    m    e\t\tClass\tTotal Payment\n");
    for (i=1;i<=DataAmount;i++) {
        fflush(stdin);fflush(stdout);
        printf("%d\t\t%15.15s\t\t%d\t$%.2f\n",bill[i].BillNumber,bill[i].name,bill[i].BillClass,TotalPayment(i));
    }
    printf("\nPress any key to the main menu");
    getch();
    menu();
}

float TotalUsed(int i) {

    return bill[i].CurrentMeter-bill[i].LastMeter;
}

float RegularCost(int i) {

    float price;

    switch (bill[i].BillClass) {
        case 1  :   price=10.0;break;
        case 2  :   price=7.5;break;
        default :   price=13.75;
    }
    return TotalUsed(i)*price;
}

float tax(int i) {

    float TaxPercentage;

    switch (bill[i].BillClass) {
        case 1  :   TaxPercentage=1.5/100;break;
        case 2  :   TaxPercentage=0.25/100;break;
        default :   TaxPercentage=3.5/100;
    }
    return RegularCost(i)-(RegularCost(i)*TaxPercentage);
}

float discount(int i) {

    float DiscountPercentage;

    switch (bill[i].BillClass) {
        case 1  :   DiscountPercentage=3.0/100;break;
        case 2  :   DiscountPercentage=2.0/100;break;
        default :   DiscountPercentage=5.5/100;break;
    }
    if (RegularCost(i)>100.0)
        return RegularCost(i)-(RegularCost(i)*DiscountPercentage);
    else
        return 0.0;
}

float TotalPayment(int i) {

    return RegularCost(i)+tax(i)-discount(i);
}
Run Code Online (Sandbox Code Playgroud)

注意:我使用IDE的代码块.

joh*_*boy 6

我在这看到一些问题.

首先,过度使用全局变量令人不安.数组bill和int 绝对DataAmount应该是全局的.这不是一个好的编程实践,我不相信那些代码看起来像这样的人.请提供您的" "," "," "和" "函数参数,以便您可以将这些变量设置为本地变量,而不是全局变量.menuentryprintcompletesearch

其次,很少有案例可以接受在同一行上有许多陈述

 printf("Customer name: ");fflush(stdin);fflush(stdout);gets(bill[DataAmount].name);
Run Code Online (Sandbox Code Playgroud)

我只是看着它让我头疼!pleeease不要!

第三,你没有在这个for循环中正确使用数组边界,这是你首先要问的bug的原因.

 for (i=1;i<=DataAmount;i++) {
    fflush(stdin);fflush(stdout);
    printf("%d\t\t%15.15s\t\t%d\t$%.2f\n",bill[i].BillNumber,bill[i].name,bill[i].BillClass,TotalPayment(i));
}
Run Code Online (Sandbox Code Playgroud)

请记住,在C语言中,数组索引从0开始,以"n - 1"结束.你的循环从1开始,到"n"结束.

伪造字符的原因是您正在访问BillDataBase数组边界之外的字符bill.

第四,正如Sami Kuhmonen所说,你没有为name阵列分配任何内存.虽然这可能不会导致您看到的错误,但几乎可以肯定会导致您的程序segmentation fault在将来某个时候崩溃.为了解决这个迫在眉睫的问题,你有两个选择

  1. 简单的方法:将BillDatabase结构更改为以下内容

    typedef struct
    {
        int BillNumber, BillClass;
        float LastMeter, CurrentMeter;
        char name[128];
    } BillDatabase;
    
    Run Code Online (Sandbox Code Playgroud)

    这很简单,但并不好,因为名称永远不会超过128个字符.另外,请不要将整个结构放在一行上.我几乎开始用萨克斯管击打头部.

  2. 更难的出路:学会使用malloc(),并手动分配名称数组.

  • "_也许这个问题在codereview.stackexchange.com._上会更好" - 没有CR是**工作代码**,而不是破解代码. (3认同)
  • 好吧,@ CoolGuy.从他的帖子中编辑出来.除此之外,很好的回答顺便说一句+1 (2认同)