• Advertisement
Sign in to follow this  

C++ Workshop - Functions, Parameters, & Scope (Ch. 5)

This topic is 3094 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Welcome to the GDNet C++ Workshop – Ch. 5

For a complete introduction to this workshop, please look here. Workshop Overview This workshop is designed to aid people in their journey to learn beginning C++. This workshop is targeted at highly motivated individuals who are interested in learning C++ or who have attempted to learn C++ in the past, but found that without sufficient support and mentoring they were unable to connect all the pieces of this highly complex but powerful programming language. This is a 'guided' self-teaching C++ workshop. Each student is responsible for taking the time to read the material and learn the information. The community and tutors that arise out of this workshop are here for making the learning process run more smoothly, but are not obligated to baby-sit a person's progress. Because everyone will be working from the same textbook (Teach Yourself C++ in 21 days 5th Ed.), students may find it easier to get answers to the specific questions they might have. There is no minimum age requirement, and there is no previous programming experience required. Additionally, this workshop does not attempt to defend C++ as a language, nor does it attempt to demonstrate that C++ is either more or less useful then other programming languages for any particular purpose. People who intend to start a discussion about the differences between C++ and ANY other languages (except as are relevant to a particular discussion), are encouraged to do so elsewhere. This workshop is for educational, not philosophical discussions. Quizzes & Exercises Each week will have quizzes and exercises posted in the weekly threads. Please try and answer them by yourself. As well, please DO NOT post the answers to Quizzes and Exercises within this thread. Once it becomes acceptable to post the answers to quizzes and exercises, an additional thread will be created each week specifically for the purpose of posting quiz answers. If you try with reasonable effort but are unable to answer the questions or complete the exercises, feel free to post a clarification question here on the thread. Tutors, myself, or others will do the best we can to point you in the right direction for finding the answer.

Chapter 5 – Organizing into Functions

Introduction Good morning all! This week we will be covering chapter 5, which is approximately 30 pages, not counting the review stuff at the end of the chapter. The topic for this week is functions. In a way, this week will explore the basis of the early procedural languages such as C. We'll take blocks of code which may need to be executed repeatedly and we'll move it out into functions. Additionally, we'll now be able to take overly complex ideas and break them up into smaller chunks of thought, and then separate them into their own procedures. Finally, when combined with previous weeks we can use functions as handy containers for expressions that take in input, perform calculations, and return an output, thus allowing us to make a library of more complicated mathematical functions. Functions by themselves are not a difficult concept, but the implementation of functions within a programming language does provide subtle complexity that is important to understand. Some of those include arguments, the difference between function definitions and declarations, scoping of variables, function overloading, inline functions, and recursion. Many of these topics do not even become relevant until we introduce the concept of functions or procedures. Roughly half way through the week myself, tutors, or anyone else simply wishing to challenge their teammates learning C++ can post review and quiz questions in this thread. Please do not post the answers in this thread however, as a new thread will be created for that purpose. Outline of the Reading
  1. What is a function?
  2. Return Values, Parameters, and Arguments
  3. Declaring and Defining functions
  4. Execution of Functions
  5. Determining Variable Scope
  6. Parameters Are Local Variables
  7. Considerations for Creating Function Statements
  8. More About Function Arguments
  9. More About Return Values
  10. Default Parameters
  11. Overloading Functions
  12. Special Topics About Functions
  13. How Functions Work - A Peek Under the Hood

Good Luck!

[Edited by - jwalsh on May 30, 2007 5:30:48 PM]

Share this post


Link to post
Share on other sites
Advertisement
Why is this posted in "For beginners"? Any particular reason, or just forgetfulness?

Share this post


Link to post
Share on other sites
Quote:
Original post by DivineGod
Why is this posted in "For beginners"? Any particular reason, or just forgetfulness?

It's posted in For Beginners for easy access by those who need it most. Each week we post a new chapter thread which is mirrored in FB and the C++ Workshop. Previous chapter threads are then removed from FB and archived in the C++ Workshop Forum. I'm just waiting for Fruny to swap out the stickied thread.

Had you read the first paragraph of the post, you would have known that. [wink]

Cheers!

Share this post


Link to post
Share on other sites
Oh.. sorry 'bout that, then.

Suppose I read too fast to notice everything in the first place.

Share this post


Link to post
Share on other sites
A comment and a question about Listing 5.5.

I've found a couple of mistakes: a typo in line 7 and there should be <using std::endl;> in line 21.

I know that a function can be used to do something (such as "void myFunction();") or it may be used to return a value (such as "int myFunction (int a, int b);") and, in this case, there should be a "return x;" at the end of the function prior to going back to the main code. Is it possible to return two values from the function back to the main code? For instance, if (in line 23), there's an assignment setting x to be 23, can both x (23) and y (10) be returned to main so that these values are printed in lines 13 and 14?

I know that it would be possible to call a function twice, returning x (23) and y (10) separately, but is it possible to return both values from one execution of the function?

Share this post


Link to post
Share on other sites
Quote:
Original post by CondorMan
A comment and a question about Listing 5.5.

I've found a couple of mistakes: a typo in line 7 and there should be <using std::endl;> in line 21.

I know that a function can be used to do something (such as "void myFunction();") or it may be used to return a value (such as "int myFunction (int a, int b);") and, in this case, there should be a "return x;" at the end of the function prior to going back to the main code. Is it possible to return two values from the function back to the main code? For instance, if (in line 23), there's an assignment setting x to be 23, can both x (23) and y (10) be returned to main so that these values are printed in lines 13 and 14?

I know that it would be possible to call a function twice, returning x (23) and y (10) separately, but is it possible to return both values from one execution of the function?


You can't really return 2 values. The easiest way (and the most correct usually) would be to just call the function twice for each variable.

<ADVANCED>
You can also pass variables to a function by reference to achieve this. Usually a variable is passed by value, meaning only the value of the variable s sent to the function, so if you modify the vaiable in the function, its value outside will not change. Example:


// Passing by value

#include <iostream>

void Increment(int value)
{
value++;
}
int main()
{
int value = 5;
std::cout << "orginal value: " << value << std::endl;
increment(value);
std::cout << "value after function: " << value << std::endl;

return 0;
}






Output would be:

original value: 5
value after function: 5


To pass a value by reference, you use the '&' operator in the parameter list of the function.


// Passing by reference

#include <iostream>

// notice the '&' operator
void Increment(int & value)
{
value++;
}
int main()
{
int value = 5;
std::cout << "orginal value: " << value << std::endl;
increment(value);
std::cout << "value after function: " << value << std::endl;

return 0;
}






Output would be:

original value: 5
value after function: 6


Passing by reference can be nice for some things and some types of items (such as file stream objects) must be passed by reference to work properly. I only use one variable, but you can easily have multiple parameters defined to be passed by reference.

</ADVANCED>

Share this post


Link to post
Share on other sites
Thank you. I suspected the best way would be to call the function twice but just wondered if there was a way of doing it which fell into the "advanced" area.

The advanced comment about passing by reference is interesting. I noticed this when I flicked through the book so I look forward to getting my teeth into that.

Share this post


Link to post
Share on other sites
Quote:
Original post by CondorMan
I know that it would be possible to call a function twice, returning x (23) and y (10) separately, but is it possible to return both values from one execution of the function?

Not in C++, but it's possible in other languages.

[Advanced]

It's really not advanced if there's language support, but I'm going to talk about tuples. The word comes from a corruption, I believe, of "multiple," as that's exactly what a tuple is: a multiple-value value. The following is a Python example:


"""apply will apply (sorry) the function supplied as the parameter fn to each value in the tuple
t, collating the results into a tuple and returning it."""

def apply(fn, t):
results = [] # create an empty list
for v in t:
results.append(fn(v))

return tuple(results) # now convert the populated list into a tuple and return it

"""mul2 multiplies its parameter by 2 and returns the result."""
def mul2(n):
return 2 * n

...

# the following is a demonstration of the functions above as would occur from the
# Python interactive command line

>>> apply(mul2, (3, 4, 5, 6, 7))
(6, 8, 10, 12, 14)




In fact, tuples are so inherent in Python that you can use them anywhere:
return 3, 4

The function apply is unnecessary because Python supplies map, which does exactly the same thing; apply was written for illustrative purposes. Similarly, mul2 is unnecessary and can be replaced with a lambda function... but we won't get into that today. [smile]

The point is, with built-in language support, tuples become extremely natural types to use, and they allow for some very elegant programming. That said, C++ classes can be written (and have been) support tuples, however they have limits on the number of elements they can store (typically about 10 for casual applications). They are written using templates to enable them handle any type, but unlike language-supported tuples (as in Python, where you can write return 4, "blah", SomeFunction), these C++ tuple implementations also have restrictions with regard to the types they can handle.

Of course, something should have popped out at you. A tuple is a sequence type, and it's very convenient, but C++ has a few other sequence types, like std::vector (admittedly, I doubt that has been introduced in your text yet). When you need to return several pieces of data, one option is to aggregate them into a container and return the container as a single object. If they are all of the same type, then you can return a std::vector. If they are of diverse types, but the operation is important enough, you can create a new data structure to hold the various fields, and then create an instance and populate that in your function, again returning a single value.

Hey, I said it was advanced! [smile] Don't worry too much about it now. Just know that, as time goes on, you'll be able to do far more complex things with C++ functions than the limitations you see now might suggest.

[Advanced]

Share this post


Link to post
Share on other sites
<Advanced>

(Hey, if the previous two posts are advanced, then I figure this qualifies as well.)

C++ does sort of support tuples natively, because you can make and return structures, but they have to have a specific size, and a type for each returned value. You cannot return an array, and returning a pointer is generally speaking a bad idea (what are you going to point it at? Keep in mind that the function's local variables are dead when the function returns; 'normal' returns only work because a copy is made, at least conceptually.)

If you are returning several values of the same type, (or, with a bit more effort, where all of them are objects with a common base class), you can return a container of those objects such as a std::vector of them.

Otherwise... if you are lazy ;) or if the structure won't be used anywhere else, you can rely on the standard library. If you only need two return values, you can return a std::pair. This is a templated structure that has two members, 'first' and 'second'.


// Sample implementation: this is what std::pair MIGHT look like in your
// library implementation.
namespace std {
template <typename T1, typename T2>
struct pair {
T1 first;
T2 second;
};

template <typename T1, typename T2>
std::pair<T1, T2> make_pair(const T1& x, const T2& y) {
std::pair<T1, T2> result;
result.first = x;
result.second = y;
return result;
}
}


See, the standard library already gives an example of the technique ;) (The reason std::make_pair() exists is so that you don't have to specify the template types when you create a std::pair object. Functions are able to infer template types from their arguments, but class constructors can't.)

"Unfortunately" the standard library doesn't provide a generic structure for three or more items. You *could*, however, abuse std::pair to do it:


typedef std::pair<std::pair<int, int>, int> triple;
triple giveMeThreeInts() {
return std::make_pair(std::make_pair(1, 2), 3);
}

int main() {
triple t = giveMeThreeInts();
int x = t.first.first;
int y = t.first.second;
int z = t.second;
}


The Boost library, among others, provides a templated tuple class holding up to some particular number of items, which is (AFAIK) basically a wrapper for this technique.



<OPINION>

But you're probably better off declaring a struct in that case.

Anyway, there are many ways to handle "returning multiple things", but as always, just because you CAN do something doesn't mean you SHOULD. Whenever it looks like a multiple return is required, always think carefully about your approach, and try to at least keep things organized.

Personally I think it's a bad idea to use the return value as a "real" return value if you will also use an out-parameter (i.e. passing something by reference and modifying it). Go for all-or-nothing; sometimes you will decide to use the return value for an error code, instead.

Sometimes, taking the "return error code and modify reference parameters" approach is a good idea even for only one return value. This is especially the case if it helps out with template parameter inference ;) But usually, you'll want to throw an exception to indicate an error anyway. As well, a function that returns a value can be used to initialize a variable, whereas if you want a variable's initial value to come from a function that uses an out-parameter, then you have to declare the variable first and then call the function with the uninitialized variable. This is quite ugly.

Oh, and about the vector returns: Some people will tell you never to return a standard library container, but instead always use out-parameters for them. This is an optimization technique (which already marks it as evil ;) ), and assumes that the calling code might already have a vector instance handy, into which the called code will dump its stuff. However, this complicates the interface, firstly because the calling code might have to declare a local vector that it wouldn't have anyway, and secondly because you have to decide whether the called code will clear out any existing items, blindly trust that there are none, or deliberately assume there may be some and append to the existing set. Plus, it's quite likely not to help in terms of optimization anyway. :)

</OPINION>
</ADVANCED>

Share this post


Link to post
Share on other sites
Heya all,

I just wanted to post a quick, friendly reminder that we're in chapter 5 of the book, and have not yet covered pointers, templates, or classes. Just be mindful of the readers. [smile]

When you post an "advanced" section, it should be a more detailed discussion of the information currently being covered, and should try not to bring in concepts which have yet to be introduced. If your "advanced" post requires significant info about features we've not yet covered its a good indication the post is premature and should be saved for later.

Sorry for the interruption. Please continue. [wink]

Cheers!

Share this post


Link to post
Share on other sites
I was wondering which of the next two code samples would be considered best.


int myFunction(int value1, bool value2 = true);

int myFunction(int value1, bool value2) {
if(value2)
{
return value1 * 2;
}
return value1;
}



int myFunction(int value1);
int myFunction(int value1, bool value2);

int myFunction(int value1) {
return myFunction(value1, true);
}

int myFunction(int value1, bool value2) {
if(value2)
{
return value1 * 2;
}
return value1;
}


Since I am a Java programmer the second looks best to me (the first is not possible in Java). But I am wondering how a C++ programmer would look at this, is the usage of default values in your prototypes something that is commonly used?

Share this post


Link to post
Share on other sites
Quote:
Original post by RinusMaximus
I was wondering which of the next two code samples would be considered best.

[...]

Since I am a Java programmer the second looks best to me (the first is not possible in Java). But I am wondering how a C++ programmer would look at this, is the usage of default values in your prototypes something that is commonly used?

Since you are not adding logic in the one-parameter version, I would use the first form. That is what default parameters are for.

Share this post


Link to post
Share on other sites
I have a question about page 101 at the bottom. It says that you can write your declarations in a file and include them. That would mean that you still have to write the definitions for it in the "main" file, doesn't it? Then why is it that cin and cout worked by just including iostream? can you write your definitions in that second file too?
If so, could I make a file "function" that has:


int addition(int a, int b)
{
return (a+b);
}




and a file "program" that has:


#include <iostream>
#include <function>

int main(){
int a, b;
std::cin >>a;
std::cin >>b;
std::cout << "/n the sum is: " << addition(a,b) << std::endl;
return 0;
}




I tried this before but it doesn't work...


EDIT: added tags

Share this post


Link to post
Share on other sites
You made 2 tiny mistakes.

First of all it is recommended you save header files with a .h extention.
Eg: function.h


Next to include it:
#include "function.h"

Note that fuction.h should be saved in the same folder as main.cpp. Also you have to use double quotes to include your own files. <> are for standard header file ;)


Compleate Program


//------------------ function.h START ------------------
int addition(int a, int b)
{
return (a+b);
}
//------------------ function.h END --------------------


//------------------ main.cpp START ------------------
#include <iostream>
#include "function.h"

int main()
{
int a, b;
std::cin >>a;
std::cin >>b;
std::cout << "/n the sum is: " << addition(a,b) << std::endl;
return 0;
}
//------------------ main.cpp END --------------------






You can also include .cpp files the same way. You can define your functions almost anywhere, as long as there is a declaration for that function before it is used

Share this post


Link to post
Share on other sites
Why do we need to use #inlcude function. We can do by defining function prototype as given in the book.



#include<iostream>
int add(int a,int b); // function prototype
int main()
{
int a,b;
using std::cout;
using std::cin;
cout<<"Enter the value of a and b:\n";
cin>>a;
cin>>b;
cout<<"the result is:"<< add(a,b);
char response;
cin>>response;
return 0;
}





int add(int a,int b)
{
return(a+b);
}






I have just now tried. This program is working for me.

Share this post


Link to post
Share on other sites
Quote:
Original post by NCLR
I have question in regarding c++.
iam trying to make a 'library' prog using a switch statement to do the following things :-
1) To enter books into library
2) To display them
3) To delete any one of them
4) To issue a book (just by asking the user various information such as name,library card number,book's name,author's name etc...)
5) To display them
6) To delete any one of them
7) Search for a book

Its a project which iam doing for school.
I used a class for enetring and displaying.Deleting i can do in 'void main()'.
i want these information saved "permenantly" in a file.But i dont how to that.
any suggesstions anyone?


Well, this definately is not the right place for the question. This chapter is about functions and we have not covered classes or file output yet. To get you started, look up the fstream header (specifically the ofstream object). They will let you write text to a file very easily. What you right and how you read it back is heavily dependant on your data.

Share this post


Link to post
Share on other sites
Quote:
Original post by NCLR
I have question in regarding c++.
iam trying to make a 'library' prog using a switch statement to do the following things :-
1) To enter books into library
2) To display them
3) To delete any one of them
4) To issue a book (just by asking the user various information such as name,library card number,book's name,author's name etc...)
5) To display them
6) To delete any one of them
7) Search for a book

Its a project which iam doing for school.
I used a class for enetring and displaying.Deleting i can do in 'void main()'.
i want these information saved "permenantly" in a file.But i dont how to that.
any suggesstions anyone?


Quote:
Original post by londonman
hello any tutors i need help on workshop 1 nobody is helping me


Uh... guys, there's sort of a set agenda in this thread :
kimi: It's so you can separate your code out into several files, for organizational purposes. (BTW, '#include' is not "a function"; it's a preprocessor directive.)

twoaterisn: Like FireNet said. Except, don't include .cpp files! You *can* include any kind of file, but it won't necessarily produce something that compiles ;)

You really want to read this on the subject of organizing source code files. But we should get back to functions, yes? :)

P.S. 'addition' sounds wrong as a function name. Consider either 'add' (imperative) or 'sum' (descriptive of the result, rather than the process).

Share this post


Link to post
Share on other sites
Quote:
Original post by Zahlman
P.S. 'addition' sounds wrong as a function name. Consider either 'add' (imperative) or 'sum' (descriptive of the result, rather than the process).


[OPTIONAL]
That's an interesting sentence, and this this chapter copes with function, I'd like to talk about function names.

A correct function naming scheme can save your (programmer) life. It will increase the code readability and will give hints about what the function does, and these are two good things. Of course, it is hard to describe what's a really good function naming scheme, but there are a few rules that can't be bad:
  • be descriptive and close to your subject: if the function is performing an addition, naming it do_something_with_two_integers() won't really help, unless do_something is a recognized idiomatic replacement for perform_an_addition. If your function's goal is to compute your debt rate, don't call it divide() (even if the forumla is, in the end, a simple division) but compute_debt_rate().

  • deal with the goal of your action, not the way you are doing it: the way you are doing things is called implementation details in our software design jargon. Implementation details might change, but the goal of the function is not likely to change. For example, find_substing_in_string() might be implemented using different algorithms, but the goal is still to find a substring in a bigger string.

  • use verbs when it make sense: most of the time, your function will perform an action. As a consequence, the imperative form is a good way to express the goal of this action - at least, it is better than a noun, because nouns describe things, not actions. Hence Zahlman's advice: use add() instead of addition().
    Of course, Zahlman is also true when it gives sum() as another possible name for addition(). Instead of using verbs, you may also be able to use nouns if this noun describe the result of the action (and not the action itself). For example, debt_rate() or position_of_substring_in_string() are good potential function names. However, this can only be true for functions that return something (let's be logic here: how can I describe the result of a function if the function don't have any result? it don't make much sense [smile])

  • sometimes, a verb is not enough: don't be afraid of putting a more detailed description in your function name. compute() is a little too simple, while compute_income() is more descritpive. In general, you should not be affraid of long function names, even if you should try to be concise (because very long function name (>60 char for example) are hard to read and can be a mess in your code). 30+ chars function names are not that ugly, and the editor you'll use is likely to support auto-completion (like VS2005 intellisense) which will ease typing.

Good function naming is hard to achieve - of course, experience might help in this area - but should definitely not be overlooked.
[/OPTIONAL]

Share this post


Link to post
Share on other sites
Errata : p. 105 " Had you passed in widthOfYard, followed by lenghtOfYard, the FindArea() function would have used [...]"

The function is actually called Area() . I found some other typo like that in earlier chapters but didnt write them down.

Day 5 , exercice #3 p.135 : When calling myFunc() from the main function, the parameter used is (int). When calling a functions, parameters should be declared by name and not by type. If this is the case well, either the author wanted to call his int, int ( which is very confusing ) or its a typo. This exercice is a Bug Busters but this "error" isnt part of the answer in appendix D.

Share this post


Link to post
Share on other sites
Heya All,

Sorry if it seems as though I've been MIA for the last few days. I've been at the hospital, and am only online long enough to pass along the news and then I must return to the hospital.

My wife gave birth to our baby boy, Connor Riley Walsh, on June 28th at 11:02am. At birth he was 20" long and 6lbs 9ounces.

Unfortunately, he was born with his cord around his neck and was having problems breathing and feeding. As a result, he's been in the NICU for the last 2 days and will remain there for another day or two. As soon as I return with my wife and baby from the hospital I will get the answers posted for the quiz.

Sorry again for being offline!

Share this post


Link to post
Share on other sites
Hmm - I suppose that's a good enough excuse!!!

Congratulations. I hope that everything goes well for them both from now on. Your colleagues have been fielding the questions and comments but don't let that lull you into the belief that your detailed explanations aren't also required.

I look forward to your return, although you may have bleary eyes as your sleep's likely to be disturbed for quite some time.

Share this post


Link to post
Share on other sites
Many congratulations to you & your wife for your new arrival! Overwhelming isn't it? I hope everything works out fine for him. In case this is your first don't worry; it gets easier after 6 weeks, then 3 months, then 6 months, even if it doesn't seem so at the time. If we don't see you here for a long time your expertise will be sorely missed but it would be completely understandable, and thank you so far for your considerable help; finally I have a chance to learn something I've wanted to learn for the past decade.

simesf

Share this post


Link to post
Share on other sites
While I'm offline, can one of the tutors or moderators that has the book post questions from the chapter in the format of my previous quizzes?

Thanks!

Share this post


Link to post
Share on other sites
Quote:
Original post by Zahlman

twoaterisn: Like FireNet said. Except, don't include .cpp files! You *can* include any kind of file, but it won't necessarily produce something that compiles ;)



Hehe, that will depend on what sort of interface (IDE,text editor,whatever) you are using. If you are using an IDE then just include the .cpp file in the project, and declare the functions before you use them, like in a header file, which you can include in your source, and the .cpp file where you are defining the function.


If you are not using an IDE, and just an editor, you will have to include both. The header first then the source. In that case things will be processed by most compilers sequentially, like they were all in one file. You will have to worry about not including a file more than once, or provide defs to exclude already included files ;).

I would recommend you use IDEs, for it may be too much for the begginer to mess with command line compilers, I've and it was quite fun, but needs a lot of time :P.




Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement