C语言转账功能异常排查:疑似空格字符导致的文件写入问题
C语言转账功能故障排查:空格与文件读写问题
问题描述
注册功能可正常将客户信息写入test.txt文件,但转账(havale)功能无法正常执行。该功能逻辑为读取文件内容、完成转账操作后重新写入文件,怀疑是空格字符引发的问题,需排查具体原因及解决方法。
核心原因分析
文件写入时的换行错误
转账函数重写文件时,错误地将换行符输出到控制台(printf("\n")),而非写入文件。这会导致所有客户记录在文件中挤成一行,后续fgets读取时无法正确拆分每条记录,进而导致IBAN匹配失败、转账逻辑失效。IBAN验证函数的越界风险
ibankontrol函数中循环条件为i < 27,但struct müşteri的iban数组长度为27(含字符串终止符'\0'),有效IBAN字符最多26位。循环到i=26时会访问数组的终止符位置,可能引发非法内存访问或验证逻辑错误。不必要的
fflush(stdin)调用fflush对标准输入流的行为是C标准未定义的,不仅无意义,还可能导致跨平台兼容性问题。
解决方法
修正文件写入的换行逻辑
将转账函数中输出换行的printf("\n")替换为fprintf(dosya, "\n"),确保每条客户记录在文件中单独占一行。调整IBAN验证的循环边界
将ibankontrol中的循环条件改为i < 26,避免访问数组的终止符位置。移除无效的
fflush(stdin)
删除所有fflush(stdin)调用,scanf("%s")会自动跳过输入中的空白字符,无需额外处理。
修正后的完整代码
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<ctype.h> #define I 27 #define DosyaAdi "test.txt" struct müşteri { char iban[I]; long long tc; int bakiye; }; int ibankontrol(char iban[]) { if(!isalpha(iban[0]) || !isalpha(iban[1])) return 0; // 修正循环边界,避免访问终止符 for (int i = 2; i < 26; i++) { if (iban[i]<48 || iban[i]>57) { return 0; } } return 1; } int tckontrol(long long tc) { int a=0,bas; long long i=1; while (a<11) { bas=(tc/i)%10; if (bas<0 || bas>9) { return 0; } i*=10; a++; } if (tc / i > 0) { return 0; } return 1; } int kaydet(struct müşteri m) { FILE *dosya; dosya=fopen(DosyaAdi,"a"); if (dosya==NULL) { printf("\nKayıt başarısız\n"); return 0; } fprintf(dosya,"%lld %d %s\n",m.tc,m.bakiye,m.iban); fclose(dosya); return 1; } int havale(char kaynak[],char hedef[],int miktar) { struct müşteri müşteriler[100]; int i=0,y=0,z=0; char string[100]; FILE *dosya; dosya=fopen(DosyaAdi,"r"); if (dosya == NULL) { // 新增文件打开失败判断 printf("Dosya okunamadı.\n"); return 0; } while (1) { if ((fgets(string,100,dosya))==NULL) { break; } sscanf(string,"%lld %d %s",&müşteriler[i].tc,&müşteriler[i].bakiye,müşteriler[i].iban); i++; } for(z=0;z<i;z++) { printf("\nGuncel bilgiler:\n"); printf("%d: %s %lld %d\n",z+1,müşteriler[z].iban,müşteriler[z].tc,müşteriler[z].bakiye); } fclose(dosya); for (int j = 0; j < i; j++) { if (strcmp(kaynak,müşteriler[j].iban) == 0) { müşteriler[j].bakiye -= miktar; y++; } if (strcmp(hedef,müşteriler[j].iban) == 0) { müşteriler[j].bakiye += miktar; y++; } } if (y != 2) { printf("Kaynak veya hedef IBAN bulunamadı.\n"); return 0; } dosya = fopen(DosyaAdi, "w"); if (dosya == NULL) { printf("Dosya açılamadı.\n"); return 0; } for (int s = 0; s < i; s++) { fprintf(dosya, "%lld %d %s", müşteriler[s].tc, müşteriler[s].bakiye, müşteriler[s].iban); if (s!=i-1) { // 修正:将换行写入文件而非控制台 fprintf(dosya, "\n"); } } fclose(dosya); printf("Havale başarılı!\n"); return 1; } int main() { int seçim; int dönüş=0,kontrol=0; char kaynak[27],hedef[27]; int miktar=0; struct müşteri m; while (1) { printf("Menü:\n"); printf("1:Kayıt\n"); printf("2:Havale\n"); printf("3:Çıkış\n"); printf("Seçiminiz: "); scanf("%d",&seçim); switch (seçim) { case 1: while (1) { printf("İban giriniz: "); scanf("%s",m.iban); // 移除fflush(stdin) dönüş=ibankontrol(m.iban); if (dönüş==0) { printf("İban yanlış!\n"); } else if (dönüş==1) { break; } } while (1) { printf("TC giriniz: "); scanf("%lld",&m.tc); // 移除fflush(stdin) dönüş=tckontrol(m.tc); if (dönüş==0) { printf("TC yanlış!\n"); } else if (dönüş==1) { break; } } printf("Bakiye giriniz: "); scanf("%d",&m.bakiye); kontrol=kaydet(m); if (kontrol==0) { printf("Kayıt başarısız!\n"); } else if (kontrol==1) { printf("Kayıt başarılı!\n"); break; } break; case 2: printf("Kaynak iban: "); scanf("%s",kaynak); // 移除fflush(stdin) printf("Hedef iban: "); scanf("%s",hedef); // 移除fflush(stdin) printf("Gönderilicek miktar: "); scanf("%d",&miktar); int a=havale(kaynak,hedef,miktar); if (a==0) { printf("Havale başarısız\n"); } break; case 3: exit(EXIT_SUCCESS); // 替换为标准退出码 break; default: printf("Geçersiz işlem!\n"); break; } } return 0; }
内容的提问来源于stack exchange,提问作者JiEunA
相关产品推荐
相关产品推荐

