我希望每个人都做得很好。我还是这个开发人员的新手,虽然我发现它真的很有趣,但我开始看到如果你不跟踪你在做什么就会变得乏味。我正在研究模拟ATM程序的更新。新版本从.txt文件中读取以验证帐户信息。验证完成后,您可以查看余额,存款,取款或退出。完成交易后,程序会假设使用该帐户的更新余额更新旧的.txt文件。我终于得到了所有工作,就像它想象的那样,但当我回去检查更新的.txt文件时,该特定帐户已更新,但文件中的其余字符串更新为null,我无法弄清楚为什么以及是什么导致我的程序这样做。我有一种感觉,问题出在upDate方法中,我忽略了一些东西。下面你可以看到我的源代码,下面是我得到的输出。任何有关此错误背后的逻辑的解释将不胜感激。
import java.util.*;
import java.io.*;
public class ATM2 {
public static Scanner kbd = new Scanner(System.in);
/*
* This method reads the number of lines in the .txt file
* and returns the array size.
*/
public static int arraySize () {
int result = 0;
try
{
Scanner lineReader = new Scanner(new FileReader("ATMData.txt"));
int lineCount=0;
while(lineReader.hasNextLine())
{
String size;
size = lineReader.nextLine();
lineCount++;
}
lineReader.close();
return lineCount;
}
catch(FileNotFoundException e)
{
System.out.println("ERROR: FILE NOT FOUND");
return result;
}
}
//Method searches .txt file and returns String
//array with all account info.
public static String[] acctLine(int size){
String[] validAccounts = null;
try
{
Scanner lineReader = new Scanner(new FileReader("ATMData.txt"));
int lineCount=0;
String [] acctNums= new String[size];
while(lineReader.hasNextLine())
{
String lineInfo;
lineInfo = lineReader.nextLine();
acctNums[lineCount]=lineInfo;
lineCount++;
}
lineReader.close();
return acctNums;
}
catch(FileNotFoundException e)
{
System.out.println("ERROR: FILE NOT FOUND");
return validAccounts;
}
}
//Method updates the txt file with new acct information.
public static void acctUpdate (String[] validAccount, String fileName){
try
{
PrintWriter newFile = new PrintWriter(new FileWriter(fileName));
for(int i=0; i<validAccount.length; i++){
newFile.println(validAccount[i]);
}
newFile.close();
}
catch(Exception e){
System.out.println("ERROR: FILE NOT PRINTED");
}
}
/*The checkID method determines if acctNum is a valid account number
* and pwd is the correct password for the account. If the account information
* is valid, the method returns the current account balance, as a string.
* If the account information is invalid, the method returns the string "error"
*/
public static String checkID(String acctNum, String pwd, String [] validAccounts)
{
String result = "ERROR";
String acctString = "ERROR";
boolean foundIt = false;
for(int i=0; i<validAccounts.length; i++) //Loop compares the input data with array data.
{
acctString = validAccounts[i];
if (acctNum.equals(acctString.substring(0, acctString.indexOf(" "))) &&
pwd.equals(acctString.substring(acctString.indexOf(" ")+1,acctString.lastIndexOf(" ")))){
foundIt = true;
result = acctString.substring(acctString.lastIndexOf(" ") + 1);
}
}
if (foundIt) //If it's true it returns the acct. balance.
{
return result;
}
else
{
System.out.println("ERROR: INVALID ACCOUNT TYPE");
}
return result;
}
/* This method finds the array index of the desired account string.
* and returns the the index of the line
*/
public static int arrayIndex(String acctNum, String pwd, String [] validAccounts)
{
int accountPos=0;
Boolean foundIt = false;
//loop searches for the index of the array.
for(accountPos=0; accountPos<validAccounts.length && !foundIt; accountPos++)
{
if (acctNum.equals(validAccounts[accountPos].substring(0, validAccounts[accountPos].indexOf(" "))) &&
pwd.equals(validAccounts[accountPos].substring(validAccounts[accountPos].indexOf(" ")+1, validAccounts[accountPos].lastIndexOf(" "))))
{
foundIt = true;
}
}
return accountPos;
}
/*Method creates menu options and returns
*the choice selected by the user.
*/
public static int menu()
{
int menuChoice;
do
{
System.out.print("\nENTER TRANSACTION TYPE: CHOOSE 1-4."
+ " \n 1. Display Balance"
+ "\n 2. Deposit\n 3. Withdraw\n 4. Log Out\n");
menuChoice = kbd.nextInt();
if (menuChoice < 1 || menuChoice > 4){
System.out.println("error");
}
}while (menuChoice < 1 || menuChoice > 4);
return menuChoice;
}
/*Method displays the balance to the screen.
*/
public static void displayBalance(double balance)
{
System.out.printf("\nYOUR NEW BALANCE IS: $%.2f\n", balance);
}
/*Method calculates the deposit going in to account.
Returns the total deposit.
*/
public static double deposit(double orgBal, double depAmt)
{
return orgBal + depAmt;
}
/*Method that calculates the balance after the withdraw.
* returns a double with the amount withdrawn.
*/
public static double withdraw(double orgBal, double wdrlAmt)
{
if (wdrlAmt > orgBal)
{
return orgBal;
}
else
{
return orgBal-wdrlAmt;
}
}
public static void main(String[] args) {
String accNum, pass, fileName="ATMData.txt", origBal = "ERROR";
String acctInfo;
int count = 0, menuOption = 0, acctPos;
double depositAmt, withdrawAmt, currentBal;
String [] validAccounts =acctLine(arraySize());
/*loop that will count the number of login attempts
*you make and will exit program if it is more than 3.
*as long as oriBal equals an error.
*/
do{
System.out.println("PLEASE ENTER YOUR ACCOUNT NUMBER: ");
accNum = kbd.next();
System.out.println("ENTER YOUR PASSWORD: ");
pass = kbd.next();
origBal = checkID(accNum, pass, validAccounts);
count++;
acctPos = arrayIndex(accNum, pass, validAccounts)-1;
if (count >= 3 && origBal.equals("ERROR:")){
System.out.print("MAX LOGIN ATTEMPTS REACHED.");
System.exit(0);
}
else if (!(origBal.equals("ERROR"))){
System.out.println("\nYOUR CURRENT BALANCE IS: $ "+ origBal);
}
else
System.out.println(origBal);
}while(origBal.equals("ERROR"));
currentBal=Double.parseDouble(origBal);
/*this loop will keep track of the options that
*the user inputs in for the menu. and will
*give the option of deposit, withdraw, or logout.
*/
while (menuOption != 4)
{
menuOption=menu();
switch (menuOption)
{
case 1:
displayBalance(currentBal);
break;
case 2:
System.out.print("HOW MUCH DO WISH TO DEPOSIT: $ ");
depositAmt = kbd.nextDouble();
currentBal = deposit(depositAmt, currentBal);
displayBalance(currentBal);
break;
case 3:
System.out.print("HOW MUCH DO YOU WISH TO WITHDRAW: $ ");
withdrawAmt = kbd.nextDouble();
if (withdrawAmt > currentBal)
System.out.println("ERROR: YOU DON'T HAVE ENOUGH FUNDS TO COMPLETE"
+ " TRANSACTION."
+ " ENTER TRANSACTION TYPE: CHOOSE 1-4");
currentBal = withdraw(currentBal, withdrawAmt);
displayBalance(currentBal);
break;
case 4://Last option logs user out after it updates the ATMData.txt
acctInfo = accNum + " " + pass + " " + String.valueOf(currentBal);
validAccounts[acctPos]=acctInfo;
acctUpdate(validAccounts, fileName);
System.out.println("LOGOUT SUCCESSFULL.");
System.exit(0);
break;
default:
}
}
}
}
这就是.txt在源代码更新之前的样子。唯一更新的是一行。
null
null
null
null
null
null
null
null
null
null
417927608 ;6FYE5l`LPX@ 4101.13
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
null
因为我们通过引用传递,我们只需要在主程序中声明一次原始数组。
7560640 6Z[NVoee1S6 4424.43
04569505 f:H>wAr@<URH 4211.42
528859 ][[79_W?]=:< 724.26
973335820 Si>G7QMp?>e 3207.28
79154675 Y>vfTYwHm0J 3327.47
5554284 6n[^PwZUZlH 1028.66
58773836 28vcgSpwA01 3131.02
95873039 @4XwrN`T9 2598.28
1034703 n@HKk`mTar2Z 1176.75
10192851 X>ATvaR:qT 3857.89
417927608 ;6FYE5l`LPX@ 3401.13
143260 s2UgJtSHYFmn 378.68
34729802 rh\<3rmk7Dm< 255.48
277791753 BR2=siCDi 345.75
1014748 PK?KTMjA63e 1196.16
496714922 M1=I`ve;Wjw 501.26
654156 AB`6cvO0ql: 4310.51
898250859 t^D90Nw?Ii 3876.05
971750 [9q_5AuLlJ 135.97
796678134 KwV^03p:WW=< 3453.65
39482807 C5?H?b9UplL 4109.48
401599 MvHL7Yv07bW 4356.96
8321377 Jc:<_ke9B: 930.90
152773 VQ6\[2k:uoj 3265.93
624426519 kralkKKEia3 4858.39
650002 Km2t\R3>3@G 1470.78
004509766 _0S`1qb^V 1332.24
0274647 WDhg3\p]w 3147.50
974502771 Q4GT<_s3D9CK 4464.22
281866 c_1F]@RpV^ 2952.03
381121 rOo?CiA[kwTs 4555.21
1549064 F7^eh=njp\r 430.24
841319 IBe^GTLGv 4050.76
6499423 tW9>r[s_<\ 1418.09
8579740 cdB12UrLU 2905.74
33581232 <os4;WcEqb 2455.32
725175174 nWjIeFLK3E 3118.08
592410029 RqgPT382p2Lk 3863.32
08274516 DDr?^vuNQ 1630.37
808471 Ow:8udlBrYP 2590.05
769854 0`lpWGrMkrG 2643.59
3591827 MmThLS1DdL5 2715.30
9001605 \n;rMknh7C 4074.83
10345766 N>^qBqhk?39J 539.43
504385 j0Rq=li0c^ 253.77
362335041 >^VN5oh?OSR 324.19
5728008 QZ>BZhGEv 4441.67
26102273 1XCWR;W?^b\ 4203.51
3317249 dmjLKbgZ? 1958.44
793249 5J>ApQZAB 1906.46
536461203 CP5U:f5\d[_p 3742.25
030298042 VBtHo909;QM 986.28
6111228 mmPgiDMALt 1348.95
621992 r7UmSJ\9j 1440.22
310072768 B1ccagCH3 4755.56
819894803 IXfcY9PZG1 4399.39
362945795 5LAdX_s^G 3624.28
99929088 `oHijc^J0u 4507.69
821671 s@OV>NYlacV 4125.72
72368663 Mi?wTcZ_@I 2845.24
22692406 uT05^2plu 2530.73
343817 pB;Glu5sVb7P 2168.28
5138360 877<cT4T;t 1562.15
答案 0 :(得分:1)
您永远不会将之前的帐户数据写入validAccounts
。运行String [] validAccounts = new String[arraySize()];
时,所有字符串实例都设置为null,并且只有在更新帐户时才会更改。您需要做的是当您启动程序时,将现有文本文件读入该String数组,然后只需更改您需要的条目。完成后,将String数组写入文件。
答案 1 :(得分:1)
在你的主要方法中 String [] validAccounts = new String [arraySize()]; 这意味着你有一个NULL值数组,你需要在这里而不是在另一个方法中分配值数据,就像你传递数组时传递对这个数组的引用而不是数据本身 所以在arrayIndex中 validAccounts = acctLine(arraySize());将数据放入此方法中,当它返回时,将丢弃此数据。 您需要分配数据ONCE然后传递它,而不在方法
中写入e.g。在主要 String [] validAccounts = new String [arraySize()]; 应该 String [] validAccounts = acctLine(arraySize()); 您不需要在arrayIndex或checkID中再次读取它。 所以读一次并存储它,将这些数据传递给方法并从这些数据中读取而不是读取新文件
一个简单的例子是这样的 - 你会看到a = new int ....不会改变原始方法,但是在doSomething中进行赋值
public static void main(String [] args){
int[] a = {1,2,3};
doesNothing(a);
for (int i: a)
System.out.print(i);
doesSomething(a);
for (int i: a)
System.out.print(i);
}
static void doesNothing(int[] a) {
a = new int[]{4,5,6};
}
static void doesSomething(int[] a) {
a[0] = 7;
a[1] = 8;
a[2] = 9;
}