Thread: Apmatrix.h -> vector

  1. #1
    *this
    Join Date
    Mar 2005
    Posts
    498

    Apmatrix.h -> vector

    I have created a program using the apmatrix class to declare 2 dimensional arrays. How could I declare 2d arrays using the vector header file or any other standard header. here is my code...if its needed, probably dont need the whole thing but if your curious.

    Code:
    #include <iostream>
    #include <fstream>
    #include <iomanip>
    #include <apmatrix.h>
    #include <apvector.h>
    using namespace std;
    
    const int MAX = 4,
              FILL = 0;
    
    void getSquare (apmatrix <int> &);
    int sumRow (const apmatrix<int> &, int &);
    bool rowAdd (const apmatrix<int> &, int);
    bool columnAdd (const apmatrix<int> &, int);
    bool diagAdd (const apmatrix<int> &, int);
    bool unique (const apmatrix<int> &);
    void print (const apmatrix<int> &);
    
    main()
    {
       int row_sum;
       apmatrix <int> square(MAX, MAX);
       
       getSquare (square);
       sumRow (square, row_sum);
       if ( 
          rowAdd (square, row_sum) &&
          columnAdd (square, row_sum) &&
          diagAdd (square, row_sum) &&
          unique (square)
          )
       {
          print (square);
          cout<< endl 
              << "All rows, columns, and diagonals add up to: "
              << row_sum << endl;
       }
       else 
       {
          print (square);
          cout<< endl
              << "Input is not a magic square...";
       }
          
       return 0;
    }
    
    void getSquare 
    (apmatrix <int> &array)
    //assign locations for the magic square, from a file
    {
       ifstream infile ("Lesson18.txt");
       for (int row = FILL; row < MAX; row++)
          for (int col = FILL; col < MAX; col++)
             infile >> array[row][col];
    }
    
    int sumRow 
    (const apmatrix<int> &square, int &row)
    //calculate the sum of the first row
    {
       row = FILL;
       for (int col = FILL; col < MAX; col++)
          row += square[FILL][col];
       return row;
    }
    
    bool rowAdd 
    (const apmatrix<int> &square, int row_sum)
    //do all rows add up to row_sum?
    {
       int add = FILL;
       bool stop = FILL;
       for (int row = FILL; row < MAX; row++)
       {   
          add = FILL;
          for (int col = FILL; col < MAX; col++)
             add += square[row][col];
          if (add != row_sum)
             stop = true;
       }
       if (stop) return false;
          else return true;
    }
    
    bool columnAdd 
    (const apmatrix<int> &square, int row_sum)
    //do all columns add up to row_sum?
    {
       int add = FILL;
       bool stop = FILL;
       for (int col = FILL; col < MAX; col++)
       {
          add = FILL;
          for (int row = FILL; row < MAX; row++)
             add += square[row][col];
          if (add != row_sum)
             stop = true;
       }
       if (stop) return false;
          else return true;
    }
    
    bool diagAdd 
    (const apmatrix<int> &square, int row_sum)
    //do all diagonals add up to row_sum?
    {
       int add = FILL;
       bool stop = FILL;
       for (int col = FILL; col < MAX; col++)  //do first diagonal
          add += square[col][col];
       if (add != row_sum)
          stop = true;
          
       add = FILL;   //reset add for next calculation
       
       int row = MAX;         //needs to start at max to find 2nd diagonal
       for (int col = FILL; col < MAX; col++)           //do second diagonal
       {
          row--;
          add += square[row][col];
       }
       if (add != row_sum)
          stop = true;
       
       if (stop) return false;
          else return true;
    }
    
    bool unique 
    (const apmatrix<int> &square)
    //is each number different, within the correct range?
    {
       const int VECTOR_MAX = MAX * MAX + 1;
       apvector<int> countNum (VECTOR_MAX, FILL);
       int singlenum;
       bool stop = FILL;
       
       for (int row = FILL; row < MAX; row++)
          for (int col = FILL; col < MAX; col++)
          {   
             singlenum = square[row][col];
             countNum[singlenum]++;
          }
       for (int start = FILL + 1; start < VECTOR_MAX; start++)
          if ((countNum[start] == FILL) || 
             (countNum[start] > 1))
             stop = true;
       if (stop) return false;
          else return true;
    }
    
    void print 
    (const apmatrix<int> &array)
    //print 2d array to the screen
    {
       for (int row = FILL; row < MAX; row++)
       {
          for (int col = FILL; col < MAX; col++)
             cout<< setw(4) << array[row][col];
          cout<< endl;
       }
    }
    
    /***************************
    OUTPUT:
      16   3   2  13
       5  10  11   8
       9   6   7  12
       4  15  14   1
    
    All rows, columns, and diagonals add up to: 34
    ****************************
      16   3   2  13
       5  11  10   8
       9   7   7  12
       4  15  15   1
    
    Input is not a magic square...
    ***************************/

  2. #2
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    You can declare a 1D matrix and access it in 2D.

    Code:
    class Array2D
    {
      int *m_pData;
      int m_iWidth;
      int m_iTotalSize;
    
      public:
        Array2D(void):m_pData(NULL),m_iWidth(0),m_iTotalSize(0) {}
       virtual ~Array2D(void) 
       {
          if (m_pData) delete [] m_pData;
          m_pData=NULL;
       }
    
       bool Create(int iTotalSize,int iWidth)
       {
          m_iTotalSize=iTotalSize;
          m_iWidth=iWidth;
         
          m_pData=new int[iTotalSize];
          if (m_pData) 
          {
             asm {
               mov  esi,[m_pData]
               mov  ecx,[m_iTotalSize]
               mov  eax,00000000h
               rep   stosd
               and ecx,03h
               rep  stosb
             }
             return true;
           } else return false;
        }
    
        bool SetDataXY(int value,int x,int y)
        {
            int offset=y*m_iWidth+x;
            if (offset<=m_iTotalSize)
           {
              m_pData[offset]=value;        
              return true;
           } else return false;
        }
        
        bool GetDataXY(int *outValue,int x,int y)
        {
           int offset=y*m_iWidth+x;
           if (offset<=m_iTotalSize)
           {
              *outValue=m_pData[offset];
              return true;
           } 
            else 
           {
             *outValue=NULL;
             return false;
           }
         }
    };
    Now this class is pretty much useless unless you want to use it for something like a tile map in a game or some other map usage. You could make the class a template so that it would then be able to deal with any data type.

    But I hope it shows how you can access a 1D array in 2D. 2D arrays are slower because when you create them they only exist compiler side. In other words all of the math I just showed you (y*width+x) is being done by your compiler to calculate the correct address in memory. Save your compiler the math and do it yourself. There are also other optimizations you can do on a 1D array to ensure that you have the fastest possible access. Re-computing offset every time you need data from the array is not the best way.

  3. #3
    *this
    Join Date
    Mar 2005
    Posts
    498
    o so theres like no way to declare a vector inside of a vector? or just declare a 2d array?

  4. #4
    Carnivore ('-'v) Hunter2's Avatar
    Join Date
    May 2002
    Posts
    2,879
    Code:
    vector< vector<int> > vect2D(height, vector<int>(width, 0));
    vect2D[y][x] = 10;
    Just Google It. √

    (\ /)
    ( . .)
    c(")(") This is bunny. Copy and paste bunny into your signature to help him gain world domination.

  5. #5
    *this
    Join Date
    Mar 2005
    Posts
    498
    is this ok according to ANSI II standards?

  6. #6
    Carnivore ('-'v) Hunter2's Avatar
    Join Date
    May 2002
    Posts
    2,879
    >>according to ANSI II standards?
    I don't know which standards, but it should be OK.

    A vector<vector<int> > is perfectly valid and commonly used (make sure there's a space between the two >'s). The constructor I used was:
    vector<T>(initial size, value of type T)

    Since for the outer vector, T is vector<int>, this becomes:
    vector<T>(initial size [height], vector<int>(initial size [width], some int value))

    And there you have a vector of vectors of int, which works pretty much like a 2D vector.
    Just Google It. √

    (\ /)
    ( . .)
    c(")(") This is bunny. Copy and paste bunny into your signature to help him gain world domination.

  7. #7
    *this
    Join Date
    Mar 2005
    Posts
    498
    thanks a bunch

  8. #8
    *this
    Join Date
    Mar 2005
    Posts
    498
    whats the difference in declaring a plain integer in 2d like:

    Code:
    #include <iostream>
    using namespace std;
    
    main()
    {
       int a [5][5];
       for (int row = 0; row < 5; row++)
          for (int col = 0; col < 5; col++)
             a [row][col] = row * col;
             
             
       for (int row = 0; row < 5; row++)
       {
          for (int col = 0; col < 5; col++)
          cout<< a [row][col] << "  ";
       cout<< endl;
       }
       cin.get();
    }
    works fine to me, is there much of a difference?

  9. #9
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    whats the difference in declaring a plain integer in 2d like:
    Read my post.

    Which is faster?


    Code:
    int width=100;
    int height=100;
    
    DWORD *temp=new DWORD[width*height]
    
    for (int i=0;i<height;i++)
    {
      for (int j=0;j<width;j++)
      {
         temp[(i*width)+j]=0;
      }
    }
    Code:
    int width=100;
    int height=100;
    int totalsize=width*height;
    
    
    DWORD *temp=new DWORD[totalsize]
    
    for (int i=0;i<totalsize;i++)
    {
      temp[i]=0;
    }
    They do the same thing except the first example requires (100*100) multiplies while the second one requires 0.

    The second portion is essentially the same as:

    Code:
    int width=100;
    int height=100;
    int totalsize=width*height;
    
    DWORD *temp=new DWORD[totalsize]
    
    asm {
      mov  edi,[temp]
      mov  ecx,totalsize
      mov eax,000000000h
      rep  stosd
    }
    Last edited by VirtualAce; 03-30-2005 at 08:10 AM.

  10. #10
    *this
    Join Date
    Mar 2005
    Posts
    498
    but i still dont see why you should declare it as a 1d array then access it in 2d, other than speed, dont you think it would be a little confusing in a matrix driven program?

  11. #11
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    but i still dont see why you should declare it as a 1d array then access it in 2d,
    ....other than speed,

  12. #12
    Carnivore ('-'v) Hunter2's Avatar
    Join Date
    May 2002
    Posts
    2,879
    >>whats the difference in declaring a plain integer in 2d like:
    Depending on what you're doing, the 2d int array may even be faster than the vector of vectors. With the vector of vectors though, you can resize it as you like whenever you want, and you can also decide what values to put in each element.

    >>Read my post. Which is faster?
    I think he was referring to my vector post.

    >>i still dont see why you should declare it as a 1d array then access it in 2d, other than speed
    Depending on what you're doing, speed may mean everything. In Bubba's case, it does. In your case, it probably doesn't. The difference in confusing-ness would probably be quite small though, if you wrapped it in a class or something with a [] operator, although if you used it wrong you'd probably lose any performance gain you'd just made.

    >>while the second one requires 0.
    Implicitly, unless the compiler optimizes it away, doesn't it require a multiplication for each random access anyway? More likely would be to use a pointer and walk through with that instead of using an index.
    Just Google It. √

    (\ /)
    ( . .)
    c(")(") This is bunny. Copy and paste bunny into your signature to help him gain world domination.

  13. #13
    *this
    Join Date
    Mar 2005
    Posts
    498
    is there a way to fill a 2d array?

    Code:
    #include <iostream>
    using namespace std;
    
    const int MAX = 20,
              FILL = 0;
              
    void fill (char [ MAX ][ MAX ]);
    void print (const char [ MAX ][ MAX ]);
    
    main()
    {
       char table[ MAX ][ MAX ];
       
       fill (table);
       print (table);
       return 0;
    }
    
    void fill (char table[ MAX ][ MAX ])
    {
       for (int row = FILL; row < MAX; row++)
          for (int col = FILL; col < MAX; col++)
             table[ row ][ col ] = '-';
    }
              
    void print (const char table[ MAX ][ MAX ])
    {
       for (int row = FILL; row < MAX; row++)
       {   
          for (int col = FILL; col < MAX; col++)
             cout<< table[ row ][ col ];
          cout<< endl;
       }
    }
    would this be the best way to fill it? or is there some easier syntax, also is this the best way to use arrays because they wont be resized or anything.

  14. #14
    Carnivore ('-'v) Hunter2's Avatar
    Join Date
    May 2002
    Posts
    2,879
    >>int row = FILL
    If I were you, I'd leave it as row = 0, since FILL isn't a particularly good name for "beginning of the array".

    >>is there some easier syntax
    That's the most conventional and straightforward syntax. You could also try this, although it's kind of a dodgy business that relies on how arrays are stored in memory (don't do this unless you really know exactly what you're doing). I'm not even 100% sure it's within standard behaviour, although it seems to work OK:
    Code:
    char* begin = &(table[0][0]);  //Get a pointer to the first element
    char* end = &(table[MAX - 1][MAX - 1]) + 1;  //Get a pointer to 1 past the last element
    
    for(char* element = begin; element != end; ++element)  //Loop through all elements.
       *element = '-';
    >>is this the best way to use arrays because they wont be resized or anything.
    I would caution you not to use the word 'best' around here, but it's certainly not a bad way. If it fits your needs nicely (which it seems it probably will), then go ahead and use it; you'll learn with experience what works well and what doesn't, so I advise you to use your best judgment for the time being and then just improve on your future code as you learn new and better tricks.
    Just Google It. √

    (\ /)
    ( . .)
    c(")(") This is bunny. Copy and paste bunny into your signature to help him gain world domination.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. can some one please tell me the cause of the error ?
    By broli86 in forum C Programming
    Replies: 8
    Last Post: 06-26-2008, 08:36 PM
  2. syntax help?
    By scoobygoo in forum C++ Programming
    Replies: 1
    Last Post: 08-07-2007, 10:38 AM
  3. Vector class
    By Desolation in forum C++ Programming
    Replies: 2
    Last Post: 05-12-2007, 05:44 PM
  4. Need some help/advise for Public/Private classes
    By nirali35 in forum C++ Programming
    Replies: 8
    Last Post: 09-23-2006, 12:34 PM
  5. Certain functions
    By Lurker in forum C++ Programming
    Replies: 3
    Last Post: 12-26-2003, 01:26 AM