How to convert a String to a char * in Arduino? - c++

I'm doing a function to convert an integer into a hexadecimal char * in Arduino, but I came across the problem of not being able to convert a String to a char *. Maybe if there is a way to allocate memory dynamically for char * I do not need a class String.
char *ToCharHEX(int x)
{
String s;
int y = 0;
int z = 1;
do
{
if (x > 16)
{
y = (x - (x % 16)) / 16;
z = (x - (x % 16));
x = x - (x - (x % 16));
}
else
{
y = x;
}
switch (y)
{
case 0:
s += "0";
continue;
case 1:
s += "1";
continue;
case 2:
s += "2";
continue;
case 3:
s += "3";
continue;
case 4:
s += "4";
continue;
case 5:
s += "5";
continue;
case 6:
s += "6";
continue;
case 7:
s += "7";
continue;
case 8:
s += "8";
continue;
case 9:
s += "9";
continue;
case 10:
s += "A";
continue;
case 11:
s += "B";
continue;
case 12:
s += "C";
continue;
case 13:
s += "D";
continue;
case 14:
s += "E";
continue;
case 15:
s += "F";
continue;
}
}while (x > 16 || y * 16 == z);
char *c;
s.toCharArray(c, s.length());
Serial.print(c);
return c;
}
The toCharArray () function is not converting the string to a char array. Serial.print (c) is returning empty printing. I do not know what I can do.

Updated: Your Question re: String -> char* conversion:
String.toCharArray(char* buffer, int length) wants a character array buffer and the size of the buffer.
Specifically - your problems here are that:
char* c is a pointer that is never initialized.
length is supposed be be the size of the buffer. The string knows how long it is.
So, a better way to run this would be:
char c[20];
s.toCharArray(c, sizeof(c));
Alternatively, you could initialize c with malloc, but then you'd have to free it later. Using the stack for things like this saves you time and keeps things simple.
Reference: https://www.arduino.cc/en/Reference/StringToCharArray
The intent in your code:
This is basically a duplicate question of: https://stackoverflow.com/a/5703349/1068537
See Nathan's linked answer:
// using an int and a base (hexadecimal):
stringOne = String(45, HEX);
// prints "2d", which is the hexadecimal version of decimal 45:
Serial.println(stringOne);
Unless this code is needed for academic purposes, you should use the mechanisms provided by the standard libraries, and not reinvent the wheel.
String(int, HEX) returns the hex value of the integer you're looking to convert
Serial.print accepts String as an argument

char* string2char(String command){
if(command.length()!=0){
char *p = const_cast<char*>(command.c_str());
return p;
}
}

Related

How to convert char into int in a function?

poziomy= char;
pionowy= digit; ( no problems with this one)
So I need to convert char into a digit in function but obviusly I cannot do char=int, so I dont know how to pass on the converted char into digit properly.
I guees i can do two functions but maybe there is an easier way?
I thought of making a new variable poziomy_c but I dont know how to pass it to Ruch_gracza()
int Convert_digit (int cyfra)
{
switch (cyfra)
{
case 10: return 0;break;
case 9: return 1;break;
case 8: return 2;break;
case 7: return 3;break;
case 6: return 4;break;
case 5: return 5;break;
case 4: return 6;break;
case 3: return 7;break;
case 2: return 8;break;
case 1: return 9;break;
}
}
int Convert_letter (char literka)
{
switch (literka)
{
case 'A': return 0; break;
case 'B': return 1; break;
case 'C': return 2; break;
case 'D': return 3; break;
case 'E': return 4; break;
case 'F': return 5; break;
case 'G': return 6; break;
case 'H': return 7; break;
case 'I': return 8; break;
case 'J': return 9; break;
}
}
void Conwert(int &pionowy, char poziomy)
{
pionowy=Convert_digit(pionowy);
int poziomy_c;
poziomy_c=Convert_letter (poziomy);
}
void Ruch_gracza1 (int plansza[10][10])
{
int pionowy ;
char poziomy;
cout << "wprowadz wspolrzedne pola na ktorym lezy pion który chcesz ruszyc ( w pionie , potem w poziomie)" << endl;
cin >> pionowy >> poziomy;
Conwert (pionowy,poziomy);
cout << pionowy << endl;
cout << poziomy << endl;
}
You can use char arithmetic to make this a whole lot easier. Since 'A' to 'Z' will be contiguous in ASCII/Unicode, you can do literka - 'A' to get how far literka is from A (which is what your switch is doing):
int Convert_letter (char literka) {
if(!std::isalpha(literka)) { return literka; } // Not a letter
return std::toupper(literka) - 'A';
}
Or if you want a more robust solution to cover even less common character encodings:
int Convert_letter (char literka) {
if(!std::isalpha(literka)) { return literka; } // Not a letter
std::string alphabet = "abcdefghijklmnopqrstuvwxyz";
return std::distance(std::begin(alphabet), std::find(std::begin(alphabet), std::end(alphabet), literka));;
}
Convert_digit will look similar (except with std::isdigit instead of std::isalpha).
You can do as
char c = 'B';
int digit = c - 'A';
return digit;
You need some knowledge about the ASCII table and data type in C++.
Simply, a char is an integer from -128 ... 127. If you declare a char variable name ch like this:
char ch = 'B';
C++ will understand that ch = 66 (look at ASCII table). So that we can do arithmetic operator with ch like an integer variable.
ch - 'A'; // result 1, because 'A' = 65
ch - 65; // same result with ch - 'A'
Finally, you can write your function like this:
int functionChar2Int(char x){
return x - 'A';
}

Basic program to convert Roman number Arabic form?

I am wanting some help in answering these two questions. The first one is this:
I am trying to write a program that converts a single Roman number in the range I (1) to IX (9) to Arabic form. The
program should read a single string from standard input and print the corresponding value to standard output.
I then want to Extend the program so that it works correctly when the input consists of either lower case or upper case Roman letters.
The simplest approach is to convert each character in the input word into uppercase before trying to find a match. Run a
loop over the characters in the string using the index operator ([]) to access each character and use the toupper
function (you will need to include the cctype header file) to get the corresponding uppercase value.
For the second question this is what it wants me to do next:
Extend the program so that it can deal with single digit numbers of any value. A single digit number is one that consists
only of thousands, hundreds, tens, or units. Thus LXX (70) and CD (400) are single digit numbers, but XIV (14) and
MC (1100) are not. Use the same approach as for units digits, but with 4 different arrays, one each for the thousands,
hundreds, tens, and units digits. Try looking for thousands digits first, then for hundreds, and so on. When you find a
match in one of the arrays, print the corresponding value and stop.
Modify the program so that it reads and converts all input numbers until end of file (eof) on standard input. You will
probably be able to do this by simply adding an appropriate reading loop around the code that reads a single line.
Currently this is what i have to start but am unsure how to write a program like this:
#include <iostream>
#include <string>
#include <stdexcept>
using namespace std;
class RomanNumeral
{
public:
const static int M = 1000;
const static int D = 500;
const static int C = 100;
const static int L = 50;
const static int X = 10;
const static int V = 5;
const static int I = 1;
RomanNumeral( const int arabic ) :
m_roman( "" ),
m_arabic( ((arabic > 0) ? arabic : 0) )
{
if( arabic > 0 )
{
int i = arabic;
while( i > 0 )
{
if( ( i - M ) >= 0 )
{
m_roman += "M";
i -= M;
continue;
}
if( ( i - D ) >= 0 )
{
m_roman += "D";
i -= D;
continue;
}
if( ( i - C ) >= 0 )
{
m_roman += "C";
i -= C;
continue;
}
if( ( i - L ) >= 0 )
{
m_roman += "L";
i -= L;
continue;
}
if( ( i - X ) >= 0 )
{
m_roman += "X";
i -= X;
continue;
}
if( ( i - V ) >= 0 )
{
m_roman += "V";
i -= V;
continue;
}
if( ( i - I ) >= 0 )
{
m_roman += "I";
i -= I;
continue;
}
}
}
else
{
m_roman = "0";
}
}
RomanNumeral( const std::string& string ) :
m_roman( ((string.size() > 0 ) ? string : "0" ) ),
m_arabic( 0 )
{
int i = 0;
while( i < (int)string.size() )
{
char c = string[i++];
switch( c )
{
case 'M':
case 'm':
m_arabic += M;
break;
case 'D':
case 'd':
m_arabic += D;
break;
case 'C':
case 'c':
m_arabic += C;
break;
case 'L':
case 'l':
m_arabic += L;
break;
case 'X':
case 'x':
m_arabic += X;
break;
case 'V':
case 'v':
m_arabic += V;
break;
case 'I':
case 'i':
m_arabic += I;
break;
default:
throw new std::out_of_range( "Not a valid Roman numeral!" );
break;
}
}
}
int getArabic()
{
return m_arabic;
}
void setArabic( const int arabic );
const std::string& getRoman()
{
return m_roman;
}
protected:
std::string m_roman;
int m_arabic;
};
int main()
{
std::string roman;
cin >> roman;
try
{
RomanNumeral rn( roman );
cout << rn.getArabic() << endl;
}
catch( exception* ex )
{
cout << roman << " " << ex->what() << endl;
}
return 0;
}
Have been doing some tutorials on it but came across this question on a website the other day but I can't find the solution to this to see how its done. Could you demonstrate how to write a program like this by any chance?
Whenever you're stuck on a problem, try to decompose it into steps and implementing the things you can.
Step one is reading a single word:
std::string word;
std::cin >> word;
Step two is converting the word into a number:
int convert_to_number(const std::string& w) {
if (w == "I") return 1;
if (w == "II") return 2;
// and so on.
}
Step three is doing the conversion and printing the result:
std::cout << convert_to_number(word) << std::endl;
Instead of writing large amounts of if statements, you may want to try using an std::map<std::string, int> or std::unordered_hash<std::string, int> for a constant-time lookup.

How to form an ASCII(Hex) number using 2 Chars?

I have char byte[0] = '1' (H'0x31)and byte[1] = 'C'(H'0x43)
I am using one more buffer to more buff char hex_buff[0] .i want to have hex content in this hex_buff[0] = 0x1C (i.e combination of byte[0] and byte[1])
I was using below code but i realized that my code is valid for the hex values 0-9 only
char s_nibble1 = (byte[0]<< 4)& 0xf0;
char s_nibble2 = byte[1]& 0x0f;
hex_buff[0] = s_nibble1 | s_nibble2;// here i want to have 0x1C instead of 0x13
What keeps you from using strtol()?
char bytes[] = "1C";
char buff[1];
buff[0] = strtol(bytes, NULL, 16); /* Sets buff[0] to 0x1c aka 28. */
To add this as per chux's comment: strtol() only operates on 0-terminated character arrays. Which does not necessarily needs to be the case for the OP's question.
A possible way to do it, without dependencies with other character manipulation functions:
char hex2byte(char *hs)
{
char b = 0;
char nibbles[2];
int i;
for (i = 0; i < 2; i++) {
if ((hs[i] >= '0') && (hs[i] <= '9'))
nibbles[i] = hs[i]-'0';
else if ((hs[i] >= 'A') && (hs[i] <= 'F'))
nibbles[i] = (hs[i]-'A')+10;
else if ((hs[i] >= 'a') && (hs[i] <= 'f'))
nibbles[i] = (hs[i]-'a')+10;
else
return 0;
}
b = (nibbles[0] << 4) | nibbles[1];
return b;
}
For example: hex2byte("a1") returns the byte 0xa1.
In your case, you should call the function as: hex_buff[0] = hex2byte(byte).
You are trying to get the nibble by masking out the bits of character code, rather than subtracting the actual value. This is not going to work, because the range is disconnected: there is a gap between [0..9] and [A-F] in the encoding, so masking is going to fail.
You can fix this by adding a small helper function, and using it twice in your code:
int hexDigit(char c) {
c = toupper(c); // Allow mixed-case letters
switch(c) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9': return c-'0';
case 'A':
case 'B':
case 'C':
case 'D':
case 'E':
case 'F': return c-'A'+10;
default: // Report an error
}
return -1;
}
Now you can code your conversion like this:
int val = (hexDigit(byte[0]) << 4) | hexDigit(byte[1]);
It looks like you are trying to convert ASCII hex into internal representation.
There are many ways to do this, but the one I use most often for each nibble is:
int nibval(unsigned short x)
{
if (('0' <= x) && ('9' >= x))
{
return x - '0';
}
if (('a' <= x) && ('f' >= x))
{
return x - ('a' - 10);
}
if (('A' <= x) && ('F' >= x))
{
return x - ('A' - 10);
}
// Invalid input
return -1;
}
This uses an unsigned int parameter so that it will work for single byte characters as well as wchar_t characters.

Assign Unicode values to char

My code includes a loop in which checks every character of a std::string, assign it to a char variable, which fails its assertion when -1 >= c >= 255.
It is a method from a JSON parser class that it's not mine:
static std::string UnescapeJSONString(const std::string& str)
{
std::string s = "";
for (int i = 0; i < str.length(); i++)
{
char c = str[i]; // << HERE FAILS WHEN 'É' CHARACTER
if ((c == '\\') && (i + 1 < str.length()))
{
int skip_ahead = 1;
unsigned int hex;
std::string hex_str;
switch (str[i+1])
{
case '"' : s.push_back('\"'); break;
case '\\': s.push_back('\\'); break;
case '/' : s.push_back('/'); break;
case 't' : s.push_back('\t'); break;
case 'n' : s.push_back('\n'); break;
case 'r' : s.push_back('\r'); break;
case 'b' : s.push_back('\b'); break;
case 'f' : s.push_back('\f'); break;
case 'u' : skip_ahead = 5;
hex_str = str.substr(i + 4, 2);
hex = (unsigned int)std::strtoul(hex_str.c_str(), nullptr, 16);
s.push_back((char)hex);
break;
default: break;
}
i += skip_ahead;
}
else
s.push_back(c);
}
return Trim(s);
}
How can I assign a Unicode value to a char? In this case the value is É, and the code is not ready to receive such a characters.
This is included into a dll library, and is giving me this error:
The std::string doesn't use Unicode. This is evident because there is a method c_str that lets you get a char array from the std::string.
Answering your question, your test is wrong:
-1 >= c && c >= 255
It should be:
-1 <= c && c <= 255
But you can't get c anywhere near 255 since the char is signed.
If you want to get 255 out a char it needs to be
unsigned char
This will not let you reach -1 though.
Read about char*'s here:
http://www.cplusplus.com/doc/tutorial/variables/
see char arrays here:
http://www.cplusplus.com/doc/tutorial/ntcs/
see std::string here:
http://www.cplusplus.com/reference/string/string/

convert number with decimal places from char to int in c++

I was playing around with VS 2012 and came across a very tricky problem (for me at least). I have a simple program that does mathematical operations on inputs from the command line. However, if you input arguments with decimal places somewhere in the program it seems to forget the numbers after the decimal place.
double add (char const *inp, char const *inp2) { //addition function
double val = std::strtol(inp, NULL, 0);
double val2 = std::strtol(inp2, NULL, 0);
return val + val2;
}
and then calling the function :
double result = add(argv[1], argv[2]);
printf("%f \n", result);
and call from command line
test 52.2 44.6
returns 96 instead of 96.8.
You want strtod, not strtol. strtol only parses integers.
strtod only takes two arguments, because floating point numbers are always in base 10 (as far as strtod is concerned, anyway.)
I think you are turning your strings into longs (I'm guessing that's what strtol() is...). I was building a calculator and I had that problem - I wrote a function to handel it:
double string_to_double(string str)
{
int length = (int)str.length();
double output = 0; //This holds value of output. Will be added for each 10's digit
int decimalPos = length - 1;
for (int i = 0; i < length; i++)
{
if(str.at(i) == '.') // Find if there is a decimal point
{
decimalPos = i - 1; //Sets Decimal Position
str.erase(str.begin()+i);
length--;
}
}
for (int i = 0; i < length; i++)
{
switch (str.at(i))
{
case '1':
output += 1*pow(10, decimalPos - i);
break;
case '2':
output += 2*pow(10, decimalPos - i);
break;
case '3':
output += 3*pow(10, decimalPos - i);
break;
case '4':
output += 4*pow(10, decimalPos - i);
break;
case '5':
output += 5*pow(10, decimalPos - i);
break;
case '6':
output += 6*pow(10, decimalPos - i);
break;
case '7':
output += 7*pow(10, decimalPos - i);
break;
case '8':
output += 8*pow(10, decimalPos - i);
break;
case '9':
output += 9*pow(10, decimalPos - i);
break;
case '0':
break;
}
}
return output;
}
...but there is probably a better way