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的代码块.
我在这看到一些问题.
首先,过度使用全局变量令人不安.数组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在将来某个时候崩溃.为了解决这个迫在眉睫的问题,你有两个选择
简单的方法:将BillDatabase结构更改为以下内容
typedef struct
{
int BillNumber, BillClass;
float LastMeter, CurrentMeter;
char name[128];
} BillDatabase;
Run Code Online (Sandbox Code Playgroud)
这很简单,但并不好,因为名称永远不会超过128个字符.另外,请不要将整个结构放在一行上.我几乎开始用萨克斯管击打头部.
更难的出路:学会使用malloc(),并手动分配名称数组.