Cicle around prompt not working - javascript

I need to make a cicle around prompt. The object of prompt - grab custumer input value and push it to eval function for making a result (converting whole string to digits with math operators('+', '*', etc...)).
The appointment of circle - is to check the result of eval function and if eval(a) != digit -> repeat prompt each time when user input in prompt non-digit values ('a', ',', etc...)
The other part of code only for catching an errors.
do {
var a = prompt('your number', '10-2*4');
} while (eval(a) != 'number');
try {
console.log( eval(a) ); //must display 2
} catch (e) {
console.log('Error: ', e);
}

Your test of eval(s) != 'number' should be something like typeof eval(+s) !='number'
You could make it a recursive function:
function doPrompt(){
try {
// if this line throws error will go to catch
var res = eval(prompt('your number', '10-2*4'));
// do it again if we don't have a number, or return number
return typeof +res ==='number' ? +res : doPrompt()
}catch(e){
return doPrompt();
}
};
var res = doPrompt();
console.log(res)
This would be a lot cleaner using an <input> instead which would allow for better ability to display errors to user. Using prompt is not very flexible

Related

How do I prevent the input of a number like 2.2.2 in my calculator?

I have been working on a simple JS calculator using an OOP approach. I am struggling to create a fix that prevents the input of extra decimals. For example, a user can input 3.2.1.5. Ideally, this calculator would display the entire expression on the digital calculator screen before solving it and returning the result. With this in mind, simply preventing a user from adding a second decimal would prevent them from adding(or whatever operator they may choose) multiple decimals together. I have considered using .split() and .join() on operators in the input, but it is beginning to get convoluted as there are multiple operators to consider. Ideally, I want to avoid regex.
const keys = document.querySelector('.calc-buttons');
keys.addEventListener('click', event => {
const {target} = event
const {value} = target
if(!target.matches('button')){
return
}else{
calculator.parseInput(value)
//console.log(value)
}
})
const calculator = {
displayText: '0',
prevTotal: null,
parseInput(value){
//have any of the special buttons(AC, decimal, =) been clicked?
switch(value){
case '=':
//calculate answer
this.calcAnswer(this.displayText)
break
case 'AC':
//clear screen & stored values
this.clearAll()
break
case '.':
//create decimal
if(this.displayText == 0){
//pass'0.'
this.addText('0.')
}else{
//add value to text string
this.addText(value)
}
break
default:
//add value to text string
this.addText(value)
break
}
},
addText(value){
if(this.displayText == '0'){
this.displayText = ''
}else if(this.prevTotal !== null){
this.displayText = this.prevTotal
this.prevTotal = null
}
//check if previous input is a number
if(isNaN(+(value)) && isNaN(+(this.displayText))){
if(isNaN(this.displayText.slice(-1))){
return
}
}else if(value == '.' && this.displayText.slice(-1) == '.'){
return
}
this.displayText += value
//output display text to screen
this.outputText(this.displayText)
},
outputText(text){
document.querySelector('.screen').value = text
},
calcAnswer(equation){
let result = Function("return " + equation)()
this.outputText(result)
//console.log(equation)
//console.log(result)
this.prevTotal = result
},
clearAll(){
this.displayText = '0',
this.prevTotal = null
this.outputText(this.displayText)
}
}
Functions are based on StepUp's answer (which is wrong AFAIK; it should be .length > 2 but I can't comment yet)
const hasManySymbols = (str, symbol) => {
const firstIndex = str.indexOf(symbol) // find the first occurrence of the symbol
if(firstIndex == -1) return false // if there is no first occurrence there are not many symbols
return str.indexOf(symbol, firstIndex + 1) != -1 // whether or not there is a second occurrence
}
const validate = str => hasManySymbols(str, '.') ? 'invalid input' : 'valid input'
console.log(validate('1.23')) // "valid input"
console.log(validate('1.2.3')) // "invalid input"
I'm not sure if this is faster or slower but it should theoretically be faster I guess.
You can create a simple function to avoid repetition of code and hiding unnecessary details in functions. In addition, it helps to reduce convolution.
So create a function which will check eligibility of input and based on result just notify user or remove last incorrect character.
The sketch of function could like this:
const hasManySigns = (str, sign) => str.split(sign).length > 2
An example:
const hasManySigns = (str, sign) => str.split(sign).length > 2
let foo = '1.2.3'
const validate = str => hasManySigns(str, '.') ? 'incorrect input' : 'correct input'
console.log(validate(foo))

Finding variable types from a string

Pardon if this question has already been answered however I'm struggling to find the any answers to it.
I'm looking to see if I can convert variable types to a string in the code below.
input = prompt('Type something please', 'your input here')
alert(input + ' is a ' + typeof input)
i.e. if the user were to type 1 typeof would return number, or if the user were to enter true it would return a boolean
You can run the input through a series of parseInt, parseFloat and
parseBool
functions.
Whenever you get a valid result, return it.
Something similar to:
if (parseInt(input) != NaN) {
return "int"
}
if (parseFloat(input) != NaN) {
return "float"
}
Generally, all inputs per your example will return a string careless of what they entered or intended to enter. We could however build a few logics to check if what they entered is; Strings (Alphabets only) or an integer (numbers only) or any other ones per a few other logics you could base your checks on.
One of the quickest ways to check if an input contains a number or not;
isNaN(input) // this returns true if the variable does NOT contain a valid number
eg.
isNaN(123) // false
isNaN('123') // false
isNaN('1e10000') // false (This translates to Infinity, which is a number)
isNaN('foo') // true
isNaN('10px') // true
you could try regex (which is not always ideal but works)
var input = "123";
if(num.match(/^-{0,1}\d+$/)){
//return true if positive or negative
}else if(num.match(/^\d+\.\d+$/)){
//return true if float
}else{
// return false neither worked
}
You could also use the (typeof input) but this will be more convenient if your user is going to enter an expected set of entries
var input = true;
alert(typeof input);
// This eg will return bolean
Let me know if this helps.

JavaScript: innerHTML outputs undefined, although console.log outputs the right value

I am trying to make a calculator app in JS, and I am struggling with the sine and cosine functions.
The line before
document.getElementByID("screenPar").innerHTML = result;
is
console.log(result);
, and in the console, the correct value shows up, however on the calculator's screen, it says undefined. My function:
function calcSin(){
try{ //Checks for syntax errors
if(calcString[calcString.length-1] == "+" || calcString[calcString.length-1] == "-" || calcString[calcString.length-1] == "*" || calcString[calcString.length-1] == "/"){
throw "Syntax Error"
}
}
catch(err){
document.getElementById("screenPar").innerHTML = err;
return 1;
}
if(calcString[calcString.length-1] == "$"){ //If last character in string is '$', clears screen
clearScreen();
document.getElementById("screenPar").style.color = "black";
}
else{
var evalRes = eval(calcString);
console.log(evalRes + typeof evalRes);
var result = Math.round(Math.sin(evalRes));
console.log(result + typeof result);
clearScreen();
console.log(result);
document.getElementById("screenPar").innerHTML = result;
}
}
calcString is a string of the inputted expression, for instance "3*4*5".
The console outputs the correct value, but innerHTML puts undefined in the paragraph.
I uploaded the code to a free hosting site: brokenCalculator.
What am I missing?
The function you've shown is fine. Something else replaces the screenPar value to undefined.
P.S. Use .textContent instead of .innerHTML unless you desire to add a text as an HTML code.
<button onclick="addToCalcString(calcSin())"...>
Above onclick event you are calling function inside a function. When you click, 1st the calcSin() is getting called and below line is executing fine
document.getElementById("screenPar").innerHTML = result;
But after that the addToCalcString(char) is executing, in which calcString is undefined
document.getElementById("screenPar").innerHTML = calcString;

How we can code the case insensitive in JavaScript?

In my project I need to take care about the case insensitive, and I don't know how can I code something like that in JavaScript.
If I write on my terminal, I need for my code to understand the same thing :
`BOB
bob
Bob`
My code :
#!/usr/bin/env node
let chunk = "";
process.stdin.on("data", data => {
chunk += data.toString();
});
process.stdin.on("end", () => {
chunk.replace(/^\s*[\r\n]/gm,"").split(/\s+/).ignoreCase.forEach(function (s) {
process.stdout.write(
s === 'bob'
? 'boy \n'
: s === 'alicia'
? 'girl\n'
: s === 'cookie'
? 'dog \n'
: 'unknown \n');
});
});
The result I need to display is :
`boy
boy
boy`
I tried to do it with ignoreCase but it does not work, can you explain me why please?
Simply use String.prototype.toLowerCase on all your strings on input so that when you compare them there is only one way they can be represented.
process.stdin.on("data", data => {
chunk += data.toString().toLowerCase();
});
Just take the input and force it to all lower or upper case with String.toLowerCase() or String.toUpperCase() and then compare it to the same cased string:
console.log("test" === "Test"); // false
console.log("test" === "Test".toLowerCase()); // true
console.log("TeSt".toUpperCase() === "Test".toUpperCase()); // true
The RegExp.prototype.ignorecase property holds a boolean value for whether the the "i" flag is set for a regular expression. This is not a function and does not provide any manipulation operation to the expression or string.
See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/ignoreCase
What you may want to consider doing is calling something like the String.prototype.toLowerCase() function which will convert the string to lower case.
Edit: if it helps, I think you might place the toLowerCase() before the split(), since toLowerCase() is the String's function, not an array's function. And unless you want to later call it separately on each string, might be fastest to do it in one place, something like this:
chunk.replace(/^\s*[\r\n]/gm,"").toLowerCase().split(/\s+/).forEach(function (s) {
// function here
});

Javascript Eval() thinks first value is a function

I am writing a function that will evaluate expressions in an input field and return the sum.
Currently is working but I am running into an error that I just cannot figure out. Here is my code in Plunker.
function linkFunction(scope) {
var PO = 10;
scope.value = PO;
scope.result = '';
scope.Evaluate = function (input) {
if (input.match(/[a-zA-Z]/g) != null) { //to check if user has inputted a letter between a-z, case sensitive.
return alert("You must only use numbers, not letters")
} else if (input.match(/[!"^£$&[{}\]?\\##~<>_'|`¬:;,=]/g) != null) { //to check if user has inputted a special symbol
return alert("You must only use the symbols specified")
} else if (input.match(/\.\d*\.+/g) != null) { //to check if user has inputted a doubled decimal eg 10.2.2
return alert("You can only use 1 decimal point")
} else if (input.match(/\.{2,}/g) != null) {//to check if user has inputted a two decimals eg 10..1
return alert("You cannot put two decimals one after another")
}
// if (input.match(/\d*\(\d\W\d\)/g) != null){
// }
var percentPattern = /[0-9]*\.?[0-9]+%/g;
var expressionResults = input.match(percentPattern);
if (scope.enablePercentage) { //if parameter = 1, then do this code.
if (expressionResults != null) { //if user has entered into the input field
if (expressionResults.length > 1) { //if you user has finished the RegEx (%, is the end of the RegEx, so code will think its the end of the array, therefore you cannot add another %)
return alert("Too many % values");
} else {// user has met all requirements
var percentageValue = parseFloat(expressionResults) * PO / 100;
input = input.replace(expressionResults, percentageValue);
}
}
} else if (expressionResults != null) { //if parameter = 0, then do this code. Parameter is off, but user has entered percentage
return alert("You cannot use %");
}
scope.result = eval(input);
}
}});
If you write 10(5+3) it gives you an error
TypeError: 10 is not a function
Obviously if a user ran this code they would expect to see the value 80.
Eval thinks that 10() is a function.
Does anyone know how to fix this problem. Thanks
eval expects you to pass it JavaScript, not algebra.
If you want to multiply two values together then you must use a Multiplicative Operator.
10 * (5+3)

Categories

Resources