C++ toUpper Implementation - c++

I made an implementation of toUpper(). It doesn't work 100%.
Code :
char* toUpper(char* string)
{
char* sv = string;
while(*sv++ != '\0')
{
if( int(*sv) >= 97 || int(*sv) <= 122) //Only if it's a lower letter
*sv = char( *sv - 32);
}
return string;
}
I know that the lower letters have the numbers from 97 to 122 (in ASCII) and the upper letters have the numbers from 65 to 90. There are exactly 32 numbers between the lower to the upper letter. So I just subtracted 32 from the lower character.
Code where I call this function :
char h[] = "Whats up?";
cout << toUpper(h) << endl;
I expected the program to output "WHATS UP?" but instead I got "WHATS". What did I do wrong?

if( int(*sv) >= 97 || int(*sv) <= 122)
should be
if( int(*sv) >= 97 && int(*sv) <= 122)
or, preferably
if( *sv >= 'a' && *sv <= 'z')
*sv = *sv - ('a' - 'A');
You also need to move the point at which you increment sv. The current code skips checking the first character in string
while(*sv != '\0')
{
if( *sv >= 'a' && *sv <= 'z')
*sv = *sv - ('a' - 'A');
sv++;
}
Lastly, I'm sure you're aware of it but just in case... if this isn't a homework assignment or other learning exercise, the standard C toupper function will do exactly the same job for you
*sv = (char)toupper(*sv);

Having ++ in the while makes you miss important cases. The int() things are unnecessary noise. You need && in the check condition. The action can be written with -=.

Here's a rewrite that uses a for loop and fixes your conditional as well as off-by-one increment:
char* toUpper(char* string)
{
for(char* p=string; *p != '\0'; p++)
{
if(*p >= 'a' && *p <= 'z') //Only if it's a lower letter
*p -= 32;
}
return string;
}

Related

Array does not store beyond first space

the input provided through temp is a sentence, and I need to remove spaces and special characters but 'mes' stores only the first word
#include <iostream>
#include <cmath>
using namespace std;
int main(){
char mes[51];
char pas[11];
char tem[51];
cin.getline(tem,51);
cin.getline(pas,11);
for(int i=0;i<51;i++){
mes[i]='\0';
}
for(int t=0;t<sizeof(pas);t++){
pas[t]=tolower(pas[t]);
}
for (int i=0;i<50;i++){
char c=tem[i];
int ch=(int)c;
if(( ch >= 65 && ch <= 90) || ( ch >= 97 && ch <= 122)){
if( ch >= 65 && ch <= 90)
ch+=32;
mes[i]=(char)ch;
}
else
continue;
}
cout<<mes<<endl;
Notice that you are setting each index in mes to '\0', aka NUL. When you are iterating through tem checking if each character is a letter, you are inadvertently separating the words by \0 inside mes. You need to have a separate index that allows you to add the letters when you find them.
Your for loop could look like this.
int currentIndex = 0;
for (int i = 0; i < 50; i++){
char c = tem[i];
int ch = (int)c;
if(( ch >= 65 && ch <= 90) || ( ch >= 97 && ch <= 122)){
if( ch >= 65 && ch <= 90)
ch+=32;
mes[currentIndex++]=(char)ch;
}
else
continue;
}
This way, you will be adding the letter directly after the next, rather than something like Hello\0World.
Also, remember that cout will only print strings up until it finds a \0 character. Technically you are storing all letters you find in a sentence, but they are separated by \0 and therefore, cout only prints the first word.

Extracting int from String on Arduino

I have a buffer of random characters streaming into my Arduino from a XBee module. I want to extract the first integer that it sees (will be <= 3-digit int if that makes a difference), then move on with that number and stop looking at the rest of the incoming characters.
For reference, I'm trying to use this as part of a 2-way handshake with a node.js server that doesn't get messed up when other Arduinos are also attempting to handshake or are already connected and sending data.
I think I have a way that might work to extract an int, but it seems really ugly, so I'm thinking there must be a much shorter/cleaner way to go about this. Here's my very long code to do something that's probably pretty simple:
String intString = "";
int intStart = 0;
for (int i = 0; i < msg.length(); i++) {
while (intStart != 2) {
if (intStart == 0) {
if ((msg[i] == '0') || (msg[i] == '1') || (msg[i] == '2') ||
(msg[i] == '3') || (msg[i] == '4') || (msg[i] == '5') ||
(msg[i] == '6') || (msg[i] == '7') || (msg[i] == '8') ||
(msg[i] == '9')) {
intString += msg[i];
intStart = 1;
}
}
// previous int, next is still int
if (intStart == 1) {
if ((msg[i] == '0') || (msg[i] == '1') || (msg[i] == '2') ||
(msg[i] == '3') || (msg[i] == '4') || (msg[i] == '5') ||
(msg[i] == '6') || (msg[i] == '7') || (msg[i] == '8') ||
(msg[i] == '9')) {
intString += msg[i];
intStart = 1;
}
}
// previous int, next is not int
else if ((msg[i] != '0') && (msg[i] != '1') && (msg[i] != '2') &&
(msg[i] != '3') && (msg[i] != '4') && (msg[i] == '5') &&
(msg[i] != '6') && (msg[i] != '7') && (msg[i] == '8') &&
(msg[i] != '9')) {
intStart = 2;
}
}
}
int number = intString.toInt();
Serial.println(number);
Any suggestions/advice is greatly appreciated.
Rather than compare against every number from 0 to 9, use the standard C function isdigit().
String intString = "";
int intStart = 0;
for (int i = 0; i < msg.length(); i++) {
while (intStart != 2) {
if (intStart == 0) {
if (isdigit(msg[i])){
intString += msg[i];
intStart = 1;
}
}
// previous int, next is still int
if (intStart == 1) {
if (isdigit(msg[i])) {
intString += msg[i];
intStart = 1;
}
}
// previous int, next is not int
else if ( isdigit(msg[i]) ) {
intStart = 2;
}
}
}
"Rubber duck debugging":
Let's assume the first char of the msg is a digit:
set intStart to 0
take the first char of the msg
while intStart is not yet 2
if intStart is 0 (it is, we haven't adjusted it) and the first char of the msg is digit (we assumed it is), then append the first char to intString and make intStart = 1
if intStart == 1 (it is, we set it at the prev step) and the first char of the msg is digit (it is still the first, i didn't change), then append the first char to intString (great, now I have it twice) and set intStart=1 (hey, intStart didn't change). Else... well, we can ignore else, we are in the good conditions for then
so back to the step 3, with the intStart==1 and i still 0 and the first char of the msg still a digit.
Should I continue or are you able to do it?
In essence, with the first char of the msg a digit, you'll never get out from while (intStart != 2) until you run out of heap-space due to intString growing by repeating the same fisrt char all over.
Is that what you want?
Is it so hard to explain this to your rubber duck before asking SO?(yes, I understand, Arduino doesn't have a debugger, but you still can use Serial.print)
[Update on the comments]
Sorry if I was unclear, but it doesn't necessarily start with an integer, the integer could be in the middle of the char buffer.
The first sequence of digits in the char buffer of any length (really doesn't have to be restricted to max 3-digit, only if it makes it easier)
So, before stating to collect, we just need to position ourselves on the first digit of the string buffer
int startScan=0;
// no body for the cycle, everything works just from
// the exit condition and increment
for(
;
startScan < msg.length() && ! isdigit(msg[i]); // as long as it's not a digit
startScan++
);
// from this position, start collecting for as long as we have digits
int intValue=0;
String intString;
for(; startScan < msg.length() && isdigit(msg[startScan]); startScan++) {
intString += msg[startScan]; // take it inside the string
// careful with this one, it may overflow if too many digits
intValue = intValue*10 + (msg[startScan]-'0');
}
// if we reached here with an empty intString, we didn't find any digits
If you don't need the intString, just the intValue, don;t use the intString - at most a bool hasDigits to init to false and set to true in place of intString += msg[startScan]; (to act as a signal for the 'no digits encountered' case).
If you don't need the intValue, just wipe out from the code anithing that uses it.
So, if my understating is correct, you have the following problem:
I have a String message which starts by at most 3 decimal digits and ends possibly with other info I don't need. I want that 'at most 3 digits' prefix transformed in an integer for me to use further
If this is you problem, then try this:
int intValue=0;
String intString;
int maxLookInto=(msg.length() > 3 ? 3 : msg.length()); // at most 3 digits
for(int i=0; i<maxLookInto && isdigit(msg[i]); i++) {
// if we got here, we know msg[i] is still a digit, otherwise
// we get out of cycle ealier
intString += msg[i]; // take it inside the string
intValue = intValue*10 + (msg[i]-'0'); // transforming in base 10 in an int
}
// Do what you like with either intString (textual representation of the
// at-most-3-digits or with the same value converted already to a number
// in intValue
If Arduino doesn't have the isdigit function available, you can implement your own like
int isdigit(char c) {
// we are using ASCII encoding for characters, aren't we?
return (c>='0' && c <='9');
}
One way is to use the String object. This has a toInt method.
BTW there is an Arduino specific stack exchange. arduino.stackexchange.com

C++ caesar cipher — understanding ascii keys

I am currently doing a caesar cipher program. It should encrypt for both lower and upper case.
e.g
If I typed in a, it will then shift the keys by 3 and the final output will become d.
Take a look at my codes
char c;
c = (((97-52)+3) % 26) + 52;
cout << c;
The letter 'a' has an ASCII code of 97.
So by right
1) ((97-52)+3) will give you 48
2) 48 % 26 will give you 8 since 48/26 will give you a remainder of 8.
3) 8 + 52 = 60(which will by right give you a value of '>' according to the ascii table)
but my output that I have got is J and I don't understand which am I getting the output of 'J' instead of '>'
My concepts might be wrong so I need help.
Let me link ASCII chart I use first: http://pl.wikipedia.org/wiki/ASCII
The website is polish, but table itself is in english.
I think it's plainly obvious that problem is the equatation you use:
(((letter-52)+3) % 26) + 52;
Actually first letter in ASCII is 65(hexadecimal 0x41 - follow with the chart provided).
Your idea with the modulo would be fine, if there were no chars between letter blocks in ASCII. But there are (again check up chart).
That is why you should manually check if the sign:
is a capital letter: if (letter >= 0x41 && letter <= 0x5a)
is a non-capital: if (letter >= 0x61 && letter <= 0x7a)
Usually when making Ceasar cipher, you should follow these:
Replace a capital letter with capital letter moved in the alphabet by a given number.
If the letter would be out of alphabet scope, continue iteration from the start of alphabet (X moved 5 to the right would give C).
Other chars stay the same
Now let's implement this (in code I'll use letter values of chars - to avoid mistakes):
#include <iostream>
#include <cstdlib>
using namespace std;
string Ceasar(string input, int offset)
{
string result = "";
for (int i = 0; i < input.length(); ++i)
{
// For capital letters
if (input[i] >= 'A' && input[i] <= 'Z')
{
result += (char) (input[i] - 'A' + offset) % ('Z' - 'A') + 'A';
continue;
}
// For non-capital
if (input[i] >= 'a' && input[i] <= 'z')
{
result += (char) (input[i] - 'a' + offset) % ('z' - 'a') + 'a';
continue;
}
// For others
result += input[i];
}
return result;
}
int main()
{
cout << Ceasar(string("This is EXamPLE teXt!?"), 8).c_str();
system("PAUSE");
}

how to compare a substring from char array with some valid range?

I have a char * which contains year and month lets say YYYYMM. How can I compare MM within the range of 01 to 12 ? Do I have to do atoi for the substring and do it or anything else exists?
If the first character of the month portion of the string is '0' the second must be between '1' and '9' inclusive to be valid. If the first character is '1' the second must be between '0' and '2' inclusive to be valid. Any other initial character is invalid.
In code
bool valid_month (const char * yyyymm) {
return ((yyymm[4] == '0') && (yyymm[5] >= '1') && (yyymm[5] <= '9')) ||
((yyymm[4] == '1') && (yyymm[5] >= '0') && (yyymm[5] <= '2'));
}
You can do atoi() of the substring or you can simply compare the ASCII values. For example:
if (buf[4] == '0')
{
// check buf[5] for values between '1' and '9'
}
else if (buf[4] == '1')
{
// check buf[5] for values between '0' and '2'
}
else
{
// error
}
Either way is acceptable. I guess it really depends on how you will eventually store the information (as int or string).
Assuming your char* variable is called "pstr" and is null terminated after the MM you can do:
int iMon = atoi(pstr + 4);
if ( (iMon >= 1) && (iMon <= 12) )
{
// Month is valid
}

C++ char hex value to byte

I have a hex value in a char pointer (for example 'F3'), and I would like to convert it to byte, because I want it to put in an array. I know that there are many solutions, but they are not what I wanted.
Thanks in advance!
EDIT:
Okay, maybe I have not written everything.
What I have now:
char aChar[5];
itoa (j, aChar, 16);
j is now 3, and I just want it in byte. Atoi, scanf doesn't help, those are the different solutions.
Since you've tagged this C++ and not C, I'm not going to use any C functions (except assert() to demonstrate the behaviour, edge conditions, et cetera). Here's a sample file. Let's call it hex2byte.cpp:
#include <sstream>
#include <cassert>
unsigned char hex2byte(const char* hex)
{
unsigned short byte = 0;
std::istringstream iss(hex);
iss >> std::hex >> byte;
return byte % 0x100;
}
int main()
{
const char* hex = "F3";
assert(hex2byte(hex) == 243);
assert(hex2byte("") == 0);
assert(hex2byte("00") == 0);
assert(hex2byte("A") == 10);
assert(hex2byte("0A") == 10);
assert(hex2byte("FF") == 255);
assert(hex2byte("EEFF") == 255);
assert(hex2byte("GG") == 00);
assert(hex2byte("a") == 10);
assert(hex2byte("0a") == 10);
assert(hex2byte("f3") == 243);
assert(hex2byte("ff") == 255);
assert(hex2byte("eeff") == 255);
assert(hex2byte("gg") == 00);
}
Make it:
% make hex2byte
g++ -Wall -Wextra -Wshadow -pedantic -Weffc++ -Werror hex2byte.cpp -o hex2byte
Run it:
% ./hex2byte
No assertions. Add error handling to taste (such as checking for when hex == NULL, et cetera).
A byte is usually simply an unsigned char
myArray[n] = (unsigned char)*p;
Or do you mean that you have a string representation of an hex value?
Given a char * with "F3":
char *hexstr = "F3";
Then you can do this:
unsigned char byteval =
(((hexstr[0] >= 'A' && hexstr[0] <= 'Z') ? (10 + hexstr[0] - 'A') :
(hexstr[0] >= 'a' && hexstr[0] <= 'z') ? (10 + hexstr[0] - 'a') :
(hexstr[0] >= '0' && hexstr[0] <= '9') ? (hexstr[0] - '0') : 0) << 4) |
((hexstr[1] >= 'A' && hexstr[1] <= 'Z') ? (10 + hexstr[1] - 'A') :
(hexstr[1] >= 'a' && hexstr[1] <= 'z') ? (10 + hexstr[1] - 'a') :
(hexstr[1] >= '0' && hexstr[1] <= '9') ? (hexstr[1] - '0') : 0);
I'm sorry for its ugliness; I'm sure it can be improved.
You can turn this into a function:
inline unsigned char hextobyte(const char *s) {
return
(((s[0] >= 'A' && s[0] <= 'Z') ? (10 + s[0] - 'A') :
(s[0] >= 'a' && s[0] <= 'z') ? (10 + s[0] - 'a') :
(s[0] >= '0' && s[0] <= '9') ? (s[0] - '0') : 0) << 4) |
((s[1] >= 'A' && s[1] <= 'Z') ? (10 + s[1] - 'A') :
(s[1] >= 'a' && s[1] <= 'z') ? (10 + s[1] - 'a') :
(s[1] >= '0' && s[1] <= '9') ? (s[1] - '0') : 0);
}
I can think of at least five ways:
using sscanf with %x
using strtol with the correct base
using istringstream (though you'll have to down cast from unsigned short to unsigned char)
boost::spirit
hand rolled loop to parse character-by-character
None of the ways you listed would work. But your question still isn't really clear, you have a char which somehow you converted to hex using itoa and now you want to convert to a byte!?! what's wrong with a cast? e.g. unsigned char byte = static_cast<unsigned char>(charvalue);