What if I need to differentiate 0 from NULL in C++? - c++

** Please don't criticize the purpose of the code itself. It's from Pat Morin's Open Data Structures book. Not my first choice, its assigned reading/practice. I just wanted to know if there is a way to differentiate, or a better way to go about this. Textbook--> http://opendatastructures.org/ods-cpp/**
** Another note: I'm coming from Java, where this would be allowed. My code still compiles, it just "fixes" it**
I'm surprised nothing like this has come up before because it seems like such a simple question. Perhaps it's buried or I'm not using the correct terminology.
I have a for loop that goes through the data in a vector. I need to return the value being searched for if it's found. What if it's not found? Here is my code.
int find(int x) {
for(int i=0;i<bag.size();i++){
// if x is equal to data, return data
if (bag[i]==x){
return bag[i]; // ends loop as soon as one instance is found
}
}
// if we made it this far, no match was found.
return NULL;
}
Pretty simple. Let's say 0 is one of the valid values that I might need to record and search for. As it is, it actually returns 0, not "NULL". Research says it is one and the same. How can I specify or differentiate? Other than returning an obsqure number that won't come up in the program because we may not always have that luxury (like -1 or -9999999). For example, searching for your account balance. No number is impossible.

Why would you return the value you are searching for from a find function? You already know the value, its the one you passed to the function. Return the position of the found element instead, as this information is much more useful. When the value isn't found, you can return a special position, like -1. Or you can follow the model of the standard library and return the end iterator, which signifies a position that is one past the end of the range.

You can write the function in several ways
bool find( int x )
{
std::vector<int>::size_type i = 0;
while ( i < bag.size() && bag[i] != x ) i++;
return i != bag.size();
}
Or
std::vector<int>::size_type find( int x )
{
std::vector<int>::size_type i = 0;
while ( i < bag.size() && bag[i] != x ) i++;
return i;
}
Or
#include <algorithm>
//...
std::vector<int>::iterator find( int x )
{
return std::find( beg.begin(), bag.end(), x );
}
And use the functions correspondingly the following ways
if ( find( x ) ) { /*...*/ }
if ( find( x ) != bag.size() ) { /*...*/ }
if ( find( x ) != bag.end() ) { /*...*/ }
As for your general question in the title of the post
What if I need to differentiate 0 from NULL in C++?
then you need fo use nullptr instead of NULL that to differentiate 0 from NULL.:)

#define XOR_MSB(x) (x^0x80000000)
int find(bool found) {
return found ? XOR_MSB(0) : NULL;
}
int main()
{
int value = find(false);
if (value == NULL) printf("not found\n");
else printf("%d\n", XOR_MSB(value));
value = find(true);
if (value == NULL) printf("not found\n");
else printf("%d\n", XOR_MSB(value));
return 0;
}

you're talking about an evil practice, coming from Java and C# developers where you can return null as invalid result.
well, you can't do it in C++.
Java and C# declares almost everything on the heap, and accessing objects is done done always by the reference. this means you always return a pointer from a function, and you can always return a null as a return value.
this is not so possible in C++ when a function does not return a pointer. for example , the function std::string returnString() can't return null as a return value.
more over, you should not return null as invalid output. this is wrong on so many levels even in C# and Java! if your function fails, simply throw an exception, or make your return value be passed as reference-argument and make the function return true or false.
you can also find less-agressive solutions like returning -1 (like indexOf() in javascript) or return somthing like std::string::npos or std::vector:end which are more C++ STL tuned.

This is what boost::optional<T> is for. Effectively, this type represents "There may be a T, but there may not be a T". The user may check if there is a T or not. Ideally you would not depend on any special value of T but use an optional<T> instead. optional<T> is fully generic and may apply to pretty much any T you may need to use, it does not depend on some special value or state of T.
boost::optional<int> find(int x) {
for(int i=0;i<bag.size();i++){
// if x is equal to data, return data
if (bag[i]==x){
return bag[i]; // ends loop as soon as one instance is found
}
}
// if we made it this far, no match was found.
return boost::none;
}
int main() {
if (auto opt = find(5))
std::cout << *opt;
}
Do not ever use NULL, it is a terrible thing. Always use nullptr which is substantially safer and one of the reasons why it is safer is because your wrong code would not compile.

Related

Is it defined behaviour to assign to function call in or in if (C++17)

During a codebase refactor I found code like this:
void myFunction (std::map<int, int> my_map)
{
int linked_element;
if (my_map[linked_element = firstIndex] != 0
|| my_map[linked_element = secondIndex] != 0)
{
// do some stuff with linked_element
}
}
Or
void myFunction (std::set<int> my_set)
{
int linked_element;
if (my_set.find(linked_element = firstIndex) != my_set.end()
|| my_set.find(linked_element = secondIndex) != my_set.end())
{
// do some stuff with linked_element
}
}
From what I understood the aim of that was to avoid checking 2 times (first when entering in the if, second when assigning the variable).
I can understand that depending on which side of the || is true linked_element will be assigned to the right value but this still feels kind of bad to me.
Is this kind of behaviour defined?
This behavior is well defined by the order of evaluation.
First, the linked_element = firstIndex assignment happens. This expression returns the value of firstIndex, that is then used as an argument for the subscript operator on my_map (i.e., my_map[linked_element = firstIndex]). The return value from that expression is checked against the != 0 condition. If it's true, the other side of the || operator is not evaluated due to short-circuit logic. If it's false, the same story happens on the other side of the operator.
Whether or not it's a good practice to write code in such a style is a different question though. Personally speaking, I'd prioritize readability and maintainability over this micro-optimization unless it's a super-critical piece of the program, but it's a matter of opinion, I guess.
In original code behavior is well defined, since operator || evaluates first argument and if this is evaluated to false evaluates second argument.
BUT: Assignment there is confusing and many (probably all) static analyzes tools will complain about this. So I would reflector this code in this way, so it would require less brain power to read:
void doSomeStuff(const std::set<int>& my_set, int linked_element)
{
.....
}
void myFunction (const std::set<int>& my_set)
{
if (my_set.find(firstIndex) != my_set.end())
{
doSomeStuff(my_set, firstIndex);
} else if (my_set.find(secondIndex) != my_set.end()) {
doSomeStuff(my_set, secondIndex);
}
}
Since you had to ask question about this code this proves that original version is bad from maintainer point of view. Code which requires lots of focus to understand is costly in maintenance.
BTW this fragment of code:
if (my_map[linked_element = firstIndex] != 0
looks suspicious. I have even more suspensions seeing set-version.
This looks like that someone do not understand how operator[] works for maps. If value for key do not exist, default value is introduced to map. So checking for default value 0 seem like attempt to adders this issue. Possibly my_map.count(firstIndex) should be used.
An alternate version, assuming firstIndex and secondIndex are literal values (like 2 and 7), or are otherwise known relative to some invalid third index value:
void myFunction (std::set<int> & my_set)
{
int linked_element =
my_set.contains (firstIndex) ? firstIndex :
my_set.contains (secondIndex) ? secondIndex :
thirdIndex;
if (linked_element != thirdIndex)
{
// do some stuff with linked_element
}
}
If the indices are not known then a std::optional<int> can step in here too.
If pre-C++20, replace .contains() with .count().
Bigger concerns with the original code are:
the pass-by-value of a potentially large container (never assume COW)
map[index] silently adds the index to the map if not present

Access an element of a vector given the vector's pointer

I am trying to create a sorting function with the parameters being a pointer of a list and I am trying to access an element of the given list. Hopefully this code speaks for the problem better than I can:
void bubbleSort(std::vector<int> *L) {
unsigned int i = 0; int temp;
while(isSorted(*L)) {
if(i==L->size()-1) {
i = 0;
}
if(i<L[i]/*<-ERROR here.*/) {
temp = L[i+1]; // ERROR HERE
L[i+1] = L[i]; // ERROR HERE
L[i] = temp; // ERROR HERE
}
}
}
You don't need to painfully dereference every individual use of L (and indeed doing so is error-prone, as you've demonstrated by missing one in your answer).
Instead, just write:
void bubbleSort(std::vector<int> *Lptr) {
auto &L = *Lptr;
and keep the rest of the code the same.
NB. It would be even better to change the function itself, to
void bubbleSort(std::vector<int> &L) {
as it should have been written in the first place, but I'm assuming there's some artificial reason you can't do that.
The function accepts a pointer to an object of type std::vector<int>.
void bubbleSort(std::vector<int> *L) {
To access the original vector using the pointer, you can write either *L or L[0]. That is, both expressions yield an lvalue reference of type std::vector<int> & to the vector.
To get the i-th element of the vector using the subscript operator through the pointer, you can write either (*L)[i] or L[0][i],
However, in this if statement:
if(i<L[i]/*<-ERROR here.*/) {
You are trying to compare the variable i of type unsigned int to the object L[i] of type std::vector<int>. When i is not equal to 0, this yields a non-existent object of the vector type.
It seems you mean something like the following instead:
if ( (*L)[i] < (*L)[i+1] ) {
or:
if ( L[0][i] < L[0][i+1] ) {
or, vice versa:
if ( L[0][i+1] < L[0][i] ) {
Depending on whether the vector is sorted in ascending or descending order.
Pay attention to the fact that there is no sense in declaring the parameter as a pointer to a std::vector<int>. The function would be much clearer and readable if it accepted the vector by reference instead:
void bubbleSort(std::vector<int> &L) {
In this case, the if statement would look like this:
if ( L[i] < L[i+1] ) {
Although I prefer to change the source code as other answer. But, for this question, you can use ->at() function to access the element in a vector pointer.
if(i<L->at(i)) {
temp = L->at(i+1);
L->at(i+1) = L->at(i);
L->at(i) = temp;
}

Checking when value in array is 0 but not NULL C++

I'm newbie and I need little help.
I tried different ways, but from what I can see NULL means 0 in c ++, so when want my (for example) int arr[4]=0, then it says that it's also NULL. Is there any way to see when value is 0 and not NULL (or empty?).
Sounds like a job for std::optional:
#include <iostream>
#include <optional>
int main()
{
std::optional<int> arr[] = { 10, 0, std::nullopt, -52 };
for (auto i = 0U; i < sizeof(arr) / sizeof(*arr); i++)
{
if (arr[i])
{
std::cout << "arr[" << i << "] = " << *(arr[i]) << std::endl;
}
else
{
std::cout << "arr[" << i << "] = std::nullopt" << std::endl;
}
}
}
Output:
arr[0] = 10
arr[1] = 0
arr[2] = std::nullopt
arr[3] = -52
It sounds like you're looking for a null concept for your data type (int array[4]), but you want 0 to be a valid (non-null) value. The null concept is useful when your variable is not guaranteed to hold valid data. You need a null concept if, for a variable x, you want to be able to ask the question "does x contain a valid value?".
First, recognize that NULL is an implementation-defined way to represent a pointer that points at nothing. Here, implementation means "specific compiler". Usually, NULL is an integer constant equal to 0, which in practice makes it ill-suited to differentiate from your otherwise-valid value of 0.
TL;DR: I think you want to use std::vector, but you have several options available.
Null concept for int
Depending on what your data represents, you may be able to represent a null by selecting a value or range of values that are not valid for your specific use case, but otherwise representable using your data type.
Some example null concepts for int data type:
0-- is a perfectly fine null when 0 is not a valid value. The null test code is very clean as well: if (x) { ... }.
negative values-- You can select a specific negative value or the entire range of negative values. Or even a subrange of all negative values, although I've never seen this last one in practice. Generally the specific value of -1 is used. The null test code looks like: if (x >= 0) { ... } or if (x != -1) { ... }.
extreme positive values-- You can select a very large number to represent the null concept. If a valid instance of your data will never reach this value. I recommend std::numeric_limits<int>::max(), which requires #include <limits>. The null test looks like: if (x != std::numeric_limits<int>::max()) { ... }
std::optional<T>
When all possible values of your data type represent valid values, then you need to include extra overhead if you want to represent the null concept. std::optional<T> wraps any data type and is used specifically for the case where you need to represent invalid data. The access semantics looks very similar to accessing a pointer.
#include <optional>
void do_something(int);
int main() {
std::optional<int> a; // default initialization is "empty"
std::optional<int> b = 1; // can be assigned just as if it were the type
if (a) { // You can check in a natural-feeling way if the data is valid
do_something(*a); // and access the data as if it were a pointer
do_something(a.value()); // or use std::optional<T>::value()
}
// If the data may be invalid, you must check before accessing
// *a; // WRONG: throws an exception
// a.value(); // WRONG: for the same reason
// If you know for certain the data is valid, feel free to access it
do_something(*b);
// You can't access it entirely as if it were an int, dereferencing is necessary
// int c = b + 2; // invalid, no overloaded operator+ for std::optional<int> type
int c = *b + 2; // valid
// An array of optionals looks similar to an array of ints
std::optional<int> array[4]; // initialized as all empty
Just don't deal with invalid data at all
If your data doesn't necessarily need to exist until it is valid then you can use a variable size container to just... not have invalid data at all.
std::vector<T> is the go-to dynamically sized container in C++, and allows you to have just enough space to handle only the data you need. std::vector<T> also has many class methods that allow easy access to container information such as std::vector<T>::size() or iterators with std::vector<T>::begin() and std::vector<T>::end().
#include <vector>
void do_something(int);
int main() {
std::vector<int> data; // initially empty, no elements
// you can add new values
data.push_back(1); // vector contains { 1 }
data.emplace_back(2); // vector contains { 1 , 2 }
// looping is the same as with arrays
for (int i = 0; i < data.size(); i++) {
do_something(data[i]);
}
// or you can use range-based for loops for cleaner looking code
for (auto& d : data) {
do_something(d);
}
}
If that is an array of pointers:
int* arr[10] = {};
Then here is how you check if an element is null:
if (arr[4] == nullptr)
And here is how you check if the pointed value is zero:
if (*arr[4] == 0) // note the *

c++ equivelant to javascript OR

I am trying to implement a comparator function, and coming from a JavaScript background attempted to chain them like so:
int MyClass::compare(MyClass & other) {
return MyClass.x.compare(other.x) || MyClass.y.compare(other.y);
}
That is, compare the objects' x values, and if they are equal compare the objects' y values.
I immediately realized this wouldn't work, because the OR function in c++ returns a bool rather than the last evaluated value.
Other than literally writing an if statement, like
int result = MyClass.x.compare(other.x);
if (result) {
return result;
}
result = MyClass.y.compare(other.y);
return result;
, is there is a concise way to write this expression?

C++ recursive function that has a byref 2D Matrix of object pointers

I have a recursive function that has a parameter that is a reference to a 2D matrix of object pointers. My simple question is in what format do I pass that within the function so that it would work?
I wrote this code purely for example to pass my point along and in no way represents my intended use of recursion.
This code checks for a 0 object ID value in a diagonal line through the matrix to 255,255. Then prints 0 or -1.
typedef object* m256x256[256][256];
int x = 0;
int y = 0;
int isThereZero(m256x256 & m){
if(m[x][y]->getID() == 0){ // Each object has an ID value
return 0;
}
x++;
y++;
if(x==256){
return -1;
}
return isThereZero(/*I need to pass M byref again... what do I put here?*/);
}
int main{
object* M[256][256];
/* Initialization Code */
cout << isThereZero(M);
return EXIT_SUCCESS;
}
So that by the 256th recursion m is still the same reference to M
Specific question: How do I format this to get it to compile:
int isThereZero(m256x256 & m){
return isThereZero(/*I need to pass M byref again... what do I put here?*/);
}
Rather than using global x and y, try something like so:
bool is_there_zero(const m256x256& m, int x = 0, int y = 0)
{
if (m[x][y]->getID() == 0)
return true;
if (++y == 256) {
y = 0;
if (++x == 256) {
return false;
}
}
return is_there_zero(m, x, y);
}
So we bump the y value, and if that reaches the end of the row we reset it to zero and bump the x coordinate, and finally terminate the recursion when both are equal to 256. The original matrix is untouched.
In other words, we've turned it into a poor man's double for loop, only with added function call overhead and the risk of running out of stack...
As such, I'm not at all sure why you'd want to do it this way rather than just iterating. The only advantage I can see is that, with some "creative" use of the ternary operator you could turn this into a one-line constexpr function, which could potentially be evaluated at compile-time for a fixed m, but that hardly seems worth the bother.
EDIT: Re-reading the question, I see you only wanted to test the leading diagonal, so it's a bit simpler:
bool is_there_zero(const m256x256& m, int x = 0)
{
if (x == 256)
return false;
if (m[x][x]->getID() == 0)
return true;
return is_there_zero(m, ++x);
}
Since you state, your code does not represent your actual code, it is difficult to give an educated answer (imho).
To pass by-reference as you state in your question:
int isThereZero(m256x256 & m);
If you do not change the reference you can pass by const-reference:
int isThereZero(const m256x256 & m);
This allows for some optimizations.
Of course if you pass a pointer to the array by-value:
int isThereZero(object ***m);
This will more or less work like the const-reference version, since it only passes a pointer, not the whole array.
I hope this answers your question
Ah thank you all. You all contributed a little bit to helping me find my problem. As most of you probably realized. Just calling return isThereZero(m); Should have worked. This helped me find that the error was in the syntax of other areas of my program and only caused the compiler to tell me that the problem was with the passing and calling of this array.