1

guys. Right now, I have an array of objects that I've assigned from reading in a text file, and I need a method that searches for a string that matches with the object and, if found, decreases the capacity of the array and deletes that element. The method is the deletePhone() method in the Provider class, but I can't seem to figure out what I'm doing wrong. This first class is only used to read in the file.

public static void main(String[] args) throws IOException {
      String fileNameIn = args[0];
      Provider provObj = new Provider();
      provObj.readCellPhoneFile(fileNameIn);

      System.out.println(provObj.summary());
      System.out.println(provObj.rates());
      System.out.println(provObj.listByNumber());
      System.out.println(provObj.listByBill());
      System.out.println(provObj.excludedRecordsList());
   }
}

This is the main class that I'm having problems with. It's only the deletePhone() method that I can't seem to figure out.

import java.util.Scanner;
import java.io.File;
import java.util.Arrays;
import java.io.IOException;
import java.text.DecimalFormat;

public class Provider {
   private String name;
   private CellPhone[] phones;
   private String[] excludedRecords;

   /**
    * Constructor for Provider class.
    */
   public Provider() {
      name = "not yet assigned";
      phones = new CellPhone[0];
      excludedRecords = new String[0];
   }

   /**
    * Reads in file name and assigns data.
    *
    * @param fileNameIn Input for file name from main
    * @throws IOException from scanning file name
    */
   public void readCellPhoneFile(String fileNameIn) throws IOException {
      //Reads in file name and creates Scanner object
      File fileIn = new File(fileNameIn);
      Scanner scanFile = new Scanner(fileIn);
      //Assigns name from first line
      name = scanFile.nextLine();
      //Assigns data from file to different categories
      while (scanFile.hasNextLine()) {
         Scanner scanPhone = new Scanner(scanFile.nextLine());
         scanPhone.useDelimiter(", *");

         String phoneType = scanPhone.next();
         char phoneChar = phoneType.toUpperCase().charAt(0);
         //Assigns phone to different category
         switch (phoneChar) {   
            case 'F':
               String number = scanPhone.next();
               int texts = Integer.parseInt(scanPhone.next());
               int minutes = Integer.parseInt(scanPhone.next());
               FlipPhone flip1 = new FlipPhone(number, texts, minutes);
               addPhone(flip1);
               break;
            case 'S':
               number = scanPhone.next();
               texts = Integer.parseInt(scanPhone.next());
               minutes = Integer.parseInt(scanPhone.next());
               int data = Integer.parseInt(scanPhone.next());
               SmartPhone smart1 = new SmartPhone(number, texts, minutes, data);
               addPhone(smart1);
               break;
            case 'I':
               number = scanPhone.next();
               texts = Integer.parseInt(scanPhone.next());
               minutes = Integer.parseInt(scanPhone.next());
               data = Integer.parseInt(scanPhone.next());
               int iMessages = Integer.parseInt(scanPhone.next());
               IPhone iPhone1 = new IPhone(number, texts,
                  minutes, data, iMessages);
               addPhone(iPhone1);
               break;
            case 'A':
               number = scanPhone.next();
               texts = Integer.parseInt(scanPhone.next());
               minutes = Integer.parseInt(scanPhone.next());
               data = Integer.parseInt(scanPhone.next());
               int hotspotMin = Integer.parseInt(scanPhone.next());
               Android android1 = new Android(number, texts,
                  minutes, data, hotspotMin);
               addPhone(android1);
               break;
            default:
               String unrecognized = scanPhone.nextLine();
               unrecognized = phoneType + unrecognized; 
               addExcludedRecord(unrecognized);   
         }
      }   
   }

   /**
    * Returns string for provider name.
    *
    * @return String
    */
   public String getName() {
      return name;
   }

   /**
    * Assigns a name input as provider name.
    *
    * @param nameIn Input for provider name
    */
   public void setName(String nameIn) {
      name = nameIn;
   }

   /**
    * Returns CellPhone array for phones.
    *
    * @return CellPhone[]
    */
   public CellPhone[] getPhones() {
      return phones;
   }

   /**
    * Returns string array for excluded records.
    *
    * @return String[]
    */
   public String[] getExcludedRecords() {
      return excludedRecords;
   }

   /**
    * Adds phone to array of phones.
    *
    * @param newPhoneIn Input for phone object
    */
   public void addPhone(CellPhone newPhoneIn) {
      //Increases size of phones array
      CellPhone[] newPhones = new CellPhone[phones.length + 1];
      for (int i = 0; i < phones.length; i++) {
         newPhones[i] = phones[i];
      }
      phones = newPhones;
      //Adds CellPhone object to phones array
      phones[phones.length - 1] = newPhoneIn;
   }

   /**
    * Determines if phone number is found and deleted.
    *
    * @return boolean
    * @param numberIn Input for phone number
    */
   public boolean deletePhone(String numberIn) {
      boolean delete = false;
      int deleteIndex = -1;
      //Searches for phone number match
      for (int i = 0; i < phones.length; i++) {
         if (numberIn.equals(phones[i].getNumber())) {
            deleteIndex = i;
         }
      }
      if (deleteIndex > -1) {
         for (int i = deleteIndex; i < phones.length - 1; i++) {
            phones[i] = phones[i + 1];
            phones[phones.length - 1] = null;
            CellPhone[] newPhones = new CellPhone[phones.length - 1];
            phones = newPhones;
         }
         return true;
      }
      else {
         return false;
      }
   }

   /**
    * Adds unrecognized phone to excluded records.
    *
    * @param excRecIn Input for unrecognized phone
    */
   public void addExcludedRecord(String excRecIn) {
      //Increases capacity of excludedRecords
      String[] newExcRecords = new String[excludedRecords.length + 1];
      for (int i = 0; i < excludedRecords.length; i++) {
         newExcRecords[i] = excludedRecords[i];
      }
      excludedRecords = newExcRecords;
      //Adds excRecIn to array
      excludedRecords[excludedRecords.length - 1] = excRecIn;
   }

   /**
    * Returns list of cell phones in phones array.
    *
    * @return String
    */
   public String toString() {
      String result = "";
      for (CellPhone phone : phones) {
         result += phone + "\n";
      }
      return result;
   }

   /**
    * Calculates total bill for all phones.
    *
    * @return double
    */
   public double calculateTotalBill() {
      double totalBill = 0;
      for (int i = 0; i < phones.length; i++) {
         totalBill += phones[i].calculateBill();
      }   
      return totalBill;
   }

   /**
    * Calculates total number of texts for all phones.
    *
    * @return int
    */
   public int calculateTotalTexts() {
      int totalTexts = 0;
      for (int i = 0; i < phones.length; i++) {
         totalTexts += phones[i].getTexts();
      }   
      return totalTexts;
   }

   /**
    * Calculates total number of minutes for all phones.
    *
    * @return int
    */
   public int calculateTotalMinutes() {
      int totalMinutes = 0;
      for (int i = 0; i < phones.length; i++) {
         totalMinutes += phones[i].getMinutes();
      }   
      return totalMinutes;
   }

   /**
    * Calculates total data for smartphones.
    *
    * @return int
    */
   public int calculateTotalData() {
      int totalData = 0;
      for (int i = 0; i < phones.length; i++) {
         if (phones[i] instanceof SmartPhone) {
            totalData += ((SmartPhone) phones[i]).getData();
         }   
      }   
      return totalData;
   }

   /**
    * Calculates total hotspot minutes for Androids.
    *
    * @return int
    */
   public int calculateTotalHotspotMin() {
      int totalHotspotMin = 0;
      for (int i = 0; i < phones.length; i++) {
         if (phones[i] instanceof Android) {
            totalHotspotMin += ((Android) phones[i]).getHotspotMin();
         }   
      }   
      return totalHotspotMin;
   }

   /**
    * Calculates total iMessage count for iPhones.
    *
    * @return int
    */
   public int calculateTotalIMessages() {
      int totalIMessages = 0;
      for (int i = 0; i < phones.length; i++) {
         if (phones[i] instanceof IPhone) {
            totalIMessages += ((IPhone) phones[i]).getIMessages();
         }   
      }   
      return totalIMessages;
   }

   /**
    * Returns string for summary report.
    *
    * @return String
    */
   public String summary() {
      DecimalFormat dfmt = new DecimalFormat("$#,000.00");
      String summary = "------------------------------"
         + "\nSummary for " + getName()
         + "\n------------------------------"
         + "\nNumber of cell phones: " + phones.length
         + "\nTexts: " + calculateTotalTexts()
         + "\nTalk Minutes: " + calculateTotalMinutes()
         + "\nData: " + calculateTotalData()
         + "\nHotspot Minutes: " + calculateTotalHotspotMin()
         + "\niMessages: " + calculateTotalIMessages()
         + "\nBill Total: " + dfmt.format(calculateTotalBill());
      return summary;
   }

   /**
    * Returns string for different rates.
    *
    * @return String
    */
   public String rates() {
      DecimalFormat dfmt = new DecimalFormat("0.00");
      String rates = "\n------------------------------\n"
         + "Rates for " + getName()
         + "\n------------------------------\n"
         + "FlipPhone Talk Rate: $" + dfmt.format(FlipPhone.TALK_RATE)
         + "   Text Rate: $" + dfmt.format(FlipPhone.TEXT_RATE)
         + "\nSmartPhone Talk Rate: $" + dfmt.format(SmartPhone.TALK_RATE)
         + "   Text Rate: $" + dfmt.format(SmartPhone.TEXT_RATE)
         + "   Max Talk Time: " + SmartPhone.MAX_TALK_TIME
         + "\n   iPhone iMessage Rate: $" + dfmt.format(IPhone.IMESSAGE_RATE)
         + "\n   Android Hotspot Rate: $" + dfmt.format(Android.HOTSPOT_RATE)
         + "\n";
      return rates;
   }

   /**
    * Returns string of phones sorted by number.
    *
    * @return String
    */
   public String listByNumber() {
      Arrays.sort(phones);
      String listByNumber = "------------------------------"
         + "\nCell Phones by Number"
         + "\n------------------------------\n";
      for (CellPhone phone : phones) {
         listByNumber += "\n" + phone.toString() + "\n";
      }
      return listByNumber;
   }

   /**
    * Returns string of phones sorted by bill.
    *
    * @return String
    */
   public String listByBill() {
      Arrays.sort(phones, new CellPhoneBillComparator());
      String listByBill = "------------------------------"
         + "\nCell Phones by Billing Amount"
         + "\n------------------------------\n";
      for (CellPhone phone : phones) {
         listByBill += "\n" + phone.toString() + "\n";
      }
      return listByBill;
   }

   /**
    * Returns string excluded records.
    *
    * @return String
    */
   public String excludedRecordsList() {
      String excRecList = "------------------------------"
         + "\nExcluded Records"
         + "\n------------------------------\n";
      for (String unrecPhones : excludedRecords) {
         excRecList += "\n" + unrecPhones + "\n";
      }
      return excRecList;
   }
}
1
  • Why not use an ArrayList? Commented Nov 21, 2013 at 3:00

5 Answers 5

1
CellPhone[] newPhones = new CellPhone[phones.length - 1]; 
phones = newPhones;

This line declares a new array, but does not fill any values, they are all null. You need to loop through newPhones and assign all the values.

CellPhone[] newPhones = new CellPhone[phones.length - 1]; 
for (int i = 0; i < newPhones.length; i++) {
  newPhones[i] = phones[i];
}
phones = newPhones;
Sign up to request clarification or add additional context in comments.

Comments

0

Please move phones[phones.length - 1] = null; out of for loop. Then you need some code to copy data between phones and newPhones, move those code to outside of for loop, too.

for (int i = deleteIndex; i < phones.length - 1; i++) {
    phones[i] = phones[i + 1];
    // Move three lines of code
    phones[phones.length - 1] = null; // <= Problem here
    CellPhone[] newPhones = new CellPhone[phones.length - 1];
    // Need some code to copy data
    phones = newPhones;
}

Finally, anyway, you must copy data to the new array, so I think you should copy it from the beginning:

CellPhone[] newPhones = new CellPhone[phones.length - 1];
int oldIndex = 0, newIndex = 0;
while (oldIndex < phones.length) {
    if (oldIndex != deleteIndex) { // Skip copying deleted number
        newPhones[newIndex++] = phones[oldIndex];
    }

    oldIndex++;
}

1 Comment

This was the most accurate answer. Thank you very much
0

The problem should happen at the loop when you tried to set your last element to null when loop and copy:

if (deleteIndex > -1) {
     for (int i = deleteIndex; i < phones.length - 1; i++) {
        phones[i] = phones[i + 1];
        phones[phones.length - 1] = null; //<====== This line
        CellPhone[] newPhones = new CellPhone[phones.length - 1];
        phones = newPhones;
     }
     return true;
  }
  else {
     return false;
  }

At any loop time, the 1st row copys the next element to the current index, but it would be a problem that every time you set the last element to null, because that will happen before you can copy it into the previous element of the array.

I would suggest to change to:

    if (deleteIndex > -1) {
         for (int i = deleteIndex; i < phones.length - 1; i++) {
            phones[i] = phones[i + 1];
         }

         CellPhone[] newPhones = new CellPhone[phones.length - 1];
         System.arraycopy(phones, 0, newPhones, 0, phones.length - 1);
         return true;
      }
      else {
         return false;
      }

Comments

0
if (deleteIndex > -1) {
  CellPhone[] tmp = new CellPhone[phones.length - 1]; // smaller array

   //copy everything before deleteIndex
  System.arraycopy(phones, 0, tmp, 0, deleteIndex);

   //copy everything after deleteIndex
  if (deleteIndex < phones.length - 1)
  {
     System.arraycopy(phones, deleteIndex+1, tmp, deleteIndex,
                      phones.length - 1 - deleteIndex);
  }

  phones=tmp; // use new smaller array
}

Comments

0

Arrays are a headache, i prefer ArrayLists; try this

public boolean deletePhone(String numberIn) {
    boolean phoneExists = false;
    List<String> phoneList = new ArrayList<>();
    for (int i = 0; i < phones.length; i++) {
        if (!numberIn.equals(phones[i].getNumber())) {
            phoneList.add(phones[i].getNumber());
            phoneExists = true;
        }
    }
    phones = phoneList.toArray(new String[phoneList.size()]);
    return phoneExists;
}

If you don't like lists, here's a solution using just arrays:

public boolean deletePhone(String numberIn) {
    boolean phoneExists = false;
    String[] newPhones;
    int newLength = phones.length;

    for (int i = 0; i < phones.length; i++) {
        if (numberIn.equals(phones[i].getPhones())) {
            phones[i] = null;
            newLength--;
            phoneExists = true;
        }
    }

    newPhones = new CellPhone[newLength];
    for (int i = 0, j = 0; i < phones.length; i++) {
        if (phones[i] != null) {
            newPhones[j++] = phones[i];
        }
    }

    phones = newPhones;
    return phoneExists;
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.