I'm going through this tutorial:
https://www.learncpp.com/cpp-tutorial/how-to-design-your-first-programs/
I noticed the author didn't use a parameter in this function:
int getUserInput()
{
std::cout << "Enter an integer ";
int input{};
std::cin >> input;
return input;
}
Would it be okay to do something like this?
int getUserInput(int input)
{
std::cout << "Enter an integer ";
std::cin >> input;
return input;
}
It would work, but it wouldn't make much sense.
The first version of your function is used something like this:
int some_number = getUserInput();
That makes sense; the caller isn't providing any input to the function, so it takes no parameters.
The second version takes a parameter though, so the caller has to provide it. The function doesn't actually do anything with that value though. All of the following behave exactly the same:
int some_number1 = getUserInput(0);
int some_number2 = getUserInput(123456);
int some_number3 = getUserInput(some_number2);
It makes no sense for the caller to provide a parameter to the function since the function doesn't use it at all.
Related
The problem i am having is when i compile my code, i get an error (uninitialized local variable "optionNumber used"
I am using visual studio 2017 on a macbook air for this.
here is my code:
#include "pch.h"
#include <iostream>
int runMenu(int optionNumber) {
std::cout << "Choose an option \n";
std::cout << "1) Create Array \n";
std::cout << "2) View Array \n";
std::cout << "3) Add/Delete Values \n";
std::cin >> optionNumber;
return(optionNumber);
};
int main()
{
int optionNumber;
int optionNum;
optionNum = runMenu(optionNumber);
std::cout << optionNum;
return(0);
}
int main()
{
int optionNumber;
^^^^^^^^^^^^^^^^
Here, you've declared a local variable. You've not provided an initialiser. Therefore the local integer has an indeterminate value. If you read an indeterminate value, the behaviour of your program will be undefined.
optionNum = runMenu(optionNumber);
^^^^^^^^^^^^
Here, you copy the variable whose value is indeterminate into an argument. Therefore the behaviour of the program is undefined. Luckily, your compiler noticed this mistake and warned about it.
Most trivial solution: Initialise the variable:
int optionNumber = 42;
On the other hand, you may want to think a bit about what you've written. The value that you pass to the function runMenu is never used in the function. Whatever value is passed in will be overwritten by whatever is extracted from standard input. The argument is completely pointless. Instead of an argument, you can read the input into a local variable:
int runMenu() {
// your std::cout stuff
int optionNumber;
std::cin >> optionNumber;
I'm trying to validate user input for integers only. My code works fine except when the user inputs 0. It doesn't consider it an integer, and it thinks the value is false. Here's a brief example of how I'm coding this project....
int main ()
{
int num;
cout << "Please enter an integer: ";
cin >> num;
cout << endl;
while (! num)
{
cout << "That is not an integer.\n";
return;
}
}
If the user inputs 0, I get sent into the while loop even though 0 is an integer.
The expression !num is true if, and only if, num is 0. So your implementation is buggy.
The easiest thing to do is to use something like
if (!(std::cin >> num)){
std::cout << "That is not an integer.\n";
}
If you want to validate the input yourself then consider reading in a std::string and checking if that can be converted to an integer. This is surprisingly non-trivial since the possible values an int can take are so platform dependent (some systems have a range as small as -32767 to +32767).
If you can, use boost::lexical_cast<int>(num); where I've upgraded num to a std::string type. (The header you need is <boost/lexical_cast.hpp>).
In c++ the built-in int type doesn't have any optional validity to it like it does in some other languages: "!num" just means "num==0" and not "num does not exist".
However C++17 has std::optional template, which can turn your vanilla int into exactly what you originally expected!
All you need is some simple template magic to make it work with istream:
template< class CharT, class Traits, class T >
basic_istream<CharT,Traits>& operator>>( basic_istream<CharT,Traits>&& st,
std::optional<T>& value )
{
T res;
st>>res;
value = (st)?res:{};
return st;
}
Come to think of it, STL should provide that overload from the box.
Now all you need is to replace your int num with std::optional<int> num and voila - your code works as intended.
Seriously though, just use Bathsheba's solution.
If I prototype a function above the main function in my code, do I have to include all parameters which have to be given? Is there a way how I can just prototype only the function, to save time, space and memory?
Here is the code where I came up with this question:
#include <iostream>
using namespace std;
int allesinsekunden(int, int, int);
int main(){
int stunden, minuten, sekunden;
cout << "Stunden? \n";
cin >> stunden;
cout << "Minuten? \n";
cin >> minuten;
cout << "Sekunden= \n";
cin >> sekunden;
cout << "Alles in Sekunden= " << allesinsekunden(stunden, minuten, sekunden) << endl;
}
int allesinsekunden (int h, int m, int s) {
int sec;
sec=h*3600 + m*60 + s;
return sec;
}
"If I prototype a function above the main function in my code, do I have to include all parameters which have to be given?"
Yes, otherwise the compiler doesn't know how your function is allowed to be called.
Functions can be overloaded in c++, which means functions with the same name may have different number and type of parameters. Such the name alone isn't distinct enough.
"Is there a way how I can just prototype only the function, to save time, space and memory?"
No. Why do you think it would save any memory?
No, because it would add ambiguity. In C++ it's perfectly possible to have two completely different functions which differ only in the number and/or type of input arguments. (Of course, in a well-written program what these functions do should be related.) So you could have
int allesinsekunden(int, int, int)
{
//...
}
and
int allesinsekunden(int, int)
{
//...
}
If you tried to 'prototype' (declare) one of these with
int allesinsekunden;
how would the compiler know which function was being declared? Specifically how would it be able to find the right definition for use in main?
You have to declare the full signature of your function, i.e. the name, the return value, all parameters with types, their constness, etc.
I have some doubts about C++ reference parameters. I am learning from this website:
http://www.doc.ic.ac.uk/~wjk/c++Intro/RobMillerL3.html
First program:
#include<iostream>
using namespace std;
int area(int length, int width);
int main()
{
int this_length, this_width;
cout << "Enter the length: ";
cin >> this_length;
cout << "Enter the width: ";
cin >> this_width;
cout << "\n";
cout << "The area of a " << this_length << "x" << this_width;
cout << " rectangle is " << area(this_length, this_width) << endl;
return 0;
}
int area(int length, int width)
{
int number;
number = length * width
return number;
}
Then the author suggests that "under some circumstances, it is legitimate to require a function to modify the value of an actual parameter that it is passed".After that he introduces new function:
void get_dimensions(int& length, int& width)
{
cout << "Enter the length: ";
cin >> length;
cout << "Enter the width: ";
cin >> width;
cout << "\n";
}
What is the main advantage when we pass values as parameters?
Advantages of passing by reference:
It allows us to have the function change the value of the argument, which is sometimes useful.
Because a copy of the argument is not made, it is fast, even when used with large structs or classes.
We can pass by const reference to avoid unintentional changes.
We can return multiple values from a function.
Disadvantages of passing by reference:
Because a non-const reference can not be made to a literal or an expression, reference arguments must be normal variables.
It can be hard to tell whether a parameter passed by reference is meant to be input, output, or both.
It’s impossible to tell from the function call that the argument may change. An argument passed by value and passed by reference looks the same. We can only tell whether an argument is passed by value or reference by looking at the function declaration. This can lead to situations where the programmer does not realize a function will change the value of the argument.
Because references are typically implemented by C++ using pointers, and dereferencing a pointer is slower than accessing it directly, accessing values passed by reference is slower than accessing values passed by value.
Sources:
http://www.learncpp.com/cpp-tutorial/73-passing-arguments-by-reference/
http://www.functionx.com/cppcli/functions/Lesson10b.htm
https://en.wikibooks.org/wiki/C++_Programming/Code/Statements/Functions
There is already a good answer (imho worth accepting). However, I would like to give a more basic answer, as it seems like you encountered passing by reference for the first time:
This function:
void foo(int x){x +=1;}
can do anything with the value of the passed (by value) parameter, but it has no chance to return anything to the caller, i.e. the x+=1 has practically no effect at all.
On the other hand, this function:
void bar(int& x){x +=1;}
gets not only the value, but it is working on the actual variable that you pass as parameter (by reference). Thus the x+=1 has an effect also outside of the function.
Both functions in action:
int main(){
int a = 1;
foo(a); // foo gets a copy of a and increments its value
// a is still 1
bar(a); // bar directly increments the value of a
// a is now 2
}
This is the main difference of passing a parameters by reference (bar) vs passing by value (foo). The main advantage of passing by reference is that the value of the parameter needs not to be copied. (This is whypassing by value is usually done with a const reference. Passing a const reference is like passing the value because the value cannot be changed even if actually a reference is passed.) However, for more details I refer to Rohits answer.
int &a is a reference to any parameter passed to that function, You should always think of references as Alias to a variable (it is similar to a const pointer).
If your reference is not const you are allowed to changed and therefore change the content of the original variable.
It is useful for many reason first of all it can improve performances by avoiding doing copies when passing a parameter by reference, and it is also useful if you have a function that your expecting to return multiple results for example =:
int f (int &a,int &b,int &c,int&d);
int main
{
int first,second,third,result;
result = f(first,third,result);
}
All your int variables can be change within you function.
I wrote a simple input validation function to check if the user has entered the right data type and if not it'll keep asking them to re-enter until they do. Now this is something that I use a lot and in most cases I am using it on multiple data types at a time. So instead of duplicating the function and changing the data type of num inside the method is there a way I can simply just pass a data type as the parameter and have it change inside the function too?
float cinInputValidation(){
float num;
while(!(cin>> num)){
cout<< "Error: Invalid Input.\n"
<< "Please try again: ";
cin.clear(); // Clears cin flags if user enters variable of the wrong data type.
cin.ignore(100, '\n'); // Ignores up to 100 characters or until a new line.
}
return num;
}
Now I am aware of typeof() and I have a hunch I can use it as a parameter like so
cinInputValidation(typeof(float))
but what would I do about the functions datatype itself and the type declaration of the num variable? Or is this just not possible.
As #chris correct pointed out, you can change cinInputValidation() into a function template so the type can be specified via a template parameter at the call site:
template<typename T>
T cinInputValidation() {
T num;
while (!(cin >> num)) {
...
}
return num;
}
Later on...
float f = cinInputValidation<float>();
double d = cinInputValidation<double>();