Non-visible char in const char * as strtok() delimiter - string

I had to split the payload of network data by the "new line" or "line feed" character (dec 10, hex 0x0A).
So i tried to use strtok() function with which i encountered several problems
when i wanted to make a const char string with the "new line" character.
Proto:
`strtok(char * StringToSplit, const char * Delimiters)`
This made an invalid initializer:
`const char delim[] = 10;`
This gave warning about making pointer from int without cast;
Allthough
printf("Delim: %x", delim)
showed correct value of delim (0xa)
the app crashes when used in strtok().
`const char * delim = 10;`
No warning or errors, printf("Delim: %x", delim) gave correct value
but strtok() didn't work (as i expected, though).
`char delim = 10;`
`(ofc strtok(..., &delim))`
This seemed to do the job but i still got a warning about passing a non const char ptr where a const char ptr was expected to strtok() function.
`char delim[] = "#";`
`delim[0] = 10;`
Finally this seems to work without warnings.
`char tmp[] = "#";`
`tmp[0] = 10;`
`const char *delim = tmp;`
Question is, what would be the simplest and most elegant way to pass such a non-visible character to the strtok() function?
To me it feels like this is just kludged code.

You need:
const char *delim = "\n";
The second parameter needs to be a C string containing the delimiters. What you have in your various incarnations are lots of things that aren't C strings being incorrectly cast to C strings.

It's not kludged or inelegant, it's just got lots of bugs.
const char delim[] = 10;
Why are you declaring an array here? This should be:
const char delim = 10;
And then:
char delim[] = "#";
Why are you declaring an array and setting it equal to a string? This shuld be:
char delim = '#';

Related

How to get the 2nd and 3rd character of a String as Integer - C89

So if I have a String
char string[4];
string = "A10";
How Can I get 10 as an Integer.
I tried getting 10 by itself using this but it didn't work.
char string[4];
char string2[2];
string = "A10";
string2[0] = string[1];
string2[1] = string[2];
I don't need to worry about the A, I know how to get that, I need to be able to get the 10 as an integer.
In java you can use the following code to convert string to integer,
int i=Integer.parseInt(s2);
for more information view this website,
https://www.javatpoint.com/java-string-to-int

Grabbing first number in string after some keyword occurrence in C++ (Arduino)

I have a string coming from PC through serial to a microcontroller (Arduino), e.g.:
"HDD: 55 - CPU: 12.6 - Weather: Cloudy [...] $";
by this function I found:
String inputStringPC = "";
boolean stringCompletePC = false;
void serialEvent() {
while (Serial.available()) {
char inChar = (char)Serial.read();
inputStringPC += inChar;
if (inChar == '$') // end marker of the string
{
stringCompletePC = true;
}
}
}
I would like to extract the first number of it after the word HDD, CPU and also get the string after Weather (ie "cloudy"); my thinking is something like that:
int HDD = <function that does that>(Keyword HDD);
double CPU = <function that does that>(Keyword CPU);
char Weather[] = <function that does that>(Keyword Weather);
What is the right function to do that?
I looked into inputStringSerial.indexOf("HDD") but I am still a learner to properly understand what it does and don't know if theres a better function.
My approach yielded some syntax errors and confused me with the difference in usage between "String inputStringSerial" (class?) and "char inputStringSerial[]" (variable?). When I do 'string inputStringSerial = "";' PlatformIO complains that "string" is undefined. Any help to understand its usage here is greatly appreciated.
Thanks a bunch.
The String class provides member functions to search and copy the contents of the String. That class and all its member functions are documented in the Arduino Reference:
https://www.arduino.cc/reference/tr/language/variables/data-types/stringobject/
The other way a list of characters can be represented is a char array, confusingly also called a string or cstring. The functions to search and copy the contents of a char array are documented at
http://www.cplusplus.com/reference/cstring/
Here is a simple Sketch that copies and prints the value of the Weather field using a String object. Use this same pattern - with different head and terminator values - to copy the string values of the other fields.
Once you have the string values of HDD and CPU, you'll need to call functions to convert those string values into int and float values. See the String member functions toInt() and toFloat() at
https://www.arduino.cc/reference/en/language/variables/data-types/string/functions/toint/
or the char array functions atoi() and atof() at
http://www.cplusplus.com/reference/cstdlib/atoi/?kw=atoi
String inputStringPC = "HDD: 55 - CPU: 12.6 - Weather: Cloudy [...] $";
const char headWeather[] = "Weather: "; // the prefix of the weather value
const char dashTerminator[] = " -"; // one possible suffix of a value
const char dollarTerminator[] = " $"; // the other possible suffix of a value
void setup() {
int firstIndex; // index into inputStringPC of the first char of the value
int lastIndex; // index just past the last character of the value
Serial.begin(9600);
// find the Weather field and copy its string value.
// Use similar code to copy the values of the other fields.
// NOTE: This code contains no error checking for unexpected input values.
firstIndex = inputStringPC.indexOf(headWeather);
firstIndex += strlen(headWeather); // firstIndex is now the index of the char just past the head.
lastIndex = inputStringPC.indexOf(dollarTerminator, firstIndex);
String value = inputStringPC.substring(firstIndex, lastIndex);
Serial.print("Weather value = '");
Serial.print(value);
Serial.println("'");
}
void loop() {
// put your main code here, to run repeatedly:
}
When run on an Arduio Uno, this Sketch produces:
Weather value = 'Cloudy [...]'

Conversion of character code for a letter to a string containing the letter itself in MSVC

MSVC 2015 CLI: I used the following code to convert the unicode for the letter A (i.e. decimal 65) into a string containing the letter itself:
int i = 65;
char c = (char)(i);
return c.ToString();
The string returned is not "A" but "65"
To resolve, I had to use the std string, i.e.
int i = 65;
char c = (char)(i);
std::string MyStdString = &c;
String^ d = gcnew String(MyStdString.c_str());
return d;
The string returned is "A"
There must be a way to solve this without the second approach. Although this solved my issue, I would be grateful for help on syntax for the first approach, and to understand why it won't work as it is.
You are mixing between char and Char(Note Capital C).
Following code should give you expected result:
int i = 65;
Char c = i;
Console::WriteLine(c.ToString());

Cannot insert character in string

So basically my function goes through every character in a string and inserts each character onto another string so it results in the initial string being reversed. I've looked up online but the answers to this problem seem to not work anymore, I'm not sure if it's because they are from 5+ years ago or I'm getting something wrong somewhere. My code goes like this:
long reverse_num(long n){
string new_str = "";
string my_str = to_string(n);
int my_int;
for (unsigned i = 0; i < my_str.size(); ++i){
new_str.insert(0, char my_str[i]);
}
my_int = stol(new_str);
return my_int;
}
The error given is: expected primary-expression before 'char'
new_str.insert(0, char my_str[i]);
What am I doing wrong?
Thanks!
First, you shouldn't specify the char type in the insert expression. Also, there isn't a string insert function that matches what you're doing here; you probably want one of these:
basic_string& insert(size_type pos, size_type n, charT c);
iterator insert(const_iterator p, charT c);
So your insert line should be one of these:
new_str.insert(0, 1, my_str[i]);
new_str.insert(new_str.begin(), my_str[i]);
Your type cast syntax was bad, but you appear to be attempting to insert a char into an std::string. This is the function you appeared to be going for:
http://en.cppreference.com/w/cpp/string/basic_string/insert
basic_string& insert( size_type index, size_type count, CharT ch );
Try
new_str.insert(0, 1, my_str[i]);
You also could have used http://en.cppreference.com/w/cpp/algorithm/reverse
std::reverse(my_str.begin(), my_str.end());

Error in using indexOf not finding char in Arduino String

I have some code that I have no clue why it isn't working.
The code takes a serial input in the form of "xxx,yyy,zzz", where digits can range from 1 to 3 in each number. Because of an odd quirk in an app, it needs to be read as a char, then converted to a string to be handled. The intention is to split into 3 ints, red green and blue, from "RRR,GGG,BBB".
Now this works fine when I manually define String str (see commented code), but when I go and enter it from the serial console, it doesn't want to work. It seems to be coming from the indexOf(',') part, as while using Serial.print(c1);, I found that when I manually entered a string, it returned an index of the comma, but when I used the serial console, it returned -1 (not found).
And yes, the entered string into the console is in the correct format of "RRR,GGG,BBB", I've confirmed that by printing both phone and str independently.
while (Serial.available() > 0) {
char phone = Serial.read();
String str = String(phone);
//String str = "87,189,183";
int ln = str.length()-1;
int c1 = str.indexOf(','); //first place to cut string
int c2 = str.indexOf(',',c1+1); //second place
red = str.substring(0,c1).toInt();
green = str.substring(c1,c2).toInt();
blue = str.substring(c2,ln).toInt();
Serial.print(red);
Edit: With the Arduino String class, creating a string from a char is returning more than just one character, eleven in fact.
This:
char phone = Serial.read();
String str = String(phone);
will never create a string in str that has more than 1 character, since that's what you say you want.
This is the code for the Arduino's String(char) constructor:
String::String(char c)
{
init();
char buf[2];
buf[0] = c;
buf[1] = 0;
*this = buf;
}
So clearly your code will create a 1-character long string.
Also, beware of using indexes computed on the full string, on substrings later.
I'm try to guess that you are using these serial API http://playground.arduino.cc/Interfacing/CPPWindows.
while (Serial.available() > 0) {
char buf[12];
int len = Serial.ReadData(buf,11);
String str = String(buf);
//String str = "87,189,183";
int ln = str.length()-1;
int c1 = str.indexOf(','); //first place to cut string
int c2 = str.indexOf(',',c1+1); //second place
red = str.substring(0,c1).toInt();
green = str.substring(c1,c2).toInt();
blue = str.substring(c2,ln).toInt();
Serial.print(red);
If you are using other API like http://arduino.cc/en/Serial/Read you should follow these API where Serial is a Stream and read() return just the first available char.
Code was fixed by using a different function.
while (Serial.available() > 0) {
char phone = Serial.read();
str += phone;
//String str = "87,189,183";
int ln = str.length()-1;
int c1 = str.indexOf(','); //first place to cut string
int c2 = str.indexOf(',',c1+1); //second place
red = str.substring(0,c1).toInt();
green = str.substring(c1,c2).toInt();
blue = str.substring(c2,ln).toInt();
Serial.print(red);
I'm not sure why this works, and why before I was getting a string with more than one character. But it works!

Resources