In the following function I clearly change the variable rightArray through the statement: rightArray[i] = dataValues[i];
However the behaviour I'm getting from the function is that the variable leftArray is changing in place of rightArray
//Returns the interquartile range
float StatisticalAnalyser::getInterquartileRange()
{
float interquartileRange = 0;
int numberOfDatums = dataFile.findNumberOfDatums();
float numberOfDatumsFloat = dataFile.findNumberOfDatums();
float dataValues[dataFile.findNumberOfDatums()];
dataFile.initialiseArrayToFileData(dataValues);
//If even number of datums
if (numberOfDatums % 2 == 0)
{
//Arrays for for each side of the median
int arraySize = numberOfDatumsFloat/2;
float leftArray[numberOfDatums/2];
float rightArray[numberOfDatums/2];
//Initialise arrays for each side of the median
for (int i = 0; i < numberOfDatums; i++)
{
if (i < numberOfDatums/2)
{
leftArray[i] = dataValues[i];
}
if (i >= numberOfDatums/2)
{
//leftArray SOMEHOW GETS CHANGED INSTEAD OF RIGHT ARRAY
rightArray[i] = dataValues[i];
leftArray gets changed instead of rightArray here: rightArray[i] = dataValues[i];
}
}
}
if (numberOfDatums % 2 == 0.5)
{
//Not relevant, isn't triggered when problem occurs
}
return interquartileRange;
}
I am running Xcode 10.1, and want to know how to fix this error so that rightArray is changed by the function instead of leftArray.
Having
float leftArray[numberOfDatums/2];
float rightArray[numberOfDatums/2];
in
if (i >= numberOfDatums/2)
{
//leftArray SOMEHOW GETS CHANGED INSTEAD OF RIGHT ARRAY
rightArray[i] = dataValues[i];
you go out of rightArray and randomly write in leftArray (of course this is an undefined behavior)
must be
if (i >= numberOfDatums/2)
{
rightArray[i - numberOfDatums/2] = dataValues[i];
Furthermore, to have
if (i < numberOfDatums/2)
{
...
}
if (i >= numberOfDatums/2)
with i unchanged is useless, the second if can be an else, but it is also better to do two for to not have to do numberOfDatums/2 all the times just to decide which array to use.
Related
I have a list of 'cell' objects in a 2d array of length [sizeX][sizeY]. These Cell objects contain an array of type *Cell, which should point to each of the given cell's adjacent cells in the format North, East, South, West (Never Eat Soggy Waffles).
This array is called compass, and is defined with a length of 4. After the cells have been initialized (at which time all values of compass are set to nullptr), I have a loop which attempts to fill Cell.compass with pointers to the appropriate nearby cells.
However, I have found that despite all this, in each cell I have found that compass still is full of null values.
In this loop, I also run a function Cell::computeTopology() which populates a vector (which is a property of Cell) of the valid non-null indexes of compass. This is similarly empty.
I have made a breakpoint both before and after this function has been called to the exact same effect. Regardless I will include this function as well. I'm utterly perplexed and some help here would be greatly appreciated.
Problem area:
const int sizeX = SCREEN_WIDTH / SCALE;
const int sizeY = SCREEN_HEIGHT / SCALE;
Cell cells[sizeX][sizeY];
for (int x = 0; x < sizeX; x++){
for (int y = 0; y < sizeY; y++){
cells[x][y].setPos(x, y);
cells[x][y] = Cell();
//cells[x][y].setColor(rand() % 255, rand() % 255, rand() % 255);
}
}
for (int x = 0; x < sizeX; x++) {
for (int y = 0; y < sizeY; y++) {
Cell c = cells[x][y];
if (x - 1 >= 0) {
c.compass[3] = &cells[x - 1][y];
}
if (x + 1 < (SCREEN_WIDTH / SCALE)) {
c.compass[1] = &cells[x + 1][y];
}
if (y - 1 >= 0) {
c.compass[0] = &cells[x][y - 1];
}
if (y + 1 < (SCREEN_HEIGHT / SCALE)) {
c.compass[2] = &cells[x][y + 1];
}
c.computeTopology();
}
}
And the computeTopology() function
void Cell::computeTopology()
{
int i = 0;
for (Cell *c : compass) {
if (c != nullptr) {
notNull.push_back(i);
i++;
}
}
}
Change
Cell c = cells[x][y]; // make a copy
to
Cell& c = cells[x][y];
you want to modify item of array, not copy.
Another issue
cells[x][y].setPos(x, y);
cells[x][y] = Cell(); // ?
you are setting some members of cells[x][y] by calling setPos and after it you are overwriting cells[x][y] by default constructed Cell object. I think the second line in above code should be removed.
Your words
which populates a vector (which is a property of Cell) of the valid
non-null indexes of compass
so i index should be advanced with every iteration of for loop:
int i = 0;
for (Cell *c : compass) {
if (c != nullptr) {
notNull.push_back(i);
}
++i; // moved
}
I have to write a program that takes in a Sudoku square(with all slots filled) and randomly assigns 25 blanks to be filled in. This is what I have so far but because this code has the chance to generate the same position in the array more than once I'm getting a varying number of blanks(17-21). I'm wondering if there is a simple way to get it to output 25 blanks no matter what. My print function inserts a blank if the value is zero at any spot in the array.
void insertBlanks(int square[9][9])
{
srand(time(NULL));
int i = 0;
while(i < 25)
{
int tempOne = rand() % 9;
int tempTwo = rand() % 9;
square[tempOne][tempTwo] = 0;
i = i + 1;
}
}
You should check if a 0 is already there.
if(square[tempOne][tempTwo] != 0)
{
square[tempOne][tempTwo] = 0;
i = i + 1;
}
Basically, I have a 6x6 board. I created a function that's supposed to place three X's on random coordinates on the board.
const int size = 6;
char board[6][6] = {0}; //this is actually somewhere else, but I included it here for clarity
char enemies[3] = {'X','X','X'};
void setup(char board[6][6]){
bool valid = false; //sets initial bool value to false
for (int x = 0; x <= 2; ++x){
do{
int a = rand() % size;
int b = rand() % size;
if (board[a][b] == 0){
board[a][b] = enemies[x];
valid = true;
}
}while(!valid); //if the value is false, redo until an empty board space is found
}
(I included srand(time(NULL)) in the main function as well)
It works, but only sometimes. Sometimes it generates 3 randomly placed X's, and sometimes only 2. I want it to generate 3 every single time. I have been over it a million times, trying minor variations and corrections, but I can't seem to figure out what's wrong. I included a condition for it to only place enemies[x] if the board is blank (board[a][b] == 0), and yet it sometimes only places 2 X's for some reason.
After the first X is placed, valid remains true for all subsequent iterations of the for loop, even if a valid square hasn't been found.
I changed the iteration variable to i (using x to mean something other than an ordinal when you're using 2d coordinates is just confusing), and fixed your inner retry loop:
for (int i = 0; i <= 2; ++i) {
// loop until we find a valid coordinate
while(true) {
int a = rand() % size;
int b = rand() % size;
if (board[a][b] == 0){
board[a][b] = enemies[i];
break; // we found one!
}
}
}
You are not resetting the valid flag inside the outer loop. So, once you've placed the first piece, you do not correctly handle duplicates.
for (int x = 0; x <= 2; ++x)
{
valid = false; // <-- you forgot to do this.
do
{
int a = rand() % size;
int b = rand() % size;
if (board[a][b] == 0)
{
board[a][b] = enemies[x];
valid = true;
}
} while(!valid);
}
After each run through the do/while loop you need to reset valid. After the first iteration (when x is 0), valid will be set to true. You never reset it back to false, and so on the next iterations (starting with x being 1), valid will be set to true already. This means that you might select a random coordinate that you've already marked and then proceed to the next x anyway.
That means it's entirely possible that only one square will have been marked, but the odds of this are low (1 in 1,225, if my math is correct).
I am trying to solve Project Euler Problem 88, and I did it without too much effort; however, I find that some seemingly irrelevant code in my program is affecting the result. Here's my complete code (it's not short, but I cannot locate the error. I believe it would be obvious to more experienced eyes, so please read my description first):
#include <iostream>
#include <set>
using namespace std;
bool m[24001][12001];
bool p[24001]; // <------------ deleting this line will cause error in result!
long long answer[12001];
int main() {
long long i;
long long j;
long long l;
set<long long> all;
long long s = 0;
for (i = 0; i <= 24000; i++) {
for (j = 0; j <= 12000; j++) {
m[i][j] = false;
}
}
m[1][1] = true;
for (i = 2; i <= 24000; i++) {
m[i][1] = true;
for (j = 2; (j <= i) && (i * j <=24000); j++) {
for (l = 1; l <= i; l++) {
if (m[i][l]) {
m[i * j][l + 1 + (i * j) - i - j] = true;
}
}
}
}
for (i = 0; i <= 24000; i++) {
for (j = 0; j <= 12000; j++) {
if (m[i][j] && (answer[j] == 0)) {
answer[j] = i;
}
}
}
for (i = 2; i <= 12000; i++) {
cout << answer[i] << endl;
all.insert(answer[i]);
}
cout << all.size() << endl;
for (set<long long>::iterator it = all.begin(); it != all.end(); it++) {
//cout << *it << endl;
s += *it;
}
cout << s << endl;
}
With the "useless" bool array, all the answers are right, between 0 and 24000; but without it, some answers in the middle got corrupted and become very large numbers.
I am completely confused now; why would that unused array affect the middle of the answer array?
Thanks and sorry for the long code! I will be grateful if someone could edit the code into a better example, I simply son't know what is with the code.
You do a silly thing in here:
m[i * j][l + 1 + (i * j) - i - j] = true;
Say, i=160, j=150, l=1... You will try to access m[24000][23692]... And you corrupt the stack, so behavior is undefined.
Next time try to use some profiler and/or debugger.
Add:
#include <cassert>
at the begining and
assert( (i * j) * 12001 + (l + 1 + (i * j) - i - j) <= 12001*24001 );
before the following line:
m[i * j][l + 1 + (i * j) - i - j] = true;
The assertion will fail, which means you write outside the bounds of the array m.
As requested, adding this to an answer.
You are definitely writing beyond the bounds of the array m somewhere, when the unused array p exists, m overwrites in to its contents which doesn't affect the answer array but once p is removed the overwriting happens in to answer array showing up the problems.
Overwriting beyond the bounds of the array is an Undefined Behavior and it causes your program to be ill-formed. With Undefined Behavior all safe bets are off and any behavior is possible. While your program may work sometimes or crash sometimes or give incorrect results.Practically, Anything is possible and the behavior may or even may not be explainable.
In one of your nested loops you use l as the index for the second dimension. This variable can run from 0 to i and i, in turn, can run from 0 to 24000. Since your second dimension of the array can only be index from 0 to 12000 this causes a classic out of range error. This also nicely explains why adding an extra array avoid the problem: the out of range accesses go to the "unused" array rather than overwriting the result.
I have started doing some stuff with dynamic allocation in C++ but I had some problems. Here's the code:
nrMare(char cifS[], char* startPos = new char())
{
n = 0;
int i;
cif = startPos;
printf("%p %i\n", cif, (cif - (char*)NULL) % 8);
for(i = strlen(cifS) - 1; i >= 0; i--)
{
cif--;
n++;
cif = new(cif) char(cifS[i] - '0');
}
}
~nrMare()
{
int i;
for(i = 0; i < n; i++)
{
delete(cif);
cif++;
}
n = 0;
cif = 0;
}
nrMare is a class (it comes from bigNumber in Romanian :D) which is supposed to be able to contain the digits of a big number.
The problem is that the destructor (~nrMare) gives a weird error, when I make a variable nrMare something() on my computer, but it works for 116 digits long ones.
Do you have any suggestion or explainations?
EDIT: cif is a (char*) type
EDIT #2: n is the length of the number. I use the char pointer this way because I want to be able to add (like n++; cif--; cif = new(cif) char(number_to_add); -> this would add number_to_add in the left side of cif) and draw elements from both sides.
EDIT #3: this is gonna be a long one... Sorry for being such a bad explainer and thanks for your patience.here are some operators:
void operator-=(nrMare nr2)
{
int i;
for(i = 1; i <= n && i <= nr2.n; i++)
cif[n - i] -= nr2[nr2.n - i];
for(i = n - 1; i >= 0; i--)
{
if(cif[i] < 0)
{
cif[i] += 10;
cif[i - 1]--;
}
}
while(cif[0] == 0)
{
cif++;
n--;
//delete(cif - 1);
}
}
int operator/=(int nr)
{
int i;
for(i = 0; i < n - 1; i++)
{
cif[i + 1] += (cif[i] % nr) * 10;
cif[i] = cif[i] / nr;
}
i = cif[n - 1] % nr;
cif[n - 1] /= nr;
while(cif[0] == 0)
{
cif++;
n--;
//delete(cif - 1);
}
return i; // the return value is this big number % nr
}
void operator*=(int cifTimes)
{
int i;
for(i = 0; i < n; i++)
{
cif[i] *= cifTimes;
}
for(i = n - 1; i >= 0; i--)
{
if(cif[i] > 9)
{
if(i != 0)
{
cif[i - 1]++;
cif[i] %= 10;
}
else
{
n++;
cif[0] %= 10;
cif--;
cif = new(cif) char(cif[0] = 1);
}
}
}
}
EDIT #4: n = length of the number = number of digits = number of bytes. Weird error means it just crashes. I don't know how to find more about it. MinGW compiler asks Visual Studio (Visual C++) to debug it because it has some problems. This is for a problem, and somewhere (in the evaluator) it says "Killed by signal 6(SIGABRT)", if this helps.
EDIT #...: #Branko Dimitrijevic: I don't wanna be lazy... I want my own... I had this problem in more attempts to make something running. If I take out the destructor, it works just fine, just I guess then it would be a memory leak that way... I really want to find out why would this occur... and only for specific sizes and, i.e. it doesn't crash on the first "delete", but on the 11'th in my case, that's why it's weird .
The delete can only work correctly on an address that is at the beginning of a dynamically-allocated block.
The cif will fail one or both of these conditions, leading to undefined behavior when the destructor calls delete, for following reasons:
You assign startPos to cif and then modify it in a very strange way before calling the placement new. So even if startPos is a properly allocated block of dynamic memory, the cif no longer points to the starting address of it.
If the caller passes an address of a stack-based variable to startPos, then you no longer deal with dynamic memory at all.
Not to mention that you call new and delete in a loop - what's up with that? There is also a fair chance for bombarding the memory unless you craft your input parameters in a very specific way. This whole block of code looks suspicious, what exactly are you trying to do?