Is this comparison inconsistent (or is there another problem)? - c++

The code below seg faults on my mac; but, works fine (without even valgrind errors) on Linux.
I suspect that the comparison function is giving an inconsistent result; but, I can't see how.
(I have a feeling I'm going to feel foolish when somebody points it out :)
For context: This is a student's code. I know there are much better ways of coding this, I'm just stumped as to why it's wrong.
using namespace std;
using Point = std::pair<double, double>;
using PointVector = vector<Point>;
extern PointVector cluster1;
bool sortComparison(const Point &point1, const Point &point2) {
if(point1.first < point2.first)
return true;
else if(point1.first > point2.first)
return false;
else if(point1.second < point2.second)
return true;
else if(point1.second > point2.second)
return false;
else
return true;
}
int main(int argc, char *argv[]) {
cout << "In" << endl;
std::sort(cluster1.begin(), cluster1.end(), sortComparison);
cout << "Out" << endl;
}

The comparison function for std::sort should return true if the first argument is less than the second (a < b), however you are returning true if it is equal (a <= b, due to else return true;). This probably breaks the implementation of std::sort.

Related

C++ There is a bool return type function returning (24) here

First of all sorry for too much code
Here there is a vector (teamNum) with type class, the class contain a vector (player) with type struct, it is a little complicated, but here in this function I need to check if there is a player in teamNum which contain tName equal to _tname (function parameter) contain (the player) pID equal to _pID (function parameter)
bool thereIsSimilarID(string _tname, int _pID)
{
for (int i = 0; i < teamNum.size(); i++)
{
if (teamNum[i].tName == _tname)
{
for (int j = 0; j < teamNum[i].player.size(); j++)
{
if (teamNum[i].player[j].pID == _pID)
return true;
}
}
else if (i == (teamNum.size() - 1))
{
return false;
}
}
}
And in the main
int main()
{
cout << "\n" << thereIsSimilarID("Leverpool", 1) << endl;
}
The output is 24 !!!!!
(good note that this happen just when the team (Leverpool) is the last team in the vector teamNum)
Again sorry for too much code but I need to know the bug not only fix the problem I need to learn from you
You encountered undefined behaviour.
If you take the if (teamNum[i].tName == _tname)-branch on the last element, but find no player with the correct pID, you don't return anything. Which means, that the return value is whatever random value is currently in the memory location that should hold the return value. In your case it happens to 24. But theoretically, everything could happen.
The same problem occurs when teamNum is empty.
The solution is to make sure to always return a value from a function (except if it has return type void of course):
bool thereIsSimilarID(string _tname, int _pID)
{
for (int i = 0; i < teamNum.size(); i++)
{
// In this loop return true if you find a matching element
}
// If no matching element was found we reach this point and make sure to return a value
return false;
}
You should take a look at your compiler settings and enable all the warnings. And often it's good to let it treat certain warnings as errors.

recursive binary search in c++ using a bool function

I have an school assignement that requires me to create a recursive Binary search function. I'm not allowed to change the function signature.
My experience with pointer isn't the best and i think my problem lies there.
I get an Stackoveflow but i dont really understand way
bool contains(const int* pBegin, const int* pEnd, int x)
{
int length = pEnd - pBegin;//gives me the length of the array
const int* pMid = pBegin + (length / 2);
if(length == 1)
{
if(*pMid != x)
return false;
return true;
}
else if(x < *pMid)
return contains(pBegin, pMid-1, x);
else
return contains(pMid, pEnd, x);
}
void main(){
setlocale(LC_ALL, "swedish");
int arr[10];
for(int i = 0; i < 10; ++i)
arr[i] = i;
bool find = contains(&arr[0], &arr[10], 3);//arr[10] points to the index after the array!
cout <<"found = "<< find << endl;
system("pause");
}
Can somebody please explain to me what I'm doing wrong, and how i could do it in a better way?
Stack overflow is due to too deep recursion.
Its unlikely your array is large enough to really be a problem, so what you have is unbounded recursion ... contains() keeps calling itself and fails to detect this.
Look at how this is possible, and add assertions.
Your code assumes
pEnd > pBegin
Your code doesn't handle this possibility.
#include <assert.h>
bool contains( ... )
{
assert(pBegin > pEnd);
...
Now, it will abort if this assumption is incorrect.
There are two possibities for (pEnd > pBegin) being false, namely "<" or "==".
What does your code do in these two cases?
Spoiler below..
Length can be zero and isn't handled.

Unexpected behavior of C++ boolean function and impossible return

I have just encountered an extremely strange result of the following code.
#include <iostream>
using namespace std;
const int N = 3;
bool gen(int l1, int l2, int p) {
if(p == N-1) {
if (l1 == l2) {
cout << "sth";
return false;
}
}
else
return gen(l1+1, l2, p+1) || gen(l1, l2+1, p+1));
}
int main() {
if(gen(0,0,0)) cout << "yes";
else cout << "no";
return 0;
}
The program does absolutely nothing and it's only a simulation. Why does it write yes each time, even though I do not allow it anywhere to do that. Moreover, the output doesn't contain "sth" word. Additionally, when I change:
cout << "sth";
return true;
into:
cout << "sth";
return false;
it still produces "yes" as output.
How can it happen?
The problem is that your function will exit without actually hitting a return if p == N-1 and l1 != l2. Your compiler would have warned you about this if it was set to a reasonable warning level.
This triggers Undefined Behavior, thus any output may happen. (I get "No" with clang for example.)

Write a program that simulates flipping a coin repeatedly and continues until three consecutive heads are tossed, in C++

Write a program that simulates flipping a coin repeatedly and continues until three consecutive heads are tossed, in C++
#include <iostream>
#include <cmath>
#include <string>
#include <cstdlib>
#include "random.h"
using namespace std;
bool FlipCoin(int flip);
int main(){
int flip;
int heads = 0;
int total_flips = 0;
while( heads < 3){
total_flips++;
if(FlipCoin(flip) == "heads"){
heads++;
} else{
heads = 0;
}
}
cout << "it took " << total_flips << "to get 3 consecutive heads. " << endl;
}
bool FlipCoin(int flip) {
if (randomChance(0.50)) {
return "heads";
} else {
return "tails";
}
}
I am getting this error in the main body of my code that states that
ISO C++ forbids comparison between pointer and integer
at the if (FlipCoin(flip) == "heads") part. If anyone can help me correct this that would be great.
Since strings are inefficient and error-prone (one typo and your comparison fails, while the compiler stays absolutely silent) and bools do not represent coin sides very well (is true heads or tails?), the best way to write this is using an enum:
enum class CoinSide { heads, tails };
CoinSide FlipCoin() { // note: you don't need the "flip" parameter
if (randomChance(0.50)) {
return CoinSide::heads;
} else {
return CoinSide::tails;
}
}
int main() {
...
if (FlipCoin() == CoinSide::heads) {
...
}
}
You have defined FlipCoin() with a return type of bool, but you're returning char* from it. You have a couple of options:
Change FlipCoin() to return char*. Then use if (strcmp(FlipCoin(flip), "heads") == 0). "heads" == "heads" works in C/C++, but only because of luck because the compiler optimizes the string table. So the pointers are equal, but it's not exactly correct. strcmp() returns 0 if the strings are equal, non-zero if they are not.
Change FlipCoin to return std::string, then use if (FlipCoin(flip) == "heads").
You should be getting a few compiler warnings from this code, about returning char* from a bool function, and about an unused parameter (flip) being passed into FlipCoin().
You wrote:
bool FlipCoin [....] return "heads";
Do you believe that "heads" / "tails" qualifies as a boolean type?
You should decide if FlipCoin is going to return true / false, or return a string.
After you've resolved that, you can fix your if-statement comparison:
if(FlipCoin(flip) == "heads"){
To either compare against a bool or a string.
But right now, it does not make any sense to declare FlipCoin to return a bool, actually return a string, try to convert the string to a bool, then try to compare the bool to a string.

return statement in c++

What means
failing to provide a return after a loop that contains a return is an error
in "C++ primer fifth", page 295?
Especially, the compiler does not detect this error, what happens at run time is undefined.
I use the book sample like: (vs2013)
#include "stdafx.h"
#include "iostream"
#include "string"
using std::string;
bool str_subrange(const string &str1, const string&str2) {
if (str1.size() == str2.size())
return str1 == str2;
auto size = (str1.size() < str2.size()) ? str1.size() : str2.size();
for (decltype(size)i = 0; i != size; ++i) {
if (str1[i] != str2[i])
return false;
else
return true;
}
}
int _tmain(int argc, _TCHAR* argv[]) {
if (str_subrange("lyc", "talent"))
std::cout << "yes" << std::endl;
else
std::cout << "nope" << std::endl;;
system("pause");
return 0;
}
It works well, I want to know which situations that "return" is must.
If size is 0, the for loop never executes and so the method has no return value.
If size ends up as 0 (e.g. one of the strings is ""), your loop is never run. If the loop never runs, then what is returned is undefined, because the program won't write a result to be returned to the caller of the function. The result you get is whatever was preexisting in the memory contents of where the return value is expected on the stack.
When you decide to return values inside loops, or other grouping statements (e.g. "if"), always manually run your code in your head checking to ensure you return a value on every valid path and even if loops don't run.
In such case where using loops, if conditions, always return from end of function, assign a return value at start and update that value based on conditions.