What is the point in returning values? - c++

I'm fairly new when it comes to C++ so bear with me. When learning about return values in functions, I was told that the proper way to write pure functions is to return a value every time. I attempted this in a small function that checks the user's age and returns whether or not they're an adult. The issue here, at least for me, is understanding the proper utilization of these return values. For example, in this code snippet here I'm returning whether or not they are an adult given their age in years.
main.h
#pragma once
#define LOG(x) std::cout << x
#define LOGCIN(x) std::cin >> x
bool check_age(int age) {
if (age >= 18)
return true;
else
return false;
}
main.cpp
#include <iostream>
#include "main.h"
bool check_age(int age);
int main() {
int age;
LOG("Enter your current age in years: ");
LOGCIN(age);
bool adult = check_age(age);
if (adult == true) {
LOG("You are an adult!");
} else {
LOG("You are not an adult!");
}
}
However, when I rewrote this code without using return values, I got this.
main.h
#pragma once
#define LOG(x) std::cout << x
#define LOGCIN(x) std::cin >> x
void check_age(int age) {
if (age >= 18)
LOG("You are an adult!");
else
LOG("You are not an adult!");
}
main.cpp
#include <iostream>
#include "main.h"
void check_age(int age);
int main() {
int age;
LOG("Enter your current age in years: ");
LOGCIN(age);
check_age(age);
}
As you can see, the latter code choices is simpler and more compact. If code requires more lines and takes longer to write with return values, then what's even the point in using them?

Often the purpose of a function is not just to log something to cout but instead make a decision based on some parameters, or return a value so it can be used flexibly. An example of this would be in binary search:
while(l <= r) {
int mid = (l+r)>>1;
if(check(/* parameters */)) {
//update answer
r = mid+1;
} else l = mid-1;
}
Of course, you could make your function edit a global variable and make decisions based off of that; but it will make the code more verbose:
while(l <= r) {
int mid = (l+r)>>1;
check(/* parameters */);
if(ok /* global variable*/) {
//update answer
r = mid+1;
} else l = mid-1;
}
As an additional example, it is a lot easier to write (and read):
round(a)+ceil(b)
than have these functions update global variables.

Imagine the function is provided by someone else.
In that case, we may not be able to know its implementation.
How does our program know whether the function succeeds or not?
Besides, sometimes we want to know some information from a function. I think that's why return values are used.

Returning a value from the function serves an important purpose - it allows you to separate the two concepts of "determine whether this person is an adult" and "print some stuff about this person".
You could imagine tons of scenarios where the program would need to know if someone was an adult without printing it to console - such as allowing them to buy alcohol, register for college, etc etc etc.
And you could also imagine that if you knew someone was an adult, there might be a ton of different ways you'd like to print that (imagine other languages, or rendering it on a webpage, or etc etc).
So by returning the value, you enable this separation of concepts which makes your code much more flexible in the future.
Maybe you don't need that for a toy example, but that's sorta beside the point when you're asking a broad design question like this.

Related

Deconstruct a C++ code block from a novice perspective

I am very new to C++ and I am trying to deconstruct someone's code, and I am not quite sure what to Google for, hence I am just going to ask here. This is a second attempt at a question I asked earlier which was poorly posed. Should this one not measure up, please let me know and I shall try to rectify.
Here is a structurally identical MWE, of the piece of code I am trying to understand.
#include <iostream>
using namespace std;
int square(int x){
// Function that squares without using *
int result = 0;
for (int counter = 0; counter < x; ++counter){
result += x;
}
return result;
}
int main()
{
int const D = 4;
int myArray[D] = {}; // all elements 0 in C++
char colour[D] = {'c','o','e','g'}; // Initialize String Array
int AEST = 5; // Initialise AEST
for (int d =0; d<D; d++){
if (colour[d]!='c' && colour[d]!='o'){
double aux= square (d);
if (aux!=0){
myArray[d]=aux;
}else{
return AEST;
}
}
}
// Lets see what we achieved.
for (int d =0; d<D; d++){
cout << myArray[d];
}
return 0;
}
Now then, lets crack on with some questions.
Precisely what I do not fully understand is this block:
}else{
return AEST;
}
Please not, AEST is not an error code, it is a numerical value that the code calculates. I have only initialized it here for the purpose of this MWE, but in actuality, it is calculated earlier on in the original code block.
My question is as follows:
The if statement is only true if the colours are not c or o and in which case we square d. In the MWE we square d twice. Hence, is the code then saying that we break out of the loop (with return AEST) IF we stumble upon a colour that is not c or o? But if we do break out of the loop under these conditions, why must we return AEST? It is already initialised AEST=5 earlier on, and nothing we do inside this loop will affect it (remember this block is structurally identical to what I am trying to understand, but obviously not fully identical). This is why I do not understand the else bit.
Again, if there is not enough information, please let me know.
The return AEST part in question exits the main() function. That means the program exits in state 5.
This is done to have some sort of error code detection. For example. If you have various things that can go wrong, you try to retun those with specific codes so you can look up and identify where the problem occured.
It is common to return 0 if everything is fine.

Problems With linesearch and Bubblesort

Im making a program in c++ that takes a few persons puts them in a vector with name and age and i got all the code down for it but i cant get it to compile properly.
this is my code so far
#include <iostream>
#include <string>
using namespace std;
class person
{
public:
string name;
int age;
void SetInfo(const string _name, int _age) //Här läggs den viktigaste informationen in
{
name = _name;
age = _age;
}
int getAge(){ return age; }
};
void bubblesort(person mylist[], int n) // Här startar Bubblesort funktionen
{
for (int i = 1; i<n; i++)
{
for (int j = 0; j<i - 1; j++)
{
if (mylist[j].getAge() > mylist[j + 1].getAge())
{
person temp;
temp = mylist[j];
mylist[j] = mylist[j + 1];
mylist[j + 1] = temp;
}
}
}
}
int main() //Program start
{
person mylist[4]; //lista på personer
mylist[0].SetInfo("Johan", 25);
mylist[1].SetInfo("Nathalie", 20);
mylist[2].SetInfo("Jessica", 60);
mylist[3].SetInfo("Coco", 54);
//anropar bubblesort()
bubblesort(mylist, 4);
int index = Linesearch(mylist, 25);
if (index == -1)
cout << "person ej funnen!";
else
cout << "personen du letade efter " << mylist[index].name;
cin.get();
return 0;
system("pause");
}
The problem i think is my knowledge since im new to programming and has only done it for 4 weeks. I put this code together from myself and from examples found online. So every answer will help me learn more :)
EDIT:
Still the same code added error message here.
50 39 C:\Skrivbordet\Skola\ccxcxcxcvx.cpp [Error] 'Linesearch' was not declared in this scope
A C++ program starts out fairly blank, without any function to use at all except for main. (There is more to say on that. I'm sure comments are going to point that out. ;)) You include headers for <iostream> and string, so you can use all of the functions declared in them, which is a good thing! Lots of stuff is already written for you; you don't have to find out how to write text out to your screen, for example.
All other functions are to be written by yourself -- which is also a good thing! After all, what would be the fun of a programming language where you cannot do the stuff you want because "there is no function for it".
You already wrote (or possibly copied) one custom function: bubblesort. From that point on, you can use it anywhere you want. It is not in the standard headers, but the compiler sees it as a general function nevertheless; all it has to do is read your code top to bottom, and store the names of new functions when it encounters them.
On to your problem: Linesearch is the name of a function. The compiler assumes that because it is followed by a parenthesized argument list. So, it looks up Linesearch in the standard headers, finds it's not in there, then goes through your source code -- and still does not find it. Presto! error.
The solution is to use an existing standard function that does what you need, if there is one (I cannot recall), or write the function yourself and place it in your source code somewhere above main. (It needs¹ to be above the first function in which it is used, and in this case that is main.)
¹ I'm telling only a half-truth there; but I guess before expanding on that in turn, you are better off reading a C++ primer first.

Error "'=' : left operand must be l-value" when writing an if-statement

I'm having to make this code to run a dice game, it's my first game program and I've encountered some errors I've never seen before so I've done my best to fix them. So the only errors I have left are these:
'=' : left operand must be l-value
for the last three if statements. I know that's probably only the beginning of my problems but I'm new to all this so any advice is GREATLY appreciated.
#include <iostream>
#include <ctime> //Include Header file for time functions
#include <cstdlib> //Include Header file for random number generators
#include "graph1.h"
using namespace std;
int main()
{
//Variable Declaration
int rv1 = 0; //Random number for the 1st dice
int rv2 = 0; //Random number for the 2nd dice
int seed=0;
int wager=0;
//Display graphics
displayGraphics();
cout<< "Wager";
cin>>wager;
//Initialize random number generator
srand(time(0));
//Generate two random numbers between 1 and 6 inclusive
rv1 = (rand()%6)+1; /* Function rand() generate a random number,
(rand()%6+1) generate a random number between 1&6 */
rv2 = (rand()%6)+1;
//rv1
if(rv1=1)
{cout<<displayBMP("1.bmp",200,150);}
else
{ if (rv1=2)
cout<<displayBMP("2.bmp",200,150);}
if (rv1=3)
{cout<<displayBMP("3.bmp",200,150);}
if (rv1=4)
{cout<<displayBMP("4.bmp",200,150);}
if (rv1=5)
{cout<<displayBMP("5.bmp",200,150);}
if (rv1=6)
{cout<<displayBMP("6.bmp",200,150);}
//rv2
if(rv2=1)
{cout<<displayBMP("1.bmp",200,250);}
if (rv2=2)
{cout<<displayBMP("2.bmp",200,250);}
if (rv2=3)
{cout<<displayBMP("3.bmp",200,250);}
if (rv2=4)
{cout<<displayBMP("4.bmp",200,250);}
if (rv2=5)
{cout<<displayBMP("5.bmp",200,250);}
if (rv2=6)
{cout<<displayBMP("6.bmp",200,250);}
if (wager<5)
{
cout<<displayBMP("smiley.bmp",250,100);
gout<<setPos(150,280)<<"Your wager of"<<wager<<"is less than required $5/";
gout<<setPos(150,295)<<"Please re-run program and enter larger amount!/n";
return-1;
}
if (((rv1+rv2)%2)=0)
{ gout<<setPos(200,280)<<"Dice total"<<(rv1+rv2)<<endg;
cout<<"You win $2 extra for even roll!/n";
cout<<"Your winnings:$2+Original Wager:$"<<wager<<"=$"<<wager+2<<endg;
}
if(rv1+rv2=7)
{gout<<setPos(200,280)<<"Dice total"<<(rv1+rv2)<<endg;
cout<<"Youre lucky today!/n";
cout<<"You double your wager/n";
cout<<"Your winnings:$10+Original Wager=$"<<wager<<"=$"<<wager*2<<endg;
}
if(((rv1+rv2)%2)=1)
{gout<<setPos(200,280)<<"Dice total"<<(rv1+rv2)<<endg;
cout<<"You lose $2 for odd roll!/n";
cout<<"Original Wager:$"<<wager<<"Losses:$2=$"<<wager-2<<endg;
}
return 0;
}
= is used for variable assignment in C++. You need to use == for comparison tests:
if (((rv1+rv2)%2)==0)
Note too that if-statement conditions written like this:
if(rv1=1)
will always evaluate to true because rv1=1 returns the result of the assignment which is 1. This is why some C++ programmers write conditions like this:
if(1==rv1)
which prevents you from accidentally forgetting the second = because:
if(1=rv1)
is a compile-time error. Of course, writing conditions like this is primarily a matter of style. I personally do not use this method because it doesn't read very well in my opinion.
You are using the assignment operator = everywhere in the if statements instead of the comparison operator == starting from here
if(rv1=1)
{cout<<displayBMP("1.bmp",200,150);}
There must be
if(rv1 == 1)
{cout<<displayBMP("1.bmp",200,150);}
and so on.
.

Why I cannot assign values to a variable with if and if else statements?

#include <iostream>
using namespace std;
void main()
{
int leftover;
int gold = 3900;//satisfies the if else statement
if( gold>=4100){//successfully build item
leftover = gold-4100;
}
else if(4100>gold>=3500){
leftover = gold-3500;
}
cout << leftover << endl;
system("pause");
}
This code doesn't work, it will show that leftover is used without being initialized. But when I changed the value of gold(etc 4200) to satisfy the if statement, it will work, displaying the remainder after gold has been deducted from 4100. I am just learning c++ in school so I am not familiar with if and if else statements yet so many thanks for telling me what went wrong!
4100>gold>=3500 doesn't do what you think. It's evaluated as (4100>gold) >= 3500, which depending on the value of gold can be 0 >= 3500 or 1>3500. Look up operator precedence.
You probably want
(4100>gold) && (gold>=3500)
If you don't initialize the value and the if statements fail, then you cout null
You have two suggestions here:
FIRST:
int leftover = -1; //Initialize the value
SECOND:
else { leftover = 0; } //Default the value if the if case fails
Yea I made a VERY careless mistake, the only problem is 4100>gold>3500 will never get evaluated.
Thanks to all who answered and pointed out to use AND gate instead of shared operands!

extracting data between having { } any other method with good run time

I have this piece of code where am extracting the data between the { }, and this takes me around O(n) is there any other method which is more effcient
#include <iostream>
#include <string>
#include <stdio.h>
int main()
{
const char *blah = "[{post:banb {bbbbbbbb}: ananmsdb},{dsgdf{9090909090}fdgsdfg}";
std::string op;
unsigned int i = 0;
int im = 0;
int found = 0;
while(strlen(blah) != i){
if(blah[i] == '{'){
found = 1;
// copy what ever u got
op+=blah[i];
im++;
}
else if(blah[i] == '}'){
//copy wat ever u got
op+=blah[i];
im--;
}
if(found ==1){
//copy wat ever u got.
op+=blah[i];
}
if(found ==1 && im == 0) {
found = 0;
cout << op <<endl;
op.clear() ;
// u have found the full one post so send it for processing.
}
i++;
}
}
output :post:banb {bbbbbbbb}: ananmsdb
dsgdf{9090909090}fdgsdfg
No. You can use library functions to make this code shorter, but it will never be more efficient than O(n) where n is the length of the input string, since you need to examine each character at least once because each one could potentially be a token that you need to extract.
I don't think you can improve on O(n) for the underlying algorithm, but you can probably improve your implementation.
Currently your implementation may well be O(n^2) rather than O(n), as strlen() could be called on every iteration (unless your compiler is particularly smart). You should probably cache the call to strlen() explicitly, e.g. change:
while(strlen(blah) != i){
...
to:
const int len = strlen(blah);
while(len != i){
...
As everybody else has said there is no way to make this faster as you have to check every character incase you miss one.
But, this being said if perhaps you already knew some information about the data aka how many pairs of '{' and'}' then I can onlythink of one way(besides sorting but that brings it back to O(n) + etc).
This would be to choose indexes between 0 - x and randomly check at spots if you can find the '{' or '}'. Just to be clear this will only work if you know how many '{' and '}'s are already in the set of data.
Edit: Addtionally the copy you provided (just from using notepad) when it hits the first cout<< it should output "{{post:banb {{bbbbbbbb}}: ananmsdb}}", as its creating additional {'s and }'s.