Scanner hasNext() doesn't match correctly inside if statements - java.util.scanner

I have created the following code through making a while loop. I cannot tell why the loop is set to look at 17 lines and not 15 lines.
while (scan.hasNext())
{
selectedUserName.setText(scan.next());
if(scan.nextLine().toString() == "Male")
{
male = new JRadioButton("Male", true);
}
else if(scan.nextLine().toString() == "Female")
{
female = new JRadioButton("Female", true);
}
selectedGenderText.setText(scan.nextLine());
if(scan.next().toString() == "Warrior")
{
userClassBox.setSelectedItem(classes[0]);
}
else if(scan.next().toString() == "Barbarian")
{
userClassBox.setSelectedItem(classes[1]);
}
else if(scan.next().toString() == "Mage")
{
userClassBox.setSelectedItem(classes[2]);
}
else if(scan.next().toString() == "Thief")
{
userClassBox.setSelectedItem(classes[3]);
}
selectedClassText.setText(scan.nextLine());
pointsText.setText(scan.nextLine());
pointsSlider.setValue(Integer.parseInt(scan.nextLine()));
intelligenceText.setText(scan.nextLine());
intelligenceSlider.setValue(Integer.parseInt(scan.nextLine()));
dexterityText.setText(scan.nextLine());
dexteritySlider.setValue(Integer.parseInt(scan.nextLine()));
strengthText.setText(scan.nextLine());
strengthSlider.setValue(Integer.parseInt(scan.nextLine()));
wisdomText.setText(scan.nextLine());
wisdomSlider.setValue(Integer.parseInt(scan.nextLine()));
}
My input file has 15 lines to match the code above,
Warrior
Male
Male
Warrior
Warrior
0
0
10
10
30
30
60
60
0
0
Do the if/else statements reference two new lines? When I run the program it gets stuck on the following line-
Exception in thread "AWT-EventQueue-0" java.util.NoSuchElementException: No line found
at java.util.Scanner.nextLine(Unknown Source)
at CharacterCreation$OpenCharListener.actionPerformed(CharacterCreation.java:450)
at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
This reference the last two lines starting at -
wisdomText.setText(scan.nextLine());
wisdomSlider.setValue(Integer.parseInt(scan.nextLine()));
Why does the .nextLine() functionality look at 17 lines instead of 15?

Note that Scanner.nextLine() consumes data from the scanner. So in this example:
if(scan.nextLine().toString() == "Male")
{
male = new JRadioButton("Male", true);
}
else if(scan.nextLine().toString() == "Female")
{
female = new JRadioButton("Female", true);
}
on the first if statement, you'll consume data from the scanner, and if the conditional is false, you'll then consume whatever follows it within the else-if statement.
You probably just want to do String input = scan.nextLine(); and then compare against that stored string.

Related

NumberFormatException in Kotlin

I was solving a question on CodeChef. A specific line to take input like:
10 232 4543
I was willing to store it in variables and then perform the calculation.
The following is the line of code I am using to achieve this.
val (d,l,r) = readLine()!!.split(" ").map{ it -> it.toInt()}
This line worked for previous question but is not working for the current question. I am inserting my code and the link to the question.
fun main(){
var t = readLine()!!.toInt()
for(i in 0 until t){
val (d,l,r) = readLine()!!.split(" ").map{ it -> it.toInt()}
if(d<l){
println("Too Early")
}
else if(d>r){
println("Too Late")
}
else{
println("Take second dose now")
}
}
}
This is the link to the question: https://www.codechef.com/LP1TO201/problems/VDATES
The following is the error I am receiving.
Exception in thread "main" java.lang.NumberFormatException: For input string: ""
at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:67)
at java.base/java.lang.Integer.parseInt(Integer.java:678)
at java.base/java.lang.Integer.parseInt(Integer.java:786)
at ProgKt.main(prog.kt:4)
at ProgKt.main(prog.kt)
An empty string is not a number. There are two easy ways to solve this:
Filter empty strings using isEmpty():
val (d,l,r) = readLine()!!.split(" ").filterNot { it.isEmpty() }.map { it -> it.toInt() }
Use toIntOrNull() and only take non-null elements:
val (d,l,r) = readLine()!!.split(" ").mapNotNull { it -> it.toIntOrNull() }

Transform char array into String

I have a function that returns a char array and I want that turned into a String so I can better process it (compare to other stored data). I am using this simple for that should work, but it doesn't for some reason (bufferPos is the length of the array, buffer is the array and item is an empty String):
for(int k=0; k<bufferPos; k++){
item += buffer[k];
}
The buffer has the right values and so does bufferPos, but when I try to convert, for example 544900010837154, it only holds 54. If I add Serial.prints to the for like this:
for(int k=0; k<bufferPos; k++){
Serial.print(buffer[k]);
Serial.print("\t");
Serial.println(item);
item += buffer[k];
}
the output is this:
5
4 5
4 54
9 54
0 54
0 54
0 54
1 54
0 54
8 54
3 54
7 54
1 54
What am I missing? It feels like such a simple task and I fail to see the solution...
If you have the char array null terminated, you can assign the char array to the string:
char[] chArray = "some characters";
String String(chArray);
As for your loop code, it looks right, but I will try on my controller to see if I get the same problem.
Three years later, I ran into the same problem. Here's my solution, everybody feel free to cut-n-paste. The simplest things keep us up all night! Running on an ATMega, and Adafruit Feather M0:
void setup() {
// turn on Serial so we can see...
Serial.begin(9600);
// the culprit:
uint8_t my_str[6]; // an array big enough for a 5 character string
// give it something so we can see what it's doing
my_str[0] = 'H';
my_str[1] = 'e';
my_str[2] = 'l';
my_str[3] = 'l';
my_str[4] = 'o';
my_str[5] = 0; // be sure to set the null terminator!!!
// can we see it?
Serial.println((char*)my_str);
// can we do logical operations with it as-is?
Serial.println((char*)my_str == 'Hello');
// okay, it can't; wrong data type (and no terminator!), so let's do this:
String str((char*)my_str);
// can we see it now?
Serial.println(str);
// make comparisons
Serial.println(str == 'Hello');
// one more time just because
Serial.println(str == "Hello");
// one last thing...!
Serial.println(sizeof(str));
}
void loop() {
// nothing
}
And we get:
Hello // as expected
0 // no surprise; wrong data type and no terminator in comparison value
Hello // also, as expected
1 // YAY!
1 // YAY!
6 // as expected
Hope this helps someone!
Visit https://www.arduino.cc/en/Reference/StringConstructor to solve the problem easily.
This worked for me:
char yyy[6];
String xxx;
yyy[0]='h';
yyy[1]='e';
yyy[2]='l';
yyy[3]='l';
yyy[4]='o';
yyy[5]='\0';
xxx=String(yyy);
May you should try creating a temp string object and then add to existing item string.
Something like this.
for(int k=0; k<bufferPos; k++){
item += String(buffer[k]);
}
I have search it again and search this question in baidu.
Then I find 2 ways:
1,
char ch[]={'a','b','c','d','e','f','g','\0'};
string s=ch;
cout<<s;
Be aware to that '\0' is necessary for char array ch.
2,
#include<iostream>
#include<string>
#include<strstream>
using namespace std;
int main()
{
char ch[]={'a','b','g','e','d','\0'};
strstream s;
s<<ch;
string str1;
s>>str1;
cout<<str1<<endl;
return 0;
}
In this way, you also need to add the '\0' at the end of char array.
Also, strstream.h file will be abandoned and be replaced by stringstream

Two digit numbers [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
I need a program that takes a two digit number such as "22" and returns "Twenty Two". I have the following started for the main method but have nothing for the string method
static string TwoDigit(int n)
{
}
static void Main(string[] args)
{
for (int i = 0; i <= 19; i++)
Console.WriteLine("{0}: {1}", i, TwoDigit(i));
for (int i = 20; i <= 110; i += 7)
Console.WriteLine("{0}: {1}", i, TwoDigit(i));
}
I don't know of an existing program but it would be easy to write the function.
I would convert the int to a string then do a switch statement on each character.
The first switch would handle the "Twenty", "Thirty", etc.
The second switch would handle one, two, three, etc.
You will need to have a special case for the teens that just spits out the word for each.
Just take time in your reseach. If you don't know how to do it, I would advise to parse the int number by one number and then format the text via case.
switch (int)
case 1:
cout << "one";
switch (int)
case 2:
cout << "two";
It would be easiest to just evaluate both digits separately and match them up to string values stored in two arrays.
So for example, you might have these two arrays...
tens[0] = ""
tens[1] = ""
tens[2] = "Twenty"
tens[3] = "Thirty"
tens[4] = "Forty"
tens[5] = "Fifty"
tens[6] = "Sixty"
etc...
ones[0] = ""
ones[1] = "One"
ones[2] = "Two"
ones[3] = "Three"
etc...
And then if the number is >= 20, you can simply take the first digit and use it as your index for the tens array, and your second digit and use it as your index for your ones array. If the number is between 10 and 19, you'll need some special logic to handle it.
Initialize this function
function Ones_String(number1) {
if (number1 == 1) {
string1 = "One";
} elseif (number2 == 9) {
string1 = "Nine";
} elseif (number2 == 10) {
string1 = "Ten";
} elseif (number2 == 0) {
string1 = "Zero";
} else {
string1 = ""; // empty value
}
return string1;
}
function Tens_String(number2) {
if (number2 == 2) {
string2 = "Twenty";
} elseif (number2 == 3) {
string2 = "Thirty";
} elseif (number2 == 9) {
string2 = "Ninety";
} else {
string2 = ""; // emtpy value
}
return string2;
}
function teens_string(number3) {
if (number3 == 11) {
string3 = "Eleven";
} elseif (number3 == 12) {
string3 = "Tweleve";
} else {
string3 = "Nineteen";
}
return string3;
}
If given number < 11 then call Ones_string()
If it is number >= 11 then do below logic
First : get the seconds digit value and call Tens_String();
Second : get the first digit vallue and call Ones_string();
And this algorithm applies till 99 .. Last used in 2006 at College on C++..
Whatever i mentioned is an algorithm / logic to detect.. not the perfect code

exception in thread main java.lang.StringIndexOutOfBoundsException: String index out of range: 6

so i am trying to wright a program to Print a word with all of the vowels replaced with $.
in java.
i keep getting this error exception in thread main java.lang.StringIndexOutOfBoundsException: String index out of range: 6 when i run it, it compiles fine.
here's the code.
import java.util.*;
public class SummerFour
{
public static void main(String[] args)
{
Scanner keyboard = new Scanner(System.in);
int cnt = 0;
String word;
String output = "";
char letter = 'x';
System.out.print("enter word to test: ");
word = keyboard.nextLine();
do {
cnt++;
letter = word.charAt(cnt - 1);
if (letter == 'a' || letter == 'i' || letter == 'e' || letter == 'u' || letter == 'o')
{
letter = '$';
}
}
while (cnt <= word.length());
System.out.println(word);
}
}
Your do...while loop has an off-by-one error. You check to see if cnt is less than or equal to the size of the string, then increment it by one and take that value - 1 to use as the index for String.charAt(). This is problematic because Strings are indexed starting at 0, so at the end of a String, you'll always go one too far.
Think about this example:
tacos
This is a five-letter word. When cnt = 5, you'll go back through the loop one more time (since 5 is less than or equal to 5) and increment cnt to 6. Then you call String.charAt() with a value of 5 (6 -1), but the range of tacos is only 0-4 (0 = t, 1 = a, 2 = c, 3 = o, 4 = s) and thus 5 is out of range. You can make your do...while loop work properly and look less confusing by doing something like this:
do
{
letter = word.charAt(cnt);
if (letter=='a'||letter=='i'||letter=='e'||letter=='u'||letter=='o')
{
letter='$';
}
cnt++;
} while(cnt<word.length());
Of course, the code still doesn't do what you want it to, but you no longer get the original error. Since this looks like it might be homework, I'll let you continue to work through it.

Is There a Groovier Way To Add Dashes to a String?

I have the following code, which works, but I'm wondering if there is a "groovier" way of doing this:
/**
* 10 digit - #-######-##-#
* 13 digit - ###-#-######-##-#
* */
private formatISBN(String isbn) {
if (isbn?.length() == 10) {
def part1 = isbn.substring(0, 1)
def part2 = isbn.substring(1, 7)
def part3 = isbn.substring(7, 9)
def part4 = isbn.substring(9, 10)
return "${part1}-${part2}-${part3}-${part4}"
} else if (isbn?.length() == 13) {
def part1 = isbn.substring(0, 3)
def part2 = isbn.substring(3, 4)
def part3 = isbn.substring(4, 10)
def part4 = isbn.substring(10, 12)
def part5 = isbn.substring(12, 13)
return "${part1}-${part2}-${part3}-${part4}-${part5}"
} else {
return isbn
}
}
You could first use the [] string operator to get the substrings instead of substring and drop the intermediate variables. For example in the case for length == 10:
"${isbn[0]}-${isbn[1..6]}-${isbn[7..8]}-${isbn[9]}"
Now, there is a bit of repetition there. You can get instead first get all the isbn segments and then .join them with '-':
[isbn[0], isbn[1..6], isbn[7..8], isbn[9]].join('-')
And, even further, instead of referencing isbn every time, you can make a list of the ranges you want to get and then get them all the same time using collect:
[0, 1..6, 7..8, 9].collect { isbn[it] }.join('-')
If you're going for code golfing, you can also do:
('-'+isbn)[1, 0, 2..7, 0, 8..9, 0, 10]
I'll leave it to you to figure out how that works, but i guess it's probably not a good idea to leave that on production code, unless you want to surprise future maintainers hehe.
Also, notice that the format when length == 13 is the same as for length == 10 but with a different prefix, you can then reuse the same function in that case. The whole function (with a couple of tests) would be:
/**
* 10 digit - #-######-##-#
* 13 digit - ###-#-######-##-#
**/
def formatIsbn(isbn) {
switch (isbn?.length()) {
case 10: return [0, 1..6, 7..8, 9].collect { isbn[it] }.join('-')
case 13: return isbn.take(3) + '-' + formatIsbn(isbn.drop(3))
default: return isbn
}
}
assert formatIsbn('abcdefghij') == 'a-bcdefg-hi-j'
assert formatIsbn('abcdefghijklm') == 'abc-d-efghij-kl-m'
Now, i think there are some bad smells in that code. Can isbn be null? At least to me, this doesn't look like a function that needs to bother about the nullity of its argument, or at least that's not clear by reading its name (it should be called something like formatIsbnOrNull instead if both ISBN strings and null values are accepted). If null values are not valid, then let it blow up with a NullPointerException when accessing isbn.length() so the caller know they have passed a wrong argument, instead of silently returning the same null.
The same goes for the return ISBN at the end. Is it expected for that function to receive a string that's neither 10 nor 13 characters long? If not, better throw new IllegalArgumentException() and let the caller know they have called it wrongly.
Finally, i'm not sure if this is the most "readable" solution. Another possible solution is having a string for the format, like '###-#-######-##-#' and then replace the #s by the isbn characters. I think it might be more self-documenting:
def formatIsbn(isbn) {
def format = [
10: '#-######-##-#',
13: '###-#-######-##-#'
][isbn.length()]
def n = 0
format.replaceAll(/#/) { isbn[n++] }
}
Consider adding the method to the String class, as shown here. Note that this answer is a spin on a clever suggestion in epidemian's answer (re: collect).
Note:
This code augments String with asIsbn().
The range [0..2] does not need the call to asIsbn(), but the symmetry of using collect twice is irresistable.
Groovy returns the last expression in if/else, so 'return' is not necessary
/**
* 10 digit - #-######-##-#
* 13 digit - ###-#-######-##-#
**/
String.metaClass.asIsbn = { ->
if (delegate.length() == 10) {
[0, 1..6, 7..8, 9].collect { delegate[it] }.join('-')
} else if (delegate.length() == 13) {
[0..2, 3..12].collect { delegate[it].asIsbn() }.join('-')
} else {
delegate
}
}
assert "abcdefghij".asIsbn() == 'a-bcdefg-hi-j'
assert "abcdefghijklm".asIsbn() == 'abc-d-efghij-kl-m'
assert "def".asIsbn() == "def"
String s = null
assert s?.asIsbn() == null
I would try using Regex... I think it's pretty much readable if you know how to use regex, and it's javascript inspired syntax in groovy is pretty cool also.
One more thing: it's pretty clear, looking at the capture groups, what your string looks like for the desired formatting.
private formatISBN(String isbn) {
if (isbn?.length() == 10) {
m = isbn =~ /(\d{1})(\d{6})(\d{2})(\d{1})/
return "${m[0][1]}-${m[0][2]}-${m[0][3]}-${m[0][4]}"
} else if (isbn?.length() == 13) {
m = isbn =~ /(\d{3})(\d{1})(\d{6})(\d{2})(\d{1})/
return "${m[0][1]}-${m[0][2]}-${m[0][3]}-${m[0][4]}-${m[0][5]}"
} else {
return isbn
}
}
Btw, #epidemian suggestion using backreferences is great! I think the code would look like:
private formatISBN(String isbn) {
if (isbn?.length() == 10) {
return isbn.replaceAll(/(\d{1})(\d{6})(\d{2})(\d{1})/, '$1-$2-$3-$4')
} else if (isbn?.length() == 13) {
return isbn.replaceAll(/(\d{3})(\d{1})(\d{6})(\d{2})(\d{1})/, '$1-$2-$3-$4-$5')
} else {
return isbn
}
}
Dunno if I like this any better. I'd make the position map a static final, too.
private isbnify(String isbn) {
def dashesAt = [ 10: [[0,1], [1,7], [7,9], [9,10]],
13: [[0,3], [3,4], [4,10], [10,12], [12,13]]]
def dashes = dashesAt[isbn?.length()]
(dashes == null) ? isbn
: dashes.collect { isbn.substring(*it) }.join('-')
}
Ranges make for a bit less clutter, IMO:
private isbnify3(String isbn) {
def dashesAt = [ 10: [0, 1..6, 7..8, 9],
13: [0..2, 3, 4..9, 10..11, 12]]
def dashes = dashesAt[isbn?.length()]
dashes == null ? isbn : dashes.collect { isbn[it] }.join("-")
}
With an inject-with-two-accumulators it should be easy to do a list-of-dash-positions version, too.
This should be a comment to #everton, but I don't have the 50 reputation needed to do that yet. So this answer is really just a suggested variation on #everton's answer.
One less regex by making the first 3 digits optional. The downside is having to remove a leading '-' if the ISBN is 10 characters. (I also prefer \d over \d{1}.)
private formatISBN(String isbn) {
String result = isbn.replaceAll(/^(\d{3})?(\d)(\d{6})(\d{2})(\d)$/,
'$1-$2-$3-$4-$5')
if (result) {
return result.startsWith('-') ? result[1..-1] : result
} else {
return isbn // return value unchanged, pattern didn't match
}
}
println formatISBN('1234567890')
println formatISBN('9991234567890')
println formatISBN('123456789') // test an ISBN that's too short
println formatISBN('12345678901234') // test an ISBN that's too long

Resources