1. ## Multidimensional Array Niggles!!!

My program is almost complete!

But why does it keep totaling the fifth product's total sales calculation as 32?

Code:
```#include <iostream>
#include <iomanip>
using namespace std;

const int employees = 4;
const int items = 5;

int validateItemNumber(); // enure only numbers within the acceptable range are passed
int validateEmployeeNumber(); // enure only numbers within the acceptable range are passed
void zeroArray( int[][items], int ); // wipe all data from the array
void sale( int[][items], int, int ); // increment sale counter dependent on item sold

int main()
{
int sales[employees][items];
int employeeNumber = 0;
int salesPerEmployee = 0;
int salesPerProduct = 0;

zeroArray( sales, employees);

while ( employeeNumber != -1 )
{
employeeNumber = validateEmployeeNumber();

if ( employeeNumber > -1 )
{
sale( sales, employees, employeeNumber );
}
}

cout << "\nEmployee" << setw( 8 ) << "Item 1" << setw( 8 ) << "Item 2" << setw( 8 ) << "Item 3" << setw( 8 ) << "Item 4" << setw( 8 ) << "Item 5" << setw( 8 ) << "Employee sales" << endl;

for ( int i = 0; i < employees; i++ )
{
cout << setw( 4 ) << i + 1;

for ( int j = 0; j < items; j++ )
{
cout << setw( 8 ) << sales[i][j];

salesPerProduct += sales[i][j];
}

cout << setw( 12 ) << salesPerProduct;

salesPerProduct = 0;

cout << "\n";
}

cout << "Total ";

for ( int i = 0; i < items; i++ )
{
for ( int j = 0; j < employees; j++ )
{
salesPerEmployee += sales[i][j];
}

cout << setw( 8 ) << salesPerEmployee;

salesPerEmployee = 0;
}

} // end main

// enure only numbers within the acceptable range are passed
int validateItemNumber()
{
int a;

cout << "\nWhich item was sold?\nItem no: ";
cin >> a;

while ( a < 1 || a > 5 )
{
cout << "Your input was not recognised!\nWhich item was sold?\nItem no: ";
cin >> a;
}

return a - 1;
} // end function validateItemNumber

// increment sale counter dependent on item sold
void sale( int sales[][items], int employees, int employeeNumber )
{
int itemNumber;

itemNumber = validateItemNumber();

sales[employeeNumber][itemNumber]++;

} // end function sale

// wipe all data from the array
void zeroArray( int sales[][items], int employees )
{
for ( int i = 0; i < employees; i++ )
{
for ( int j = 0; j < items; j++ )
{
sales[i][j] = 0;
}
}
} // end function zeroArray

// enure only numbers within the acceptable range are passed
int validateEmployeeNumber()
{
int empNo;

cout << "\nEnter employee number ( or 0 to show summary ): ";
cin >> empNo;

while ( empNo < 0 || empNo > 4 )
{
cout << "Your input was not recognised!\nEnter employee number ( or 0 to show summary ): ";
cin >> empNo;
}

return empNo - 1;
} // end function validateEmployeeNumber```

2. > salesPerEmployee += sales[i][j];
Your i index is counting items, but it is indexing the employees dimension (and vice-versa for employees indexing items).

Copy/paste bug.

3. Thanks Salem! Case closed!!!
You've the eyes of an eagle!

4. A good tip for you: SourceForge.net: Do not remove parameter names - cpwiki
Another good tip is to use std::vector or std::array instead of pure C arrays. They are unsafe, and hard to debug.
Use the at method of the aforementioned classes to protect yourself from buffer overruns in release code.

5. Thanks Elysia! I think Vectors are the next chapter in my textbook! I'll be sure to learn them thoroughly!!!

6. [C arrays] are ... hard to debug.
Use the at method of the aforementioned classes to protect yourself from buffer overruns in release code.
The implication here being that C arrays are harder to debug. I fail to see how they are harder to debug since std::array and std::vector are implementations of the same data structure as C arrays. You would debug all three of these things in a similar way. Plus the OPs code didn't have a buffer overflow error in it.

7. Many implementations I am told have debug checks to catch out-of-bound errors. Plus you will get an exception if you use the at member function while you get undefined behavior using the index operator or C arrays. This means if you use the at function, you will know there was a bug in the code, but with C functions, it might just succeed silently and corrupt some other variable.

Whether or not the OP had a buffer overflow in the code or not is irrelevant. It's not safe, and it can be hard to debug. Why spent time debugging when some simple code modifications can reduce the number of bugs and time spent debugging?

8. But you debug them all the same way. You watch your subscripts. Just like you would watch your subscripts and make sure at() doesn't throw. But the OP transposed subscripts in his matrix. at() really doesn't help you debug that more than anything else.

Originally Posted by Elysia
Use the at method of the aforementioned classes to protect yourself from buffer overruns in release code.
Plus, an uncaught exception is just a random crash. It might protect you, but it's just as uninformative as anything else.

9. Oh, come on. Don't tell you put watches on your subscripts all the time you debug. Especially newbies.
at() isn't a tool to check if a subscript exists or not; it is there to tell you something bad happened. You are guaranteed to get an exception with out-of-bounds access, whereas if you don't, the behavior is undefined and may silently succeed.

Plus, uncaught exceptions may crash the program, but any debugger will catch them for you. You aren't guaranteed to get an access violation if you do out-of-bounds access.
Furthermore, you know that as soon as you get an out-of-bounds access, you are guaranteed to get an exception. That means you can catch it if you want. That isn't guaranteed with out-of-bounds access with normal C arrays.

10. Oh, come on. Don't tell you put watches on your subscripts all the time you debug.
I do.

Especially newbies.
Don't care. They should debug properly.

Plus, uncaught exceptions may crash the program, but any debugger will catch them for you. You aren't guaranteed to get an access violation if you do out-of-bounds access.
I'm just against this whole notion that exceptions somehow help you debug. Meanwhile you say stuff like this:
Use the at method of the aforementioned classes to protect yourself from buffer overruns in release code.
Which is only half the story in using exceptions.

I don't treat exceptions like a debugging tool and why should they be treated that way if they have things like this and this and this? The trouble with exceptions is you won't be able to discern which object threw the exception. Also why is it good that we leave uncaught exceptions in release code, to protect against an error, that do nothing informative. Wouldn't that frustrate anyone who actually used your program?

11. Originally Posted by whiteflags
I do.
Indeed, and can you guarantee that every path is properly tested that they do not go out of bounds? This would only work when you debug, not in release code.

I'm just against this whole notion that exceptions somehow help you debug. Meanwhile you say stuff like this:
They are not great debugging tools, but they can help tell you that you got a buffer overrun. No tool is perfect, and if you combine it with other debugging tools, you protect yourself from more bugs. Especially in release mode where all debugging checks are disabled!

I don't treat exceptions like a debugging tool and why should they be treated that way if they have things like this and this and this?
They complement the protection.
OK, to be honest, if you have catch blocks, it might be a little harder to catch the problems, but debuggers can be configured and code can be disabled.
Regardless, for release builds, they are your best friend.

The trouble with exceptions is you won't be able to discern which object threw the exception.
But you know that the problem occurred, which you may or may not have if you didn't have them.

Also why is it good that we leave uncaught exceptions in release code, to protect against an error, that do nothing informative. Wouldn't that frustrate anyone who actually used your program?
Yes, it would, but who says you can't catch them?
You cannot guarantee to catch out-of-bounds errors without range checking. And you have perfectly working range checking with at().

12. Indeed, and can you guarantee that every path is properly tested that they do not go out of bounds? This would only work when you debug, not in release code.
This whole argument is dumb. You can't say every path is properly tested and does not go out of bounds just because you use exceptions.

Regardless, for release builds, they are your best friend.
That's meaningless, but you've already admitted that exceptions aren't debugging tools so I guess you're just proud that they caught a programming error you missed and should have debugged. That however has never been the purpose of exceptions. Exceptions are for reporting errors in exception safe code. Particularly the kind of exception safe where errors are permitted to occur but you recover the state of the program before the error occurred.

Yes, it would, but who says you can't catch them?
You cannot guarantee to catch out-of-bounds errors without range checking. And you have perfectly working range checking with at().
What if the code isn't supposed to throw exceptions? The no-throw guarantee in exception safety. OK, that isn't a "who" but the point is valid. If you write an exception in code that merits a no-throw guarantee, I'd clobber you. Especially if I'd found out after we've shipped.

You're using exceptions like debugging tools when they aren't and telling other people to do the same thing. Exceptions aren't about protecting the world from your mistakes.

13. Really, it's pointless discussing this with you. You assume we are all perfect and nothing slips out of our grasp. You reject extra security measures to lower the chance of bugs escaping and hurting end users.

I would rather see an error message saying "Internal error, report this?" and the ability to retry whatever I did instead of the application crashing or producing woefully wrong results or corrupting existing data.
It will happen, even if you properly debug your code, because as I am pointing out, but you rejecting, we are not perfect. We make mistakes. You cannot possibly test everything in a software. And you simply cannot--or won't due to restraints--fix every bug.

Exception safety does not mean the code does not throw exceptions. It means that the object's state shall be restored to what it was before the action that caused the exception to be thrown. For example, if push_back has a strong exception guarantee, it means that if push_back throws, no item is added to the vector and the vector's state will be the same as before we called push_back.

14. Originally Posted by Elysia
Really, it's pointless discussing this with you. You assume we are all perfect and nothing slips out of our grasp. You reject extra security measures to lower the chance of bugs escaping and hurting end users.
What extra security measures are these? Either you ran a test that exposed the error, in which case you can debug (if you chose debug) or you can maybe debug (if you chose exceptions); or you didn't run a test that exposed the error, in which case debug vs. exceptions don't matter.
Originally Posted by Elysia
I would rather see an error message saying "Internal error, report this?" and the ability to retry whatever I did
Exceptions for user errors?!

15. I would agree with Elysia about using at, if it actually added sizable failure guarantees. The problem is, it has such a limited effect, that it's not worth it. There are so many other ways to have undefined, sporadic errors in C++. For instance, by using invalid iterators.

Now a hypothetical STL implementation could be made that keeps track of iterator validity, that would throw, or otherwise signal those kinds of errors, but I would expect such an implementation to do the same bounds checking on operator[].