Hello ladies and gents,

I was trying to write a small example of a pointer to a two dimensional array like this after looking up how to write the syntax at Narue's Et.Conf. world like this:

#include <iostream>
#include <iomanip>

void array(short (*myArray)[4][4]);

using namespace std;

int main()
{	
	short Map[4][4] = {0};
	short (*pMap)[4][4] = &Map;

	array(pMap);

	cout << "Press enter to exit\n";

	cin.ignore(cin.rdbuf()->in_avail() + 1);
	
    return 0;
}

void array(short (*myArray)[4][4])
{
	
	short size = sizeof myArray[0]/ sizeof myArray[0][0];

	for (int i = 0; i < size; i++)
		for (int j = 0; j < size; j++)
		{
			cout << (*myArray)[i][j] << " ";
			if (j%4 == 3) cout << endl;
		}
}

Works like a charm, though, when I wrote *myArray[j] instead of (*myArray)[j], the output was that the first row was all 0, but the rest were random numbers :-|

Can someone tell me why this happens :?:

Thanks for the help,

Recommended Answers

All 3 Replies

>Can someone tell me why this happens
Sure. Since you're working with a pointer to an array, you need to dereference the pointer first before you start trying to index the array. When you say *myarray[j], you're doing the indirection in the wrong order, with [j] first, then * because array indexing binds more tightly than indirection.

So the question is, why are the first 4 numbers correct when the rest ar obviously out of bounds array indexes? Let's say that the size of a pointer to an array of short is 4 bytes and a short is 2 bytes. myarray[0][0] is the same as *myarray, so you have a pointer to the first element, which when dereferenced gives you the first element.

Then j is incremented so you're looking at myarray[0][1], but since you're indexing a pointer to an array rather than the array that the pointer points to, you're actually at myarray[1][0], and dereferencing that pointer gives you the fifth element. Repeat the process and *myarray[0][2] is actually *myarray[2][0], which gives you the ninth element, and *myarray[0][3] is actually *myarray[3][0] which gives you the thirteenth element.

Then all hell breaks loose because you move to the first element of the next array, but since there isn't one, you're out of bounds and should expect nothing less than improper behavior.

>cin.ignore(cin.rdbuf()->in_avail() + 1);
As a side note, this isn't portable. in_avail() tells you how many characters are known to be available in the stream's internal buffer, which could be less than the actual number of characters left in the stream and the effect of ignoring them would still fail to give you a blocking read.

For example, if the streambuf has one character left in the buffer, but there are leftover characters from the device stored in a system buffer from which the streambuf fills its own internal buffer, cin.ignore will discard the character in the streambuf and the streambuf will refill its buffer from the system buffer. cin.ignore will then discard the first character from the newly filled streambuf buffer, and promptly not block if there's more than one.

A better way (though still not perfect due to a more extreme version of the above example) is to attempt to empty the streambuf buffer completely:

cin.ignore ( numeric_limits<streamsize>::max(), '\n' );

That all doesn't matter in this case since you don't have any input in that program, cin.ignore will be the blocking read you need, and pressing Return will satisfy it. But you should be aware that using in_avail in the way you did is non-portable. You could have been correct, portable, and saved yourself some typing by simply doing this:

cin.ignore();

Or even this:

cin.get();

:)

Thanks Narue, that explanation made it very clear why it happens :!:

How do you actually know when to use cin.get() or cin.ignore()
or another.

Because as you said, when I used the cin.ignore(cin.rdbuf()->in_avail() + 1) piece of code, depending on wich program I was trying out, it either worked or it didn't and I had to add a cin.get() to it or not.

Ive read several posts about it, but none actually have ever really explained how you determine what to use in your program ?

>How do you actually know when to use cin.get() or cin.ignore() or another
Until you've gained enough experience with one method or another, you guess. :) But I'll describe a few of the methods and when/why you should or shouldn't use them.

1) First and foremost, if you only need to read and discard a single character, and you're sure that it's only a single character all of the time, you can use either cin.get() or cin.ignore(). They both do the same thing except cin.get() returns the character and cin.ignore() doesn't.

2) If you need a blocking read, you make sure that the stream is empty and then use either cin.ignore() or cin.get(). Making sure that the stream is empty is where the other stuff comes in.

3) To clear the stream of characters and you know that there's at least one character in the stream, you use cin.ignore() with a suitable size. In this case, numeric_limits<streamsize>::max() is ideal because it tells you the size of the streambuf buffer.

You'll see two other common ways to empty an input stream. The first is the way you did it, using in_avail(). I already explained why that's to be avoided, but in the cases where it works, you have the benefit of not blocking if in_avail() returns 0. So this would work if you couldn't guarantee that the stream has at least one character to discard:

cin.ignore ( cin.rdbuf()->in_avail() );
cin.get();

But if the stream is empty, the following wouldn't do what you expect because cin.ignore() is also a blocking read, so you would have to hit Return twice:

cin.ignore ( numeric_limits<streamsize>::max(), '\n' );
cin.get();

Next is the dreadfully non-portable cin.sync(). The standard in no way suggests that it clears the streambuf buffer, but some highly regarded books describe it as such, and a bunch of compilers implement it that way:

cin.sync();
cin.get();

The good news is that it's short, and the best of both worlds for the first two methods. The bad news is that you can't guarantee that it'll do anything remotely similar to what you want. :)

Another method is much easier to figure out and verify for portability. Since people want to read and throw away everything in the stream, it's easily done with a loop:

char c;

while ( cin.get ( c ) && c != '\n' )
  ;

cin.get(); // Blocking read

But that requires at least one character to already be present in the stream or you'll get the double blocking problem. Some people like to do this to avoid it:

if ( cin.rdbuf()->in_avail() > 0 )
  cin.ignore ( numeric_limits<streamsize>::max(), '\n' );
cin.get();

If in_avail() returns 0 or less, the stream is either empty or in an error state and you avoid double blocking. However, that test is non-portable, so it's really no better than using cin.sync().

The trick is to know a bunch of different methods and the mix and match them to get the desired effect. Stream input in C++ is far from trivial, and sometimes you don't care as much about portability as you do functionality. But when you choose to do something non-portable, at least know that it's non-portable and you'll be in a better position to defend your choice. :)

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.