Pass variable "name" in C++ - c++

I currently use the following template simply as a way to check for NULL pointer and if NULL then print out an error message to a log file and then return false.
template< typename T >
static bool isnull(T * t, std::string name = "")
{
_ASSERTE( t != 0 );
if( !t )
{
if( !(name.length()) ) name = "pointer";
PANTHEIOS_TRACE_ERROR(name + " is NULL");
return false;
}
return true;
}
I currently call this as follows:
if( !(isnull(dim, BOOST_STRINGIZE(dim))) ) return false;
If you notice I need to pass in the "name" of the pointer-variable that I want to print to the log file, as the 2nd parameter. I am currently using BOOST_STRINGIZE that simply converts any text inside the parentheses to a string.
The following are the disadvantages of my template implementation (for my usage at least)
Anyone could pass in anything as parameter to BOOST_STRINGIZE to print out in log file - since the 2 parameters are not related in anyway - so I would not necessarily see the "variable name" that is actually NULL
We have to remember to pass in the 2nd parameter, else useless.
Is there anyway I can have the "name" of that 1st variable be automatically determined, so that I can omit passing it in, as the 2nd parameter, with every call?

You could put it all in one macro:
#define IS_NULL(name_) isnull(name_, #name_)
Note that BOOST_STRINGIZE expands its argument if its a macro, which may or may not be what you want:
#define X(x_) std::cout << BOOST_STRINGIZE(x_) << " = " << x_ << std::endl;
X(NULL); // prints: "0 = 0"

The only way to do anything lexically like this is with macros. If you always want the correct printout, your best option is to wrap the whole statement in a macro:
//if( !(isnull(dim, BOOST_STRINGIZE(dim))) ) return false;
#define ISNULL(a) isnull((a), #a)
if (!ISNULL(dim)) return false;
Note that, as always, macros have a number of disadvantages associated with them.

Sure, why not:
#define new_isnull(x) isnull(x, BOOST_STRINGIZE(x))

Related

How to ignore null objects when writing JSON with JsonCpp

According to the Google JSON style guide, it is advisable to remove empty or null values.
When using JsonCpp, how can empty or null values be removed, either from the object structure or when writing to a stream?
I want the following code:
#include <json/json.h>
#include <json/writer.h>
Json::Value json;
json["id"] = 4;
// The "name" property is an empty array.
json["name"] = Json::Value(Json::arrayValue);
Json::FastWriter fw;
std::cout << fw.write(json) << std::endl;
to produce:
{
"id": 4,
}
You may add a pre-process to remove empty members, something like:
void RemoveNullMember(Json::Value& node)
{
switch (node.type())
{
case Json::ValueType::nullValue: return;
case Json::ValueType::intValue: return;
case Json::ValueType::uintValue: return;
case Json::ValueType::realValue: return;
case Json::ValueType::stringValue: return;
case Json::ValueType::booleanValue: return;
case Json::ValueType::arrayValue:
{
for (auto &child : node)
{
RemoveNullMember(child);
}
return;
}
case Json::ValueType::objectValue:
{
for (const auto& key : node.getMemberNames())
{
auto& child = node[key]
if (child.empty()) // Possibly restrict to any of
// nullValue, arrayValue, objectValue
{
node.removeMember(key);
}
else
{
RemoveNullMember(node[key]);
}
}
return;
}
}
}
And so finally:
Json::Value json;
json["id"] = 4;
json["name"] = Json::Value(Json::arrayValue); // The "name" property is an empty array.
RemoveNullMember(json); // Or make a copy before.
Json::FastWriter fw;
std::cout << fw.write(json) << std::endl;
Personally I'd prefer an option in the writer which allows to filter out empty/null properties when writing. Thereby, one could define an own class like class MyFastWriter : public FastWriter, override printValue for handling type objectValue accordingly and call FastWriter::writeValue for the rest. Unfortunately, JsonCpp API has defined member function printValue as private, such that you cannot override it (and not even call it) from a custom derived class.
Hence, I see only three principal ways to achieve what you want: (1) Adapting the json value before writing, (2) defining an own writer class and copying a lot of code from FastWriter, or (3) change the source code of FastWriter.
There is already a proper answer for option (1) provided by Jarod42.
Option (2) and (3) share the major drawback that you copy or alter implementation details which might change in future versions of JsonCpp; But still, if one is very aware of the drawbacks coming with altering or copying a library's source code, it might be an option. A situation might be that the json value at hand shall keep empty properties, is very large, and has to be written rather often; then it becomes unhandy to copy the value, altering it just for writing, and writing it then again and again.
I'm for sure not a friend of altering source code; Anyway, see the following adapted version of FastWriter::writeValue which achieves the output you want:
void FastWriter::writeValue(const Value& value) {
switch (value.type()) {
// cases handling the other value.types remain as is...
...
// case handling objectValue is adapted:
case objectValue: {
Value::Members members(value.getMemberNames());
document_ += '{';
// inserted flag indicating that the first element is to be written:
bool isFirst = true;
for (Value::Members::iterator it = members.begin(); it != members.end();
++it) {
const std::string& name = *it;
// inserted to skip empty/null property values
if(value[name].empty() || value[name].isNull())
continue;
// Replaced: necessary because the first written entry is not necessarily members.begin:
// if (it != members.begin())
// document_ += ',';
if (!isFirst)
document_ += ',';
else
isFirst = false;
// Kept as is...
document_ += valueToQuotedStringN(name.data(), static_cast<unsigned>(name.length()));
document_ += yamlCompatiblityEnabled_ ? ": " : ":";
writeValue(value[name]);
}
document_ += '}';
} break;
}
}
I'm assuming that the values you're setting are not constant values and you're saving data from a class or some other data structure. In this case, you can simply check the data in C++ side and skip json["varName"] part completely.
Whatever you put in a JSON file is going to be in the final JSON because you're setting that field in the JSON file to something. As you said, it is advisable to not include NULL / empty values but it's not a must. NULL, empty or default values are still values that some people might want in their JSON file specifically to show that particular entity doesn't have that entry but it is still a field in that data.
I'd use the empty array as is for the name field in your JSON file, this way the reader can say that "Oh ok, this object doesn't have any name values to it" and if that wasn't supposed to happen or if it feels odd, even non-technical clients would be able to guide you through it and debugging would be much simpler. Unless this is a part of a networking code and you need to have the fastest response times. Otherwise, just include it.
Golden rule of debugging: Thich files save lives.

c++ how to compare a string to a dynamic structure string using pointers?

I have to code a method of a class in C++ that shows me all the attributes of a class when they give me only the name. For example, I have a class 'Team' with a_name, a_goals and a_points. So when they give me a string with the name, I have to compare it to my dynamic structure and find the team with the same name to show it. I have this code:
void Classificacio::mostrar(string nom) const {
Equip eq;
Node* i=a_inici;
bool trobat=false;
while(!trobat && i!=NULL) {
if(nom.compare(i->a_equip.NomEquip())==0) trobat=true;
else i=i->seg;
}
if(trobat==true) eq=i->a_equip;
cout << eq << endl;
}
NomEquip() is a method that returns the team name.
But it doesn't work. Every time I try to execute it with the debugger, it stops in the line with the if. Any ideas what I'm doing wrong?
EDIT: Wanted to translate it to english but I forgot some things, just copy/pasted it this time.
There is a possibility of crashing in the line:
if (trobat == true) eq=i->a_equip;
Because you check for 'i!=NULLin thewhileloop. One of the terminating conditions of thewhileloop is thati == NULL`.
Assuming the while loop was terminated because i == NULL, your if statement will dereference a NULL pointer which is undefined behavior.
Edit 1:
If it crashes at if (nom.compare(i->a_equip.NomEquip()) == 0), and we know i is valid, it leads that the NomEquip function is a leading culprint.
Change your while loop to:
while (...)
{
std::string nom_equip = i->a_equip.NomEquip();
if (nom == nom_equip)
//...
}
Now place breakpoint at the std::string line and step into the function to trace it.

creating a function to match a string in the main

This is a group assignment and it's become rather difficult to the point our professor has extended the project by 1 week. there are 50 stages/tests, we've only been able to reach up to stage 11 and then the function fails.
this function is in our .cpp file (we're positive it's this function causing the problem's because when we change parts of it, it affects stage 11 which we've passed).
int segment::match(const char word[]) {
int i;
cout << data[0];
data[0] == "OOP";
cout << data[0];
for(i=0;i<NUM_MAX;i++) {
cout << "word = " << &word[i] << " data[i] = " << data[i];
if(strstr(&word[i],data[i])!= NULL)
break;
}
return i==NUM_MAX ? 1 : i-1;
and from the main.cpp (provided to us as the assignment) this is the what we are trying to accomplish
Passed test 11...
Your match( ) return value ----> -1
Actual match( ) return value --> -1
Press the ENTER key to continue...
word = OOP data[i] =
Failed while testing the match( )
function... Failed on test 12...
Your match( ) return value ----> -1
Actual match( ) return value --> 1
Press the ENTER key to continue...
You passed 11/50 tests...
Your program is 22.00% complete!
Your program still needs some work!
Keep at it!
what the function is suppose to do is check for "oop" and if it isn't there it exits with -1, and if it is there it should return true with 1.
I guess what I'm asking is how do I make that function that it returns both -1 and 1 in the proper order?
If you would like access to the main.cpp and segement.cpp i can upload that as files somewhere because they're very long and I did not want to cram the post.
Any help is appreciated, thank you.
EDIT*
Here is the full code that we have
http://jsfiddle.net/h5aKN/
The "html" section has the segement.cpp which is what we built.
and the jscript section has the a2main.cpp which is what our professor built.
data[0] == "OOP"; is probably not what you want to do. The double = (==) tests for equality, so here you're testing if the item at the first index of data (data[0]) and the character string "OOP" are equal.
In the running of the test, you are cout'ing: word = OOP data[i] =, which means that word[i] is probably defined correctly, but data[i] is not. This goes back to the usage of the equivalence test above.
If you set initialize data correctly, (correctly meaning allocating the memory correctly, I don't know where data is instantiated), then the test would likely return -1, as it would get a non NULL pointer from the strstr() call (assuming that data is the correct type), i would be 0 on breaking, and the ternary operator would yield i-1, = -1.
So fix the initialization / assignment of the data variable
And if you're not limited to c style strings (char arrays), I'd use the std::string type and its associated methods (see the c++ string reference if you haven't already). Usually much nicer to work with
If you are passing a list of words to the function:
As the use of (strstr(&word[i],data[i])) suggests you are looking for a string inside another string. Thus you are looping over a list of strings (words).
Then this looks wrong:
int segment::match(const char word[]) {
Here you are passing one word.
Its impossable to tell what it should be, but a guess would be:
int segment::match(const char* word[]) {
// ^^^^^
But to be honest the whole thing is rather ugly C++. If you were writting C I would say fine, but if you had been writing C++ correctly the type system would have saved you from all these problems. Use std::string to represent words.

Add custom messages in assert?

Is there a way to add or edit the message thrown by assert? I'd like to use something like
assert(a == b, "A must be equal to B");
Then, the compiler adds line, time and so on...
Is it possible?
A hack I've seen around is to use the && operator. Since a pointer "is true" if it's non-null, you can do the following without altering the condition:
assert(a == b && "A is not equal to B");
Since assert shows the condition that failed, it will display your message too. If it's not enough, you can write your own myAssert function or macro that will display whatever you want.
Another option is to reverse the operands and use the comma operator. You need extra parentheses so the comma isn't treated as a delimiter between the arguments:
assert(("A must be equal to B", a == b));
(this was copied from above comments, for better visibility)
Here's my version of assert macro, which accepts the message and prints everything out in a clear way:
#include <iostream>
#ifndef NDEBUG
# define M_Assert(Expr, Msg) \
__M_Assert(#Expr, Expr, __FILE__, __LINE__, Msg)
#else
# define M_Assert(Expr, Msg) ;
#endif
void __M_Assert(const char* expr_str, bool expr, const char* file, int line, const char* msg)
{
if (!expr)
{
std::cerr << "Assert failed:\t" << msg << "\n"
<< "Expected:\t" << expr_str << "\n"
<< "Source:\t\t" << file << ", line " << line << "\n";
abort();
}
}
Now, you can use this
M_Assert(ptr != nullptr, "MyFunction: requires non-null argument");
And in case of failure you will get a message like this:
Assert failed:  MyFunction: requires non-null argument
Expected: ptr != nullptr
Source: C:\MyProject\src.cpp, line 22
Nice and clean, feel free to use it in your code =)
BOOST_ASSERT_MSG(expre, msg)
http://www.boost.org/doc/libs/1_51_0/libs/utility/assert.html
You could either use that directly or copy Boost's code. Also note Boost assert is header only, so you could just grab that single file if you didn't want to install all of Boost.
As zneak's answer convolutes the code somewhat, a better approach is to merely comment the string text you're talking about. ie.:
assert(a == b); // A must be equal to B
Since the reader of the assert error will look up the file and line anyway from the error message, they will see the full explanation here.
Because, at the end of the day, this:
assert(number_of_frames != 0); // Has frames to update
reads better than this:
assert(number_of_frames != 0 && "Has frames to update");
in terms of human parsing of code ie. readability. Also not a language hack.
assert is a macro/function combination. you can define your own macro/function, using __FILE__, __BASE_FILE__, __LINE__ etc, with your own function that takes a custom message
If the assert is done within a class, an alternative approach is to call a static predicate function with a self-describing name. If the assertion fails, the message will already contain the predicate's pretty and self-describing name.
E.g.:
static bool arguments_must_be_ordered(int a, int b) {return a <= b;}
void foo(int a, int b)
{
assert(arguments_must_be_ordered(a, b));
// ...
}
You may even want to make that predicate function public so that the class' user can verify the precondition themselves.
Even if assert is not disabled for release builds, the compiler will likely inline the predicate if it's fairly trivial.
The same approach can be used for complex if conditions needing a comment. Instead of a comment, just call a self-describing predicate function.
You could also just write your own custom assert function. A very simple example:
bool print_if_false(const bool assertion, const char* msg) {
if(!assertion) {
// endl to flush
std::cout << msg << std::endl;
}
return assertion;
}
int main()
{
int i = 0;
int j = 1;
assert(print_if_false(i == j, "i and j should be equal"));
return 0;
}
play with the code.
The assertion reads Assertion print_if_false(i == j, "i and j should be equal").
int x=10, y=25;
assert(x > y); // Add message along with this assert
Option 1) Since fprintf returns number of characters printed so we can or assert expression with !fprintf. Using stderr here since this is an error message
assert((x > y) || !fprintf(stderr, "Error: x %d is expected to be greater than y %d \n", x, y));
We can wrap this inside a macro for convinient use.
// Define macro over assert
#define assert_msg(cond, fmt, ...) assert( cond || !fprintf(stderr, fmt, ##__VA_ARGS__))
// Use above macro
assert_msg(x > y, "Error: x %d is expected to be greater than y %d \n", x, y);
Option 2) Define error message wrapped inside lambda.
auto err = [x, y] { fprintf(stderr, "Error: x %d should be greater than y %d \n", x, y); return false; };
assert((x > y) || err()); // Assert calls lambda func only when condition fails
Here is the dumped message.
Error: x 10 should be greater than y 25
File.cpp:10: int main(): Assertion `(x > y) || err()' failed.
Option 3) Or we can refine above solution to do it in one line with help of immediately invoked lambda
assert((x > y) || ([x, y] { fprintf(stderr, "Error: x %d is expected to be greater than y %d \n", x, y); return false; }()));
For vc, add following code in assert.h,
#define assert2(_Expression, _Msg) (void)( (!!(_Expression)) || (_wassert(_CRT_WIDE(#_Msg), _CRT_WIDE(__FILE__), __LINE__), 0) )

Checking lists and running handlers

I find myself writing code that looks like this a lot:
set<int> affected_items;
while (string code = GetKeyCodeFromSomewhere())
{
if (code == "some constant" || code == "some other constant") {
affected_items.insert(some_constant_id);
} else if (code == "yet another constant" || code == "the constant I didn't mention yet") {
affected_items.insert(some_other_constant_id);
} // else if etc...
}
for (set<int>::iterator it = affected_items.begin(); it != affected_items.end(); it++)
{
switch(*it)
{
case some_constant_id:
RunSomeFunction(with, these, params);
break;
case some_other_constant_id:
RunSomeOtherFunction(with, these, other, params);
break;
// etc...
}
}
The reason I end up writing this code is that I need to only run the functions in the second loop once even if I've received multiple key codes that might cause them to run.
This just doesn't seem like the best way to do it. Is there a neater way?
One approach is to maintain a map from strings to booleans. The main logic can start with something like:
if(done[code])
continue;
done[code] = true;
Then you can perform the appropriate action as soon as you identify the code.
Another approach is to store something executable (object, function pointer, whatever) into a sort of "to do list." For example:
while (string code = GetKeyCodeFromSomewhere())
{
todo[code] = codefor[code];
}
Initialize codefor to contain the appropriate function pointer, or object subclassed from a common base class, for each code value. If the same code shows up more than once, the appropriate entry in todo will just get overwritten with the same value that it already had. At the end, iterate over todo and run all of its members.
Since you don't seem to care about the actual values in the set you could replace it with setting bits in an int. You can also replace the linear time search logic with log time search logic. Here's the final code:
// Ahead of time you build a static map from your strings to bit values.
std::map< std::string, int > codesToValues;
codesToValues[ "some constant" ] = 1;
codesToValues[ "some other constant" ] = 1;
codesToValues[ "yet another constant" ] = 2;
codesToValues[ "the constant I didn't mention yet" ] = 2;
// When you want to do your work
int affected_items = 0;
while (string code = GetKeyCodeFromSomewhere())
affected_items |= codesToValues[ code ];
if( affected_items & 1 )
RunSomeFunction(with, these, params);
if( affected_items & 2 )
RunSomeOtherFunction(with, these, other, params);
// etc...
Its certainly not neater, but you could maintain a set of flags that say whether you've called that specific function or not. That way you avoid having to save things off in a set, you just have the flags.
Since there is (presumably from the way it is written), a fixed at compile time number of different if/else blocks, you can do this pretty easily with a bitset.
Obviously, it will depend on the specific circumstances, but it might be better to have the functions that you call keep track of whether they've already been run and exit early if required.