use of 'n' before deduction of 'auto' C++ - c++

I'm trying to have my function return 3 values (n, down and across) I've read online how 'auto' can be used but must be doing something wrong.
The function takes in a 2D vector of integers (as well as other variables) and checks for how many numbers are connected to board[0][0] such that they are the same number.
I've tried putting auto in front of the function inside the function itself, tried leaving it blank, tried just having chain = chainNodes(...) but I always seem to get an error. Here's the code:
tuple<int, int, int> chainNodes(vector<vector<int>> board, int originalNum,
unsigned int across, unsigned int down, int ijSum,
int n)
{
struct chain {
int n, down, across;
};
if(down + across > ijSum) {
ijSum = down + across;
} else if((down + across == ijSum) &&
((down - across) * (down - across) < (ijSum) * (ijSum))) {
ijSum = down + across;
}
board[down][across] = 0;
n += 1;
// Check below
if((down != (board.size() - 1)) && (board[down + 1][across]) == originalNum) {
down += 1;
auto [n, iPoint, jPoint] = chainNodes(board, originalNum, across, down, ijSum, n);
down -= 1;
}
// Check right, up and left (I've removed so its not too messy here)
return chain{n, down, across};
}
Sorry, I forgot to include the error message.
error: use of 'n' before deduction of 'auto'
It occurs on the line that uses auto.

Issue with
auto [n, iPoint, jPoint] = chainNodes(board, originalNum, across, down, ijSum, n);
is similar to
auto n = foo(n); // `foo(n)` uses `n` from `auto n`,
// not the one from outer scope as function parameter
The construct int a = a + 1; is legal but lead to UB as reading uninitialized variable.
That kind of construct allows legal and valid behavior void* p = &p;.
Your code has other errors and it is not clear for me expected behavior of the function.
So not sure if following is the correct fix, but you might want:
n = std::get<0>(chainNodes(board, originalNum, across, down, ijSum, n));

Related

Initializing An Array with a Variable Size

I am almost done with my code except I need help on two thing. Here is my code: Code. For the function below, I am trying to make it so that I can use the input of "n" to initialize my array, myBits, instead of a constant, which is currently 5.
My Other question is right below that. I am trying to switch all of the right most bits to "true". I wrote the for loop in "/* .....*/" but it doesn't seem to be working. Right above it, I do it long ways for C(5,4) ....(myBit[0] = myBit[1]....etc...... (I am using this to find r-combinations of strings).... and it seems to work. Any help would be appreciated!!
void nCombination(const vector<string> &Vect, int n, int r){
bool myBits[5] = { false }; // everything is false now
myBits[1] = myBits[2] = myBits[3] = myBits[4] = true;
/* for(int b = n - r - 1; b = n - 1; b++){
myBits[b] = true; // I am trying to set the r rightmost bits to true
}
*/
do // start combination generator
{
printVector(Vect, myBits, n);
} while (next_permutation(myBits, myBits + n)); // change the bit pattern
}
These are called variable length arrays (or VLAs for short) and they are not a feature of standard C++. This is because we already have arrays that can change their length how ever they want: std::vector. Use that instead of an array and it will work.
Use std::vector<bool>:
std::vector<bool> myBits(n, false);
Then you have to change your while statement:
while (next_permutation(myBits.begin(), myBits.end()));
You will also have to change your printVector function to take a vector<bool>& as the second argument (you won't need the last argument, n, since a vector knows its own size by utilizing the vector::size() function).
As to your program: If you're attempting to get the combination of n things taken r at a time, you will need to write a loop that initializes the last right r bools to true instead of hard-coding the rightmost 4 entries.
int count = 1;
for (size_t i = n-1; i >= 0 && count <= r; --i, ++count)
myBits[i] = true;
Also, you should return immediately from the function if r is 0.

Copying arrays via pointers in C++

I've never programmed in C++ before and I'm trying to figure out how to recursively pass segments of an array in a C++ method. I am trying to convert the following pseudo code into C++.
SlowSort(A[1...n])
if n = 2
if A[1] > A[2]
Swap(A[1], A[2])
else if n > 2
SlowSort(A[1...(2n/3)])
SlowSort(A[(n/3+1)... n])
SlowSort(A[1...(2n/3)])
The recursive calls are the bits I'm having a problem with. I was thinking about creating two new arrays that point to the wanted locations but don't know how to go about that, specifically doing that and defining the length of the array. I've tried googling it and searching this site, but there doesn't seem to be anything, that I understand, on it. Also, in case I fudged up somewhere in my code, here's what I have for the first bit.
int SlowSort(int A[])
{
int length = (sizeof(A)/sizeof(*A));
if(length ==2)
{
if(A[0] > A[1])
{
int temp = A[0];
A[0] = A[1];
A[1] = temp;
}
}
In short, how do In covert the else if statement into C++? Explanation would be nice too.
Thanks
You will want to pass indices into the array instead, and use those.
void SlowSort(int A[], int left, int right)
{
if (right - left == 2)
if (A[left] > A[right])
Swap(A[left], A[right]);
else
{
int n = right - left + 1;
SlowSort(A, left, 2 * n / 3);
SlowSort(A, left + n / 3 + 1, right);
SlowSort(A, left, left + 2* n / 3);
}
The above code might not be correct regarding what the algorithm is supposed to do, but you get the idea I'm trying to describe. The thing is: you don't make a copy of the array. Instead, pass the same array always and the range (i.e. the indices) you are sorting.
You simply pass required pointer using the pointer arithmetic. For example the following pseudo code
SlowSort(A[(n/3+1)... n])
could be written as
SlowSort( A + n/3+1, n - n/3 - 1 );
So the function could be declared as
void SlowSort( int A[], size_t n );
As for this code snippet
int SlowSort(int A[])
{
int length = (sizeof(A)/sizeof(*A));
then it is invalid because array is implicitly converted to a ponter to its first element when it is passed as an argument to a function seclared such a way. So the value of length will not be equal to the number of elements.
This is pretty simple. Since arrays are just consecutive pointers. If you have a method:
Your code would look like this:
void slowSort(int[] array, int length)
{
if(length == 2)
{
if(array[0] > array[1])
{
int temp = array[0];
array[0] = array[1];
array[1] = temp;
}
}
else
{
slowSort(&array[0], (2 * length) / 3 - 1);
slowSort(&array[length / 3], length - (length / 3 - 1));
slowSort(&array[0], (2 * length) / 3 - 1);
}
}
The trick I use here is that I pass the pointer of the element I want to start with and the pass the end point.
This works because when you pass an array in C++ you just pass the pointer of the first element. Here I pass a custom pointer of the array.
The modern C++ way to do this would be to pass iterators to the beginning and one-past-the-end of the range. In this case, the iterators are pointers.
void SlowSort(int* begin, int* end)
{
unsigned length = end-begin;
if(length == 2)
{
if(begin[0] > begin[1])
{
std::swap( begin[0], begin[1] );
}
} else if(length>2) {
SlowSort(begin, begin+2*length/3);
SlowSort(begin+length/3, end);
SlowSort(begin, begin+2*length/3);
}
}
then, for the case of working with an entire array:
template<unsigned N>
void SlowSort( int(&Arr)[N] ) {
return SlowSort( Arr, Arr+N );
}
we dispatch it to the iterator version, relying on decaying of array-to-pointer. This has to be a template function, as we want it to work with multiple different array sizes.
Note that an int Arr[] is not an array. It is a different way to say int* Arr, left over as a legacy from C. In fact, as a parameter to a function, saying void foo( int A[27] ) results in void foo( int* A ): function parameters cannot be arrays.
They can, however, be references-to-arrays, which is what the above template function uses.

C++ puttting one element of vector to another vector

I am working on a RTS game using SDL. I have a woodyard class whose object will collect wood from nearby trees. In the class I create a vector called temp_trees and as an argument for the constructor I use a vector of tree objects that I pass in.
The woodyard constructor:
woodyard::woodyard(int x, int y, int HP, int id, vector<Tree> trees)
{
...
vector<Tree> temp_trees;
for(int i = 0; i < trees.size(); i++)
{
if((trees[i].xPos - 100) / 50 >= x - 5 && (trees[i].xPos - 100) / 50 <= x + 4)
{
if((trees[i].yPos - 100) / 50 >= y - 5 && (trees[i].yPos - 100) / 50 <= y + 4)
{
temp_trees.push_back(trees[i]);
}
}
}
collect_control = 0;
no = 0;
}
the collect_wood function:
void woodyard::collect_wood(){
if(no == 5)
{
temp_trees[collect_control].drewno -= 1;
if(temp_trees[collect_control].drewno <= 0){
collect_control++;
temp_trees.erase(temp_trees.begin());
}}
no++;
if(no >= 10){
no = 0;
}}
The program crashes just after start.
Can anybody see any errors in this code??
PS: I suppose that there might be something wrong with copping elements from one vector to another in the constructor.
The constructor doesn't contain any illegal operation.
And collect_wood(), although unintelligible, doesn't contain any obvious reason for making it crash.
Which is the value of collect_control? Do you check if it is < temp_trees.size()? Being aware that temp_trees.size() keep changing since you are erasing elements.
Probably collect_control shouldn't be incremented after the erase: all elements shift back, and collect_control after the erase is already pointing to the next element.
Note: Consider that temp_trees.erase(temp_trees.begin()); is one of the most inefficient things you could do with a vector (deleting the first element).
In the woodyard constructor, you are declaring a temporary, function-scoped variable "temp_trees".
woodyard::woodyard(int x, int y, int HP, int id, vector<Tree> trees)
{
...
vector<Tree> temp_trees;
If you have a vector member called temp_trees, this declaration is hiding it. So your member function is NOT seeing the same vector:
void woodyard::collect_wood(){
if(no == 5)
{
temp_trees[collect_control].drewno -= 1;
Also, without seeing the rest of the code, I wouldn't know how you are ensuring that there are at least "collect_control" members in the vector.
#include <assert.h>
...
assert(collect_control < temp_trees.size());
or if you're using visual studio you can do
if(collect_control >= temp_trees.size())
DebugBreak();
"size()" is a 1-based value but array index operators are zero based. That means, when there is one entry in the vector, it will be vector[0]. If the vector is empty, vector[0] is illegal - it does not exist. And emptiness is denoted by size being 0. size must always be greater than the element index you are trying to access.

Segfault working with vectors of type bool

I'm trying to solve a programming puzzle and running up against some difficulty. It's similar to Project Euler problem 215 but with blocks of width 3 and 4.5. Anyway, I initially approached it by brute forcing the combinations in C, but am trying to speed up the runtime by just calculating all the combinations in the first row and seeing how many valid ways there are to combine them and then going from there. I figured it'd be easier to do this working with vectors of booleans (tried bitsets but I can't use them since I don't have the width available at compile-time), but I'm not that experienced working with vectors and I've done something to make the segfault gods angry. I just can't see where.
I'm getting segmentation fault 11 when I feed the program arguments, so it's definitely something I did, and when I run a backtrace in GDB I get the following:
#0 0x0000000100002645 in std::_Bit_reference::operator= ()
#1 0x0000000100001be2 in build ()
#2 0x0000000100002287 in main ()
I know there's just got to be something I'm not seeing. It only happens when build() actually gets called, but I'm including main() just in case I might have done something wrong with the call.
#include <vector>
void build(std::vector<std::vector<bool> > possibilities, std::vector<bool> current, float width)
{
if(current.size() > 0)
{
if(current.size() > width) return; // If we went over the specified width, bail out-invalid
if (current.size() == width) // If we just matched the width for this row, push it on to our vector of possibilities
{
possibilities.push_back(current);
return;
}
}
// Try adding a block of length 3 and a block of length 4.5
std::vector<bool> branch1;
std::vector<bool> branch2;
if(current.size() > 0)
{
branch1.assign( current.begin(), current.end() );
branch2.assign( current.begin(), current.end() );
branch1[ current.size() + 5 ] = 1;
branch2[ current.size() + 8 ] = 1;
}
else
{
branch1[5] = 1;
branch2[8] = 1;
}
// Split off and check both branches
build(possibilities, branch1, width);
build(possibilities, branch2, width);
}
int main( int argc, char *argv[] )
{
if ( argc == 3 ) // Number of arguments should be 3-the program name, plus our width and height
{
float width = (atof(argv[1]) * 2); // Width is assumed to be entered first, converting to integer
int height = atoi(argv[2]); // The second argument should be height, ditto above
if ( (width < 3) || (height < 1) ) // Catches non-number inputs (atof/i returns 0) and invalid entries
{
printf("Expected two numeric arguments, width and height, in that order.");
}
else // Continue the program
{
std::vector<bool> noo;
std::vector<std::vector<bool> > possibilities;
build(possibilities, noo, width);
printf("%llu", (unsigned long long)possibilities.size());
}
}
else
{
printf("Expected two numeric arguments, width and height, in that order.");
}
}
Your noo vector:
std::vector<bool> noo;
Which is the second argument of build:
build(possibilities, noo, width);
Is empty. However, inside build, you perform some actions based on the size of that vector:
std::vector<bool> branch1;
std::vector<bool> branch2;
if(current.size() > 0) //current is actually noo
{
branch1.assign( current.begin(), current.end() );
branch2.assign( current.begin(), current.end() );
branch1[ current.size() + 5 ] = 1;
branch2[ current.size() + 8 ] = 1;
}
else
{
branch1[5] = 1;
branch2[8] = 1;
}
Since it is empty, you'll be accessing positions 5 and 8 of vectors branch1 and branch2(which are also empty), leading to undefined behaviour.
You should somehow resize branch1 and branch2 so that you don't perform an out-of-bounds access.
This way:
std::vector<bool> branch1(someNumber);
Will do it, but you should have a look at your code's logic, there surely is something else wrong. Moreover, you're passing arguments by value, so you're making unnecessary copies, and you won't see the modifications made to the possibilities vector from main.

c++ method sometimes returns unexpected high values

I've traced a bug down to a function which should be returning float values between 20 and 100 or so, but is sometimes (1 time in 10) returning values much much higher than that. The problem exists when I have an expression in the last line of the method, like this:
return snap(baseNumber, targets) + (octave * NOTES_PER_OCTAVE);
If I store the return value in a variable first, then return that variable, the problem goes away:
float ret = snap(baseNumber, targets) + (octave * NOTES_PER_OCTAVE);
return ret;
Here's the complete method:
static inline float octaveSnap(float number, std::vector<float>* targets){
static const int NOTES_PER_OCTAVE = 12;
int octave = number / NOTES_PER_OCTAVE;
float baseNumber = number - (octave * NOTES_PER_OCTAVE);
float ret = snap(baseNumber, targets) + (octave * NOTES_PER_OCTAVE);
return ret;
}
and here's 'snap':
// given a single value and a list of values (a scale), return the member of the list which is closest to the single value
static inline float snap(float number, std::vector<float>* targets){
float ret;
float leastDistance = -1;
for(int i = 0; i<targets->size(); i++){
float distance = targets->at(i) - number;
if(distance < 0){
distance = -distance;
}
if(leastDistance == -1){
leastDistance = distance;
}
if(distance < leastDistance){
leastDistance = distance;
ret = targets->at(i);
}
}
return ret;
}
I'm completely baffled by this. Any idea why the first explodes and the second works perfectly?
My psychic debugging powers tell me that when you use the temp variable the problem only appears to go away and that either you're accidentally doing targets[<foo>] inside snap or you use it correctly but rarely run off the end, returning garbage.
EDIT for comment:
I should elaborate a bit: targets is a pointer to vector so using [] on it will select one of several vectors, NOT elements from the vector. That said I can't understand how you could call .at on such a pointer, so I suspect the code in your program is not the code you showed us.
In snap() the local variable ret is never initialized so if the input vector is either zero-sized or the "found" element is the first one then your return value is unspecified.
Try modifying snap to be:
static inline float snap(float number, std::vector<float>* targets){
float ret = 0;
float leastDistance = -1;
for(int i = 0; i<targets->size(); i++){
float distance = targets->at(i) - number;
if(distance < 0){
distance = -distance;
}
if(leastDistance == -1){
leastDistance = distance;
ret = targets->at(i);
}
else if(distance < leastDistance){
leastDistance = distance;
ret = targets->at(i);
}
}
return ret;
}
and see if that fixes things.
Edit: I realized this doesn't address why adding a temporary variable appears to fix things in the original question. The uninitialized ret will probably take on whatever value is left on the stack: this, of course, is unspecified and system/platform dependent. When a new local variable is added to store the result of snap(), however, this shifts the stack such that ret has a different position, most likely, a different uninitialized value. The return result is still "wrong" but it may simply appear "less wrong" due to whatever uninitialized value ret has.