I have a variable v in my program, and it may take any value from the set of values
"a", "b", "c", ..., "z"
And my goal is to execute some statement only when v is not "x", "y", or "z".
I have tried,
for C-like languages (where equality operators compare the actual string values; e.g. c#, javascript, php)
if (v != "x" || v != "y" || v != "z")
{
// the statements I want to be executed
// if v is neither "x", nor "y", nor "z"
}
for Pascal-like languages (e.g. plsql)
IF (v != 'x' OR v != 'y' OR v != 'z') THEN
-- the statements I want to be executed
-- if v is neither "x", nor "y", nor "z"
END IF;
The statements inside the if condition always get executed. Am I doing anything wrong?
Use &&/AND/and, not ||/OR/or:
v != "x" && v != "y" && v != "z"
Problem
If an if block is always executed, the condition for the if block always evaluates to true. The logical expression must be wrong.
Let us consider v != "x" || v != "y" || v != "z" for each value of v.
When v = "x",
v != "x" becomes "x" != "x", which is false.
v != "y" becomes "x" != "y", which is true.
v != "z" becomes "x" != "z", which is true.
The expression evaluates to false || true || true, which is true.
When v = "y", the expression becomes
"y" != "x" || "y" != "y" || "y" != "z"
or true || false || true, which is true.
When v = "z", the expression becomes
"z" != "x" || "z" != "y" || "z" != "z"
or true || true || false, which is true.
For any other value for v, the expression evaluates to true || true || true, which is true.
Alternatively, consider the truth-table:
│ A B C │
v │ v != "x" v != "y" v != "z" │ A || B || C
───────┼──────────────────────────────────┼──────────────
"x" │ false true true │ true
"y" │ true false true │ true
"z" │ true true false │ true
other │ true true true │ true
As you can see, your logical expression always evaluates to true.
Solution
What you want to do is, find a logical expression that evaluates to true when
(v is not "x")and(v is not "y")and(v is not "z").
The correct construction is,
for C-like languages (eg. c#, javascript-(may need the strict equality operator !==), php)
if (v != "x" && v != "y" && v != "z")
{
// the statements I want to be executed
// if v is neither "x", nor "y", nor "z"
}
for Pascal-like languages plsql
IF (v != 'x' AND v != 'y' AND v != 'z') THEN
-- the statements I want to be executed
-- if v is neither "x", nor "y", nor "z"
END IF;
De Morgan's law
By De Morgan's law, the expression can also be rewritten as (using C-like syntax)
!(v == "x" || v == "y" || v == "z")
meaning
not((v is "x")or(v is "y")or(v is "z")).
This makes the logic a bit more obvious.
Specific languages
Some languages have specific constructs for testing membership in sets, or you can use array/list operations.
sql: v NOT IN ('x', 'y', 'z')
javascript: ["x", "y", "z"].indexOf(v) == -1
python: v not in {"x", "y", "z"}
java: !Arrays.asList("x", "y", "z").contains(v)
java-9 (and above): !Set.of("x", "y", "z").contains(v)
I figured I'd contribute an answer for Bourne shell script, since the syntax is somewhat peculiar.
In traditional/POSIX sh the string equality test is a feature of the [ command (yes, that is a distinct command name!) which has some pesky requirements on quoting etc.
#### WRONG
if [ "$v" != 'x' ] || [ "$v" != 'y'] || [ "$v" != 'z' ]; then
: some code which should happen when $v is not 'x' or 'y' or 'z'
fi
Modern shells like Ksh, Bash, Zsh etc also have [[ which is somewhat less pesky.
#### STILL WRONG
if [[ $v != 'x' || $v != 'y' || $v != 'z' ]]; then
: some code which should happen when $v is not 'x' or 'y' or 'z'
fi
We should highlight the requirement to have spaces around each token, which is something many beginners overlook (i.e. you can't say if[[$v or $v!='y' without whitespace around the commands and operators), and the apparent optionality of quoting. Failing to quote a value is often not a syntax error, but it will lead to grave undesired semantical troubles if you fail to quote a value which needs to be quoted. (More on this elsewhere.)
The obvious fix here is to use && instead of || but you should also note that [[ typically sports support for regular expressions, so you can say something like
if [[ ! $v =~ ^(x|y|z)$ ]]; then
: yeah
fi
and don't forget the trusty old case statement which is quite natural for this, and portable back into the late 1970s:
case $v in
x | y | z)
;; # don't actually do anything in this switch
*) # anything else, we fall through to this switch
yeah
some more yeah
in fact, lots of yeah;;
esac
The trailing double semicolons cause aneurysms at first, but you quickly recover, and learn to appreciate, even love them. POSIX lets you put an opening parenthesis before the match expression so you don't have unpaired right parentheses, but this usage is rather uncommon.
(This is obviously not a suitable answer for Unix shells which are not from the Bourne family. The C family of shells -- including the still somewhat popular tcsh -- use a syntax which is supposedly "C-like" but that's like being unable to tell apart Alice Cooper from the girl who went to Wonderland; and the Fish shell has its own peculiarities which I'm not even competent to comment on.)
You could use something like this, for PHP:
if(strpos('xyz',$v[0])===false)//example 1
//strpos returns false when the letter isn't in the string
//returns the position (0 based) of the substring
//we must use a strict comparison to see if it isn't in the substring
if(!in_array($v[0],array('x','y','z')))//example 2
//example 3
$out=array('x'=>1,'y'=>1,'z'=>1); //create an array
if(!$out[$v[0]]) //check if it's not 1
if(!preg_match('/^[xyz]$/',$v))//example 4, using regex
if(str_replace(array('x','y','z'),'',$v[0]))//example 5
if(trim($v[0],'xyz'))//example 6
For Javascript:
if(~'xyz'.search(v[0]))//example 1(.indexOf() works too)
if(!(v[0] in {x:0,y:0,z:0}))//example 2
if(~['x','y','z'].indexOf(v[0]))//example 3, incompatible with older browsers.
if(!/^[xyz]$/.match(v))//example 4
if(v.replace(/^[xyz]$/))//example 5
For MySQL:
Select not locate(#v,'xyz'); -- example 1
select #v not in ('x','y','z'); -- example 2
-- repetition of the same pattern for the others
For C:
if(!strstr("xyz",v))//example 1, untested
There are more ways, I'm just too lazy.
Use your imagination and just write the one that you like more!
Related
Each single digit from 0-9 is valid.
two or more digits are valid as long as it doesn't start with 0.
x+y
x-y
x/y
x*y
are valid expressions
Nothing else is a valid expression
Probably what you need based on those rules : https://i.stack.imgur.com/zwgaO.png
import re
userInput = input("Enter expression : ")
if re.match(r'^([0-9]|[1-9][0-9]+)([\+\-\*/]([0-9]|[1-9][0-9]+))*$', userInput):
print("Valid expression")
else:
print("Invalid expression")
Here's some explanation of the regex used :
"^([0-9]|[1-9][0-9]+)([\+\-\*/]([0-9]|[1-9][0-9]+))*$"
First part : ([0-9]|[1-9][0-9]+)
You either match a single digit within range 0-9 or 2+ digits with the first digit within range 1-9 (excluding 0)
Second part : ([\+\-\*/]&first_part)*
First of all you search for any of these operators : + - * /, you need to escape +, - and * characters because they are used in the Python regex syntax. No need to escape the / character though.
The * at the end means you expect the second part to be repeated 0 or more times.
What if I don't want to use regexes ?
userInput = input("Expression : ")
allowedDigits, allowedOPs = [str(a) for a in range(10)], ["+", "-", "*", "/"]
pile = ""
valid = True
for c in userInput:
if c in allowedDigits and pile != "" and pile[0] == "0": valid = False
elif c in allowedDigits: pile += c
elif c in allowedOPs and pile == "": valid = False
elif c in allowedOPs: pile = ""
else: valid = False
if pile == "": valid = False
if valid:
print("Valid Expression !")
else:
print("Invalid Expression !")
This code is pretty simple and straightforward, we just detect the 4 possible fail cases :
The number contains more than one digit and begins with 0
if c in allowedDigits and pile != "" and pile[0] == "0"
There's an operator and no number before
elif c in allowedOPs and pile == ""
There's a non-allowed character
else
Expression ends with an operator (doesn't end with a number)
if pile == ""
I'm trying to check whether or not all chars in my string are either one of these numbers: 1,2,3,4,5,6,7,8,9,0 OR a decimal point and whether they contain spaces or not. I'm using this piece of code but it's not working and I can't figure out why:
print("Confirming added item")
local validAmountString = true
print(addScreen.amountTxtField.text)
for i = 1, #addScreen.amountTxtField.text do
local c = addScreen.amountTxtField.text:sub(i,i)
print("Char " .. i .. " in the amount textflied is " .. c)
if c == "0" or c == "1" or c == "2" or c == "3" or c == "4" or c == "5" or c == "6" or c == "7" or c == "8" or c == "9" or c == "." then
validAmountString = true
else
validAmountString = false
end
print(validAmountString)
end
if string.gsub(addScreen.nameTxtField.text, "%s+", "") ~= "" and string.gsub(addScreen.amountTxtField.text, "%s+", "") ~= "" and validAmountString == true then
--Proceed...
end
The spaces part is working, but for some reason, when I try to check whether validAmountString == true in my if statement, it stops working. The validAmountString returns the correct boolean value according to my print statement though.
Any help? :)
An easier way to go about this would be string.find
local validAmountString = not addScreen.amountTxtField.text:find( "[^%d%.]" )
I'm afraid I can't tell why validAmountString is not true, but you don't have to compare boolean values.
if (validAmountString) then
--is equivilent to
if (validAmountString == true) then
For checking your strings refer to KingOfGamesYami's answer. He's using something called string patterns btw. Check the Lua reference http://www.lua.org/manual/5.3/manual.html#6.4.1 for details.
"[^%d%.]" matches every character that not a digit or a dot. So if find returns something but nil, your string is invalid
For why your program isn't working as is (in case you want to stick to your complicated way:
You check every character of your string. If it is a number or a dot you asign true, if it's not you asign false.
So let's say you have "12A3" as a string.
Then the final value of validAmountString is true because the last character is a number. So you assign true 2 times, then false for the "A" and after that you asign true again. You mess up your total result.
What you should do here is either assign validAmountString = validAmountString and true, else validAmountString = false so you can never overwrite a false, once set.
The even better and more efficient way would be to simply stop your check once you've hit an invalid character. There is no need to check further characters if you find one invalid.
So simply add a break after validAmountString = false
You do not need the loop to check whether it does or does not have valid characters.
You can simply do tonumber(string). It will return nil if there is any character other than a digit in the string.
I am scanning user input as a string to get a month (user inputs March and month = 3), and I am using if else statements to check which month was input.
if (user_input[0] == 'J' && user_input [1] == 'a' && user_input[2] == 'n'
&& user_input[3] == 'u' && user_input[4] == 'a' && user_input[5] == 'r'
&& user_input[6] == 'y')
Is how i'm checking for January. Is there any way to test this without typing all that out?
like
user_input[0-6] == 'January'
thanks
You can use for loop.Create a switch case state.If you didn't understand I can write the code for you but i prefer you to work yourself with your code except some help
I use the following code in PHP to validate if a password includes invalid characters
function validate_password($str) {
if(strlen($str) < 5 || strlen($str) > 30) {
return false;
} else {
return preg_match('/^[-._A-Za-z0-9]*$/',$str);
}
}
I'm trying to do the same in Lua but not sure the best way to check if a string contains only certain characters. My valid characters are alphanumeric with the addition of "-" and "."
local function validate_password(str)
if string.len(str) < 5 or string.len(str) > 30 then
return false
else
if(str:match("%W")) then
-- this isn't right. need to check if alpha numeric or - or .
return false
else
return true
end
end
end
Appreciate any help!
return #str >= 5 and #str <= 30 and str:find('^[%-%.%w_]+$') ~= nil
Note 1: as mentioned in the comments, ~= nil part can be removed as the position returned by find will be evaluated as true (when it's not nil) in logical operators. However, since it's a number, it will fail when used in validate_password(str) == true comparisons (since 1 == true is not true). An alternative is to use not str:find('[^...]') as suggested by Egor.
Note 2: as mentioned in the comments, - and . don't need to be escaped in this particular case. However, since - is a range operator inside square brackets [_-.] is not the same as [-._], as it will match nothing as the range of symbols between _ and . is empty. It's safe to escape - and . even inside square brackets.
I keep getting this error on my project and i cant figure it out! please help!
error C2143: syntax error : missing ')' before 'constant'
the line is:
while (selection == ('a','b','c', 'd', 'e', 'f', 'g', 'h', 'i','A','B' 'C', 'D', 'E', 'F', 'G', 'H', 'I');
also i know there is an easier way to write that line out but im not sure how i can do it. im a beginner at this so can any of you pros edit this line for me!
How many open parentheses do you have?
How many closed parentheses do you have?
Are these the same number? If not, where is one missing?
Also, the syntax a == (b,c,d) is not shorthand for a == b || a == c || a == d like you seem to think. It's actually equivalent to a == d due to the way the comma operator works.
To be completely explicit, what you actually want is this:
while (selection == 'a' || selection == 'b' ||
selection == 'c' || selection == 'd' ||
selection == 'e' || selection == 'f' ||
selection == 'g' || selection == 'h' ||
selection == 'i' || selection == 'A' ||
selection == 'B' || selection == 'C' ||
selection == 'D' || selection == 'E' ||
selection == 'F' || selection == 'G' ||
selection == 'H' || selection == 'I')
{
/* Do stuff */
}
Or, to be a lot more consice about it, you can take advantage of the fact that the letters are arranged alphabetically in the ASCII table, and write
while (tolower(selection) >= 'a' && tolower(selection) <= 'i')
{
/* Do stuff */
}
This requires inclusion of <ctype.h> for the tolower function.
Given your comments on Tyler's post, it seems like what you really want is:
while ((selection >= 'a' && selection <= 'i') || (selection >= 'A' && selection <= 'I'))
{
// loop
}
Characters can be compared as if they were numbers (because they are numbers in the CPU), which means that you can check for a range of characters using the < > <= >= operators.