What is wrong with my logic? - c++

if(location[0] <= 'H' || location[0] >= 'A'
&& location[1] <= 8 || location[1] >= 1)
I am checking to see if the first indice is between 'A' and 'H' and the second indice is between 1 - 8.
so the argument would = 1 if the user entered { A, 1 }
-1 if the user entered { J, 1 }

And (&&) has higher precedence than or (||), so to express what you want you need:
if ((location[0] <= 'H' || location[0] >= 'A') && (location[1] <= 8 || location[1] >= 1))
Otherwise what's happening is that it does the equivalent of this:
if (location[0] <= 'H' || (location[0] >= 'A' && location[1] <= 8) || location[1] >= 1)
Which is clearly not what you intended.
You can put as many expressions in the condition as you want, but you must remember the precedence rules; I suggest always using extra parentheses for clarity.
As Jeremiah has pointed out in the comments, the condition still wouldn't be doing what you wanted -- you are asking if something is in a given range by checking if it's either less than the upper bound or greater than the lower bound (this covers all input), when you intended to check whether the input was both larger than the lower bound and smaller than the upper:
if (location[0] <= 'H' && location[0] >= 'A' && location[1] <= 8 && location[1] >= 1)
In this case, since the operators are all &&, no extra parentheses are needed, though you can add them for extra clarity.

You need &&s not ||s. For example: 'Z' >= 'A' || 'Z' <= 'H' is true.
if(location[0] <= 'H' && location[0] >= 'A' && location[1] <= 8 && location[1] >= 1)
While not necessary in this case, you should group your logic together with parenthesis (and if they were ||s you would have to for it to work as expected):
if((location[0] <= 'H' && location[0] >= 'A') && (location[1] <= 8 && location[1] >= 1))

Add parenthesis to group the conditions:
if( (location[0] <= 'H' || location[0] >= 'A') && (location[1] <= 8 || location[1] >= 1))

If location[0] was equal to 'J' (definitely NOT between 'A' and 'H'), your if-clause would be TRUE because even though location[0] <= 'H' is FALSE, location[0] >= 'A' is TRUE and you are using || (OR). The problem is that you are using || (OR) instead of && (AND). You need to use all && (AND) in the if-clause.

&& has higher precedence than ||. So, you may want to write it as
if((location[0] <= 'H' || location[0] >= 'A') && (location[1] <= 8 || location[1] >= 1))
If you already tried this, please tell what error you got

Sorry guys, new here. I should have posted my entire method. Thank you for explaining the precedence of the operators, but my issue was that I was comparing a char with an int. All I needed to do was put ' ' around my numbers.
void GameBoard::enterShips()
{
char location[2];
int ships = 0;
int count = 1;
while( ships < NUM_SHIPS )
{
cout << "Enter a location for Ship " << count << ": ";
cin >> location[0];
cin >> location[1];
cout << endl;
if((location[0] <= 'H' && location[0] >= 'A') && (location[1] <= '8' && location[1] >= '1'))
{
location[0] = location[0] - 64;
location[1]--;
Grid[location[0]][location[1]] = SHIP;
ships++;
count++;
}
else
{
cout << "Wrong coordinates entered. Try again." << endl << endl;
}
}
}

As you can see in this operator precedence table, && is #13. It's higher up than ||, which is #14.
Therefore:
if(location[0] <= 'H' || location[0] >= 'A'
&& location[1] <= 8 || location[1] >= 1)
Is equivalent to:
if(location[0] <= 'H' || (location[0] >= 'A'
&& location[1] <= 8) || location[1] >= 1)
You want:
if((location[0] <= 'H' || location[0] >= 'A') &&
(location[1] <= 8 || location[1] >= 1))
Or even better:
if(((location[0] <= 'H') || (location[0] >= 'A')) &&
((location[1] <= 8) || (location[1] >= 1)))
I always put brackets around everything except when */ and +- are concerned. Even if you memorize the table, you shouldn't assume others do.
It helps code readability and helps prevent bugs... even compiler bugs! Triple bonus. :)
EDIT: Ah, you want ALL of them to be true. Just use all &&s, then! This works:
if(((location[0] <= 'H') && (location[0] >= 'A')) &&
((location[1] <= 8) && (location[1] >= 1)))

Related

Counting vowels c++

While user inputs 10 alphabets, program should tell how many of them are vowels. I have written this code:
while (count<10)
{
cin >> n;
count++;
if (n == 'A' || n == 'a' && n == 'E' || n == 'e' && n == 'I' || n == 'i' && n == 'O' || n == 'o' && n == 'U' || n == 'u')
{
total++;
}
}
cout << total << endl;
This generates output of 0 even if there are vowels entered by user. something wrong?
Let's start by cutting down the condition down a bit, to only look at a and e
if (n == 'A' || n == 'a' && n == 'E' || n == 'e')
and then only considering the lowercase letters for simplicity (but retains the problem)
if (n == 'a' && n == 'e')
if you read this out loud it says "if n is 'a' AND n is 'e'". The "AND" (from the && operator) means that both conditions must be true. You've created an impossible condition here, if n is 'a', then it is not 'e', so you get if (true && false) - which is false. If n is 'e', then it is not 'a', so you get if (false && true).
Simply replace all of your && (and) operators with || (or) operators to have the condition be true if at least one of your equality comparisons is true.
if (n == 'A' || n == 'a' || n == 'E' || n == 'e'
|| n == 'I' || n == 'i' || n == 'O' || n == 'o'
|| n == 'U' || n == 'u')
There are some ways to simplify the condition.
One is to add a #include <cctype> and use std::tolower to convert n to lowercase, then you only need to compare against lowercase characters.
n = std::tolower(n);
if (n == 'a' || n == 'e' || n == 'i' || n == 'o' || n == 'u')
Another, less repetitive approach is to create a std::string with all the vowels in it, and then see if it contains n, #include <string> up top.
std::string vowels = "aeiouAEIOU";
while (/*...*/) {
// ...
if (vowels.find(n) != std::string::npos) {
++total;
}
}
As n314159 pointed out, if you are using C++17 or later, you can use a std::string_view instead, which is cheaper. #include <string_view>
static constexpr std::string_view vowels = "aeiouAEIOU";
while (/*...*/) {
// ...
if (vowels.find(n) != std::string_view::npos) {
++total;
}
}
I recommend using a switch statement with fall-through, which is more readable but also potentially more efficient (may be implemented with jump table).
int count = 10;
while (count--) {
switch(std::tolower(n)) {
case 'a': case 'e':
case 'i': case 'o':
case 'u': total ++; break;
default:;
}
}

Program to count evens odds vowels and consonants in a string

Hello i don't know how to fix my program to find how many evens, odds, vowels and consonants are in my string.
The program compiles and runs but i never get any vowels or consonants and everything else is added in either evens or odds (even characters).
Edit 1: By evens and odds i mean like if the user types in the string John123 i want to find how many characters are vowels in this case 1 the 'o' how many are consonants in this case 3 the 'J', 'h', 'n' how many are evens in this case 1 the '2' and how many are odds in this case 2 the '1' and the '3'.
#include <iostream>
#include <string>
using namespace std;
int main ()
{
string s1;
int evens = 0; //
int odds = 0; //
int vowels = 0; //
int consonants = 0; //
cout << "Please type in Something: ";
getline(cin, s1);
cout << "You typed: " << s1 << endl;
for(int i = 0; i < s1.size(); ++i)
{
if((s1[i] % 2) == 0 )
{
++evens;
}
else if((s1[i] % 2 ) != 0) // What would an algorithm (formula) be to find when a number is odd without the not-equals != ?
{
++odds;
}
else if(s1[i] == 'A' || 'a' || 'E' || 'e' || 'O' || 'o' || 'I' || 'i' || 'U' || 'u')
{
++vowels;
}
else if(s1[i] == 'Q' || 'W' || 'R' || 'T' || 'Y' || 'P' || 'S' || 'D' || 'F' || 'G' || 'H' || 'J' || 'K' || 'L' || 'Z' || 'X' || 'C' || 'V' || 'B' || 'N' || 'M'||
'q' || 'w' || 'r' || 't' || 'y' || 'p' || 's' || 'd' || 'f' || 'g' || 'h' || 'j' || 'k' || 'l' || 'z' || 'x' || 'c' || 'v' || 'b' || 'n' || 'm')
// I specify every letter so that it dosn't pick whitespaces, symbols etc.
{
++consonants;
}
}
cout << "Evens in string are: " << evens << "\nOdds in string are: " << odds << "\nVowels in string are: " << vowels << "\nConsonants in string are: " << consonants;
return 0;
}
if((s1[i] % 2) == 0 )
This code is not correct. You are modulating the character, which isn't what you want. You want to first convert the character to an integer using atoi or something like that, I can't remember the function. (Just look up string to int c++). Then, once you've converted the character to an integer, then you can modulate it correctly.
Also, your || syntax is totally wrong, as Jongware mentioned. You need to have an == comparison for each character.
Should look like this (very long):
(s1[i] == 'A' || s1[i] == 'a' || s1[i] == 'E' || s1[i] == 'e' || s1[i] == 'O' || s1[i] == 'o' || s1[i] == 'I' || s1[i] == 'i' || s1[i] == 'U' || s1[i] == 'u')
You might want to store s1[i] in a char beforehand so it's more concise.
And you should place your character testing BEFORE the odd/even testing, so that you don't accidentally try and convert h or another non-numeric character to an integer.
A char is a number. For example, a is (on most computers) the ASCII code 97. So either your even test or your odd test will always match. You need to rearrange your if blocks.
Also, your character tests don't do what you intended. s1[i] == 'A' || 'a' tests as true whenever s1[i] is equal to 'A' or whenever 'a' as a number is not zero. But 97 is never zero, so that test will always result in true. You need code more like s1[i] == 'A' || s1[i] == 'a', testing the s1[i] value each time.
(One way to make things simpler: Once you know the character is not a vowel, you can test for an ASCII consonant with ((s1[i] >= 'a' && s1[i] <= 'z') || (s1[i] >= 'A' && s1[i] <= 'Z')).)
You have basically two problems:
Characters are interpreted as numbers, taking into account the character code. When you are checking whether the character is even or odd, you are checking its character code which will always be either event of odd, this is why your code will always enter into the first or second case. You must check whether your character is digit and if so, you must check whether it is even
Your OR is incorrect, see Ruby van Soelen's answer
Suggested, untested code:
for(int i = 0; i < s1.size(); ++i)
{
if (isdigit(s1[i])) {
if ((s1[i] == '0') || (s1[i] == '2') || (s1[i] == '4') || (s1[i] == '6') || (s1[i] == '8'))
{
++evens;
}
else // What would an algorithm (formula) be to find when a number is odd without the not-equals != ?
{
++odds;
}
}
else
{
if(s1[i]=='A' || s1[i]=='a' || s1[i]=='E' || s1[i]=='e' || s1[i]=='O' || s1[i]=='o' || s1[i]=='I' || s1[i]=='i' || s1[i]=='U' || s1[i]=='u')
{
++vowels;
}
else if(s1[i]=='B' || s1[i]=='b' || s1[i]=='C' || s1[i]=='c' || s1[i]=='D' || s1[i]=='d' || s1[i]=='F' || s1[i]=='f' || s1[i]=='G' || s1[i]=='g' || s1[i]=='H' || s1[i]=='h' || s1[i]=='J' || s1[i]=='j' || s1[i]=='K' || s1[i]=='k' || s1[i]=='L' || s1[i]=='l' || s1[i]=='M' || s1[i]=='m' || s1[i]=='N' || s1[i]=='n' || s1[i]=='P' || s1[i]=='p' || s1[i]=='Q' || s1[i]=='q' || s1[i]=='R' || s1[i]=='r' || s1[i]=='S' || s1[i]=='s' || s1[i]=='T' || s1[i]=='t' || s1[i]=='V' || s1[i]=='v' || s1[i]=='X' || s1[i]=='x' || s1[i]=='Y' || s1[i]=='y' || s1[i]=='Z' || s1[i]=='z')
// I specify every letter so that it dosn't pick whitespaces, symbols etc.
{
++consonants;
}
}
}
Your || syntax is making no sence, what you currently have is something like this
else if(s1[i] == 'A' || 'a' || 'E' || 'e' || 'O' || 'o' || 'I' || 'i' || 'U' || 'u')
while it should be like this:
else if(s1[i]=='A' || s1[i]=='a' || s1[i]=='E' || s1[i]=='e' || s1[i]=='O' || s1[i]=='o' || s1[i]=='I' || s1[i]=='i' || s1[i]=='U' || s1[i]=='u')
Expression in the else-if statement will be always equal to true
else if(s1[i] == 'A' || 'a' || 'E' || 'e' || 'O' || 'o' || 'I' || 'i' || 'U' || 'u')
becuase it is equivalent to
( s1[i] == 'A' ) || 'a' || 'B' /*...*/
where 'a' as it is not equal to zero evaluates to true.
So you have to write at least like
s1[i] == 'A' || s1[i] == 'a' || s1[i] == 'B' /*...*/
Also take into account that for example character 'B' though is not a digit but its code is even. So you will get a wrong result if will start checks from statement
if((s1[i] % 2) == 0 )
You should check at first whether the character is a digit. Also you could define an array of vowels and consonants and use standard function strchr that to check whether a character is a vowel or consonant.
For example
#include <iostream>
#include <string>
#include <cctype>
//...
const char *alpha_vowels = "AEIOU";
const char &alpha_consonants = "BCD...";
//...
if ( std::isdigit( s[i] ) )
{
s[i] % 2 == 0 ? ++evens : ++odds;
}
else if ( std::strchr( alpha_vowels, std::toupper( ( unsigned char )s[i] ) ) != nullptr )
{
++vowels;
}
else if ( std::strchr( alpha_consonants, std::toupper( ( unsigned char )s[i] ) ) != nullptr )
{
++consonants;
}
In addition to the other answers, here's a simpler way to accomplish the same thing.
std::set<char> vs{'a', 'o', 'u', 'e', 'i'};
for (auto&& c : s1) {
if (std::isdigit(c))
if ((c - '0') % 2 == 0) // Trick to convert numeric char -> int.
++evens;
else
++odds;
else if (std::isalpha(c))
if (vs.count(std::tolower(c)))
++vowels;
else
++consonants;
}

Arduino check non alphanumeric

How to check if a string contains non alphanumeric values? I want to create a condition to return if match one non alphanumeric character.
void checkTag(char tag[]){
if(strlen(tag) == 0) return;
if(strlen(tag) == 1) return;
if(strlen(tag) == 2) return;
if(strlen(tag) == 3) return;
In Serial Monitor is showed:
À¨À¨Àª®)
for (int i=0;i<strlen(tag); i++){
if ( (tag[i] >= 'a' && tag[i] <= 'z') || (tag[i] >= 'A' && tag[i] <= 'Z') || (tag[i] >= '0' && tag[i] <= '9'){
//this char is OK
}else{
return;
}
}
//if you are here tag is valid
edit: changed the comments to be sure you don't put code in the if

Query whether a char is a digit at compile time

I want to check whether a given char is a digit at compile time. In particular I need the implementation of the following function prototype:
template<char c>
constexpr bool IsDigit();
For clarification: I dont must use a custom implementation. If there is already a built-in way in the std, I would prefer that method.
This should work for ASCII:
constexpr bool IsDigit(char c) { return c >= '0' && c <= '9'; } // ASCII only
If you need to keep your prototype:
template<char C>
constexpr bool IsDigit() { return C >= '0' && C <= '9'; } // ASCII only
For wchar_t support you could try something like:
constexpr bool IsDigit(wchar_t c)
{
return (c >= L'0' && c <= L'9') ||
(c >= L'\u0660' && c <= L'\u0669') || // Arabic-Indic
(c >= L'\u06F0' && c <= L'\u06F9') || // Extended Arabic-Indic
(c >= L'\u07C0' && c <= L'\u07C9') || // NKO
(c >= L'\u0966' && c <= L'\u096F') || // Devanagari
(c >= L'\u09E6' && c <= L'\u09EF') || // Bengali
(c >= L'\u0A66' && c <= L'\u0A6F') || // Gurmukhi
(c >= L'\u0AE6' && c <= L'\u0AEF') || // Gujarati
(c >= L'\u0B66' && c <= L'\u0B6F') || // Oriya
(c >= L'\u0BE6' && c <= L'\u0BEF') || // Tamil
(c >= L'\u0C66' && c <= L'\u0C6F') || // Telugu
(c >= L'\u0CE6' && c <= L'\u0CEF') || // Kannada
(c >= L'\u0D66' && c <= L'\u0D6F') || // Malayalam
(c >= L'\u0E50' && c <= L'\u0E59') || // Thai
(c >= L'\u0ED0' && c <= L'\u0ED9') || // Lao
(c >= L'\u0F20' && c <= L'\u0F29'); // Tibetan
// Missing check for Myanmar, Khmer, Mongolian, Limbu, New Tai Lue,
// Tai Tham Hora, Tai Tham Tham, Balinese, Sundanese, Lepcha, Ol Chiki,
// Vai, Surashtra, Kayah, Javanese, Cham, Meetei Mayek, Osmanya, Brahmi,
// Sora, Chakma, Sharada, Takri, Mathematical.
// For codes see http://www.unicode.org/ucd/
}

Best way to format the conditional checks in "if" statement

This code looks dirty and I can't figure out how to format it so that I can read it, understand it, and look clean at the same time.
if(center==2 && ((((y-height/2)==j) && ((x+width/2)==i)) || (((y+height/2)==j) && ((x+width/2)==i))))
regenerateDot(i+1, j, dots);
Any suggestions?
I would break down the boolean expressions into variables named for readability. Something like:
bool isCentered = center == 2;
bool inLowerRegion = (y-height/2) == j && (x+width/2) == i;
bool inUpperRegion = (y+height/2) == j && (x+width/2) == i;
bool inEitherRegion = inLowerRegion || inUpperRegion;
if (isCentered && inEitherRegion) {
regenerateDot(i+1, j, dots);
}
Consider refactoring. You could put sub expressions into their own functions, thus naming their purpose.
For example:
if (IsCentered(center) && IsInsideLower(y, j, i) && IsInsideUpper(y, j, i))
regenerateDot(i + 1, j, dots);
Note that in the above example the function names might be bogus (I haven't really attempted to understand what the purpose of the code is), but you should get the picture.
Almost all the parenthesis are redundant... and adding some whitespace it becomes:
if(center == 2 &&
(y - height/2 == j && x + width/2 == i ||
y + height/2 == j && x + width/2 == i))
regenerateDot(i+1, j, dots);
For something complicated I'd probably break it down into what each condition (grouped by shared &&) is trying to signify and assign it to a sensible variable name.
At most you can remove extra braces, add some spaces and put the logical partitions in different lines as,
if(center == 2 &&
(((y - height/2) == j || (y + height/2) == j) && (x + width/2) == i))
{
regenerateDot(i+1, j, dots);
}
Edit: You have one redundant condition (x + width/2) == i which I have optimized here.
This is the same as the code you posted:
if( center == 2 )
{
if( (x+width/2) == i )
{
if( (y-height/2) == j ) || (y+height/2) == j ) )
{
regenerateDot(i+1, j, dots);
}
}
}
Re-ordering it would give something like :
if (center==2 && (i-x)==(width/2) && abs(j-y)==(height/2))
regenerateDot(i+1, j, dots);
I would do it like this
if (2 == center &&
(((y - height/2) == j && (x + width/2) == i) ||
((y + height/2) == j && (x + width/2) == i))
)
{
regenerateDot(i + 1, j, dots);
}