Arduino check non alphanumeric - c++

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

Related

If statement incorrectly recognising spaces in a bracket

I am writing a mini programming language and I am currently working on my first proper command. My command is called 'prout("Sample text")'. When my program sees a space in between the letter t from the word prout and the opening bracket, it outputs an unexpected indent error, which is supposed to happen. What isn't supposed to happen is it recognising spaces in the text that the user wants to output and outputs an unexpected indent error. Does anybody know how to implement a way to stop the program from recognising that spaces in the text that the user wants to output is an unexpected indent error?
Here is the current output:
>>> prout("Hello")
Hello
>>> prout ("Hello")
Error: Unexpected indent //That is supposed to happen
>>> prout("Hello I am a programmer!")
Error: Unexpected indent //That is the problem
I've tried to use the attribute .npos to filter the spaces but this hasn't worked.
#include <iostream>
#include "printoutput.h"
#include "Line.h"
using namespace std;
void printoutput::print(string input) {
int i = 0;
int length = input.length();
if (input.find('(') != input.npos && (input.find(')') != input.npos) && (input.find('\"') != input.npos)) {
for (int i = 0; i <= input.length(); i++) {
char letter = input[i];
if (input.find(' ') != input.npos && (i == 5)) {
cout << "Error: Unexpected indent";
break;
}
if ((letter == 'p') && (i != 0) || (letter == 'r') && (i != 1) || (letter == 'o') && (i != 2) || (letter == 'u') && (i != 3) || (letter == 't') && (i != 4) || (letter == '(') && (i != 5) || (letter == '\"') && (i != 6 && i != input.length() - 2) || (letter == ')') && (i != length - 1)) {
char inputletter = input[i];
cout << inputletter;
}
else if ((i != 0 && (i != 1) && (i != 2) && (i != 3) && (i != 4) && (i != 5)) && (i != 6 && i != length - 2) && (i != length - 1)) {
char inputletter = input[i];
cout << inputletter;
}
}
}
if (input.find('\"') == input.npos) {
cout << "Syntax error: Missing quotation marks";
}
else if (input.find('(') == input.npos || (input.find(')')) == input.npos) {
cout << "Syntax error: Missing parenthesis";
}
cout << endl;
}
I expect the output to show the user's text that they have wanted to output with the spaces that they may have included.
Think about what this line does
if (input.find(' ') != input.npos && (i == 5)) {
If says if the input contains a space and if i equals 5 then output an error. Since i loops through all the indexes of the string this will be true of any string of length at least 5, which contains a space anywhere.
I'm thinking that what you really meant is this
if (input[5] == ' ')
but I'm not really sure.

How can I switch what points on an array equal in c++?

These change the array that I print to the screen. direc is an input before this. However, when array[1][2] == '#', it still moves '#' to array[1][0].
if (array[1][1] == '#' && direc == 'A' || direc == 'a' ) {
array[1][1] = '_';
array[1][0] = '#';
}
else {
if (array[1][1] == '#' && direc == 'D' || direc == 'd' ) {
array[1][1] = '_';
array[1][2] = '#';
}
else {
if (array[1][2] == '#' && direc == 'A' || direc == 'a' ) {
array[1][1] = '#';
array[1][2] = '_';
}
}
}
You can either add parentheses, as already noted in the comments, like this
if (array[1][1] == '#' && (direc == 'A' || direc == 'a' )) {
Alternatively you could use std::tolower in which case you no longer nee
if (array[1][1] == '#' && std::tolower(direc) == 'a') {
You could still add extra parentheses if you are not comfortable that operator && is lower precedence than operator ==
(the full table of operator precedences can be seen here)

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;
}

Simplifying a function based on matching the pattern of a string

Question: I'm new to C++ and after writing the following code seems like there should be a way to shorten it. Maybe by somehow matching the string? How would this be done?
The function takes a string message received via Serial port and sets the value of a particular element of the pinValues[] array depending on the message. The value that will be set is determined by the last character H or L just before the \n.
String pattern: (a number)(H or L)\n
Eg: message == "4H\n" will set the 5th element pinValues[4] to HIGH. The number at the start of the string can be 1 to 2 digits.
void setPinValues(String message) {
if( message == "1H\n" ) {
pinValues[1] = HIGH;
}
if( message == "1L\n" ) {
pinValues[1] = LOW;
}
if( message == "2H\n" ) {
pinValues[2] = HIGH;
}
if( message == "2L\n" ) {
pinValues[2] = LOW;
}
if( message == "3H\n" ) {
pinValues[3] = HIGH;
}
if( message == "3L\n" ) {
pinValues[3] = LOW;
}
if( message == "4H\n" ) {
pinValues[4] = HIGH;
}
if( message == "4L\n" ) {
pinValues[4] = LOW;
}
if( message == "5H\n" ) {
pinValues[5] = HIGH;
}
if( message == "5L\n" ) {
pinValues[5] = LOW;
}
if( message == "6H\n" ) {
pinValues[6] = HIGH;
}
if( message == "6L\n" ) {
pinValues[6] = LOW;
}
}
This is probably not the official "C++"-approved way of doing it, but you could do:
unsigned int pinNo = 0;
unsigned char level = 0;
int result = sscanf(message.c_str(), "%u%c", &pinNo, &level);
if (result < 2)
// it failed
if (pinNo > 6)
// bad data
levelVal = (level == 'H') ? HIGH : LOW;
I'd do some sanity checking on the string while extracting the key and value from the first two chars. If you don't need to sanity check the message, it could be as short as
void setPinValues(String message) {
pinValues[ message[0] - '0' ] = (message[1] == 'H') ? HIGH:LOW;
}
Although you may want to make that a little longer, i.e. check the string length, and that the 2 chars your checking are in the right range. i.e
void setPinValues(string message) {
if (
message.size() >= 2
and
message[0] >= '1' and message[0] <= '6'
and (message[1]=='H' or message[1]=='L')
) {
pinValues[ message[0] - '0' ] = (message[1] == 'H') ? HIGH:LOW;
}
}
EDIT: you could also extend that to checking two leading digits, i.e.
int n, off=0;
if ( s[off] <= '9' and s[off] >= '0')
{
n = s[off++] - '0';
}
if ( s[off] <= '9' and s[off] >= '0')
{
n = 10*n + s[off++] - '0';
}
if (off > 0 and (s[1]=='H' or s[1]=='L')) {
pinValues[ message[0] - '0' ] = (message[1] == 'H') ? HIGH:LOW;
}
Assuming String is actually a std::string or has an identical interface, and also assuming an ASCII-compatible character set...
void setPinValues(String message) {
const size_t sz = message.size();
// input validation, ignore the message if it doesn't fit the pattern
// you can remove this "if" block if the message has already been validated
if ( (sz < 3) || (sz > 4)
// note how message[0] will be checked twice if sz == 3
// once as message[0] and once as message[sz -3]
// but if sz == 4 we check message[0] and message[1]
|| (message[0] < '0') || (message[0] > '9')
|| (message[sz - 3] < '0') || (message[sz - 3] > '9')
|| ((message[sz - 2] != 'H') && (message[sz - 2] != 'L'))
|| (message[sz - 1] != '\n'))
return;
// convert the first or two characters to a number
int pinNumber = message[0] - '0';
if (sz == 4)
pinNumber = (pinNumber * 10) + (message[1] - '0');
// additional check to verify the pin number is in the correct range
if ((pinNumber < 1) || (pinNumber > 6))
return;
// apply
pinValues[pinNumber] = (message[sz - 2] == 'H' ? HIGH : LOW);
}

What is wrong with my logic?

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)))