Extra Credit Exercise (Simple Functions)

Hi, I'm a new to the forum, I'm currently studying C++ and I'm really enjoying it (as difficult as it is lol). I'm still getting to grips with understanding OPP as a paradigm.. I just wanted to ask if there are any resources online that have simple exercises for me to practise coding and to help me get used to the syntax.

I am studying at a private institution, I get theory from my lessons with my tutor, but practising what I learn e.g. homework exercises, demo projects and little practise projects to aide my understanding are pretty much down to me, which is fine because I feel it makes my learning pro-active and allows me to be creative as well.
I just wondering if there are any resources online that have really simple coding tasks (coding functions) to help practise. I've been using a book which has some exercises and I have found a few on online, an example of the level I am at is an example of the following exercise which I was able to cope with pretty well....

Temperature Exercise
=====================

Q. Write a program that allows the user to input the temperature in degrees celcius and outputs the temperature in degree's Fahrenheit and vice versa..

Also.......

Radius Exercise
================

Q. Write a program that allows the user to enter the radius of a circle and calculates and outputs the area of a circle...

Please feel free to come up with any exercises similar to this involving creating simple sub-routines to calculate stuff, I'll post the code back up for evaluation...... I want to learn by working through the errors and the bugs, that's the only way I feel I'll really become confident with the syntax....

Sorry if post is to long.


Thanks
Hi, welcome to the forum! Take a look at this, I think it's very close to what you want:

http://cplusplus.com/forum/articles/12974/
Master Roshi your name is VERY fitting, your right on the mark with those exercises..... A trillion

thank you's
haha, thank Blitz Coder and Bazzy instead :P
ok then.... A trillion 2 thanks to Blitz coder and Bazzy...... One question, I'm doing the first exercise in the grading program..........


Write a program that allows the user to enter the grade scored in a programming class (0-100).
If the user scored a 100 then notify the user that they got a perfect score..............

What I wanted to do was incorporate something similar to exception handling in the sense that
if the user entered 101, it would return a message saying " Not a Valid Grade" I tried to do this with a nested else if but its coming up with the grade and the message even if the user enters something like 50 ???? Help please

Code
======

if(GradeVar == 100) // If else statement to return the perfect score message
{
cout << "Congratulation YOU Have Achieved a perfect score" <<endl
<<endl
<< "Keep up the good work Grrrrrrrrrrrrrrrrrrrrrrr" <<endl;
}
else if(GradeVar < 100)
{
cout << "Your Grade is" << endl
<< endl
<< GradeVar << endl
<< endl;
}
else(GradeVar > 101); // ???? Gonna have to explore this a bit further
{ // to find out why its still

cout << "Not a Valid Grade" << endl;

};
Turn this -> else(GradeVar > 101); into this -> else if(GradeVar > 101 100)

More info on if statement:

http://cplusplus.com/doc/tutorial/control/
http://www.learncpp.com/cpp-tutorial/52-if-statements/

EDIT: Corrected my correction...
Last edited on
You could also do else if (GradeVar >= 101) but r0shi's version is probably better.

Personally, I would do something like:

 
else if (GradeVar < 0 && GradeVar > 100) cout << "Error: Invalid grade\n";

or use a while loop to keep asking for the grade instead of exiting when it's invalid, like

Enter grade: 101
Error: Invalid grade

Enter grade: -1
Error: Invalid grade

Enter grade: 50
Sorry, you got an F.

Exiting ...


Of course, I personally would also make a bool function that accepts the min value and max value of a range of numbers and a number to compare to, that returns true if the number is greater than min and less than max, like so:

1
2
3
4
5
6
7
8
9
10
11
12
13
bool Range(int num, int min, int max) {
    if (num >= min && num <= max)
        return true;
}

int main() {
    if (Range(grade, 0, 59))    // if in range of 0-59
        cout << "Sorry, you got an F.";
    if (!Range(grade, 0, 100))    // if not in range 0-100
        cout << "Error: Invalid grade\n";

    return 0;
}


... But that's just me.
Last edited on
RyanCaywood wrote:
but r0shi's version is probably better

Why?

RyanCaywood wrote:
Personally, I would do something like:

else if (GradeVar < 0 && GradeVar > 100) cout << "Error: Invalid grade\n";

or use a while loop to keep asking for the grade instead of exiting when it's invalid

+1

RyanCaywood wrote:
I personally would also make a bool function that accepts the min value and max value of a range of numbers and a number to compare to, that returns true if the number is greater than min and less than max

+1

I would do it like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include <iostream>
#include <sstream>
#include <string>
using namespace std;

bool get_int(int & n,const char * invalid_msg=0,
    int min=0, int max=0,const char * range_msg=0)
{
    if (min>max) return get_int(n,invalid_msg,max,min,range_msg);

    stringstream buffer;
    string input;

    getline(cin,input);
    buffer<<input;
    buffer>>n;

    if (!buffer)
    {
        if (invalid_msg)
            cout << invalid_msg << endl;

        return false;
    }

    if (min!=max)
    {
        if (n<min || n>max)
        {
            if (range_msg)
                cout << range_msg << endl;

            return false;
        }
    }

    return true;
}

int main()
{
    int GradeVar;

    cout << "enter your grade:\n";

    while (!get_int(GradeVar,"please, enter a number",
        0,100,"min=0, max=100"));

    cout << "your grade is: " << GradeVar;

    cin.get();
    return 0;
}

Instead of get_int, you could write a templated function, get_num<T>, so that you don't have to write different functions to get ints, longs, floats, doubles etc...

http://cplusplus.com/doc/tutorial/templates/
m4ster r0shi wrote:
Why?

Easier to read. But besides that, it's exactly the same (functionally) I'm pretty sure.

m4ster r0shi wrote:

I would do it like this:

// code

Instead of get_int, you could write a templated function, get_num<T>, so that you don't have to write different functions to get ints, longs, floats, doubles etc...

http://cplusplus.com/doc/tutorial/templates/

Nice!
Last edited on
Thanks again you guys, this just highlights one of the amazing things about learning C++, there are so many different ways of implementing code..... @Master Roshi, I'm gonna have to lean towards your approach because (coincidentally) I've just started looking at generic programming in lesson. My tutor stated that the best way to identify if you can apply a template to something is to ask the question, "Am I doing the same thing more than twice" if the answer is YES then use a template........

Thanks again
@ m4ster r0shi
1
2
bool get_int(int & n,const char * invalid_msg=0,
    int min=0, int max=0,const char * range_msg=0)

I think you are overdoing the function.
Instead of asking for messages to show, you should throw exceptions and let the program to resolve them.
Changing this:
1
2
3
getline(cin,input);
    buffer<<input;
    buffer>>n;

to
1
2
if( !(cin>>n) )
   throw 42;  //invalid_msg 

(You could pass an istream object instead of using cin too)

Besides, with the getline, if the input comes like this
10 99 20 30
you'll only read the first number and ignore the rest of the line.


Also
if (min>max) return get_int(n,invalid_msg,max,min,range_msg);

If you always call the function with the right arguments (i.e. constants), you'll make an unnecessary check in every function call.
Last edited on
ne555 wrote:
Instead of asking for messages to show, you should throw exceptions and let the program to resolve them.

I think that's an overkill.

There's a good reason why I use getline instead of the >> operator. In general, it's not good practice to use both of them. That's because getline doesn't leave the delimitation character (usually being '\n') in the buffer, while the >> operator does. And since getline is what I want to use to get strings, I use it to get numbers as well. Using both (getline and operator >>) allows situations like this to arise:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
#include <string>
using namespace std;

int main()
{
    string str;
    int n;

    cout << "enter your age: ";
    cin >> n;

    cout << "enter your name: ";
    getline(cin,str);

    cout << "hello, " << str << endl;
    cout << "you are " << n << " years old" << endl;

    cin.get();
    return 0;
}

You'll notice that the above piece of code doesn't work as expected. It's because cin >> n; leaves a '\n' in the buffer. getline(cin,str) then "sees" that '\n' and assumes that you've entered a blank line. Thus str is set to "". Furthermore, if the user enters something like "23asdf" when asked for his age, n is set to 23 and str is set to "adsf". This is something you don't want. You can easily fix it by replacing cin >> n; with something like this:

1
2
3
4
5
6
cin >> n;
if (!cin)
{
    cin.clear();
    while (cin.get()!='\n');
}

OR you could do something like this:

1
2
3
string input;
getline(cin,input);
istringstream(input)>>n;

I find the latter to be a cleaner way. getline(cin,input) doesn't leave anything in the input buffer, and bad input can't affect your stream's status.

ne555 wrote:
(You could pass an istream object instead of using cin too)

Yes, I suppose I could do that. But why? In most of the cases I'll work with cin/cout for console input/output. And I don't suppose I can use this to validate input from a file, since I can't ask a file to re-enter the data correctly (to the best of my knowledge...).

ne555 wrote:
Besides, with the getline, if the input comes like this

10 99 20 30

you'll only read the first number and ignore the rest of the line.

Well, I think that's actually an advantage of the method I use. If you allow input like this, how will you implement the validation procedure? You can't check them separately, you have to get them all before you check them. Well, I suppose you could do something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
int a,b,c,d;
bool oka, okb, okc, okd;
oka=okb=okc=okd=false;
while (true)
{
    cout << "enter a b c d : ";

    if (!oka)
    {
        cout << "enter a: ";
        cin>>a;
        if (!cin) {cin.clear(); while(cin.get()!='\n'); continue;}
        else oka=true;
    }

    if (!okb)
    {
        cout << "enter b: ";
        cin>>b;
        if (!cin) {cin.clear(); while(cin.get()!='\n'); continue;}
        else okb=true;
    }

    if (!okc)
    {
        cout << "enter c: ";
        cin>>c;
        if (!cin) {cin.clear(); while(cin.get()!='\n'); continue;}
        else okc=true;
    }

    if (!okd)
    {
        cout << "enter d: ";
        cin>>d;
        if (!cin) {cin.clear(); while(cin.get()!='\n'); continue;}
        else okd=true;
    }

    break;
}

But that's an overkill too. I prefer this, even if it doesn't allow me to enter the numbers in one line.

1
2
3
4
5
6
int a,b,c,d;
cout << "enter a b c d : ";
while (!get_int(a,"enter a: "));
while (!get_int(b,"enter b: "));
while (!get_int(c,"enter c: "));
while (!get_int(d,"enter d: "));

ne555 wrote:
Also
if (min>max) return get_int(n,invalid_msg,max,min,range_msg);

If you always call the function with the right arguments (i.e. constants), you'll make an unnecessary check in every function call.

I don't think that check really slows me down, but if you don't like it you can remove it.

Last edited on
m4ster r0shi wrote:
In most of the cases I'll work with cin/cout for console input/output. And I don't suppose I can use this to validate input from a file, since I can't ask a file to re-enter the data correctly (to the best of my knowledge...).

Why not? Validates don't require to re-enter. You can have a file with the scores of a class. Or you are doing testing and need to know if the quality is correct. Or an statistical analyses and you want to ignore the extremes values. Or your input is the output of another program. Avoid expecting a user to be typing your input.
You still can use cin if redirect the input with < or |


1
2
if( !(cin>>n) )
   throw 42;  //invalid_msg  

I put the throw statement because, if you're expecting to read an integer but instead you get a string, then there is something really wrong (like the file is corrupted). However you could say that it's not your responsibility and just crash.
Also permits to know if was an error in the lecture (what I think it's too dangerous) or in the range (you only say false).
But I don't know about its efficiency and may be self-defeating.


However I believe that the best solution for validation is
RyanCaywood wrote:
1
2
3
4
bool Range(int num, int min, int max) {
    if (num >= min && num <= max)
        return true;
}
handling everything else outside.
ne555 wrote:
I put the throw statement because, if you're expecting to read an integer but instead you get a string, then there is something really wrong (like the file is corrupted).

Yes, now that I look at it again, it may be better to throw in that case (i.e. when you read from a file).

ne555 wrote:
However I believe that the best solution for validation is handling everything else outside.

I won't disagree with that. I should probably have had two functions, one to check for non numeric input and one to check if the value is within the desired range. After all, you don't always want to restrict the input between two values.
Last edited on
Topic archived. No new replies allowed.