Tag Archives: C++

Accelerated C++ Solution to Exercise 1-5

Exercise 1-5

Part 1: Is this program valid? If so, what does it do? If not, say why not, and rewrite it to be valid.

#include <iostream>
#include <string>

int main()
{
    {
        std::string s = "a string";
        {
            std::string x = s + ", really";
            std::cout << s << std::endl;
        }
        std::cout << x << std::endl;
    }
    return 0;
}

Solution

No. The program is not valid and require correction.

Like the previous exercises (1-3 / 1-4), the key to this question is to understanding the term scope. One scope may not “see” what’s inside the other scope(s).

For clarity let me add some comments to the code to visualise these scopes.

// original program with comments added to visualise scope
#include <iostream>
#include <string>

int main()
{ // scope main starts

    { // scope main-1 starts

        std::string s = "a string";

        { // scope main-1-1 starts

            std::string x = s + ", really";
            std::cout << s << std::endl;

        } //scope main-1-1 ends

        std::cout << x << std::endl;

    } // scope main-1 ends

    return 0;

} // scope main ends

} // scope main ends
[/code]

Let me start off by stating the following facts (in general)

  • All local variables defined at the outer scope level may be seen/used by the inner scopes (at all levels).
  • The reverse is not possible however. i.e. All local variables defined at the inner scope level may NOT be seen/used by the outer scopes (at all levels), nor the scopes adjacent to it. (i.e. same level scopes).
  • i.e. the permeation of variables go from outer scope, to inner scope. It does not permeate to other scopes at the same level, and/or the inner scopes (at all levels).

To apply these facts to our case:

  • scope main-1-1 can see std::string variable s (which is defined in the outer scope main-1), and its own defined std::string variable x.
  • scope main-1 can see only its own defined variable std::string s. It cannot see the std::string variable x that lives at the inner scope main-1-1 level. Problem! Fail to perform that std::cout << x << std::endl step because it does not not what x is. from scope main-1 perspective the variable x is not declared.
  • scope main-1 has no idea of any variables defined in the inner scopes main-1 nor main-1-1. All it knows is that whenever the implementation hits the return statement, it is done.

To prove the point if we run the program as it is, we expect to see a compilation error

line (19): error: ‘x’ was not declared in this scope

To make the std::string x visible to the scope main-1, simply move the scope main-1-1 up 1 level by removing the curly braces. Like this:

// corrected - likely to work
#include <iostream>
#include <string>

int main()
{ // scope main starts

    { // scope main-1 starts

        std::string s = "a string";
        std::string x = s + ", really";
        std::cout << s << std::endl;
        std::cout << x << std::endl;

    } // scope main-1 ends

    return 0;

} // scope main ends

Running this corrected version program gives us the desirable result, as expected.

a string
a string, really

Process returned 0 (0x0)   execution time : 0.245 s
Press any key to continue.

Reference

Koenig, Andrew & Moo, Barbara E., Accelerated C++, Addison-Wesley, 2000

Accelerated C++ Solution to Exercise 1-4

Exercise 1-4

Part 1: Is the following program valid? if so what does it do? If not, why not?

Part 2: What if we add a semi-colon between the second-last and third-last (right) curly braces?

#include <iostream>
#include <string>

int main()
{ 
    {
        const std::string s = "a string";
        std::cout << s << std::endl;
        {  
            const std::string s = "another string";
            std::cout << s << std::endl;
        }
    }

}

Solution (Part 1)

Yes. The program is valid.

Like the previous exercise (1-3), the key to this question is to understanding the term scope. Each pair of curly braces {} form a scope. It is okay to have scopes nested within a scope.

For clarity let me add some comments to the code to visualise these scopes.

#include <iostream>
#include <string>

int main()
{//scope main starts

    {   //scope main-1 start

        const std::string s = "a string";
        std::cout << s << std::endl;

        {   //scope main-1-1 starts

            const std::string s = "another string";
            std::cout << s << std::endl;

        }  //scope main-1-1 ends 

    }  //scope main-1 ends 

} //scope main ends

The const std::string variable s in scope main-1 is not the same const std::string variable s in scope main-1-1 (which is nested inside scope main-1). Even though scope main-1-1 is nested inside scope main-1, all local variables inside scope main-1-1 is hidden from view of main-1.

For completeness, let’s run the program at the top to confirm it runs okay.

a string
another string

Process returned 0 (0x0)   execution time : 0.317 s
Press any key to continue.

The program runs okay as expected.

Memory Treatment

Another thing to bear in mind is the fact that all local variables within a scope only has a life time within the scope. i.e. once the implementation reaches the closing curly brace, }, (in other words, the end of the scope) the local variables of that scope are destroyed. The memory that was taken up by the local variables are now freed up and returned back to the system.

In this case, we expect to see the followings memory allocations / de-allocations.

  • When scope main starts: memory allocated for any local variables of scope main (in this case, none).
  • When scope main-1 starts: memory allocated for the std::string s variable of scope main-1.
  • When scope main-1-1 starts: memory allocated for the std::string s variable of scope main-1-1.
  • When scope main-1-1 ends: The std::string s variable of scope main-1-1 is destroyed. Memory is freed up and returned to the system.
  • When scope main-1 ends: The std::string s variable of scope main-1 is destroyed. Memory is freed up and returned to the system.
  • When scope main ends: Any scope main local variables are destroyed (in this case none). Memory is freed up and returned to the system. (in this case none)

Notice how this differs to the case in exercise 1.3?

Solution (Part 2)

Adding a semi-colon (;) between the second last and third last right curly braces will still constitute a valid program. For clarity, this is what the program would look like with that semi-colon.

#include <iostream>
#include <string>

int main()
{//scope main starts

    {   //scope main-1 start

        const std::string s = "a string";
        std::cout << s << std::endl;

        {   //scope main-1-1 starts

            const std::string s = "another string";
            std::cout << s << std::endl;

        }  //scope main-1-1 ends 

        ;  // the additional semi-colon

    }  //scope main-1 ends 

} //scope main ends

The additional semi-colon essentially creates a null-statement within the main-1 scope. i.e. it has no effect to the code. I think the reason the authors ask this question is to solidify our understanding on scope. i.e. which scope does that semi-colon belong to? Writing a C++ code in the above manner helps us visualise this easier.

Submitting the program with this semi-colon would yield the same output.

Reference

Koenig, Andrew & Moo, Barbara E., Accelerated C++, Addison-Wesley, 2000

Accelerated C++ Solution to Exercise 1-3

Exercise 1-3

Is the following program valid? if so what does it do? If not, why not?

#include <iostream>
#include <string>

int main()
{
    {
        const std::string s = "a string";
        std::cout << s << std::endl;
    }
    {
        const std::string s = "another string";
        std::cout << s << std::endl;
    }

}

Solution

Yes. The program is valid.

The key to this question is to understanding the term scope. Each pair of curly braces form a scope.

Within the main function (scope), we have two sub-scopes, as defined by the two pairs of curly braces. Visualise these as block 1 and block 2. Block 1 corresponds to line 6 to 9. Block 2 corresponds to line 10 to 13.

Each block constitute its own scope – all local variables and statements within each scope are independent to each other. The const std::string variable s in block 1 is not the same as the const std::string variable s in block 2.

Because of this, even though there is a const std::string variable s in block 1, it is okay to define another constd std::string variable s in block 2 – due to the fact the two variables are in different scope.

It is however not possible to re-define a const std::string variable s within the same block (scope). For instance, the following would not be valid:

    {
        const std::string s = "a string";
        const std::string s = "another string"; // this is not valid.
        std::cout << s << std::endl;
    }

For completeness, let’s run that program at the top to confirm it compiles and runs okay.

a string
another string

Process returned 0 (0x0)   execution time : 0.456 s
Press any key to continue.

The program runs okay as expected.

Memory Treatment

Another thing to bear in mind is the fact that all local variables within a scope only has a life time within the scope. i.e. once the implementation reaches the closing curly brace, }, (in other words, the end of the scope) the local variables of that scope are destroyed. The memory that was taken up by the local variables are now freed up and returned back to the system.

In this case, as the two blocks of scopes are implemented in a sequential manner, we expect to see the followings memory allocations / de-allocations.

  • Line 7: memory allocated for the std::string s variable of scope block 1.
  • Line 9: The std::string s variable of scope block 1 is destroyed. Memory is freed up and returned to the system.
  • Line 11: memory allocated for the std::string s variable of scope block 2.
  • Line 13: The std::string s variable of scope block 2 is destroyed. Memory is freed up and returned to the system.

Reference

Koenig, Andrew & Moo, Barbara E., Accelerated C++, Addison-Wesley, 2000

Accelerated C++ Solution to Exercise 1-2

Exercise 1-2

Are the following definitions valid? Why or why not?

const std::string exclam = "!";
const std::string message = "Hello " + ", world" + exclam;

Solution

No. The use of the concatenation operator is not valid. i.e. we bump into a “taboo” scenario: string literal + string literal. This is not valid.

The key in answering this question is to acknowledge the use of the string concatenation operator +.

  • It is left associative.
  • We can use + to concatenate a string and a string literal (and vice versa), or a string and a string, but not a string with a string literal (nor vice versa).

Line 1 defines a string variable exclam. This line is valid.

Line 2 defines a string variable message with the concatenation operator. The logic looks like this:

message = ( ( "Hello " + ", world" ) + exclam) 
        = ( ( a string literal + a string literal ) + a string )
        = ( ( compilation error! ) + a string)

i.e. We expect to encounter the invalid string literal + string literal scenario. This will likely cause compilation error.

Let’s test running the following program to prove the invalidity of the program.

#include <iostream>
#include <string>
int main()
{
    const std::string exclam = "!";
    const std::string message = "Hello  + ", world" + exclam;
    std::cout << message << std::endl;
    return 0;
}

Result

As expected, we get a compilation error.

error: invalid operands of types 'const char [6]' and 'const char [8]' to binary 'operator+'|

The const char [6] corresponds to the string literal “Hello”.

The const char [8] corresponds to the string literal “, world”.

(Note: I recall from reading another C++ book that the length of a string is usually the number of character plus one – that plus one is for reserving a space for a backslash, \ , character at the end)

We can easily fix this by avoiding the string literal + string literal scenario. For instance, we may imply merge the two string literal together upfront. (Keep it simple and stupid!)

    const std::string exclam = "!";
    const std::string message = "Hello, world" + exclam;

For completeness sake, let’s run the following corrected program – we should expect to avoid that compilation error.

#include <iostream>
#include <string>
int main()
{
    const std::string exclam = "!";
    const std::string message = "Hello, world" + exclam;
    std::cout << message << std::endl;
    return 0;
}

Running this program produces the output as expected.

Hello, world!

Process returned 0 (0x0)   execution time : 0.244 s
Press any key to continue.

Reference

Koenig, Andrew & Moo, Barbara E., Accelerated C++, Addison-Wesley, 2000

Accelerated C++ Solution to Exercise 1-1

Exercise 1-1

Are the following definitions valid? Why or why not?

const std::string hello = "Hello";
const std::string message = hello + ", world" + "!";

Solution

Yes. These definitions are valid.

The key in answering this question is to acknowledge the use of the string concatenation operator +.

  • It is left associative.
  • We can use + to concatenate a string and a string literal (and vice versa), or a string and a string, but not a string with a string literal (nor vice versa).

Line 1 defines a string variable hello with length of 5 characters (which is Hello). This line is valid.

Line 2 defines a string variable message with the concatenation operator. The logic looks like this:

message = ( ( hello + ", world" ) + "!") 
        = ( ( a string + a string literal ) + a string literal )
        = ( ( a string ) + a string literal )
        = ( a string + a string literal )
        = ( a string )

i.e. at every single stage, we have not encountered any invalid string literal + string literal scenario. The concatenation is therefore valid.

Let’s test running the following program to prove the validity of the program.

#include <iostream>
#include <string>
int main()
{
    const std::string hello = "Hello";
    const std::string message = hello + ", world" + "!";
    std::cout << message << std::endl;
    return 0;
}

Result

As expected, the program compiled okay and produce the expected output.

Hello, world!

Process returned 0 (0x0)   execution time : 0.214 s
Press any key to continue.

Reference

Koenig, Andrew & Moo, Barbara E., Accelerated C++, Addison-Wesley, 2000

Accelerated C++ Solution to Exercise 1-0

Exercise 1-0

Compile, execute, and test the programs in this chapter.

Solution

I will be taking the programs directly from the book (chapter 1 – Working with Strings), test run them, and see what we get. This exercise is purely to get our hands dirty right away on writing a submitting very simple programs on handling strings. Nothing too clever.

Test (Program 1)

The goal of this program is to

  • ask for a person’s name,
  • read the name in as a string variable, and
  • output a greeting message.
// ask for a person's name, and greet the person
#include <iostream>
#include <string>

int main()
{
    // ask for the person's name
    std::cout << "Please enter your first name: ";

    // read the name
    std::string name;   //define name
    std::cin >> name;   //read into name

    // write a greeting
    std::cout << "Hello, " << name << "!" << std::endl;
    return 0;
}

Result (Program 1)

Run the program. The followings are produced in the console output window:

Please enter your first name:

Type in some texts (my name) on the keyboard

Please enter your first name: Johnny

Hit enter key and it gives:

Please enter your first name: Johnny
Hello, Johnny!

Process returned 0 (0x0)   execution time : 2.631 s
Press any key to continue.

Test (Program 2)

The goal of program 2 is to read in a person’s name, and generate a framed greeting like this:

******************
*                *
* Hello, Johnny! *
*                *
******************

To do this the following C++ program is taken directly from the book.

// ask for a person's name, and generate a framed greeting
#include <iostream>
#include <string>

int main()
{
    std::cout << "Please enter your first name: ";  //ask for the person's name
    std::string name;   //define name
    std::cin >> name;   //read into name

    // build the message that we intend to write
    const std::string greeting = "Hello, " + name + "!";

    // build the second and forth lines of the output
    const std::string spaces(greeting.size(),' ');
    const std::string second = "* " + spaces + " *";
    const std::string first(second.size(),'*');

    // write it all
    std::cout << std::endl;
    std::cout << first << std::endl;
    std::cout << second << std::endl;
    std::cout << "* " << greeting << " *" << std::endl;
    std::cout << second << std::endl;
    std::cout << first << std::endl;
    return 0;
}

Result (Program 2)

Run the program. The followings are produced in the console output window:

Please enter your first name:

Type in some texts (my name) on the keyboard

Please enter your first name: Johnny

Hit enter key and it gives:

Please enter your first name: Johnny

******************
*                *
* Hello, Johnny! *
*                *
******************

Process returned 0 (0x0)   execution time : 2.520 s
Press any key to continue.

Some core learning:

  • Use double quote to define string literal. Use single quote to define character (char) literal.
  • We can use + to concatenate a string and a string literal (and vice versa), or a string and a string, but not a string with a string literal (nor vice versa). i.e.
    • string + string is okay.
    • string literal + string is okay.
    • string + string literal is okay.
    • string literal + string literal is NOT okay.
  • Use the object component size() , which is a function, to determine the length (number of characters) of a string (the object itself). e.g. greeting.size gives the length of the string greeting.
  • Refer to the book to see the various ways to define a string variables, including the use of overload.
  • Keep It Simple and Stupid (KISS) – write the code in a way that is easy to write and understand. Nothing too clever.

Reference

Koenig, Andrew & Moo, Barbara E., Accelerated C++, Addison-Wesley, 2000

Accelerated C++ Solution to Exercise 0-9

Exercise 0-9

What is the shortest valid program?

Solution

According to chapter 0 (Getting Started) of the book Accelerated C++ …

On Main function:

  • Every C++ program must define exactly one function, named main, that returns an int.
  • The implementation runs the program by calling main.
  • A zero returns indicates success; a non-zero return indicates failure.
  • In general, functions must include at least one return statement and are not permitted to fall off the end of the function.
  • The main function is special: it may omit the return; if it does so, the implementation will assume a zero return value.
  • However, explicitly including a return from main is good practice.

The shortest valid program can therefore be as short as a one-liner like this (or can this be made even shorter I wonder?)

int main() {}

Result

The program compiles okay in Code::Block and gives me the following output the the console output window.

Process returned 0 (0x0)   execution time : 0.141 s
Press any key to continue.

Reference

Koenig, Andrew & Moo, Barbara E., Accelerated C++, Addison-Wesley, 2000

Accelerated C++ Solution to Exercise 0-8

Exercise 0-8

Is this a valid program? why or why not?

#include <iostream>
int main{}
{
    // This is a comment that extends over several lines
    // by using // at the beginning of each line instead of using /*
    // or */ / to delimit comments.
       std::cout << "Does this work?" << std::endl;
       return 0;
}

Solution

Yes. This is a valid C++ Program.

Line comment starts the comment by beginning the line with the //. Whatever follows is a comment, as long as within the same line. The

Once a new line is created, the // is required at the beginning to start another comment.

You can also use the line comment in the middle of a line (so the first part of the line is not a comment, and the second part is a comment). It looks something like this:

std::cout << "Hello World!" << std::endl;  // this is a comment

What I sometimes do is to try out writing the code in an IDE like Code::Block. The auto syntax highlighting within the IDE should give us hints whether the parts in the code are comment or not, indicated by the different colour highlighting. (I would not rely 100% on this though. But it is a good and quick guide I’ve found).

Reference

Koenig, Andrew & Moo, Barbara E., Accelerated C++, Addison-Wesley, 2000

Accelerated C++ Solution to Exercise 0-7

Exercise 0-7

Is this a valid program? why or why not?

#include <iostream>
int main{}
{
    /* This is a comment that extends over several lines
       because it uses /* and */ as its starting and ending delimiters */
       std::cout << "Does this work?" << std::endl;
       return 0;
}

Solution

No. This is not a valid C++ Program.

The issue is the way the code treats comment. A correct block-comment looks like this.

/* this is a comment */

i.e. a correctly written comment is surround by the /* and */. Anything in between is a comment. Anything outside is not a comment.

In this case, the actual comment part is highlighted in blue below (and the remaining red part is not qualified as a comment)

/* This is a comment that extends over several lines
because it uses /* and */ as its starting and ending delimiters */

I would correct the comment to something like this (using the line comment //), should we wish to keep the comments.

// This is a comment that extends over several lines
// because it uses /* and */ as its starting and ending delimiters

Reference

Koenig, Andrew & Moo, Barbara E., Accelerated C++, Addison-Wesley, 2000

Accelerated C++ Solution to Exercise 0-6

Exercise 0-6

Is this a valid program? Why or why not?

#include <iostream>
int main() {{{{{{std::cout << "Hello World!" << std::endl;}}}}}}

Solution

Yes. This is a valid C++ program.

In C++ curly braces tell the implementation to treat whatever (statement) appears between them as a unit.

It is okay to have nested curly braces, as long as all the curly braces are balanced out. i.e. for every single open/left brace it is matched by a close/right brace.

Let’s run the program and see what we get?

Result

The program compiles okay. And gives us the following result in the console output window.

Hello World!

Process returned 0 (0x0)   execution time : 0.187 s
Press any key to continue.

Experiment – Nested Curly Braces

Let us, for curiosity sake to see if nested curly braces actually work? Here is a very simple program that I write for this experiment.

// Experiment with nested curly braces
#include <iostream>
int main()
{
    std::cout << "I am block 1" << std::endl;
    {
        std::cout << "I am block 1-1, son of block 1" << std::endl;
        {
            std::cout << "I am block 1-1-1, son of block 1-1, grandson of block 1." << std::endl;
            std::cout << "I am block 1-1-2, son of block 1-1, grandson of block 1." << std::endl;
        }
    }
    {
        std::cout << "I am block 1-2, son of block 1" << std::endl;
    }
}

The program compiles okay and gives us the followings in the console output window as expected.

I am block 1
I am block 1-1, son of block 1
I am block 1-1-1, son of block 1-1, grandson of block 1.
I am block 1-1-2, son of block 1-1, grandson of block 1.
I am block 1-2, son of block 1

Process returned 0 (0x0)   execution time : 0.187 s
Press any key to continue.

This experiment has demonstrated that nested curly braces essentially provides a way to group blocks of statements together, which I think is a very cool feature as it allows us breakdown tons of statements into smaller blocks. This is very handy if we are to define a chunky function.

Reference

Koenig, Andrew & Moo, Barbara E., Accelerated C++, Addison-Wesley, 2000