UBound checks - C++

Started by
10 comments, last by DeadXorAlive 18 years ago

testMethod(const double array[])
{
	int x = 0;
	for(int i = 0; i < 4; i++)
	{
		if (array > 0)
			x++;
	}
        
        //.... rest of code using x as ubound for array[]
}





While this isn't exactly what I'm doing I think it expresses my intent. I've got a situation where an array could have 1 to 4 unsigned doubles in it, instead of having to manually pass the ubound to the intended function, I use the for statement to check the array for positive numbers. The problem is that it's erratic, sometimes it returns the correct ubound of the array, sometimes it doesn't...after debugging it seems that sometimes the memory being accessed outside the array is positive hence throwing my if array > 0 check into a false positive. Is there a good way to check dynamic bounds? Any thoughts are appreciated as always. [Edited by - senelebe on April 17, 2006 10:40:34 AM]
Advertisement
Use a vector :)

#include <vector>void testMethod(const std::vector<double> &array){	for(int i = 0; i < array.size(); i++)	{		//...	}                //.... array.size() is ubound}


A const double array[] is basically a pointer and as such, contains no information about the size of the memory it points to.

A vector on the other hand is basically a pointer and an upper bound tied together.

See this page for more information
http://www.sgi.com/tech/stl/Vector.html
Unless you happen to be in the same function that created the array, it's impossible to get the size of said array. You're just referring to random points in memory that might be positive or negative after your allocated segment.

Use a vector instead, raw arrays are evil.
Gotcha, I'm just now getting the feel for strings over const chars, I suspect it's time to get the feel for vectors as well.

I didn't want to cut my array learning short, but from the sounds of it there is little use for them... would that be an accurate statement?

When is an array not an array? When you're in C++ and it's a vector! lol, Coming from higher level languages to C++ has been a learning experience to say the least.

I appreciate the help greatly and I'll dive into vectors, I kind of thought that would be the solution, but I hate just skipping over arrays.
I believe the answer is no. My c++ book here says an array passed to a function decays into a pointer, which means you lose all type information of the array. So you can't know inside a function what size the array was.
Besides passing the size anyway, boost::array may be an option. (I haven't used it myself, but I assume it's good.)

edit1: I need to learn how to type faster!
edit2: yes vectors rule, arrays suck.
The vector did a fine job, had to play around with it for awhile but it seems to be working quite well now. There's still a ton to learn about vectors, one thing I was curious about that I didn't see, is there a way to instantiate vectors like you do arrays...

string teams[5] = {"Astros", "Braves", "Mets", "Cubs", "Cardinals"};
vector<string> teams(5) = <~~~ throws an error about right side =

Anyways, this was the finished product of the method using the vector. I realize alot of those for/if's should probably be private methods. The main reason I needed the dynamic index was because of a default ctor that collected data (via cin) then passed to this ctor, some Sales objects will be passed with all 4 quarters of sales complete (past), whereas current sales figures will be of variable quarter length.

Thanks again for the suggestions, I'll probably spend the majority of tommorow working through vectors, At this point it's probably a greater priority then continuing my oop practice.


//Static ctorSales::Sales(string name, const vector<double> &sales){        //get the dynamic ubound of sales	int iUbound = sales.size(); 	m_name = name;        //set our internal array field m_sales	for(int iter = 0; iter < iUbound; iter++)	{		m_sales[iter] = sales[iter];	}	//set our internal double field m_max	m_max = m_sales[0];	for(int iter = 1; iter < iUbound; iter++)	{		if (m_max < m_sales[iter])		{			m_max = m_sales[iter];		}	}        //set our internal double field m_min	m_min = m_sales[0];	for(int iter = 1; iter < iUbound; iter++)	{		if(m_min > m_sales[iter])		{			m_min = m_sales[iter];		}	}        //set our internal double field m_totalSales	m_totalSales = m_sales[0];	for(int iter = 1; iter < iUbound; iter++)	{		m_totalSales += m_sales[iter];	}        //only calculate double average from quarters (iUbound) passed        m_average = m_totalSales / iUbound;        //set projected sales for year if quarters (iUbound) not 4        //internal field saved regardless, show method filters.	m_projectedSales = m_average * 4;        //Fill our m_sales array with 0.00 for unfinished quarters.	for(int iter = 0; iter < (4 - iUbound); iter++)	{		int y = iUbound + iter;		m_sales[y] = 0.00;	}}

Short answer: No.

You can of course make a function to populate it, or if you need a repetition of values you could use this constructor: vector(size_type count, const Ty& val);, which creates count repetitions of val

If you pass a single number to the constructor it tells it to create a vector of that size, which saves you time in allocation if you're expecting to populate it with that many elements. Less resizes and all.
Time for some clean-up :) I'll let the code speak for itself, to the best of its ability... if you don't understand something, just ask :)

#include <algorithm>#include <iterator>// I will assume m_sales is also a vector<double>.// The strategy will be to copy across the elements, then later pad it to a// length that is a multiple of 4. Except we don't need to copy elements: we// can copy-construct the member itself, because vectors know how to do that :)//Static ctorSales::Sales(string name, const vector<double> &sales) :  m_name(name),   m_sales(sales),  m_max(*max_element(sales.begin(), sales.end())),  m_min(*min_element(sales.begin(), sales.end())),  m_totalSales(accumulate(sales.begin(), sales.end(), 0.0)),  m_average(m_totalSales / sales.size()),  m_projectedSales(m_average * 4) {  // Fill our m_sales array with 0.00 for unfinished quarters.  // This also allows for the 'sales' to cover more than one year.  int remainingQuarters = 4 - (m_sales.size() % 4);  if (remainingQuarters != 4) {    for (int i = 0; i < remainingQuarters; ++i) {      m_sales.push_back(0.0);    }  }}
Quote:
Time for some clean-up :)


Wow, that is pretty slick. Private methods my ass... lol.

#include <algorithm>
#include <iterator>

I'm assuming the iterator header is used in conjunction with vector to get it to do some of the fancier sorting *max_element, *min_element;

What are you using in the algorithm header though?


also this line...

int remainingQuarters = 4 - (m_sales.size() % 4);

I'd assume (m_sale.size() % 4) would return 0 on a full vector(4 quarters) [giving us the statment 4 - (4 % 4)] since we're checking for != 4 below, I'm curious as to why the modulus instead of just 4 - m_salesize();


[Edited by - senelebe on April 17, 2006 8:15:28 AM]
Alright, first off sorry for double post, not a self-loving bump.

m_average(m_totalSales / sales.size()),

Is returning erroneous results. I cannot put a break on the line, but m_totalSales is correct, and breaking after shows that sales.size() is correct...

It's returning huge negative doubles, that look like :

-23222922849289000000000000000000000000000000000000000000000000000000000.00

while that might not be the exact return it's similiar. As a side note it's also throwing off the m_projectedSales, but that's expected.

This topic is closed to new replies.

Advertisement