LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   getting size of an array in c++ (https://www.linuxquestions.org/questions/programming-9/getting-size-of-an-array-in-c-112958/)

qanopus 11-06-2003 03:21 AM

getting size of an array in c++
 
Hi there. I want to make an function that calculates the vector product of two vectors. Something like

Code:

int dotProd(int *v1, int *v2)
{
    // we can define them as integers because the vectors contain only
    // integer values

    int size = somehowgetsize(v1);
    int i;
    int prod = 0;

    for(i=0;i<=size;i++)
    {
          prod += v1[i] * v2[i];
    }

    return prod;

}

So how do I define the function "somehowgetsize"?

gradedcheese 11-06-2003 03:32 AM

hmm... I am weird so I normally don't do stuff like this with arrays. Instead I'll create a simple linked list object, with the last element having the usual NULL next-element-pointer. I then pass the address of the list's head nodes to the function you're writing rather than the addresses of arrays. To calculate the length of a linked list you can simply traverse it and keep count of nodes (you stop of course when you hit that NULL next element pointer). Or you can have the list object have a function that returns the size.

cdlen 11-06-2003 04:09 AM

the classical way of getting the number of elements in an array is:
sizeof (array)/ sizeof(elem)
But when the array is passed as a pointer, sizeof(array) returns the size of a pointer !
That's the strength and weakness of the C language. A pointer is a pointer is pointer... The compiler has no way to know what the pointer refers to. That provides a convenient way to switch the objects a pointer is pointing to but then it is your entire responsability of knowing what it is referring to. Just look at Windows api (must be the same for Linux) : all those structures passed as arguments. Each time the structure has an element to give the size of the structure.
Looking at Stroustrup's (p147): an array can't be passed by value in a function's arguments. Ways around:
When you got a zero-terminated string array it's easy to get the length.
Or you pass the number of elements as well
Or use standard lib vector type (which do the same thing only automatically)

If you have used other higher-level languages like Python,.. that must look tedious but don't forget that the objects they manage store their length inside them.
When you work with C you are as close as possible to the brass metal; when you ask for an array of 5 elements you got just that: 5 memory cells no more no less. And a pointer can point to anything (or be made to); if you use the pointer of the array to access a 6th inexistent element nobody's there to tell you you are getting in big troubles...

mr_segfault 11-06-2003 06:23 AM

schatoor & gradedcheese,

I would suggest that you dont use arrays, nor create your own linked list class (well not if your using c++ anyway). The STL has some great containers (including linked list) that will do what you want much better.

Incase you dont know, the STL is part of the C++ standard is part of your c++ library.. (with most modern compilers)


Code:

#include <vector>

int dotProd(std::vector<int> &v1, std::vector<int> &v2)
{
  // we can define them as integers because the vectors contain only
  // integer values

  int size = v1.size(); // this code assumes that v2 is atleast as large as v1
                        // therefore its not so good!
  int i;
  int prod = 0;

  for(i=0;i<size;++i) // note I changed i<=size to i<size, the former would explode :) see note below.
  {
    prod += v1[i]  * v2[i];
  }

  return prod;
}

void dummyFunc()
{
  // create two vectors
  std::vector<int> myVec1;
  std::vector<int> myVec2;

  // set their size
  myVec1.resize(4);
  myVec2.resize(4);

  // set some values.
  myVec1[0] = 22;
  myVec1[1] = 2;
  myVec1[2] = 34;
  myVec1[3] = 8;

  myVec2[0] = 6;
  myVec2[1] = 7;
  myVec2[2] = 73;
  myVec2[3] = 11;

  // do the work
  int theDotProduct = dotProd(myVec1, myVec2);
}

Note: Because of these type of errors, it is often best to use iterators to traverse through containers, since they eliminate these types of 'past the end' errors..

std::vectors are nice since they allow indexing like arrays (the operator[] is overloaded to return a reference to the item at the specified location)

Depending on what you are actually doing, you might want to look as using the vector's push_back() method instead of size() and operator[]. push_back adds an element to the vector (increases its size by 1) and assigns the value you pass to it. Like :myVec1.push_back(10); will add the int '10' to the said vector..

For some good reference material see this thread where I posted some good links: Good reference material for C++

I hope that helps.

Cheers.

qanopus 11-06-2003 06:41 AM

Wow, cool guy's, thanks for the detaild answers.
I my self thought of an solution along the lines of what cdlen said. I made an c++ vector class with an member var. indicating the size of the vector. But mr_segfault solution seems better.
Thanks again for all the help.

dakensta 11-06-2003 08:55 AM

Another alternative (depending on your use of the vector class - i.e. it is not going to change size):

Code:

template<typename T, size_t N>
struct Vector
{
        T val[N];
        T& operator[] ( size_t i ) { return val[i]; }
        const T& operator[] ( size_t i ) const { return val[i]; }
};

template<typename T, size_t N>
T dot_prod( const Vector<T,N>& v1, const Vector<T,N>& v2 )
{
        T prod=0;
        for( size_t s=0; s<N; ++s )
                prod += v1[s]*v2[s];
        return prod;
}

int main()
{
        Vector<float, 3> v1 = { 1, 2, 3 };
        Vector<float, 3> v2 = { 3, 2, 1 };
        cout << dot_prod( v1, v2 ) << endl;

}

which will ensure that the two Vectors dot producted will always be the same size.

Another advantage of making your own vector class is that you can include things like normalisation and all the other useful vector operations.

jim mcnamara 11-06-2003 10:10 AM

Check out the concept of smart pointers, or consider the boost library

www.boost.org

mr_segfault 11-06-2003 03:38 PM

dakensta,

Why did you choose float when it is storing ints?

dakensta 11-06-2003 05:19 PM

Most vector calculations I use are float or double precision (and I would have thought in general too), so force of habit I guess - int's would be fine for a dot product but add in, say magnitude, and you really need better precision.


1, 2, 3 were just the first numbers to come into my head, the type has already been specified in the template parameter, so there is no ambiguity ;)

While I am in the confession box, I used a struct in the example, rather than a class, out of habit too - slightly easier when selecting an example and cutting and pasting some code to quickly check and compile.

The example was really only to show the use of a template parameter as one possible method to include the size into a vector, where the size is not going to change. I added the type T to show maybe more familiar(?) template syntax for comparison and also allows int's to be used if that is what the original poster specifically requires. The operator[] was to keep the array-like syntax of arrays and std::vectors --- there are plenty of extensions that could be added (one useful one is cast to pointer, to substitute with functions that are defined like schatoor's dotProd)

Sorry for any confusion, point duly noted and I hope this clears things up.


All times are GMT -5. The time now is 04:30 PM.