This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 2 years ago.
I'm trying to code a project that deals with a dumb downed version of an excel sheet. One of the commands I am allowing from the user is assigning a value into specific cells in the format of = . i.e A3 = 72.3%. Once it assigns the value to the cell, it then prints out the entire spreadsheet with the updated changes.
I created different classes to represent different types of cells.
Value Cell is a cell that will contain any double value, Percent Cell is a cell that will contain any percentage value, Text Cell is a cell that will contain text.
While I was trying to run my program, I tried assigning a percentage value to a cell. (A2 = 7.25%)
When the program prints out the entire spreadsheet with the newly assigned A2 percentage cell, it's supposed to truncate the decimal from the percentage and just display 7%.
However, I keep getting this error message
Exception in thread "main" java.lang.NullPointerException
at PercentCell.abbreviatedCellText(PercentCell.java:18)
at Spreadsheet.getGridText(Spreadsheet.java:127)
at Spreadsheet.processCommand(Spreadsheet.java:73)
at TextExcel.main(TextExcel.java:20)
This is part of my code that assigns specific cell types depending on what the user inputs:
//assignment command
} else if (command.contains("=")) {
int eqIndex = command.indexOf("=");
if (!command.substring(eqIndex - 1, eqIndex).equals(" ") || !command.substring(eqIndex + 1, eqIndex + 2).equals(" ")) {
return "Formatting Error: please include a space before and after the ="; //error message
} else {
String[] input = command.split(" ", 3);
SpreadsheetLocation cell = new SpreadsheetLocation(input[0]);
int col = cell.getCol();
int row = cell.getRow();
if (col > COLUMNS || row > ROWS) {
return "Error: cell outside of spreadsheet"; //error message
}
//assigning a textcell
if (input[2].contains("\"")) {
String inputValue = input[2].substring(1, input[2].length() - 1);
TextCell textCell = new TextCell(inputValue);
spreadsheet[row][col] = textCell;
//assigning a percent cell
} else if (input[2].contains("%")) {
PercentCell percentCell = new PercentCell(input[2]);
spreadsheet[row][col] = percentCell;
The percent cell extends super class, Real Cell:
public class RealCell implements Cell {
private String fullText;
public RealCell(String input) {
this.fullText = input;
}
//method that returns the display of the abbreviated cell
public String abbreviatedCellText() {
if (fullText.length() > 10) {
return fullText.substring(0, CELLWIDTH);
} else {
String output = fullText;
while(output.length() < CELLWIDTH) {
output += " ";
}
return output;
}
}
//method that returns the actual value in a real cell
public String fullCellText() {
return fullText;
}
//method that parses the user input into a double
public double getDoubleValue() {
return Double.parseDouble(fullText);
}
}
Here is now the problem part of my code, the Percent Cell class:
public class PercentCell extends RealCell {
private String fullText;
public PercentCell(String input) {
super(input);
}
//method that returns the display of the abbreviated cell, truncating the decimal
public String abbreviatedCellText() {
String value = fullText;
if (value.contains(".")) {
int decIndex = fullText.indexOf(".");
value = value.substring(0, decIndex) + "%";
}
if (value.length() > 10) {
return value.substring(0, CELLWIDTH);
} else {
String output = value;
while(output.length() < CELLWIDTH) {
output += " ";
}
return output;
}
}
//method that parses the user input into a double and returns the percent value into a decimal
public double getDoubleValue() {
double decimal = Double.parseDouble(fullText.substring(0, fullText.length() - 1));
return decimal/100;
}
}
How could I fix this error?
If any clarifications regarding my code are needed (because this is not my entire project) please let me know!
public class PercentCell extends RealCell {
public PercentCell(String input) {
super(input);
}
//method that returns the display of the abbreviated cell, truncating the decimal
public String abbreviatedCellText() {
String value = super.fullCellText();
if (value.contains(".")) {
int decIndex = value.indexOf(".");
value = value.substring(0, decIndex) + "%";
}
if (value.length() > 10) {
return value.substring(0, CELLWIDTH);
} else {
String output = value;
while(output.length() < CELLWIDTH) {
output += " ";
}
return output;
}
}
You used fullText field without giving value and fullText value was always null
I think that was the problem, but let me know please if it helps!
Related
I have an array of y values that I am displaying over the dates of a month. To simplify, for the first week of April, I would have the values {0,200,0,0,500,0,100} over the x values {1,2,3,4,5,6,7}. I am able to display them as a bar chart using MPAndroidChart. I am also able to hide and display the values over each bar using
barChart.getData().setDrawValues(true); //or false when I want to hide
However, I want to display only the number that are non-zero, how would I be able to do so? Any pointers would be appreciated!
I tried creating my formatter the following way:
public class MyYAxisValueFormatter implements IAxisValueFormatter {
private DecimalFormat mFormat;
public MyYAxisValueFormatter() {
// format values to 1 decimal digit
mFormat = new DecimalFormat("###,###,##0.0");
}
#Override
public String getFormattedValue(float value, AxisBase axis) {
String val = "";
if(value != 0)
val = String.valueOf(value);
return mFormat.format(value) + " $";
}
}
and called it using this in my main function:
YAxis yAxis = barChart.getAxisLeft();
yAxis.setValueFormatter(new MyYAxisValueFormatter());
However the values of zero are still displayed.
Try making your own IValueFormatter Interface
public class MyYAxisValueFormatter implements IValueFormatter {
private DecimalFormat mFormat;
public MyYAxisValueFormatter() {
// format values to 1 decimal digit
mFormat = new DecimalFormat("###,###,##0.0");
}
#Override
public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) {
// "value" represents the position of the label on the axis (x or y)
if(value > 0) {
return mFormat.format(value);
} else {
return "";
}
}
}
try setting value formatter to your barchart.
bar.setValueFormatter(new MyYAxisValueFormatter ());
try this:
private class MyValueFormatter implements ValueFormatter {
#Override
public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) {
// write your logic here
if(value > 0)
return value+"";
else
return "";
}
}
OR
try this likn it helps you
https://github.com/PhilJay/MPAndroidChart/issues/2402
I am following a tutorial which partially deals with printing the elements of ArrayLists. The program runs exactly as I'd expect when dealing with small lists. However the string formatting ( I believe ) causes some strange results when larger numbers are input.
My code is as follows:
public class Theatre {
private final String theatreName;
public List<Seat> seats = new ArrayList<>();
public Theatre(String theatreName, int numRows, int seatsPerRow) {
this.theatreName = theatreName;
int lastRow = 'A' + (numRows -1);
for (char row = 'A'; row <= lastRow; row++) {
for(int seatNum = 1; seatNum <= seatsPerRow; seatNum++) {
Seat seat = new Seat(row + String.format("%02d", seatNum));
seats.add(seat);
}
}
}
public String getTheatreName() {
return theatreName;
}
public boolean reserveSeat(String seatNumber) {
int low = 0;
int high = seats.size()-1;
while(low <= high) {
System.out.print(".");
int mid = (low + high) /2;
Seat midVal = seats.get(mid);
int cmp = midVal.getSeatNumber().compareTo(seatNumber);
if(cmp <0) {
low = mid + 1;
} else if(cmp > 0) {
high = mid -1;
} else {
return seats.get(mid).reserve();
}
}
System.out.println("There is no seat " + seatNumber);
return false;
}
// for testing
public void getSeats() {
for(Seat seat : seats) {
System.out.println(seat.getSeatNumber());
}
}
public class Seat implements Comparable<Seat > {
private final String seatNumber;
private boolean reserved = false;
public Seat(String seatNumber) {
this.seatNumber = seatNumber;
}
public boolean reserve() {
if(!this.reserved) {
this.reserved = true;
System.out.println("Seat " + seatNumber + " reserved");
return true;
} else {
return false;
}
}
public boolean cancel() {
if(this.reserved) {
this.reserved = false;
System.out.println("Reservation of seat " + seatNumber + " cancelled");
return true;
} else {
return false;
}
}
public String getSeatNumber() {
return seatNumber;
}
#Override
public int compareTo(Seat seat) {
// returns integer greater than 0 if greater than, less than if less than, 0 if equal
return this.seatNumber.compareTo(seat.getSeatNumber());
}
}
With a Main method class:
public static void main(String[] args) {
Theatre theatre = new Theatre("Olympian", 800, 12);
List<Theatre.Seat> seatCopy = new ArrayList<>(theatre.seats); // shallow copy, contains references to all
// elements of both lists, original and copy
printList(seatCopy);
seatCopy.get(1).reserve();
if (theatre.reserveSeat("A02")) {
System.out.println("Please pay for A02");
} else {
System.out.println("seat already reserved");
}
// see that they are clearly two separate array lists
Collections.reverse(seatCopy);
System.out.println("Printing seat copy");
printList(seatCopy);
System.out.println("Printing theatre.seats");
printList(theatre.seats);
System.out.println("Shuffling seatCopy");
Collections.shuffle(seatCopy);
printList(seatCopy);
}
public static void printList(List<Theatre.Seat> list) {
for (Theatre.Seat seat : list) {
System.out.print(" " + seat.getSeatNumber());
}
System.out.println();
System.out.println("===============================");
}
}
The output (I only quote enough to see ) is:
12 ͠11 ͠10 ͠09 ͠08 ͠07 ͠06 ͠05 ͠04 ͠03 ͠02 ͠01 ͟12 ͟
===============================
Printing theatre.seats
A01 A02 A03 A04 A05 A06 A07 A08 A09 A10
===============================
===============================
Shuffling seatCopy
V07 Ý11 11 ű05 Ú02 ̄06 ̓01 ŕ12 ȣ03 Ǔ05 S07
I am aware that I run out of alphabetical characters and that the formatting in this line:
Seat seat = new Seat(row + String.format("%02d", seatNum));
is intended only to deal with seats of the format "X##".
What I want to understand is specificallty why the odd characters appear ( the "~" and "'", etc. ). Obviously, the formatting is inappropriate. But why does it produce specifically this output?
Thank you for your help,
Marc
You said it yourself. You're running out of alphabetical characters. In fact, you're running out of ASCII characters altogether. From this line:
for (char row = 'A'; row <= lastRow; row++)
What you are doing is starting the row letters from 'A' and continuing across the Unicode character set. So, with more than 26 rows, you start getting symbols like ~, and with enough rows, you leave ASCII altogether and start getting weird row letters like Ý.
If you don't want this to happen, you'll need to ditch the for loop and come up with an entirely different (and more complex) way of assigning row labels.
I am new in java and I have to use the code below but the code it does work because I have to specifying the path for input data and output data. The code is got it from the internet. please help me
class Svm_scale
{
private BufferedReader rewind(BufferedReader fp, String filename) throws IOException
{
fp.close();
return new BufferedReader(new FileReader(filename));
}
private void output_target(double value)
{
LnCount++;
if(y_scaling)
{
if(value == y_min)
value = y_lower;
else if(value == y_max)
value = y_upper;
else
value = y_lower + (y_upper-y_lower) *
(value-y_min) / (y_max-y_min);
}
formatterscaled.format(value+" ");
System.out.println(" Line Number "+LnCount + " ");
}
private void output(int index, double value)
{
count++;
double Threshold1=0,Threshold2=0;
Threshold1= Avg[index]+(STDV[index]/2);
Threshold2= Avg[index]-(STDV[index]/2);
if(value > Threshold1 )
value = 2;
else if(value < Threshold2 )
value = -2;
else
value = 0;
formatterscaled.format( formatter.format(value) + ",");
// System.out.println(" Counter "+count);
// }
}
String save_filename =Save1; // = null?
String restore_filename =null;
String scale_data_filename =Disc; // set this to the path where the output should be stored, e.g. = "C:\\temp\\scaled";
String data_filename =Libsvm; // set this to the path where the input can be get, e.g. = "C:\\temp\\inputdata"
These are the Strings you need to adapt in order that the program can read and write. Save1, Disc, Libsvm are not in your code, so it can only be guessed where they come from.
data_filename and scale_data_filename are required. save_filename seems to be optional and may be set to null.
I am reading a text file abc .txt which is tab delimited as shown below
gfh hgh thf
--- --- ---
fgh sji irj
rhf dhh fhf
kji idj ddt
and I am able to read it successfully (for all the columns in the table I have developed a separate pojo along with getters and setters), the advantage is that I can get the value of complete row through its getters.
Now I have to make sure that no column in the table should be null and if any column value is null, then I should throw a new exception, for example ..
gfh hgh thf
--- --- ---
fgh sji irj //row 1
rhf dhh fhf
kji idj ddt
fgq fio //As seen in this row that second column value is null
Now the approach that I am following is that getting the value row wise in a string as shown below
String n = f.getgfh()+f.gethgh()+f.getthf(); //it will contain the contents of the row 1
make a separate method and will pass this string
private boolean validaterow(String f)
{
}
in this method here I am taking the complete row in a string and inside this method I want to break this string in tokens and then further evaluate those tokens for empty or null , if there are then I will return false
Try this,
private boolean validateRow(String f)
{
if(f.getgfh() != null && !f.getgfh().trim().isEmpty() &&
f.gethgh() != null && !f.gethgh().trim().isEmpty() &&
f.getthf() != null && !f.getthf().trim().isEmpty())
{
return true;
}
else
{
return false;
}
}
You can set a null check like in getters
public String gethgh()
{
return (String) ((null == hgh) ? new UserDefinedException() : hgh);
}
here UserDefinedException must be declared as a class
I consider this should work
Why do you pass it to a method?
Use
String row1,row2,row3;
row1=f.getgfh();
row2=f.gethgh();
row3=f.getthf();
You can check for your condition at the time of concatenation.
if(row1==null)
'throw your message
else
row1=""
if(row2==null)
'throw your message
else
row2=""
if(row3==null)
'throw your message
else
row3=""
At last,
String n = row1+row2+row3;
Look at apache string utils library. It might have what you need
Split each line on tab like string.split("\t") and check each token using isEmpty() method of string class.
use StringIsNullOrEmtpy to check if row is valid for every entry of the row
private boolean ValidateRow()
{
return !(StringIsNullOrEmpty((f.getgfh())) ||
StringIsNullOrEmpty((f.gethgh())) ||
StringIsNullOrEmpty((f.getthf()))
);
}
private bool StringIsNullOrEmtpy(string input)
{
return input.isEmpty() || input == null;
}
Let's assume that you have a method getNextValueAndPosPair() which returns the next value of your tsv (tab separate values) file and the position of the last space found after the value read (i.g. a Tab or a Newline).
Then you can validate your input row by chechking that it contains exactly three distinct values separated by a Tab.
Below the implementation:
// A simple general pair class.
class Pair<A, B> {
Pair(A first, A second) {
this.first = first;
this.second = second;
}
public A first() { return first; }
public A second() { return second; }
private final A first;
private final B second;
}
// Returns true if this rows contains 4 distinct values, false otherwise.
private boolean validaterow(String f) {
int pos = 0;
for (int i = 0; i < 3; i++) {
Pair<String, Integer> valueAndPos = getNextValueAndPosPair(f, pos);
String value = valueAndPos.first();
int pos = valueAndPos.second();
if (value.isEmpty()) {
System.err.println("The " + i + "-th value is null.");
return false;
}
pos += 1;
}
return true;
}
// Returns a Pair holding the next tsv value in the row and the position of the delimiter space
private Pair<String, Integer> getNextValueAndPosPair(String f, int start) {
int length = 0;
for (int i = start; i < f.length && !Character.isSpaceChar(f.charAt(i)); i++) length++;
int end = start + length;
String value = f.substring(start, end);
Pair<String, Integer> valueAndPos = new Pair<>(value, end);
return valueAndPos;
}
I am reading a text file abc .txt which is tab delimited as shown below
gfh hgh thf
--- --- ---
fgh sji irj
rhf dhh fhf
kji idj ddt
and I am able to read it successfully (for all the columns in the table I have developed a separate pojo along with getters and setters), the advantage is that I can get the value of complete row through its getters.
Now I have to make sure that no column in the table should be null and if any column value is null, then I should throw a new exception, for example ..
gfh hgh thf
--- --- ---
fgh sji irj //row 1
rhf dhh fhf
kji idj ddt
fgq fio //As seen in this row that second column value is null
Now the approach that I am following is that getting the value row wise in a string as shown below
String n = f.getgfh()+f.gethgh()+f.getthf(); //it will contain the contents of the row 1
make a separate method and will pass this string
private boolean validaterow(String f)
{
}
in this method here I am taking the complete row in a string and inside this method I want to break this string in tokens and then further evaluate those tokens for empty or null , if there are then I will return false
Try this,
private boolean validateRow(String f)
{
if(f.getgfh() != null && !f.getgfh().trim().isEmpty() &&
f.gethgh() != null && !f.gethgh().trim().isEmpty() &&
f.getthf() != null && !f.getthf().trim().isEmpty())
{
return true;
}
else
{
return false;
}
}
You can set a null check like in getters
public String gethgh()
{
return (String) ((null == hgh) ? new UserDefinedException() : hgh);
}
here UserDefinedException must be declared as a class
I consider this should work
Why do you pass it to a method?
Use
String row1,row2,row3;
row1=f.getgfh();
row2=f.gethgh();
row3=f.getthf();
You can check for your condition at the time of concatenation.
if(row1==null)
'throw your message
else
row1=""
if(row2==null)
'throw your message
else
row2=""
if(row3==null)
'throw your message
else
row3=""
At last,
String n = row1+row2+row3;
Look at apache string utils library. It might have what you need
Split each line on tab like string.split("\t") and check each token using isEmpty() method of string class.
use StringIsNullOrEmtpy to check if row is valid for every entry of the row
private boolean ValidateRow()
{
return !(StringIsNullOrEmpty((f.getgfh())) ||
StringIsNullOrEmpty((f.gethgh())) ||
StringIsNullOrEmpty((f.getthf()))
);
}
private bool StringIsNullOrEmtpy(string input)
{
return input.isEmpty() || input == null;
}
Let's assume that you have a method getNextValueAndPosPair() which returns the next value of your tsv (tab separate values) file and the position of the last space found after the value read (i.g. a Tab or a Newline).
Then you can validate your input row by chechking that it contains exactly three distinct values separated by a Tab.
Below the implementation:
// A simple general pair class.
class Pair<A, B> {
Pair(A first, A second) {
this.first = first;
this.second = second;
}
public A first() { return first; }
public A second() { return second; }
private final A first;
private final B second;
}
// Returns true if this rows contains 4 distinct values, false otherwise.
private boolean validaterow(String f) {
int pos = 0;
for (int i = 0; i < 3; i++) {
Pair<String, Integer> valueAndPos = getNextValueAndPosPair(f, pos);
String value = valueAndPos.first();
int pos = valueAndPos.second();
if (value.isEmpty()) {
System.err.println("The " + i + "-th value is null.");
return false;
}
pos += 1;
}
return true;
}
// Returns a Pair holding the next tsv value in the row and the position of the delimiter space
private Pair<String, Integer> getNextValueAndPosPair(String f, int start) {
int length = 0;
for (int i = start; i < f.length && !Character.isSpaceChar(f.charAt(i)); i++) length++;
int end = start + length;
String value = f.substring(start, end);
Pair<String, Integer> valueAndPos = new Pair<>(value, end);
return valueAndPos;
}