return statement in c++ - 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.

Related

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

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.

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.

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.

Searching a vector of object pointers

I have a Player class where each object of the type Class has a name, wins, losses, and draws. Each object of the Player class is created by calling the_player = new Player(the_name). When the user inputs a new name to add a Player object to the program a pointer is pushed into a vector AllPlayers. The program should check before pushing the new pointer that the desired player does not already exist in said vector. I have to do this check several times throughout my program so I thought I'd write a function for it. Here is my function:
int findPlayer(vector<Player*> &vals, string name_in)
{
for (int i = 0; i < vals.size(); i++){
if (vals[i]->getName() == name_in){
cout << vals[i]->toString() << endl;
return i;
}
else
return -1;
}
};
When the option is requested to add a new Player the following code is used:
do {
cout << "Name: ";
cin >> the_name;
if (findPlayer(AllPlayers, the_name) != -1){
cerr << "Player already exists\n";
}
} while (findPlayer(AllPlayers, the_name) != -1);
the_player = new Player(the_name);
AllPlayers.push_back(the_player);
For some reason, though, every time I try to add a new player it throws "Player already exists" and never leaves the do-while loop. This is even true when the AllPlayers vector is empty. I added a cout << findPlayer(AllPlayers, the_name) for debugging and it printed 4192252 which I assume is the largest element possible in a vector.
So the question is: Why does it return 4192252 rather than -1?
If vals is empty then the for loop is never entered and the function exits without hitting a return statement. Meaning that you get a random value returned instead, in this case 4192252 happens to be in the return register. Your compiler warnings will have told you this if you read them.
What you think, what will be returned from findPlayer if vals is empty?
Is it defined?
If the vector is empty, you don't enter the loop at all, so don't reach a return statement and don't return a valid value. You should enable compiler warnings to catch this error.
Otherwise, you only check the first item, and return immediately whether or not it matched. You want to return if you find a match, but keep looking otherwise, and only return -1 if there is no match:
for (int i = 0; i < vals.size(); i++){
if (vals[i]->getName() == name_in){
cout << vals[i]->toString() << endl;
return i;
}
}
return -1;
The find player function should be something like:
int findPlayer(vector<Player*> &vals, string name_in)
{
if(vals.size() == 0)
return -1;
for (int i = 0; i < vals.size(); i++){
if (vals[i]->getName() == name_in){
cout << vals[i]->toString() << endl;
return i;
}
}
return -1;
};
Rewrite the function the following way
bool findPlayer( const std::vector<Player*> &vals, const std::string &name_in )
{
std::vector<Player*>::size_tyoe i = 0;
while ( i < vals.size() && vals[i]->getName() != name_in ) ++i;
return i != vals.size();
}
Take into account that member function getName has to be defined with qualifier const.
As for your function then it returns nothing in case when the vector is empty or returns -1 in case when the first element of the vector does not coincide with the string.
Take into account that there is standard algorithm std::find_if declared in header <algorithm> that can be used instead of your function.

Multiple return value method fails with goto statements

The following code:
#include <cstdlib>
#include <iostream>
using namespace std;
int function(void)
{
static int i,state=0;
switch(state)
{
case 0: goto labeL0;
case 1 :goto labeL1;
}
labeL0:
for (i = 0; i < 10; i++)
{
state=1;
return i;
labeL1:;
}
}
int main(int argc, char *argv[])
{
cout << function() << endl;
system("PAUSE");
return EXIT_SUCCESS;
}
fails. I mean it returns only 0 instead of 0,1,2,...
I wanted just use label and goto statements to implement such functions. It is for practice (let's say homework), but I can't get it to work. Is this even possible?
How can I use goto and label statements so that this function prints 0 1 2... so on?
It's not clear to me exactly what you're trying to do. If your goal is
jsut to use goto, the simplest solution is to implement the algorithm
exactly as you'ld normally do, replacing looping constructs wit goto;
i.e. instead of:
for ( int i = 0; i < 10; ++ i ) {
std::cout << i << std::endl
}
you could write:
int i = 0;
goto label1:
label2:
std::cout << i << std::endl;
++ i;
label1:
if ( i < 10 ) goto label2;
Back in the old days, with Fortran IV, this is what we actually did.
There's absolutely no reason to do it today (except maybe obfuscation).
I wonder, however, given the static variables, if you're not trying to
implement some sort of co-routine; that each time you call the function,
you output one higher than the previous time. In this case, I'd
recommend maintaining the state in a class, rather than using static
variables. In addition the function will need some sort of return value
so that the caller will know when it's finished, and the caller will
have to loop. Something like the following should do the trick:
class CoRoutine
{
int i;
public:
CoRoutine() : i( 0 ) {}
bool function()
{
if ( i < 10 ) {
std::cout << i <<std::endl;
++ i;
}
return i < 10;
}
};
int
main()
{
CoRoutine c;
while ( c.function() ) {
}
return 0;
}
(There's still no need for goto, of course.)
This won't work since after the return statement, the compiler leaves the function ignoring all statements after it.
Also, using labels is ugly, horrible and unmaintainable. Why are you using them? Do you want the maintenance guy arriving at your house with a chain-saw?
After executing the return statement the execution returns from function().....
So initially when i=0, "return i" returns 0 and it is displayed on screen
You should use recursive call to function to get it executed and more over your use of GOTO is a typical example of why we should avoid using goto.
void function(void)
{
static int i=0;
for(;i<10;)
{
cout<<i;
i++;
function();
}
}
void main()
{
function();
}
but if you still want to use goto statements then use this
void function(void)
{
static int i =0;
lablelA:
cout<<i;
i++;
if(i == 10)
return;
goto lablelA;
}
Jumping to labeL1 is jumping in a loop with uninitialized variable i. How could this go right? This is only 1 of the reasons to avoid goto.
EDIT: actually, it should probably work as some sort of poor man's generator (because of the static local variables), but still the case of i >= 10 should be handled. Now it is returning nothing. So your main concern in the code is that you need a loop in main to call function maximum 10 times.
Still, this is not a construct I would want to see in real code.
The code reminds me of Coroutines in C.
To print 0, 1, etc you should call the function several times. That's the whole point.