I have the following function
std::vector<bool> buildBoolList(node* n)
{
std::vector<bool> boolList;
for(int i = 0; i < n->next.size(); i++)
{
int ival = atoi(n->next[i]->val.c_str());
bool b = !!ival;
boolList.push_back(b);
}
return boolList;
}
However every time I run my code boolList is always returned with a size of 0. I've run the debugger to ensure that atoi is returning a valid numeric and I've also ensured that b becomes the appropriate boolean value, however I can't seem to figure out why boolList is not populated.
std::vector<bool> has been a kind of experiment by the C++ committee. It is actually a template specialization that stores the bool values tightly packed in memory: one bit per value.
And since you cannot have a reference to a bit, so you might be seeing the size as 0.
Why vector<bool>::reference doesn't return reference to bool?
There's nothing wrong with vector<bool>, except that it isn't equivalent to a vector were T is the integer type equivalent to bool. This only shows in performance (CPUs only access bytes at a time, where in a vector<bool> every element is stored in one bit) and memory access (a reference to a first element of a vector is not equivalent to an array like with any other vector<T>. It is part of the Standard, unfortunately: see section 23.3.7 (C++0x FDIS)
I think your problem is with:
for(int i = 0; i < n->next.size(); i++)
{
int ival = atoi(n->next[i]->val.c_str());
I am almost certain you meant something along the lines of:
for(node* i = n; i->next != NULL; i=i->next)
{
int ival = atoi(i->val.c_str());
Related
Need to implement a function
int* linearSearch(int* array, int num);
That gets a fixed size array of integers with a number and return an array with indices to the occurrences of the searched number.
For example array={3,4,5,3,6,8,7,8,3,5} & num=5 will return occArray={2,9}.
I've implemented it in c++ with a main function to check the output
#include <iostream>
using namespace std;
int* linearSearch(int* array, int num);
int main()
{
int array[] = {3,4,5,3,6,8,7,8,3,5}, num=5;
int* occArray = linearSearch(array, num);
int i = sizeof(occArray)/sizeof(occArray[0]);
while (i>0) {
std::cout<<occArray[i]<<" ";
i--;
}
}
int* linearSearch(int* array, int num)
{
int *occArray= new int[];
for (int i = 0,j = 0; i < sizeof(array) / sizeof(array[0]); i++) {
if (array[i] == num) {
occArray[j] = i;
j++;
}
}
return occArray;
}
I think the logic is fine but I have a syntax problems with creating a dynamic cell for occArray
Also a neater implantation with std::vector will be welcomed
Thank You
At very first I join in the std::vector recommendation in the question's comments (pass it as const reference to avoid unnecessary copy!), that solves all of your issues:
std::vector<size_t> linearSearch(std::vector<int> const& array, int value)
{
std::vector<size_t> occurrences;
// to prevent unnecessary re-allocations, which are expensive,
// one should reserve sufficient space in advance
occurrences.reserve(array.size());
// if you expect only few occurrences you might reserve a bit less,
// maybe half or quarter of array's size, then in general you use
// less memory but in few cases you still re-allocate
for(auto i = array.begin(); i != array.end(); ++i)
{
if(*i == value)
{
// as using iterators, need to calculate the distance:
occurrences.push_back(i - array.begin());
}
}
return occurences;
}
Alternatively you could iterate with a size_t i variable from 0 to array.size(), compare array[i] == value and push_back(i); – that's equivalent, so select whichever you like better...
If you cannot use std::vector for whatever reason you need to be aware of a few issues:
You indeed can get the length of an array by sizeof(array)/sizeof(*array) – but that only works as long as you have direct access to that array. In most other cases (including passing them to functions) arrays decay to pointers and these do not retain any size information, thus this trick won't work any more, you'd always get sizeOfPointer/sizeOfUnderlyingType, on typical modern 64-bit hardware that would be 8/4 = 2 for int* – no matter how long the array originally was.
So you need to pass the size of the array in an additional parameter, e.g.:
size_t* linearSearch
(
int* array,
size_t number, // of elements in the array
int value // to search for
);
Similarly you need to return the number of occurrences of the searched value by some means. There are several options for:
Turn num into a reference (size_t& num), then you can modify it inside the function and the change gets visible outside. Usage of the function get's a bit inconvenient, though, as you need to explicitly define a variable for:
size_t num = sizeof(array)/sizeof(*array);
auto occurrences = linearSearch(array, num, 7);
Append a sentinel value to the array, which might be the array size or probably better maximum value for size_t – with all the disadvantages you have with C strings as well (mainly having to iterate over the result array to detect the number of occurences).
Prepend the number of occurrences to the array – somehow ugly as well as you mix different kind of information into one and the same array.
Return result pointer and size in a custom struct of yours or in e.g. a std::pair<size_t, size_t*>. You could even use that in a structured binding expression when calling the function:
auto [num, occurences] = linearSearch(array, sizeof(array)/sizeof(*array), 7);
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// here the trick yet works provided the array is declared above the call, too,
// as is in your example
Option 4 would be my personal recommendation out of these.
Side note: I switched to size_t for return values as negative indices into an array are meaningless anyway (unless you intend to use these as sentinel values, e. g. -1 for end of occurrences in option 2).
I have defined:
const vector<vector<int>> *ElementLines::Quad4 = new vector<vector<int>>
{
{ 0, 1 },
{ 1, 2 },
{ 2, 3 },
{ 3, 0 }
};
Later on, I want to iterate over that collection, to which an object is pointing:
for (int j = 0; j < e->LinesIndices->size(); j++)
{
int n1Index = e->LinesIndices[j][0]; //I expect 0 (for j = 0)
int n2Index = e->LinesIndices[j][1]; //I expect 1 (for j= 0)
}
The code above won't compile:
no suitable conversion function from "const std::vector<int, std::allocator<int>>" to "int" exists
But if I add LinesIndices[j][0][0] it indeed delivers an int. I don't quite understand what is happening here. To access a vector I just use one pair of square brackets [i], is it different for this nested vector of vectors? (I would expect to be able accessing the contents by using two pairs of square brackets).
Your code is not compiling because your e->LinesIndices is a vector<vector<int>>* (i.e. a pointer).
In C++, as in C, you can use array notation on pointers—a[index] is equivalent to *(a + index). If your pointer pointed to the first element of an array, that is exactly how you would use that array. Unfortunately for you, you only have a single vector allocated via new. Accessing that pointer via e->LinesIndices[j] is a Very Bad Thing if j is not 0 (because you access a vector where there is no actual vector).
There is two ways to fix this. If you really want to keep your vector on the heap, allocated via new (I hope you delete it at some point!), you could dereference the pointer before accessing it:
for (int j = 0; j < e->LinesIndices->size(); j++)
{
int n1Index = (*e->LinesIndices)[j][0];
int n2Index = e->LinesIndices[0][j][1]; // This would work too, but I wouldn't recommend it
}
However, the data in your vector is already on the heap. Allocating a std::vector via new is something that is—in my personal experience—very rarely necessary, and if it is not necessary for you to have a pointer here (which will heavily depend on the context you use it in), I would suggest directly creating the vector (with no pointer). If you choose this method, you will need to use e->LinesIndices.size() instead of e->LinesIndices->size().
I'm still quite inexperienced in C++ and i'm trying to write sum code to add numbers precisely. This is a dll plugin for some finite difference software and the code is called several million times during a run. I want to write a function where any number of arguments can be passed in and the sum will be returned. My code looks like:
#include <cstdarg>
double SumFunction(int numArgs, ...){ // this allows me to pass any number
// of arguments to my function.
va_list args;
va_start(args,numArgs); //necessary prerequisites for using cstdarg
double myarray[10];
for (int i = 0; i < numArgs; i++) {
myarray[i] = va_arg(args,double);
} // I imagine this is sloppy code; however i cannot create
// myarray{numArgs] because numArgs is not a const int.
sum(myarray); // The actual method of addition is not relevant here, but
//for more complicated methods, I need to put the summation
// terms in a list.
vector<double> vec(numArgs); // instead, place all values in a vector
for (int i = 0; i < numArgs; i++) {
vec.at(i) = va_arg(args,double);
}
sum(vec); //This would be passed by reference, of course. The function sum
// doesn't actually exist, it would all be contained within the
// current function. This is method is twice as slow as placing
//all the values in the static array.
double *vec;
vec = new double[numArgs];
for (int i = 0; i < (numArgs); i++) {
vec[i] = va_arg(args,double);
}
sum(vec); // Again half of the speed of using a standard array and
// increasing in magnitude for every extra dynamic array!
delete[] vec;
va_end(args);
}
So the problem I have is that using an oversized static array is sloppy programming, but using either a vector or a dynamic array slows the program down considerably. So I really don't know what to do. Can anyone help, please?
One way to speed the code up (at the cost of making it more complicated) is to reuse a dynamic array or vector between calls, then you will avoid incurring the overhead of memory allocation and deallocation each time you call the function.
For example declare these variables outside your function either as global variables or as member variables inside some class. I'll just make them globals for ease of explanation:
double* sumArray = NULL;
int sumArraySize = 0;
In your SumFunction, check if the array exists and if not allocate it, and resize if necessary:
double SumFunction(int numArgs, ...){ // this allows me to pass any number
// of arguments to my function.
va_list args;
va_start(args,numArgs); //necessary prerequisites for using cstdarg
// if the array has already been allocated, check if it is large enough and delete if not:
if((sumArray != NULL) && (numArgs > sumArraySize))
{
delete[] sumArray;
sumArray = NULL;
}
// allocate the array, but only if necessary:
if(sumArray == NULL)
{
sumArray = new double[numArgs];
sumArraySize = numArgs;
}
double *vec = sumArray; // set to your array, reusable between calls
for (int i = 0; i < (numArgs); i++) {
vec[i] = va_arg(args,double);
}
sum(vec, numArgs); // you will need to pass the array size
va_end(args);
// note no array deallocation
}
The catch is that you need to remember to deallocate the array at some point by calling a function similar to this (like I said, you pay for speed with extra complexity):
void freeSumArray()
{
if(sumArray != NULL)
{
delete[] sumArray;
sumArray = NULL;
sumArraySize = 0;
}
}
You can take a similar (and simpler/cleaner) approach with a vector, allocate it the first time if it doesn't already exist, or call resize() on it with numArgs if it does.
When using a std::vector the optimizer must consider that relocation is possible and this introduces an extra indirection.
In other words the code for
v[index] += value;
where v is for example a std::vector<int> is expanded to
int *p = v._begin + index;
*p += value;
i.e. from vector you need first to get the field _begin (that contains where the content starts in memory), then apply the index, and then dereference to get the value and mutate it.
If the code performing the computation on the elements of the vector in a loop calls any unknown non-inlined code, the optimizer is forced to assume that unknown code may mutate the _begin field of the vector and this will require doing the two-steps indirection for each element.
(NOTE: that the vector is passed with a cost std::vector<T>& reference is totally irrelevant: a const reference doesn't mean that the vector is const but simply puts a limitation on what operations are permitted using that reference; external code could have a non-const reference to access the vector and constness can also be legally casted away... constness of references is basically ignored by the optimizer).
One way to remove this extra lookup (if you know that the vector is not being resized during the computation) is to cache this address in a local and use that instead of the vector operator [] to access the element:
int *p = &v[0];
for (int i=0,n=v.size(); i<n; i++) {
/// use p[i] instead of v[i]
}
This will generate code that is almost as efficient as a static array because, given that the address of p is not published, nothing in the body of the loop can change it and the value p can be assumed constant (something that cannot be done for v._begin as the optimizer cannot know if someone else knows the address of _begin).
I'm saying "almost" because a static array only requires indexing, while using a dynamically allocated area requires "base + indexing" access; most CPUs however provide this kind of memory access at no extra cost. Moreover if you're processing elements in sequence the indexing addressing becomes just a sequential memory access but only if you can assume the start address constant (i.e. not in the case of std::vector<T>::operator[]).
Assuming that the "max storage ever needed" is in the order of 10-50, I'd say using a local array is perfectly fine.
Using vector<T> will use 3 * sizeof(*T) (at least) to track the contents of the vector. So if we compare that to an array of double arr[10];, then that's 7 elements more on the stack of equal size (or 8.5 in 32-bit build). But you also need a call to new, which takes a size argument. So that takes up AT LEAST one, more likely 2-3 elements of stackspace, and the implementation of new is quite possibly not straightforward, so further calls are needed, which take up further stack-space.
If you "don't know" the number of elements, and need to cope with quite large numbers of elements, then using a hybrid solution, where you have a small stack-based local array, and if numargs > small_size use vector, and then pass vec.data() to the function sum.
Ok, so I was getting some pretty off course answers so I thought I would edit this post and add the notes from the textbook for clarity:
Sometimes, the number of elements in the array might be less than the size of the array. For example, the number of elements in an array storing student data might increase or decrease as students drop or add courses. In such situations, we want to process only the components of the array that hold actual data. To write a function to process such arrays, in addition to declaring an array as a formal parameter, we declare another formal parameter specifying the number of elements in the array, as in the following function:
void initialize(int list[], int listSize)
{
int count;
for (count = 0; count < listSize; count++)
list[count] = 0;
}
The first parameter of the function initialize is an int array of any size. When the function initialize is called, the size of the actual array is passed as the second parameter of the function initialize.
Ok, now that I posted the entire example with textbook notes in it, my confusion is why they set the array to zero. The notes give me the impression that this function is allowing a user to use the array for any size that they wish because the size is set to zero which (I am guessing here) allows the user to pick any size array they want? and it will just reset every time back to zero so if you need more or less units for the next time, it will be default to zero so you can fill it again?
you said:
I know the function initialize is used to determine the value of the
array list by passing the value of the array to listsize
no. it's not true. this function is not to determine something but to INITIALIZE all the array (up to listsize index, btw: it might be dangerous since you can pass listsize greater than this list size in fact) with 0.
and
by passing the value of the array to listsize
no! listsize is here not the value of element, it is array size, look at "for" loop #Jason xD.
have you tried to call this function on some array with some listsize?
If your code was properly formatted, it might be more apparent that the statement list[count] = 0; gets executed each time through your for loop.
That is, it sets an element to zero each time through the loop. The result is that after the loop is complete, all elements in the array will be set to zero.
If you are talking about the "count = 0", then:
The more usual syntax is:
for(int blah = 0; blah < max; blah++)
But there's no reason why 'blah' has to be declared inside the for() statement itself:
int blah;
for(blah = 0; blah < max; blah++)
...is also acceptable.
Or:
int blah = 0;
for( ; blah < max; blah++)
Sometimes (but not in your example) it's desired to have 'blah' exist beyond the scope of the for() statement, so you can do something with it afterward:
int fileNum = 0;
for( ; fileNum < maxFiles && file_exists(fileNum); fileNum++)
{
//...do something...
}
int lastFileWas = fileNum; //Either it's 'maxFile', or the first file that didn't exist.
Another reason for putting variables outside of the for() statement, is when variables are really really large, and it would make the code easier to read if it's outside of the statement:
std::vector< std::pair<std::string, int> >::iterator myIterator = myVector.begin();
for( ; myIterator != myVector.end(); myIterator++)
This would be very messy if it was inside the for-statement itself (std::vector< std::pair >::iterator is a very long variable name to write out that would be messy to cram into a for() statement). (Though this is less a problem with C++11's 'auto' keyword).
If you are talking about the "list[count] = 0;", then:
With arrays, to assign a value, you "index into" the array using the square brackets (called the 'subscript operator'), and you can access individual variables (called 'elements') held in the memory of the array:
int myArray[10]; //10 integers in a block of memory.
myArray[0] = 5; //Accessing the first element in the block of memory.
myArray[3] = 17; //Accessing the fourth element in the block of memory.
In general:
Since you are using C++, you usually (90% of the time) would be better off using a std::vector. Arrays are rather odd, because they are very similar to pointers to blocks of memory, and can't be treated like regular variables. A std::vector, aside from many other benefits, wraps the array so you can treat it like a regular variable (because a vector is one).
Another quick way of accomplishing the same thing:
memset(list, 0, sizeof(int)*listSize);
This gets the whole block of memory allocated to list by calculating the size of the data type times the number of elements and setting it all to 0.
It is doing what it says, it is initializing. In this case the method is just setting every element of list to 0. It is probably more clear if you add braces:
for (count = 0; count < listSize; count++)
{
list[count] = 0;
}
So based on your updated post, the book's description is saying 1) You may not want to process the whole array because only a portion of it may have valid data 2) In order to write functions to process arrays that behave this way, functions that process these array's must not only take the array as a parameter but also the number of valid elements. 3) We are going to provide an example function initialize which follows the rules we just described BUT nothing in the text actually speaks to end result of initialize.
My above description as well as the other posts provide an accurate description of initialize.
I am attempting to write a template/class that has a few functions, but I'm running into what seems like a rather newbie problem. I have a simple insert function and a display values function, however whenever I attempt to display the value, I always receive what looks like a memory address(but I have no idea), but I would like to receive the value stored (in this particular example, the int 2). I'm not sure how to dereference that to a value, or if I'm just completely messing up. I know that vectors are a better alternative, however I need to use an array in this implementation - and honestly I would like to gain a more thorough understanding of the code and what's going on. Any help as to how to accomplish this task would be greatly appreciated.
Example Output (running the program in the same way every time):
003358C0
001A58C0
007158C0
Code:
#include <iostream>
using namespace std;
template <typename Comparable>
class Collection
{
public: Collection() {
currentSize = 0;
count = 0;
}
Comparable * values;
int currentSize; // internal counter for the number of elements stored
void insert(Comparable value) {
currentSize++;
// temparray below is used as a way to increase the size of the
// values array each time the insert function is called
Comparable * temparray = new Comparable[currentSize];
memcpy(temparray,values,sizeof values);
// Not sure if the commented section below is necessary,
// but either way it doesn't run the way I intended
temparray[currentSize/* * (sizeof Comparable) */] = value;
values = temparray;
}
void displayValues() {
for (int i = 0; i < currentSize; i++) {
cout << values[i] << endl;
}
}
};
int main()
{
Collection<int> test;
int inserter = 2;
test.insert(inserter);
test.displayValues();
cin.get();
return 0;
}
Well, if you insist, you can write and debug your own limited version of std::vector.
First, don't memcpy from an uninitialized pointer. Set values to new Comparable[0] in the constructor.
Second, memcpy the right number of bytes: (currentSize-1)*sizeof(Comparable).
Third, don't memcpy at all. That assumes that Comparable types can all be copied byte-by-byte, which is a severe limitation in C++. Instead:
EDIT: changed uninitialized_copy to copy:
std::copy(values, values + currentSize - 1, temparray);
Fourth, delete the old array when it's no longer in use:
delete [] values;
Fifth, unless the code is going to make very few insertions, expand the array by more than one. std::vector typically increases its size by a factor of 1.5.
Sixth, don't increment currentSize until the size changes. That will change all those currentSize-1s into currentSize, which is much less annoying. <g>
Seventh, an array of size N has indices from 0 to N-1, so the top element of the new array is at currentSize - 1, not currentSize.
Eighth, did I mention, you really should use std::vector.
This line is wrong:
memcpy(temparray,values,sizeof values);
The first time this line is run, the values pointer is uninitialized, so it will cause undefined behavior. Additionally, using sizeof values is wrong since that will always give the size of a pointer.
Another issue:
temparray[currentSize] = value;
This will also cause undefined bahavior because you have only allocated currentSize items in temparray, so you can only access indices 0 to currentSize-1.
There is also an error in your array access.
temparray[currentSize/* * (sizeof Comparable) */] = value;
Remember that arrays start at index zero. So for an array of length 1, you would set temparray[0] = value. Since you increment currentSize at the top of the insert function, you will need to do this instead:
temparray[currentSize-1] = value;