Multidimensional Array Niggles!!!

This is a discussion on Multidimensional Array Niggles!!! within the C++ Programming forums, part of the General Programming Boards category; My program is almost complete! But why does it keep totaling the fifth product's total sales calculation as 32? Please ...

  1. #1
    Registered User JM1082's Avatar
    Join Date
    Mar 2011
    Posts
    51

    Angry Multidimensional Array Niggles!!!

    My program is almost complete!

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

    Please find my source code below for your perusal:

    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. #2
    and the hat of wrongness Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    32,337
    > 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.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.
    I support http://www.ukip.org/ as the first necessary step to a free Europe.

  3. #3
    Registered User JM1082's Avatar
    Join Date
    Mar 2011
    Posts
    51
    Thanks Salem! Case closed!!!
    You've the eyes of an eagle!

  4. #4
    C++まいる!Cをこわせ! Elysia's Avatar
    Join Date
    Oct 2007
    Posts
    22,170
    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.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.
    For information on how to enable C++11 on your compiler, look here.
    よく聞くがいい!私は天才だからね! ^_^

  5. #5
    Registered User JM1082's Avatar
    Join Date
    Mar 2011
    Posts
    51
    Thanks Elysia! I think Vectors are the next chapter in my textbook! I'll be sure to learn them thoroughly!!!

  6. #6
    Registered User whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    7,525
    [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.
    Last edited by whiteflags; 07-20-2011 at 04:14 AM.

  7. #7
    C++まいる!Cをこわせ! Elysia's Avatar
    Join Date
    Oct 2007
    Posts
    22,170
    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?
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.
    For information on how to enable C++11 on your compiler, look here.
    よく聞くがいい!私は天才だからね! ^_^

  8. #8
    Registered User whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    7,525
    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.

    Quote 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.
    Last edited by whiteflags; 07-20-2011 at 02:46 PM.

  9. #9
    C++まいる!Cをこわせ! Elysia's Avatar
    Join Date
    Oct 2007
    Posts
    22,170
    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.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.
    For information on how to enable C++11 on your compiler, look here.
    よく聞くがいい!私は天才だからね! ^_^

  10. #10
    Registered User whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    7,525
    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. #11
    C++まいる!Cをこわせ! Elysia's Avatar
    Join Date
    Oct 2007
    Posts
    22,170
    Quote Originally Posted by whiteflags View Post
    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().
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.
    For information on how to enable C++11 on your compiler, look here.
    よく聞くがいい!私は天才だからね! ^_^

  12. #12
    Registered User whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    7,525
    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.
    Last edited by whiteflags; 07-20-2011 at 04:15 PM. Reason: small changes

  13. #13
    C++まいる!Cをこわせ! Elysia's Avatar
    Join Date
    Oct 2007
    Posts
    22,170
    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.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.
    For information on how to enable C++11 on your compiler, look here.
    よく聞くがいい!私は天才だからね! ^_^

  14. #14
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,185
    Quote Originally Posted by Elysia View Post
    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.
    Quote Originally Posted by Elysia View Post
    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. #15
    Registered User
    Join Date
    Apr 2006
    Posts
    2,012
    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[].
    It is too clear and so it is hard to see.
    A dunce once searched for fire with a lighted lantern.
    Had he known what fire was,
    He could have cooked his rice much sooner.

Page 1 of 2 12 LastLast
Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Help with MultiDimensional Array (I think)
    By RommelTJ in forum C Programming
    Replies: 5
    Last Post: 11-25-2009, 01:30 AM
  2. 2d multidimensional array
    By epica in forum C Programming
    Replies: 2
    Last Post: 08-20-2009, 04:43 PM
  3. help with multidimensional array
    By keira in forum C++ Programming
    Replies: 4
    Last Post: 10-30-2008, 11:28 AM
  4. Copy multidimensional array to single array?
    By seepox in forum C Programming
    Replies: 9
    Last Post: 05-08-2006, 11:19 AM
  5. Multidimensional Array
    By Unregistered in forum C++ Programming
    Replies: 1
    Last Post: 11-17-2001, 05:18 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21