Iterating over char* error no conversion from char* to int - c++

I'm iterating over a char* as follows, but on the line indicated, I'm getting error C2446 '!=' no conversion from char* to int.
int errorLineNumber = 0;
char* json; //this is a long json with multiple \n's in it.
int offset = errorOffset;
char* p = json + offset;
while (*p-- != '\n' && offset--); //check that this gives offset on that error line and not char position of end of last line before error
errorLineOffset = errorOffset - offset; //get offset on error line only
//count lines to json error
long errorLineNumber = 0;
while (*p!= json) //this is error line
errorLineNumber += *p-- == '\n';
I looked at conversion const char to tchar, but it's a little different, and I also looked at conversion const char to int, which I still don't think is the same issue, unless I'm missing something.
That would be great if someone had a good idea what I'm missing. Thanks!

In line
while (*p != json)
you compare a *p which is of type char to json, which, according to the code above should be a pointer, I assume it is of type `const char*. So you should do
while (p != json) ...

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

Invalid conversion of const to const char*, how do I fix it? Fails with gcc7

This compiles with older versions of gcc, but fails with GCC 7 with C++17.
This is the error I get:
error: invalid conversion from 'char' to 'const char*' [-fpermissive] end_of_line = '\0';
Can't seem to resolve this compilation error.
This is the code:
/*!
* \brief Find the beginning of the next line in the given buffer.
*
* \param[in] str buffer to search for the beginning of the next line
* \param[inout] ctx
* \parblock
* pointer to the end of the line (saved by this method)
*
* This pointer must be valid, and it must be set to NULL by the caller the first time.
* \endparblock
*
* \return a pointer to the first character in the next line, or NULL if we have already hit EOF
*/
const char* Foo::GetNextLine(const char* str, const char** ctx)
{
if(str == NULL)
{
return NULL;
}
// Save a pointer to the end of the line (first time, it should be set to NULL by the caller).
const char*& end_of_line = *ctx;
if(end_of_line && *end_of_line == '\0')
{
end_of_line = '\0';
return NULL;
}
// The start of this line is one character after the end of the last one.
const char* start_of_line = end_of_line ? end_of_line + 1 : str;
// Are we at the end of the whole thing?
if(*start_of_line == '\0')
{
end_of_line = '\0'; // Reset the context state to get ready for the next load!
return NULL;
}
// Read forward to the end of the line.
end_of_line = start_of_line;
while(*end_of_line != '\n')
{
if(*end_of_line == '\0')
{
break;
}
++end_of_line;
}
return start_of_line;
}
Since C++11 (as amended by a Defect Report), you can't assign an arbitrary zero valued expression to a pointer. It has to be either the constant 0 or an object of type nullptr_t, which is nullptr. This can be hidden behind the macro NULL.
The expression end_of_line = '\0'; tries to assign a character constant to a pointer. This is no longer allowed. Assuming your intent is to NULL out the original pointer, you should change the line to read
end_of_line = nullptr;

Base Pair Map - moving for argv[i] to integer or char as input

Trying to keep this simple, I am defining some base pair maps like so:
int main(int argc, char * argv[])
{
std::string s1;
s1 = argv[1]; //<-- copy argument to a string type to use string iterator
std::vector<int> args_vector;
for (char c : s1)
{
args_vector.push_back(static_cast<int>(c - 48)); // convert char to integer and save it in vector
}
for (int i : args_vector)
{
typedef std::map<string, int> BasePairMap;
BasePairMap m;
m["0"] = 48;
m["1"] = 49;
m["2"] = 50;
m["3"] = 51;
m["4"] = 52;
char ii = static_cast<char>(i);
int in_arg = m[argv[i]]; //works
int in_arg = m[ii]; //does not work
}
return 0
}
In an earlier version of this project I was passing in multiple command line arguments as so:
C:\MyLocation\MyExecutable.exe 4 0 1
However because of a requirement to plug into a wider code base, I am now receiving a single argument like so:
C:\MyLocation\MyExecutable.exe 401
As a result, I now need to break 401 back out into 4 0 1 and can no longer use m[argv[i]] directly as previously.
The errors I am now getting in Visual Studio 2017 are:
Error (active) E0349 no operator "[]" matches these operands SkyQChannelChanger g:\Visual Studio 2017\C++ Projects\SkyQChannelChanger\SkyQChannelChanger\Main.cpp 147 operand types are: BasePairMap [ char ]
...and:
Severity Code Description Project File Line Suppression State
Error C2679 binary '[': no operator found which takes a right-hand operand of type 'char' (or there is no acceptable conversion) SkyQChannelChanger g:\visual studio 2017\c++ projects\skyqchannelchanger\skyqchannelchanger\main.cpp 147
I'm only a part time C++ user, but I can tell argv[i] is a char * and ii is an ordinary char variable, but I am unsure of two things:
Why this matters for a base pair map defined in this way.
How (if required) I can define ii as a char * instead.
Thanks
To create a std::string containing just one character c, just do
std::string(1, c);
(More generally, the string constructor taking a number n and a char c results in n repetitions of c. std::string(3, 'q') has the same value as std::string("qqq").)
However, it looks like you don't want to do this to the variable ii, which is a number from zero to nine, and not the character representing a decimal digit (which in most encodings are the char values from 48 to 57). So you can skip the vector<int> and the (c - 48) parts, and just do:
typedef std::map<string, int> BasePairMap;
BasePairMap m;
// Initialize m...
std::string s1 = argv[1];
for (char c : s1)
{
std::string digit_str(1, c);
int in_arg = m[digit_str];
// ...
}

How to convert a dynamic string to wchar_t to change background

I've been looking around the internet for some solutions however they all convert it from a constant string. Here's a piece of code I took to convert strings to wchar_t without additional libraries. What I'm trying to do is, I want to change the background of my windows computer with my background. Now I can't assume that the folder that I downloaded is in C:\Downloads because some people change their downloads folder or maybe they moved the whole folder to another location. So in the first code, I'm trying to get the path of the .exe file.
string GetExePath() {
char buffer[MAX_PATH];
GetModuleFileNameA(NULL, buffer, MAX_PATH);
string::size_type pos = string(buffer).find_last_of("\\/");
return string(buffer).substr(0, pos + 1);//gets the first character in path up to the final backslash
}
Next I'm going to grab the picture that I want to make as my background in the same folder as the .exe file.
//error on the third parameter
int return_value = SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, L(string)(GetExePath() + "\\picture.png"), SPIF_UPDATEINIFILE);
Error (active) E0040 expected an identifier
Error (active) E0020 identifier "L" is undefined
Error (active) E0254 type name is not allowed
Error (active) E0018 expected a ')'
After a while, I replaced the return type of the function and so it would return wchar_t*.
const wchar_t* GetExePath() {
char buffer[MAX_PATH];
GetModuleFileNameA(NULL, buffer, MAX_PATH);
string::size_type pos = string(buffer).find_last_of("\\/");
string path = string(buffer).substr(0, pos + 1);
path += "\\HandleCamWallpaperwithgradient.png";
cout << path << endl;
wstring wide;
for (int i = 0; i < path.length(); ++i){
wide += wchar_t(path[i]);
}
const wchar_t* result = wide.c_str();
return result;
}
However, the third parameter is showing an error saying
Error E0167 argument of type "const wchar_t *" is incompatible with parameter of type "PVOID"
So how can I fix it?
Edit: Someone thought that this was a duplicate and it isn't. How to convert string to wstring in C++ is NOT correlated with this question as the one who is asking on that thread is asking help for special characters.
Call the Unicode version GetModuleFileNameW() in the first place so you don't have to convert.
Also, never return a pointer to a string that is a local variable of a function (unless it is static)! Otherwise you will be returning a dangling pointer. Instead, return a std::wstring similar to your first version. You can use std::wstring directly as the buffer by using the "pointer-to-first-character" trick.
std::wstring GetExePath() {
std::wstring buffer(MAX_PATH, L'\0'); // reserve buffer
int len = GetModuleFileNameW(NULL, &buffer[0], buffer.size() );
buffer.resize(len); // resize to actual length
string::size_type pos = buffer.find_last_of(L"\\/");
return buffer.substr(0, pos + 1);//gets the first character in path up to the final backslash
}
The second error can be fixed like this:
std::wstring path = GetExePath() + L"picture.png";
int return_value = SystemParametersInfoW(SPI_SETDESKWALLPAPER, 0, &path[0], SPIF_UPDATEINIFILE);
The pvParam parameter of SystemParametersInfoW is a pointer to non-const data, so we have to use the "pointer-to-first-character" trick here again (to avoid ugly const_cast).
With C++17, this could be written as a one-liner:
int return_value = SystemParametersInfoW(SPI_SETDESKWALLPAPER, 0, (GetExePath() + L"picture.png").data(), SPIF_UPDATEINIFILE);
Other things to improve, left as an exercise:
Check for the error condition ERROR_INSUFFICIENT_BUFFER as described in the comments of GetModuleFileName() MSDN reference so you can support pathes longer than MAX_PATH.

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