sscanf error: cannot convert 'String' to 'const char*' - c++

I'm trying to extract two numbers separated by a space from a string and save them as two ints. For example:
if input_string = "1 95" then:
servo_choice = 1
input_number = 95
Code:
String input_string = "";
int input_number = 0;
int servo_choice = 0;
input_string = Serial.readString();
sscanf( input_string, "%d %d", &servo_choice, &input_number );
The IDE gives me this error:
exit status 1
cannot convert 'String' to 'const char*' for argument '1' to 'int scanf(const char*, ...)'
Edit: I guess
input_number = input_string.substring(1,5).toInt();
Actually works and does what I want. I'd still like to know how to get sscanf to work if possible.
Thanks for any replies in advance..

You could try to convert your String into a char array with toCharArray and pass that to sscanf. Something like that (not tested though)
int buffer_len = input_string.length() + 1;
char buffer[buffer_len];
input_string.toCharArray(buffer, buffer_len);
sscanf(buffer, "%d %d", &servo_choice, &input_number);

The String is a class, not a basic type. That means that you need a method to convert / return a pointer to char if you want to use it in a sscanf. That method exists and it's called c_str() .
So, your line has to be:
sscanf( input_string.c_str(), "%d %d", &servo_choice, &input_number );

Related

convert uint_8 ascii to string

I am sending a string from RaspberryPi to ESP32 via BT.I am getting an ascii values one per line. How to convert it into a whole one String? I tried as follow but I get an error while running the method printReceivedMEssage(buffer):
invalid conversion from 'uint8_t {aka unsigned char}' to 'uint8_t* {aka unsigned char*}' [-fpermissive]
uint8_t buffer;
void printReceivedMessage(const uint8_t* buf) {
char string_var[100];
size_t bufflen = sizeof(buf);
for (int i = 0; i < bufflen; ++i) {
Serial.println(static_cast<char>(buf[i]));
}
memcpy( string_var, buf, bufflen );
string_var[bufflen] = '\0'; // 'str' is now a string
Serial.print("string_var=");
Serial.println(string_var);
}
void loop()
{
buffer = (char)SerialBT.read();
Serial.println(buffer); // THIS SHOWS AN ASCII VALUES ONE PER LINE
printReceivedMessage(buffer); // ERROR
delay(1000);
}
One error that should be fixed is the incorrect sizeof(). The code is getting the size of a pointer, which in C and C++ does simply that (you will get the value 4 for 32-bit pointers for example), but doesn't return the size of any "contents" being pointed to. In your case, where the buffer contains a null-terminated string, you can use strlen()
size_t bufflen = strlen(buf);
To remove the compiler error you need to pass a byte array to printReceivedMessage(). For example:
uint8_t buffer[200];
Also, you could print the buffer in one call with Serial.println(a_string), but then you need to read a whole string with SerialBT.readString().
The byte array seems to be an unnecessary intermediary. Just read a String over BT, and print it, as in the post I linked to.
Serial.println(SerialBT.readString());

Can "const char[18]* be changed to an entity of type LPCWSTR(C++)? [duplicate]

After getting a struct from C# to C++ using C++/CLI:
public value struct SampleObject
{
LPWSTR a;
};
I want to print its instance:
printf(sampleObject->a);
but I got this error:
Error 1 error C2664: 'printf' : cannot convert parameter 1 from
'LPWSTR' to 'const char *'
How can I convert from LPWSTR to char*?
Thanks in advance.
Use the wcstombs() function, which is located in <stdlib.h>. Here's how to use it:
LPWSTR wideStr = L"Some message";
char buffer[500];
// First arg is the pointer to destination char, second arg is
// the pointer to source wchar_t, last arg is the size of char buffer
wcstombs(buffer, wideStr, 500);
printf("%s", buffer);
Hope this helped someone! This function saved me from a lot of frustration.
Just use printf("%ls", sampleObject->a). The use of l in %ls means that you can pass a wchar_t[] such as L"Wide String".
(No, I don't know why the L and w prefixes are mixed all the time)
int length = WideCharToMultiByte(cp, 0, sampleObject->a, -1, 0, 0, NULL, NULL);
char* output = new char[length];
WideCharToMultiByte(cp, 0, sampleObject->a, -1, output , length, NULL, NULL);
printf(output);
delete[] output;
use WideCharToMultiByte() method to convert multi-byte character.
Here is example of converting from LPWSTR to char*
or wide character to character.
/*LPWSTR to char* example.c */
#include <stdio.h>
#include <windows.h>
void LPWSTR_2_CHAR(LPWSTR,LPSTR,size_t);
int main(void)
{
wchar_t w_char_str[] = {L"This is wide character string test!"};
size_t w_len = wcslen(w_char_str);
char char_str[w_len + 1];
memset(char_str,'\0',w_len * sizeof(char));
LPWSTR_2_CHAR(w_char_str,char_str,w_len);
puts(char_str);
return 0;
}
void LPWSTR_2_CHAR(LPWSTR in_char,LPSTR out_char,size_t str_len)
{
WideCharToMultiByte(CP_ACP,WC_COMPOSITECHECK,in_char,-1,out_char,str_len,NULL,NULL);
}
Here is a Simple Solution. Check wsprintf
LPWSTR wideStr = "some text";
char* resultStr = new char [wcslen(wideStr) + 1];
wsprintfA ( resultStr, "%S", wideStr);
The "%S" will implicitly convert UNICODE to ANSI.
Don't convert.
Use wprintf instead of printf:
wprintf
See the examples which explains how to use it.
Alternatively, you can use std::wcout as:
wchar_t *wstr1= L"string";
LPWSTR wstr2= L"string"; //same as above
std::wcout << wstr1 << L", " << wstr2;
Similarly, use functions which are designed for wide-char, and forget the idea of converting wchar_t to char, as it may loss data.
Have a look at the functions which deal with wide-char here:
Unicode in Visual C++

error: cannot convert ‘std::string {aka std::basic_string<char>}’ to ‘char*’ in initialization

I'm tinkering with C++ (I have a COBOL, Perl and PHP background) and I'm having trouble splitting a string so that I can act on each parsed field. I believe the trouble is to do with my lack of understanding of how C++ handles variables.
I've slurped a file's contents into an array successfully and I can act on each complete line (e.g. search/replace text). I also found some great examples of how to parse strings. The problem occurs when I try to apply the parse examples to the strings in my array.
The strings are created via:
std::vector<std::string> File_Lines;
ifstream file(filename.c_str());
while ( file.good() ) {
getline ( file, line, '\n' );
string InputLine = string( line );
File_Lines.push_back(line);
}
One working example of parsing strings (that I found on this site) is:
char myString[] = "The quick brown fox";
char *p = strtok(myString, " ");
while (p) {
printf ("Token: %s\n", p);
p = strtok(NULL, " ");
}
The problem starts when I try to feed my string to the code that does the parsing. Feeding it directly:
char myString[] = File_Lines[array_counter];
gives "error: initializer fails to determine size of ‘myString’"
If I try converting using "std::string" (as suggested in other answers on this site):
std::string File_Line;
File_Line = File_Lines[array_counter];
char myString[] = File_Line;
...I get the same error.
Other answers suggested adjusting the code to:
char *myString = File_Line;
but that just gives me "error: cannot convert ‘std::string {aka std::basic_string}’ to ‘char*’ in initialization"
I'm aware that the problem is due to my own ignorance, but I'd really appreciate any help on how to feed a string into a parser.
Also, if anyone has any simple explanation of how to convert between the data types, that would be great.
This should be fine:
std::string ThisLine = File_Lines[array_counter]; // make a copy for strtok to mess up
char *p = strtok(&ThisLine[0], " "); // strtok needs a pointer to the first character
while (p) {
printf ("Token: %s\n", p);
p = strtok(NULL, " ");
}
But C++ has nicer ways to tokenize than strtok. For example, std::strstream with operator>> (for whitespace delimiters) or getline (for delimiter you specify).
use the following:
const char * myString1 = File_Lines[array_counter].c_str();
char * myString=const_cast<char*>myString1;

Managed c++/cli .net convert fixed Byte array to a String^

How do I convert a fixed byte array to a String in managed c++/cli ?
For example I have the following Byte array.
Byte byte_data[5];
byte_data[0]='a';
byte_data[1]='b';
byte_data[2]='c';
byte_data[3]='d';
byte_data[4]='e';
I have tried the following code
String ^mytext=System::Text::UTF8Encoding::UTF8->GetString(byte_data);
I get the following error:
error C2664: 'System::String ^System::Text::Encoding::GetString(cli::array<Type,dimension> ^)' : cannot convert parameter 1 from 'unsigned char [5]' to 'cli::array<Type,dimension> ^'
Arm yourself with some knowledge about casting between pointers to signed and unsigned types and then you should be set to use String::String(SByte*, Int32, Int32). It might also pay to read the Remarks on the page, specifically around encoding.
I've reproduced the sample from the page here:
// Null terminated ASCII characters in a simple char array
char charArray3[4] = {0x41,0x42,0x43,0x00};
char * pstr3 = &charArray3[ 0 ];
String^ szAsciiUpper = gcnew String( pstr3 );
char charArray4[4] = {0x61,0x62,0x63,0x00};
char * pstr4 = &charArray4[ 0 ];
String^ szAsciiLower = gcnew String( pstr4,0,sizeof(charArray4) );
// Prints "ABC abc"
Console::WriteLine( String::Concat( szAsciiUpper, " ", szAsciiLower ) );
// Compare Strings - the result is true
Console::WriteLine( String::Concat( "The Strings are equal when capitalized ? ", (0 == String::Compare( szAsciiUpper->ToUpper(), szAsciiLower->ToUpper() ) ? (String^)"TRUE" : "FALSE") ) );
// This is the effective equivalent of another Compare method, which ignores case
Console::WriteLine( String::Concat( "The Strings are equal when capitalized ? ", (0 == String::Compare( szAsciiUpper, szAsciiLower, true ) ? (String^)"TRUE" : "FALSE") ) );
Here is one option:
array<Byte>^ array_data = gcnew array<Byte>(5);
for(int i = 0; i < 5; i++)
array_data[i] = byte_data[i];
System::Text::UTF8Encoding::UTF8->GetString(array_data);
Not compiled but I think you get the idea.
Or use the String constructor, as indicated by #ta.speot.is, with encoding set to System.Text::UTF8Encoding.
For those interested in another working solution. I used the notes of ta.speot.is and developed a working solution,You should be able to use this solution or that provided by Rasmus.
Byte byte_data[5];
byte_data[0]='a';
byte_data[1]='b';
byte_data[2]='c';
byte_data[3]='d';
byte_data[4]='e';
char *pstr3 = reinterpret_cast<char*>(byte_data);
String^ example1 = gcnew String( pstr3 );//Note: This method FAILS if the string is not null terminated
//After executing this line the string contains garbage on the end example1="abcde<IqMŸÖð"
String^ example2 = gcnew String( pstr3,0,sizeof(byte_data)); //String Example 2 correctly contains the expected string even if it isn't null terminated

C basics, const unsigned char* to integer or bool

I'm trying to get integer or bool from database result this way:
bool tblexist = false;
int t_exists = 0;
tblexist = (bool)sqlite3_column_text(chkStmt, 1);
t_exists = atoi(sqlite3_column_text(chkStmt, 1));
... but no one works.
Expected value from sqlite3_column_text(chkStmt, 1) is always 0 or 1.
But I get error message:
invalid conversion from ‘const unsigned char*’ to ‘const char*’
initializing argument 1 of ‘int atoi(const char*)’
||=== Build finished: 2 errors, 0 warnings ===|
How to solve this and get integer or bool on elegant way?
The first line, trying to convert to bool will always return true, as a string pointer will always be "true" if it's not NULL. If you want to use this there are a couple of ways to handle this:
// 1. Dereference pointer to get first character in string
tblexist = (*sqlite3_column_text(chkStmt, 1) != '0');
// 2. Using string comparison
tblexist = (strcmp(sqlite3_column_text(chkStmt, 1), "0") != 0);
For the second, try this instead:
t_exists = atoi((const char *) sqlite3_column_text(chkStmt, 1));
This is because sqlite3_column_text returns the type const unsigned char * but atoi wants const char *.
First of all, the columns are indexed beginning with zero, so unless the query requested two (or more) columns, sqlite3_column_text(..., 1) returns the second column.
Secondly, the function returns a pointer to a character string, so you have to dereference the value from the pointer, and convert the string there:
const char *data = sqlite3_column_text(chkStmt, 0);
int val = atoi (data); // for ascii representation of a number
atoi or similar conversion would be expensive to use.
const unsigned char _TRUE = '1';
const unsigned char* dbDATA = sqlite3_column_text(chkStmt, 1);
bool exists = (_TRUE == dbDATA[0]); //i assume you are expecting "0" or "1" from DB