How do I fix this error? (arduino casting) - c++

I'm using a library called DS3231 by rinkydinkelectronics
Link: http://www.rinkydinkelectronics.com/library.php?id=73 (click on manual)
i'm trying to run the following code
String alarmTime = "08:52:00";
void loop(){
if (rtc.getTimeStr() == alarmTime){
alarmState = true;
}
}
but i get the following error:
exit status 1 no match for 'operator==' (operand types are 'char*' and
'String')
the library manual however says that the return value is a string so I don't see why this shouldn't work :(
Can someone help me fix this or tell me what might be wrong?
Thank you!

If understood your code right, you want to check whether both strings are equal. Because the standard library is not available in the Arduino IDE, you must choose a different way. Convert the C string (char*) to a String object.
Example:
if(String(rtc.getTimerStr()) == alarmTime) {
....
}
This should work.

You're trying to compare two different things with confusingly similar names. A string(C style string) is a null terminated char array. This is different from the String object. It's generally accepted that with extremely memory limited hardware such as the standard Arduino boards you should avoid the use of the String class if possible as it uses more memory and may cause memory fragmentation from dynamic memory allocation. Much better to use strings instead, which are actually pretty much just as easy to work with as String.
Your code using only strings:
char alarmTime[] = "08:52:00";
void loop() {
if (strcmp(rtc.getTimeStr(), alarmTime) == 0) {
alarmState = true;
}
}

Related

Why can't I read apostrophes using ifstream without it crashing?

I'm using this code:
std::string word;
std::ifstream f((file_name + ".txt").c_str());
while (f >> word) {
good_input = true;
for (int i = 0; i < word.length(); ++i) {
if (ispunct(word.at(i))) {
word.erase(i--, 1);
}
else if (isupper(word.at(i))){
word.at(i) = tolower(word.at(i));
}
}
Every time I read the word "doesn't" from a text file, I get this error:
Debug Assertion Failed!
Program: directory\SortingWords(Length).exe
File: minkernel\crts\ucrt\src\appcrt\convert\istype.cpp
Line: 36
Expression: c >= -1 && c <= 255
For more information please visit... [etc.]
When I click "abort", my program exits with code 3. Don't know if that's helpful?
It looks like it's got something to do with the apostrophe maybe? This code works find for all other words in my document up until this one. And works great with documents that don't include apostrophes, yet they include plenty of other punctuation...
I tried changing the encoding of the text file (simply made with notepad), but that didn't help. Generally found lots of complaints about apostrophes but no working answers. Can anyone help me figure out what's going on?
As documentation for ispunct says:
The behavior is undefined if the value of ch is not representable as
unsigned char and is not equal to EOF.
Visual C++ is nice enough to add an almost explicit message for this error if you link to the debug runtime (this is often the case with undefined behaviour - with the release runtime, it just crashes or behaves strangely; with the debug runtime, you get an error dialog box).
In theory, this means that in the character set used by your environment, ' is not representable as an unsigned char, i.e. its character code is too big or too low.
In practice, this seems very unlikely and perhaps even impossible on Windows. It is much more likely that your file doesn't really contain an apostrophe but a character that merely looks like one, e.g. an accent: ´
Here's how you can reproduce the problem in a simple manner:
#include <ctype.h>
int main()
{
ispunct('\'');
ispunct('´'); // undefined behaviour (crash or error message with Visual C++)
}
isupper has the same problem.
You can use those functions safely with static_cast, e.g.:
if (ispunct(static_cast<unsigned char>(word.at(i))))
Of course, now ispunct will return zero for the character. If you really need to cover ´, you have to do so explicitly, for example with a helper function like this:
bool extended_ispunct(int c)
{
return static_cast<unsigned char>(c) || c == '´';
}

How To Compare Strings In C++?

I am just messing around in C++ with some things I recently learned and I wanted to know how to correctly compare two strings to each other. I looked at a previous thread for help, but I am not sure I am getting the variables right and there was a repeating error. (P.S. This is executed to the command prompt.)
string Users = "Username1";
//Set an empty string.
string UserChoice;
//Print out a line that warns the user to type a user.
std::cout << "Username: ";
std::cin >> UserChoice;
//If the user types out whatever "Users" is, run the code below.
if (strcmp(Users, UserChoice) == 0){
//Do Stuff
}
You want:
if (Users == UserChoice) {
The std::string class (well, really std::basic_string) overloads the == operator (and many others) to do what you want. You should not be using C functions like strcmp in C++ code, and in any case they cannot be directly applied to C++ std::strings.
Comparing strings is the same as comparing int values, char values, etc... . You should use the following method:
string a
string b
if (a == b)
{
// Do something
}
In your case, 'a' and 'b' would be replaced by 'Users', 'UserChoices'. But the basic format of comparing 2 variables of the same type stays the same regardless of the type (I'm not sure whether there are any exceptions to this rule or not).
It is also recommended, just as #latedeveloper mentioned, not to use c-language functions in a c++ program. The 2 languages are NOT interchangeable!
** Helpful tip: Always strive to keep your code as simple as possible. With some exceptions possible, the more complicated you make your code, the more hard you will make it for others to understand your code. To connect it to your case, why use a function strcmp() when you can keep it simple by using the == sign? This is just my 2 bits based on personal experience.
c style:
string a
string b
if(strcmp(a.c_str(),b.c.str()) == 0)

C++ rapidjson Error: free(): invalid next size (normal)

I am reading in data on JavaScript an pass the Jsonstring like that:{"data_size":500, "array":[0,0,0,0,..,0,0]} to the webserver. The numbers in the array could be anything between 0 to 4294967295.
On the Mongoose webserver I am using the lib rapidjson to work with the Jsonstring. Therefore, I create a Document d and reads values from the "jsonstring" into an uint32_t Array using this:
#include "rapidjson/document.h"
int i_data_size=0;
Document d;
conn->content[conn->content_len]=0; //to zero terminate
if (d.Parse(conn->content).HasParseError())
{
//Error
}
else
{
Value& s = d["data_size"];
i_data_size=s.GetInt();
uint32_t *Data=NULL;
Data=new uint32_t[i_data_size];
Value& a = d["array"];
for(SizeType i=0;i<a.Size();i++)
{
Data[i]=a[i].GetUint();
}
}
conn->content is containing the json char*.
When I am sending: {"data_size":500, "array":[0,0,0,0,..,0,0]} everything works find. But sometimes, not everytime, when the a number becomes greater, like this:
{"data_size":500, "array":[123,222,0,0,..,0,0]}
I get the Error:
free(): invalid next size (normal)
This error is not related to rapidJson it is from C, showing because something is messed up with memory management. C++, the heir to the language C, won't check anything regarding to memory management because it supposed to be fast and it will trust you with this. Because of that, the error you are getting won't just tell you what is wrong exactly. In your code, you are using an array but you are not managing its boundaries well, double check what you are doing regarding to reading and writing that unsigned array (check boundaries more carefully) or use a container like std::vector which will do that for you. Take a look at here:
http://www.codeguru.com/cpp/cpp/cpp_mfc/stl/article.php/c4027/C-Tutorial-A-Beginners-Guide-to-stdvector-Part-1.htm
Solved the problem!
Writing a zero out of the boundry was causing the error:
conn->content[conn->content_len]=0; //to zero terminate
Solved the problem by using a string instead:
string json="";
json = string(conn->content);
json=json.substr(0,conn->content_len);
if (d.Parse(json.c_str()).HasParseError())
{ ...

C++ code with GCC optimisation causes core with invalid free() on strings

I have C++ code that is built with gcc (4.1.2) with -O2.
When this code is compiled and run with no optimisation, the program executes without any issue.
When compiled with O1/O2/O3, the code will crash with a valgrind indicating an invalid free.
This has been narrowed to the string variables inside the function.
The code will read in a file, and will iterate the contents.
I have removed all processing code, and the following code snippet causes the core...
int MyParser::iParseConfig(Config &inConfig)
{
bool keepGoing = true;
while(keepGoing)
{
string valueKey = "";
keepGoing = false;
}
return 0;
}
When this is run with non-optimised, it works fine.
When I build and run this optimised, it will not work.
It looks to be an issue with the way GCC optimises the string class.
Any ideas how we can circumvent this?
If you are overflowing the charIndex, (when i gets higher than 99) who knows what your program state is in... the storage you declare is not very big (2 chars and a null).
I cannot explain why exactly this code crashes for you when compiled with optimizations, perhaps i gets more than 2 digits and you have a buffer overflow, maybe it's something different, but anyway I would change the code:
sprintf(charIndex, "%d", i++);
string valueKey = "";
valueKey.append("Value").append(charIndex);
string value = inConfig.sFindField(valueKey);
like this:
stringstream ss;
ss << "Value" << i++;
string value(ss.str());
It is more C++-like and should work. Try it.
If you are curious if this is really a buffer overflow situation, insert the line:
assert(i < 99);
before the call to printf. Or use snprintf:
snprintf(charIndex, sizeof(charIndex), "%d", i++);
Or make your buffer bigger.
This was an issue with header files being incorrectly included - there was a duplicate include of the MyParser.h file in the list of includes.
This caused some strange scenario around the string optimisation within the GCC optimisation levels.

What's the reasoning behind putting constants in 'if' statements first?

I was looking at some example C++ code for a hardware interface I'm working with and noticed a lot of statements along the following lines:
if ( NULL == pMsg ) return rv;
I'm sure I've heard people say that putting the constant first is a good idea, but why is that? Is it just so that if you have a large statement you can quickly see what you're comparing against or is there more to it?
So that you don't mix comparison (==) with assignment (=).
As you know, you can't assign to a constant. If you try, the compiler will give you an error.
Basically, it's one of defensive programming techniques. To protect yourself from yourself.
To stop you from writing:
if ( pMsg = NULL ) return rv;
by mistake. A good compiler will warn you about this however, so most people don't use the "constant first" way, as they find it difficult to read.
It stops the single = assignment bug.
Eg,
if ( NULL = pMsg ) return rv;
won't compile, where as
if ( pMsg = NULL) return rv;
will compile and give you headaches
To clarify what I wrote in some of the comments, here is a reason not to do this in C++ code.
Someone writes, say, a string class and decides to add a cast operator to const char*:
class BadString
{
public:
BadString(const char* s) : mStr(s) { }
operator const char*() const { return mStr.c_str(); }
bool operator==(const BadString& s) { return mStr == s.mStr; }
// Other stuff...
private:
std::string mStr;
};
Now someone blindly applies the constant == variable "defensive" programming pattern:
BadString s("foo");
if ("foo" == s) // Oops. This compares pointers and is never true.
{
// ...
}
This is, IMO, a more insidious problem than accidental assignment because you can't tell from the call site that anything is obviously wrong.
Of course, the real lessons are:
Don't write your own string classes.
Avoid implicit cast operators, especially when doing (1).
But sometimes you're dealing with third-party APIs you can't control. For example, the _bstr_t string class common in Windows COM programming suffers from this flaw.
When the constant is first, the compiler will warn you if you accidentally write = rather than == since it's illegal to assign a value to a constant.
Compilers outputting warnings is good, but some of us in the real world can't afford to treat warnings as errors. Reversing the order of variable and constant means this simple slip always shows up as an error and prevents compilation. You get used to this pattern very quickly, and the bug it protects against is a subtle one, which is often difficult to find once introduced.
They said, "to prevent mixing of assignment and comparison".
In reality I think it is nonsense: if you are so disciplined that you don't forget to put constant at the left side, you definitely won't mix up '=' with '==', would you? ;)
I forget the article, but the quote went something like:
Evidently it's easier remembering to put the constant first, than it is remembering to use ==" ;))