Hello I'm a beginning programming Student and I am practicing using loops to validate input. Unfortunately, the loop works but skips the inner loop entirely... I get now error message or prompt...
Here is my code: [I BORROWED IT FROM AN ANSWER ON THIS SITE ABOUT VALIDATING INPUT SO I COULD TEST IT.]
import java.util.Scanner;
public class ValidationTest
{
public static void main(String[] args)
{
Scanner sc = new Scanner(System.in);
int number;
do {
System.out.println("Please enter a positive number!");
while (!sc.hasNextInt())
{
System.out.println("That's not a number!");
sc.next(); // this is important!
}
number = sc.nextInt();
} while (number <= 0);
System.out.println("Thank you! Got " + number);
}
}
The inner loop :
while (!sc.hasNextInt())
{
System.out.println("That's not a number!");
sc.next(); // this is important!
}
number = sc.nextInt();
only check if your input is not a number, if you input -123, the function !sc.hasNextInt() is false so it'll skip the loop, if you want to check the number is negative, add this check after the assign number value:
if(number <= 0 ){
System.out.println("The number is negative!");
}
You don't have to make another loop for checking the number is negative or not because of the first loop had it, and do...while loop will make sure you have to run the loop at least one time
The while loop will be skipped if the condition (in parentheses after while) is false when the while loop is first executed.
You can use a debugger to step through the code to see what is going on.
If you do not know how to use a debugger, stop everything you are doing and do some Google searches or whatever you need to do to find out how to use one.
your int number is NaN (not a number). Try setting it to -1, so you can enter the first loop.
In second loop sc didn't ever scan for input it's only initialized.
Related
I am fairly new to developing smartcontracts and have run into an issue while testing. My intention is to ensure the smartcontract cannot mint more than 13 ERC721 tokens. My understanding is that a require function can have a second string argument that will revert a string as an error if the require condition is not met. Is this correct?
The following is my smart contract code:
contract TheCondemned_Episode is ERC721Enumerable {
string[] public episodes;
constructor() ERC721("TheCondemned_e1", "TCe1") public {
}
function mint(string memory _episode) public {
require(episodes.length <= 13, "Cannot make more than 13 episodes");
episodes.push(_episode);
uint _id= episodes.length;
_mint(msg.sender, _id);
}
}
And the test I am running is as follows:
it('Cannot create more than 13 episodes', async() => {
for(var i=0; i===13; i++){
var episode= `Episode ${i}`
await contract.mint(episode)
}
try {
await contract.mint('Episode 14');
assert(true);
}
catch (err) {
return;
}
assert(false, "The contract did not throw.");
The test fails and returns "The contract did not throw". What is the best practice in regards to catching a revert string from a failed require condition when testing?
My understanding is that a require function can have a second string argument that will revert a string as an error if the require condition is not met. Is this correct?
That's correct. Here's an example of an always failing require() condition that throws an exception with the error message.
require(false, 'Error message');
However, you have a logical error in the Solidity require() condition, as well as in the JS test snippet.
First, let's uncover the Solidity code. For simplicity, let's assume you're allowing to mint only 1 episode.
require(episodes.length <= 1, "Cannot make more than 1 episode");
First iteration (expected to pass)
episodes.length is 0, that's <= 1. Condition passes, you mint the first token, and then push to the episodes array, so its length becomes 1 after the condition.
Second iteration (expected to fail)
episodes.length is 1, that's still <= 1. So the condition passes as well.
Solution: Replace the <= (less than or equal) to just < (less than).
require(episodes.length < 1, "Cannot make more than 1 episode");
First iteration (expected to pass)
episodes.length is 0, that's < 1. Condition passes, you mint the first token, and then push to the episodes array, so its length becomes 1 after the condition.
Second iteration (expected to fail)
episodes.length is 1, which fails the condition 1 < 1, as you expect.
I'm assuming that your intention in the JS snippet is to call the mint() function 13 times in the loop, and then 14th time in the try/catch block.
However, the loop currently doesn't perform any iteration. So in fact, you're only executing the mint() function once (in the try/catch block).
The second parameter in the for loop is a condition stating "this loop will keep iterating for as long as this condition is met". But since you set the value of i to 0 in the first parameter, the loop condition (i===13) is not met, and the loop doesn't perform even the first iteration.
Solution: Check whether the i is "less than 13" instead of just "equals 13".
for(var i = 0; i < 13; i++) {
This way, the loop will iterate 13 times.
I am trying to write a code that will loop you in case you provide wrong data. The problem is that I need to have some type of "Bad data" message for both 2 cases:
- you enter not an integer value
- you enter the value below 0
In this code if you type a letter, it loops you with a message: "Bad data", but if you type for example negative value like -10 Bad data is not appearing (even though validation works and you need to correct number to positive)
How can I do it more universal, so in both scenarios sysout with print on-screen Bad data
Random rand = new Random();
int los = rand.nextInt(11);
int NumberOfPlayers ;
Scanner scan7 = new Scanner(System.in);
System.out.println(" Type number of players :");
do {
while (!scan7.hasNextInt()){
System.out.println(" Bad data");
scan7.next();
}
NumberOfPlayers = scan7.nextInt();
}while (NumberOfPlayers < 0);
you are only validating if scanner has next int, you do not validate it's value, and integers can be negative.
try this solution:
do {
while (!scan7.hasNextInt()) {
System.out.println(" Bad data");
scan7.next();
}
NumberOfPlayers = scan7.nextInt();
if (NumberOfPlayers <= 0) {
System.out.println(" Number must be larger than zero");
}
} while (NumberOfPlayers <= 0);
After checking for next int, I added part checking value of provided int.
ALSO please remember about naming variables and classes - start with small letter, so in your case NumberOfPlayers should be numberOfPlayers.
Why you named scanner scan7? is there valid reason for that name? if no, you should avoid adding numbers to names.
I am new to Arduino programming. My condition is I want to count up a value of i from 0 using while loop. At the same time, a calculation, b is needed to be performed continuously when counting up the value. However, the counting start from 90 instead of start from 0 when the calculation b is performing. Can anyone can help me on it? Thanks.
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
void setup() {
lcd.begin(20, 4);
}
void loop() {
int i;
while (i>=0){
i++;
lcd.setCursor(1,1);
lcd.print("b");
lcd.setCursor(3,1);
lcd.print(i);
delay(1000);
int c;
c = i + 2;
lcd.setCursor(1,2);
lcd.print(c);
delay(1000);
}
}
First of all your code should not even compile as b is not declared.
You initialize i with 0. So while (i>0) is never the case.
If you fix both you end up in an infinite loop. Not sure if you want that as there is some code after the while loop.
So pick a limit for i and use that in a for loop.
If you want to use a while loop make sure your loop condition is true >=0
You also might want to add a delay as otherwise your values change way too fast for you to see.
Can anyone help me to get the time complexity of this prog. ? here i have put 3 loop and each loop is dependent on the other one. I mean inner loop is dependent on top inner loop and top inner loop is dependent on outer loop .
public static String getLargestPallindrome(String str)
{ StringBuffer s=new StringBuffer();
for(int i=0;i<str.length()-1;i++) //outer loop
{
for(int j=str.length()-1;j>i;j--) //top inner loop
{
for(int k=i;k<=j;k++){ // inner lopp
s=s.append(str.charAt(k)+"");}
System.out.println("substring is "+s);
System.out.println("hey sub string is "+s.toString()); checkPallindrome(s.toString());
s=s.append(""); s=new StringBuffer();
}
}
return largestPallindrome;
}
There is no easy way to find time complexity by looking at the number of for loops used. You need to understand the code flow and calculate number of computations happened. In this case it is around n*n*(n-1)/2 which makes the time complexity O(n^3) since the highest degree of the polynomial is n^3. Where n is the size of the string str
Thats incorrect when you say it ran only 6 times.
Try putting putting print statments in each loop and you will come to know how many time it executes.
public static String getLargestPallindrome(String str)
{ StringBuffer s=new StringBuffer();
for(int i=0;i<str.length()-1;i++) //outer loop
{
System.out.println("Foo");
for(int j=str.length()-1;j>i;j--) //top inner loop
{
System.out.println("Bar");
for(int k=i;k<=j;k++){ // inner lopp
s=s.append(str.charAt(k)+"");}
System.out.println("substring is "+s);
System.out.println("hey sub string is "+s.toString()); checkPallindrome(s.toString());
s=s.append(""); s=new StringBuffer();
}
}
return largestPallindrome;
}
When normally using a for-in-loop, the counter (in this case number) is a constant in each iteration:
for number in 1...10 {
// do something
}
This means I cannot change number in the loop:
for number in 1...10 {
if number == 5 {
++number
}
}
// doesn't compile, since the prefix operator '++' can't be performed on the constant 'number'
Is there a way to declare number as a variable, without declaring it before the loop, or using a normal for-loop (with initialization, condition and increment)?
To understand why i can’t be mutable involves knowing what for…in is shorthand for. for i in 0..<10 is expanded by the compiler to the following:
var g = (0..<10).generate()
while let i = g.next() {
// use i
}
Every time around the loop, i is a freshly declared variable, the value of unwrapping the next result from calling next on the generator.
Now, that while can be written like this:
while var i = g.next() {
// here you _can_ increment i:
if i == 5 { ++i }
}
but of course, it wouldn’t help – g.next() is still going to generate a 5 next time around the loop. The increment in the body was pointless.
Presumably for this reason, for…in doesn’t support the same var syntax for declaring it’s loop counter – it would be very confusing if you didn’t realize how it worked.
(unlike with where, where you can see what is going on – the var functionality is occasionally useful, similarly to how func f(var i) can be).
If what you want is to skip certain iterations of the loop, your better bet (without resorting to C-style for or while) is to use a generator that skips the relevant values:
// iterate over every other integer
for i in 0.stride(to: 10, by: 2) { print(i) }
// skip a specific number
for i in (0..<10).filter({ $0 != 5 }) { print(i) }
let a = ["one","two","three","four"]
// ok so this one’s a bit convoluted...
let everyOther = a.enumerate().filter { $0.0 % 2 == 0 }.map { $0.1 }.lazy
for s in everyOther {
print(s)
}
The answer is "no", and that's a good thing. Otherwise, a grossly confusing behavior like this would be possible:
for number in 1...10 {
if number == 5 {
// This does not work
number = 5000
}
println(number)
}
Imagine the confusion of someone looking at the number 5000 in the output of a loop that is supposedly bound to a range of 1 though 10, inclusive.
Moreover, what would Swift pick as the next value of 5000? Should it stop? Should it continue to the next number in the range before the assignment? Should it throw an exception on out-of-range assignment? All three choices have some validity to them, so there is no clear winner.
To avoid situations like that, Swift designers made loop variables in range loops immutable.
Update Swift 5
for var i in 0...10 {
print(i)
i+=1
}