Wednesday 21 October 2009

The challenging 'Infinite loop' problem

Picked this one up from The C++ blog.

Consider the following program:



#include <iostream>

int
main()
{

int
i;
int
array[4];
for
(i=0; i<=8; i++)
{

array[i]=0;
}


return
0;
}


Most people including myself expect this program to crash. This is not the case. The reason being the way everything is stored on stack. In simple representation, the storage is something like this:



So when i = 6, value of i is reset to 0 and the loop continues forever.

After digging some information on stack, heap, etc. I found some useful info in C++ in 24 hours:

Programmers generally deal with five areas of memory:
  • Global name space
  • The free store (a.k.a. Heap)
  • Registers
  • Code space
  • The stack

Local variables are on the stack, along with function parameters. Code is in code space, of course, and global variables are in global name space. The registers are used for internal housekeeping functions, such as keeping track of the top of the stack and the instruction pointer. Just about all remaining memory is given over to the free store, which is sometimes referred to as the heap.

The problem with local variables is that they don't persist. When the function returns, the local variables are thrown away. Global variables solve that problem at the cost of unrestricted access throughout the program, which leads to the creation of code that is difficult to understand and maintain. Putting data in the free store solves both of these problems.

You can think of the free store as a massive section of memory in which thousands of sequentially numbered cubbyholes lie waiting for your data. You can't label these cubbyholes, though, as you can with the stack. You must ask for the address of the cubbyhole that you reserve and then stash that address away in a pointer.

The stack is cleaned automatically when a function returns. All the local variables go out of scope, and they are removed from the stack. The free store is not cleaned until your program ends, and it is your responsibility to free any memory that you've reserved when you are done with it.

The advantage to the free store is that the memory you reserve remains available until you explicitly free it. If you reserve memory on the free store while in a function, the memory is still available when the function returns.

The advantage of accessing memory in this way, rather than using global variables, is that only functions with access to the pointer have access to the data. This provides a tightly controlled interface to that data, and it eliminates the problem of one function changing that data in unexpected and unanticipated ways.

For this to work, you must be able to create a pointer to an area on the free store and to pass that pointer among functions. The pointer is created using new and once you are done with it you can free the memory using delete.

Wednesday 14 October 2009

Reading string via cin and flushing input buffers

The following program shows three different approaches to read string via Cin. It also shows two different approaches for flushing input buffer.






//Program tested on Microsoft Visual Studio 2008 - Zahid Ghadialy
//Program to read input string and to flush input buffer
#include<iostream>
#include<string>
#include <istream>
#include <limits>

using namespace
std;

int
main()
{

string s1;
cout << "\nAPPROACH 1" <<endl;
cout << "Input a string : ";
cin >> s1;
cout << "Entered string = " <<s1.c_str()<<endl;

//Lets flush the buffer from Approach 1 here
istream& in(cin);
in.ignore( numeric_limits<std::streamsize>::max(), '\n' );

cout << "\nAPPROACH 2" <<endl;
cout << "Input a string : ";
istreambuf_iterator<char> eos; // end-of-range iterator
istreambuf_iterator<char> iit (cin.rdbuf()); // stdin iterator
string s2;
while
(iit!=eos && *iit!='\n') s2+=*iit++;
cout << "Entered string = " << s2 << endl;

//Another approach for flushing the input
int ch;
while
((ch = cin.get()) != '\n' && ch != EOF);

cout << "\nAPPROACH 3" <<endl;
cout << "Input a string : ";
char
buf[BUFSIZ];
if
(cin.getline(buf, sizeof(buf)))
{

cout << "Entered string = " << buf << endl;
}


cout << endl;
return
0;
}







The output is as follows:



More information:

Thursday 8 October 2009

Using #pragma message directive

Sometimes you would like to remind the user or yourself of something while compiling and there is an option to remind yourself using the #pragma message directive. See the following program:



//Program tested on Microsoft Visual Studio 2008 - Zahid Ghadialy
//Program to show how to remember things using #pragma message
#include<iostream>

using namespace
std;

int
someFunction(int a=0, int b=0)
{

#pragma message("TODO: Coding of someFunction()")
return 0;
}


int
main()
{

someFunction();
return
0;
}

In this case the user wants to remind himself that someFunction() needs to be coded at a later time and hence he uses a preprocessor message statement. The result is when compilation is done, a message will be output as shown below:

Tuesday 6 October 2009

Using Preprocessor Statements #ifdef, #elif, #else and #endif

Sometimes it becomes necessary to write two (or more) different peices of behaviour in a common code. Depending of its mode/place/time/version the behaviour has to be changed. It can be done by the use of simple preprocessor statements. Consider the following program:






//Program tested on Microsoft Visual Studio 2008 - Zahid Ghadialy
//Program to show use of preprocessor macros for dynamic behaviour

#include<iostream>
#include<string>

using namespace
std;

#define USE_CAR //Comment or Uncomment this if using preprocessor option

int
main()
{

int
someNum = 3;
#ifdef USE_CAR
string modeOfTransport("Use a Car");
#elif USE_BUS
string modeOfTransport("Use a Bus");
#elif USE_TRAIN
string modeOfTransport("Use a Train");
#else
string modeOfTransport("Use any mode of transport");
#endif

cout<<"Mode of Transport = "<<modeOfTransport<<" and someNum = "<<someNum<<endl;

return
0;
}



The output is as follows:

In the program above, the statement in the start #define USE_CAR says that the code with USE_CAR should be used during compile time. Instead if USE_BUS is defined, that particular peice of code will be used. If nothing is defined then the behaviour with else will be used.

There is another way to use these preprocessor directives. It is by defining in the properties below. If defined this way then the statement should be omitted from the main program.


The output is as follows in this case:

For more information see this.