Cannot solve warning C6386 - c++

Please guys I need some help. I get Warning C6386 Buffer overrun while writing to 'AnArray': the writable size is 'nrows*8' bytes, but '16' bytes might be written. on the following code
#include <math.h>
void SubMain(int, int);
int CSTEBit(int, int, int);
double Fact(int);
double Perm(int, int);
int Comb(int, int);
int main()
{
SubMain(13, 5);
}
void SubMain(int N, int R)
{
int** AnArray;
int nrows = Comb(N, R) + 1;
int ncolumns = 8;
int Pos;
int Count;
AnArray = new int* [nrows];
for (int i = 0; i < nrows; i++)
AnArray[i] = new int[ncolumns];
for (int a = 0; a < nrows; a++)
{
for (int b = 0; b <= 7; b++)
AnArray[a][b] = 0;
}
Pos = 0;
Count = 0;
do
{
Pos += 1;
if ((CSTEBit(3, AnArray[Pos][7], 4) == 0) && (CSTEBit(3, AnArray[Pos][7], 5) == 0))
Count += 1;
} while (Count != nrows - 1);
AnArray[Pos][7] = CSTEBit(1, AnArray[Pos][7], 4);
}
int CSTEBit(int CSTE, int Byt, int Bit)
{
int tempCSTEBit = 0;
if (Bit < 8)
{
int Mask = (int)pow(2, Bit);
switch (CSTE)
{
case 0:
tempCSTEBit = (int)(Byt && ~Mask);
break;
case 1:
tempCSTEBit = (int)(Byt | Mask);
break;
case 2:
tempCSTEBit = (int)(Byt ^ Mask);
break;
case 3:
if ((Byt & Mask) > 0)
{
tempCSTEBit = 1;
}
else
{
tempCSTEBit = 0;
}
break;
default:
tempCSTEBit = Byt;
break;
}
}
else
{
tempCSTEBit = Byt;
}
return tempCSTEBit;
}
double Fact(int N)
{
double tempFact = 0;
if (N <= 1)
{
tempFact = 1;
}
else
{
tempFact = N * Fact(N - 1);
}
return tempFact;
}
double Perm(int N, int R)
{
double tempPerm = 0;
int a = 0;
double b;
b = 1;
if (N < R)
{
tempPerm = 0;
}
else
{
for (a = (N - (R - 1)); a <= N; a++)
{
b = b * a;
}
tempPerm = b;
}
return tempPerm;
}
int Comb(int N, int R)
{
int tempComb = 0;
if (N < R)
{
tempComb = 0;
}
else
{
tempComb = (int)(Perm(N, R) / Fact(R));
}
return tempComb;
}
The variable Pos will never be higher than what Comb function returns which is used to initialize the AnArray. Thanks in advance for any answer.

Well actually I insert "if (Pos < nrows)" inside the do loop after Pos += 1; and the warning was gone.

Related

I tried to implement the RSA encryption algorithm using cpp, but it takes too long and I don't know if it will work

My code is here
//RSA.cpp
#include <iostream>
#include <cstring>
#include <ctime>
#include <random>
#include <vector>
#include <string>
#include "BigNum.hpp"
using namespace std;
BigNum mygcd(BigNum a, BigNum b)
{
while(a != b)
{
if(a>b)
{
a = a - b;
}
else
{
b = b - a;
}
}
return a;
}
BigNum prime(int n)
{
vector<BigNum> ans;
ans.push_back(BigNum(2));
ans.push_back(BigNum(3));
for (int i = 0; i < n; i++)
{
BigNum addend = 1;
for (auto j : ans)
{
addend = addend * j;
}
ans.push_back(addend + 1);
}
return ans[ans.size() - 1];
}
BigNum exgcd(BigNum a, BigNum b, BigNum &x, BigNum &y)
{
if (b == 0)
{
x = 1, y = 0;
return a;
}
BigNum g = exgcd(b, a - (a / b) * b, x, y);
BigNum t;
t = x;
x = y;
y = t - a / b * y;
return g;
}
BigNum niyuan(BigNum a, BigNum b)
{
BigNum x, y;
BigNum aa = exgcd(a, b, x, y);
return (x + b) - ((x + b) / b) * b;
}
vector<BigNum> yinshu(BigNum n)
{
vector<BigNum> ans;
int a = 2;
while (n / 2 > a)
{
if (n % a == 0)
{
ans.push_back(a);
}
a++;
}
return ans;
}
vector<int> ToBit(BigNum obj){
vector<int> r;
while (obj != 0){
r.push_back( (obj - (obj / 2) * 2 == 0) ? 0 : 1 );
obj = obj / 2;
}
return r;
}
BigNum jiami(BigNum e, int i, BigNum n)
{
BigNum addend = i;
BigNum result = 1;
vector<int>bitE = ToBit(e);
int now = 0;
while (now != bitE.size())
{
if (bitE[now])
{
result = addend * result;
result = result - (result / n) * n;
}
addend = addend * addend;
now = now + 1;
}
return result;
}
BigNum jiemi(BigNum d, BigNum i, BigNum n)
{
BigNum addend = i;
BigNum result = 1;
vector<int>bitD = ToBit(d);
int now = 0;
while (now != bitD.size())
{
if (bitD[now])
{
result = addend * result;
result = result - (result / n) * n;
}
addend = addend * addend;
now = now + 1;
}
return result;
}
int main()
{
srand(time(0));
BigNum p = prime(rand() % 20 + 1);
srand(time(0));
BigNum q = prime(rand() % 20 + 1);
BigNum N = p * q;
BigNum r = (p - 1) * (q - 1);
sss:
srand(time(0));
BigNum e = random() + 2;
if (mygcd(e, r) - BigNum(1) > 0)
goto sss;
vector<BigNum> yinshus = yinshu(r);
BigNum d = BigNum(niyuan(e, r));
cout << "Alice send(" << N << ',' << e << ")to Bob" << endl;
cout << "Please input your massage:";
string m;
cin >> m;
vector<int> message;
for (auto i : m)
{
message.push_back((int)i);
}
vector<BigNum> miwen;
for (auto i : message)
{
miwen.push_back(jiami(e, i, N));
}
cout << "coded text:";
for (auto i : miwen)
{
cout << i << " ";
}
vector<BigNum> minwen;
for (auto i : miwen)
{
minwen.push_back(jiemi(d, i, N));
}
cout << "明文:";
for (auto i : minwen)
{
cout << i << " ";
}
cout << endl;
}
I used a self-defined data structure called BigNum in order to store some large integers without them overflowing.
//BigNum.hpp
#include <iostream>
#include <cstring>
#include <string>
#include <iomanip>
#include <algorithm>
using namespace std;
#define MAXN 9999
#define MAXSIZE 10
#define DLEN 4
class BigNum
{
private:
int a[999];
int len;
public:
BigNum()
{
len = 1;
memset(a, 0, sizeof(a));
}
BigNum(const int);
BigNum(const char *);
BigNum(const BigNum &);
BigNum &operator=(const BigNum &);
friend istream &operator>>(istream &, BigNum &);
friend ostream &operator<<(ostream &, BigNum &);
BigNum operator+(const BigNum &) const;
BigNum operator-(const BigNum &) const;
BigNum operator*(const BigNum &) const;
BigNum operator/(const int &) const;
BigNum operator/(const BigNum &) const;
BigNum operator^(const int &) const;
int operator%(const int &) const;
bool operator>(const BigNum &T) const;
bool operator>(const int &t) const;
bool operator<(const BigNum &) const;
bool operator<=(const BigNum &) const;
bool operator>=(const BigNum &) const;
bool operator==(const BigNum &) const;
bool operator!=(const BigNum &) const;
void print();
};
BigNum::BigNum(const int b)
{
int c, d = b;
len = 0;
memset(a, 0, sizeof(a));
while (d > MAXN)
{
c = d - (d / (MAXN + 1)) * (MAXN + 1);
d = d / (MAXN + 1);
a[len++] = c;
}
a[len++] = d;
}
BigNum::BigNum(const char *s)
{
int t, k, index, l, i;
memset(a, 0, sizeof(a));
l = strlen(s);
len = l / DLEN;
if (l % DLEN)
len++;
index = 0;
for (i = l - 1; i >= 0; i -= DLEN)
{
t = 0;
k = i - DLEN + 1;
if (k < 0)
k = 0;
for (int j = k; j <= i; j++)
t = t * 10 + s[j] - '0';
a[index++] = t;
}
}
BigNum::BigNum(const BigNum &T) : len(T.len)
{
int i;
memset(a, 0, sizeof(a));
for (i = 0; i < len; i++)
a[i] = T.a[i];
}
BigNum &BigNum::operator=(const BigNum &n)
{
int i;
len = n.len;
memset(a, 0, sizeof(a));
for (i = 0; i < len; i++)
a[i] = n.a[i];
return *this;
}
istream &operator>>(istream &in, BigNum &b)
{
char ch[MAXSIZE * 4];
int i = -1;
in >> ch;
int l = strlen(ch);
int count = 0, sum = 0;
for (i = l - 1; i >= 0;)
{
sum = 0;
int t = 1;
for (int j = 0; j < 4 && i >= 0; j++, i--, t *= 10)
{
sum += (ch[i] - '0') * t;
}
b.a[count] = sum;
count++;
}
b.len = count++;
return in;
}
ostream &operator<<(ostream &out, BigNum &b)
{
int i;
cout << b.a[b.len - 1];
for (i = b.len - 2; i >= 0; i--)
{
cout.width(DLEN);
cout.fill('0');
cout << b.a[i];
}
return out;
}
BigNum BigNum::operator+(const BigNum &T) const
{
BigNum t(*this);
int i, big;
big = T.len > len ? T.len : len;
for (i = 0; i < big; i++)
{
t.a[i] += T.a[i];
if (t.a[i] > MAXN)
{
t.a[i + 1]++;
t.a[i] -= MAXN + 1;
}
}
if (t.a[big] != 0)
t.len = big + 1;
else
t.len = big;
return t;
}
BigNum BigNum::operator-(const BigNum &T) const
{
int i, j, big;
bool flag;
BigNum t1, t2;
if (*this > T)
{
t1 = *this;
t2 = T;
flag = 0;
}
else
{
t1 = T;
t2 = *this;
flag = 1;
}
big = t1.len;
for (i = 0; i < big; i++)
{
if (t1.a[i] < t2.a[i])
{
j = i + 1;
while (t1.a[j] == 0)
j++;
t1.a[j--]--;
while (j > i)
t1.a[j--] += MAXN;
t1.a[i] += MAXN + 1 - t2.a[i];
}
else
t1.a[i] -= t2.a[i];
}
t1.len = big;
while (t1.a[t1.len - 1] == 0 && t1.len > 1)
{
t1.len--;
big--;
}
if (flag)
t1.a[big - 1] = 0 - t1.a[big - 1];
return t1;
}
BigNum BigNum::operator*(const BigNum &T) const
{
BigNum ret;
int i, j, up;
int temp, temp1;
for (i = 0; i < len; i++)
{
up = 0;
for (j = 0; j < T.len; j++)
{
temp = a[i] * T.a[j] + ret.a[i + j] + up;
if (temp > MAXN)
{
temp1 = temp - temp / (MAXN + 1) * (MAXN + 1);
up = temp / (MAXN + 1);
ret.a[i + j] = temp1;
}
else
{
up = 0;
ret.a[i + j] = temp;
}
}
if (up != 0)
ret.a[i + j] = up;
}
ret.len = i + j;
while (ret.a[ret.len - 1] == 0 && ret.len > 1)
ret.len--;
return ret;
}
BigNum BigNum::operator/(const int &b) const
{
BigNum ret;
int i, down = 0;
for (i = len - 1; i >= 0; i--)
{
ret.a[i] = (a[i] + down * (MAXN + 1)) / b;
down = a[i] + down * (MAXN + 1) - ret.a[i] * b;
}
ret.len = len;
while (ret.a[ret.len - 1] == 0 && ret.len > 1)
ret.len--;
return ret;
}
int BigNum::operator%(const int &b) const
{
int i, d = 0;
for (i = len - 1; i >= 0; i--)
{
d = ((d * (MAXN + 1)) % b + a[i]) % b;
}
return d;
}
BigNum BigNum::operator^(const int &n) const
{
BigNum t, ret(1);
int i;
if (n < 0)
exit(-1);
if (n == 0)
return 1;
if (n == 1)
return *this;
int m = n;
while (m > 1)
{
t = *this;
for (i = 1; i << 1 <= m; i <<= 1)
{
t = t * t;
}
m -= i;
ret = ret * t;
if (m == 1)
ret = ret * (*this);
}
return ret;
}
bool BigNum::operator>(const BigNum &T) const
{
int ln;
if (len > T.len)
return true;
else if (len == T.len)
{
ln = len - 1;
while (a[ln] == T.a[ln] && ln >= 0)
ln--;
if (ln >= 0 && a[ln] > T.a[ln])
return true;
else
return false;
}
else
return false;
}
bool BigNum::operator>(const int &t) const
{
BigNum b(t);
return *this > b;
}
void BigNum::print()
{
int i;
cout << a[len - 1];
for (i = len - 2; i >= 0; i--)
{
cout.width(DLEN);
cout.fill('0');
cout << a[i];
}
cout << endl;
}
bool BigNum::operator<(const BigNum &obj) const
{
for (int i = 0; i < len; i++)
{
if (a[i] < obj.a[i])
return true;
if (a[i] > obj.a[i])
return false;
}
return false;
}
bool BigNum::operator<=(const BigNum &obj) const
{
for (int i = 0; i < len; i++)
{
if (a[i] < obj.a[i])
return true;
if (a[i] > obj.a[i])
return false;
}
return true;
}
bool BigNum::operator>=(const BigNum &obj) const
{
for (int i = 0; i < len; i++)
{
if (a[i] > obj.a[i])
return true;
if (a[i] < obj.a[i])
return false;
}
return true;
}
bool BigNum::operator==(const BigNum &obj) const
{
for (int i = 0; i < len; i++)
{
if (a[i] != obj.a[i])
return false;
}
return true;
}
bool BigNum::operator!=(const BigNum &obj) const
{
for (int i = 0; i < len; i++)
{
if (a[i] != obj.a[i])
return true;
}
return false;
}
BigNum BigNum::operator/(const BigNum &op2) const
{
BigNum temp(*this);
if (op2 == 0)
{
cout << "ERROR!!";
for (int i = 0; i < len; i++)
temp.a[i] = 0;
}
else if (*this < op2)
{
for (int i = 0; i < len; i++)
temp.a[i] = 0;
}
else if (*this == op2)
{
temp.a[len - 1] = 1;
}
else if (op2 == 1)
{
temp = *this;
}
else if (op2 == 2)
{
int from = 0;
for (int i = 0; i < len; i++)
{
if (temp.a[i] != 0)
{
from = i;
break;
}
}
int carry = 0;
for (int i = from; i < len; i++)
{
if (temp.a[i] & 1)
{
if (carry == 1)
temp.a[i] = (temp.a[i] + 10) / 2;
else
temp.a[i] = temp.a[i] / 2;
carry = 1;
}
else
{
if (carry == 1)
temp.a[i] = (temp.a[i] + 10) / 2;
else
temp.a[i] = temp.a[i] / 2;
carry = 0;
}
}
}
else
{
BigNum begin(1), end("500000000000000000000000000000"); // 500000000000000000000000000000
while (begin < end)
{
BigNum mid = (begin + end) / 2;
BigNum res = mid * op2;
if (res == 0 || res >= *this)
end = mid;
else
begin = mid + 1;
}
temp = begin;
if (temp == 1)
return 0;
int tmp = len - 1;
while (temp.a[tmp] == 0)
{
temp.a[tmp] = 9;
tmp++;
}
temp.a[tmp]--;
return temp;
}
return temp;
}
When I run it, sometimes I get the error "malloc(): corrupted top size", sometimes it will run and then nothing happens, when I debug it, I find that the problem is in the "mygcd" function, the algorithm I use is too slow for a huge The algorithm I'm using is too slow for the huge number, but I don't know how to change it. I'm not sure where in the two files something is going wrong that I don't know about, and I can't guarantee that all the algorithms I'm using are correct and appropriate. Can anyone help me? Thanks a lot.
My system is Ubuntu 22.04.1LTS
gcc version 11.2.0
Now I deleted all the Chinese comments
After applying all of the changes suggested in the comments:
Remove using namespace std;
Remove superfluous BigNum::operator= and BigNum::BigNum(BigNum&)
Only implement fully BigNum::operator< and BigNum::operator==, and the other relational operators are based on those two operators
Make BigNum::operator << have the second argument as a const reference to BigNum.
the compiler here warns of j not being initialized.
BigNum BigNum::operator*(const BigNum &T) const //两个大数之间的相乘运算
{
BigNum ret;
int i, j, up;
//...
ret.len = i + j;
//...
}
You see the results of the run, with the Address Sanitizer showing that things are not working right.
When j is initialized to 0, then the program runs without error, at least the main you provided runs without error.
Edit:
On further inspection, you are accessing arr out-of-bounds. After changing the a to std::array<int, 999> a; and used at() within BigNum::operator *, a std::out_of_range exception is thrown:
Here is the updated code.
Also, please name your variables with meaningful names, not one letter names like a. Naming your variables properly will aid in understanding the code a lot better.

B-Tree implementation on C++ has a memory leak?

I have this B-Tree implementation, which I'm testing using search() and insert(). Testing is basically this:
void function(){
BTree b16(16);
// do lots of inserts and searchs on b16
}
for(many_times){
function();
}
If I understand correctly, after each iteration of function(), b16 should get destroyed. However, after ~250 iterations, I get a bad_alloc error, which means I have a memory leak.
Is there a problem with the destructors? Here's the implementation:
#include <iostream>
#include <vector>
using namespace std;
typedef unsigned int uint;
class BNode{
private:
uint *keys;
int B;
BNode **C;
int n;
bool leaf;
public:
BNode(int temp, bool bool_leaf);
~BNode();
void insertNonFull(uint k);
void splitChild(int i, BNode *y);
void traverse();
BNode *search(uint k);
friend class BTree;
};
class BTree{
private:
BNode *root;
int B;
public:
BTree(int temp);
~BTree();
BNode *search(uint k);
int search_bool(uint k);
void insert(uint k);
};
BNode::BNode(int t1, bool leaf1) {
B = t1;
leaf = leaf1;
keys = new uint[2*B - 1];
C = new BNode *[2*B];
n = 0;
}
BNode::~BNode(){
delete[] keys;
delete[] C;
}
BNode *BNode::search(uint k){
int i = 0;
while (i < n && k > keys[i]){
i++;
}
if(keys[i] == k){
return this;
}
if (leaf == true){
return NULL;
}
return C[i]->search(k);
}
void BTree::insert(uint k){
if (root == NULL) {
root = new BNode(B, true);
root->keys[0] = k;
root->n = 1;
}
else{
if (root->n == 2*B - 1){
BNode *s = new BNode(B, false);
s->C[0] = root;
s->splitChild(0, root);
int i = 0;
if (s->keys[0] < k){
i++;
}
s->C[i]->insertNonFull(k);
root = s;
}
else{
root->insertNonFull(k);
}
}
}
void BNode::insertNonFull(uint k) {
int i = n - 1;
if (leaf == true) {
while (i>=0 && keys[i] > k) {
keys[i+1] = keys[i];
i--;
}
keys[i+1] = k;
n = n + 1;
}
else {
while (i>=0 && keys[i] > k){
i--;
}
if (C[i+1]->n == 2*B-1) {
splitChild(i+1, C[i+1]);
if (keys[i + 1] < k){
i++;
}
}
C[i+1]->insertNonFull(k);
}
}
void BNode::splitChild(int i, BNode *y) {
BNode *z = new BNode(y->B, y->leaf);
z->n = B - 1;
for (int j = 0; j < B - 1; j++){
z->keys[j] = y->keys[j+B];
}
if (!y->leaf){
for (int j = 0; j < B; j++)
z->C[j] = y->C[j + B];
}
y->n = B - 1;
for(int j=n; j >= i+1; j--){
C[j+1] = C[j];
}
C[i + 1] = z;
for (int j = n - 1; j >= i; j--){
keys[j+1] = keys[j];
}
keys[i] = y->keys[B - 1];
n = n + 1;
}
BTree::BTree(int temp){
root = NULL;
B = temp;
}
BTree::~BTree(){
delete root;
}
BNode *BTree::search(uint k){
return (root == NULL) ? NULL : root->search(k);
}
int BTree::search_bool(uint k){
if(search(k) != NULL){
return true;
}
else{
return false;
}
}
Thanks in advance.
So, the simple diagnosis is that
delete[] C;
deletes only the array, not the nodes contained by it. So, (a) make sure they're properlu zero-initialized (b) delete them as well:
BNode** C = new BNode* [2 * B] { 0 };
// in the destructor:
for (int i = 0; i < 2 * B; ++i)
delete C[i];
delete[] C;
HOWEVER.
This doesn't work well because nodes can be split. After you moved some nodes from one node's C to another node's C, you run into double-free. So, when you split nodes, you have to make sure you set the moved-from C elemeent to NULL again:
z->C[j] = y->C[j + B];
y->C[j + B] = nullptr;
Now, this program runs clean under valgrind, ubsan and asan and without leaks:
Live On Coliru
#include <iostream>
#include <vector>
using uint = unsigned;
class BNode {
private:
int B;
bool leaf;
uint* keys = new uint[2 * B - 1]{0};
BNode** C = new BNode* [2 * B] { 0 };
int n = 0;
public:
BNode(int t1, bool leaf1) : B(t1), leaf(leaf1) {}
~BNode()
{
delete[] keys;
for (int i = 0; i < 2 * B; ++i)
delete C[i];
delete[] C;
}
BNode const* search(uint k) const
{
int i = 0;
while (i < n && k > keys[i]) {
i++;
}
if (keys[i] == k) {
return this;
}
return leaf ? nullptr : C[i]->search(k);
}
void insertNonFull(uint k)
{
int i = n - 1;
if (leaf == true) {
while (i >= 0 && keys[i] > k) {
keys[i + 1] = keys[i];
i--;
}
keys[i + 1] = k;
n = n + 1;
} else {
while (i >= 0 && keys[i] > k) {
i--;
}
if (C[i + 1]->n == 2 * B - 1) {
splitChild(i + 1, C[i + 1]);
if (keys[i + 1] < k) {
i++;
}
}
C[i + 1]->insertNonFull(k);
}
}
void splitChild(int i, BNode* y)
{
BNode* z = new BNode(y->B, y->leaf);
z->n = B - 1;
for (int j = 0; j < B - 1; j++) {
z->keys[j] = y->keys[j + B];
}
if (!y->leaf) {
for (int j = 0; j < B; j++) {
z->C[j] = y->C[j + B];
y->C[j + B] = nullptr;
}
}
y->n = B - 1;
for (int j = n; j >= i + 1; j--) {
C[j + 1] = C[j];
}
C[i + 1] = z;
for (int j = n - 1; j >= i; j--) {
keys[j + 1] = keys[j];
}
keys[i] = y->keys[B - 1];
n = n + 1;
}
friend class BTree;
};
class BTree {
private:
BNode* root = nullptr;
int B;
public:
BTree(int temp)
{
root = nullptr;
B = temp;
}
~BTree() { delete root; }
BNode const* search(uint k) const
{
return (root == nullptr) ? nullptr : root->search(k);
}
bool search_bool(uint k) const { return search(k) != nullptr; }
void insert(uint k)
{
if (!root) {
root = new BNode(B, true);
root->keys[0] = k;
root->n = 1;
} else {
if (root->n == 2 * B - 1) {
BNode* s = new BNode(B, false);
s->C[0] = root;
s->splitChild(0, root);
int i = 0;
if (s->keys[0] < k) {
i++;
}
s->C[i]->insertNonFull(k);
root = s;
} else {
root->insertNonFull(k);
}
}
}
};
int main()
{
for (int b = 8; b < 17; ++b) {
BTree tree(b);
for (int i = 0; i < 100'000; ++i)
tree.insert(rand() % 1000);
}
}
In Closing
Kudos for getting the algorithmics largely right here. That's not easy.
As you can see in my cleanup/review I hardened a lot of stuff, mainly around initialization. This is an important habit. I can't actually rule out that not having that would have exposed other sleeping bugs.
Also note the increased const-correctness.
Also, like other said, prefer smart pointers and modern C++ techniques. It will be amazing how much less error prone just using std::array, unique_ptr and so will be. For example, the bug with moving nodes in splitChild would never have compiled because you have to explcitly move-assign unique_ptr
Bonus
Example in more modern C++:
without any new/delete
without any raw pointer
no more manual destructors (even no constructors required, really)
compiler checked move semantics, NICE!
statically known B factor, so everything becomes 10x more performant, while still being tunable
generic key (element) type, so you can now store std::string, double, whatnot
generic comparator, so you sort your keys in alternative orders (e.g. Btree<std::string, 16, std::greater<> > to store the keys in descending order instead of ascending).
No leaks!
Live On Coliru
#include <array>
#include <algorithm>
#include <memory>
#include <iostream>
template <typename T, unsigned B = 16, typename Cmp = std::less<T>>
class BTree {
private:
static constexpr unsigned MaxKeys = 2 * B - 1;
static constexpr unsigned MaxChildren = 2 * B;
struct BNode;
using NodePtr = std::unique_ptr<BNode>;
struct BNode {
bool _leaf;
int _n = 0;
std::array<T, MaxKeys> _keys{};
std::array<NodePtr, MaxChildren> _children{};
BNode(bool leaf1) : _leaf(leaf1) {}
BNode const* search(T k, Cmp cmp) const
{
int i = 0;
while (i < _n && cmp(_keys[i], k)) {
i++;
}
if (_keys[i] == k) {
return this;
}
return _leaf ? nullptr : _children[i]->search(k, cmp);
}
void insertNonFull(T k, Cmp cmp)
{
int i = _n - 1;
if (_leaf == true) {
while (i >= 0 && cmp(k, _keys[i])) {
_keys[i + 1] = _keys[i];
i--;
}
_keys[i + 1] = k;
_n = _n + 1;
} else {
while (i >= 0 && cmp(k, _keys[i])) {
i--;
}
if (_children[i + 1]->_n == MaxKeys) {
splitChild(i + 1, *_children[i + 1]);
if (cmp(_keys[i + 1], k)) {
i++;
}
}
_children[i + 1]->insertNonFull(k, cmp);
}
}
void splitChild(int i, BNode& y)
{
NodePtr z = std::make_unique<BNode>(y._leaf);
z->_n = B - 1;
for (unsigned j = 0; j < B - 1; j++) {
z->_keys[j] = y._keys[j + B];
}
if (!y._leaf) {
for (unsigned j = 0; j < B; j++) {
z->_children[j] = std::move(y._children[j + B]);
}
}
y._n = B - 1;
for (int j = _n; j >= i + 1; j--) {
_children[j + 1] = std::move(_children[j]);
}
_children[i + 1] = std::move(z);
for (int j = _n - 1; j >= i; j--) {
_keys[j + 1] = _keys[j];
}
_keys[i] = y._keys[B - 1];
_n = _n + 1;
}
};
NodePtr root = nullptr;
Cmp _cmp{};
public:
BTree(Cmp cmp = {}) : _cmp(std::move(cmp)) {}
BNode const* search(T k) const {
return root ? root->search(k, _cmp) : nullptr;
}
bool search_bool(T k) const { return search(k) != nullptr; }
void insert(T k)
{
if (!root) {
root = std::make_unique<BNode>(true);
root->_keys[0] = k;
root->_n = 1;
} else {
if (root->_n == MaxKeys) {
NodePtr s = std::make_unique<BNode>(false);
s->splitChild(0, *root);
s->_children[0] = std::move(root);
int i = 0;
if (_cmp(s->_keys[0], k)) {
i++;
}
s->_children[i]->insertNonFull(k, _cmp);
root = std::move(s);
} else {
root->insertNonFull(k, _cmp);
}
}
}
};
int main()
{
using Asc = std::less<>;
using Desc = std::greater<>;
BTree<double, 8, Asc> b8;
BTree<int, 9, Desc> b9;
BTree<unsigned, 10, Asc> b10;
BTree<size_t, 11, Desc> b11;
BTree<double, 12, Asc> b12;
BTree<int, 13, Desc> b13;
BTree<unsigned, 14, Asc> b14;
BTree<size_t, 15, Desc> b15;
BTree<int, 16> b16; // default is ascending
for (int i = 0; i < 100'000; ++i) {
b8.insert(rand() % 10000);
b9.insert(rand() % 10000);
b10.insert(rand() % 10000);
b11.insert(rand() % 10000);
b12.insert(rand() % 10000);
b13.insert(rand() % 10000);
b14.insert(rand() % 10000);
b15.insert(rand() % 10000);
b16.insert(rand() % 10000);
}
{
struct NC {
int v;
bool operator==(NC const& o) const { return v == o.v; }
};
struct CMP {
bool operator()(NC const& a, NC const& b) const { return a.v < b.v; }
};
BTree<NC, 8, CMP> b8;
b8.insert({42});
bool ok = b8.search_bool({42});
}
}

Blank output screen when I run this searching algorithm

I have been practicing median search algorithm, and this is what I wrote-
#include <iostream>
#include <stdlib.h>
using namespace std;
int S1[10] = { 0 };
int S2[1] = { 0 };
int S3[10] = { 0 };
int mediansearch(int A[], int k, int size)
{
int ran = rand() % size;
int i = 0;
int a = 0;
int b = 0;
int c = 0;
for (i = 0; i < size; i++)
{
if (A[ran] > A[i])
{
S1[a] = A[i];
a++;
}
else if (A[ran] == A[i])
{
S2[b] = A[i];
b++;
}
else
{
S3[c] = A[i];
c++;
}
}
if (a <= k)
{
return mediansearch(S1, k, a);
}
else if (a + b <= k)
{
return A[ran];
}
else
{
return mediansearch(S3, k - a - b, c);
}
}
int main()
{
int arr[] = { 6, 5, 4, 8, 99, 74, 23 };
int n = sizeof(arr) / sizeof(arr[0]);
int x = mediansearch(arr, 5, n);
cout << "5th smallest is:" << x << endl;
}
And I have been getting output as-
Process returned -1073741676 (0xC0000094) execution time : 1.704 s
So, what am I doing wrong? Any kind of help will be appreciated.
There are a few issues with this code, the first one being the naming of variables.
I suggest you choose more significative names in the future, because good naming is fundamental when someone else has to understand your code and your ideas.
Another thing is that the arguments of are in a counterintuitive order because the pair related to the array are separated by the index you want to look for.
I'd write int mediansearch(int A[], int size, int k)
Here the comparisons are reversed, k should be less than rather than greater than equal a
if (a <= k) // (k < a)
{
return mediansearch(S1, k, a);
}
else if (a + b <= k) // (k < a + b)
{
return A[ran];
}
else
{
return mediansearch(S3, k - a - b, c);
}
The other thing is that you're sharing S1, S2, and S3 among all the recursive calls and that causes some error that I wasn't able to identify, maybe someone commenting will help me out.
However, I suggest you read this article that explains in detail the procedure you're trying to implement: https://rcoh.me/posts/linear-time-median-finding/
It's python, but it can be easily ported to C/C++, and in fact that's what I did.
#include <iostream>
#include <stdlib.h>
#include <assert.h>
#include <time.h>
using namespace std;
int medianSearch(int A[], int size, int k)
{
int *lows = (int *)calloc(size, sizeof(int));
int lowsLen = 0;
int *highs = (int *)calloc(size, sizeof(int));
int highsLen = 0;
int *pivots = (int *)calloc(size, sizeof(int));
int pivotsLen = 0;
int median;
int pivot;
int i;
if (size == 1)
return A[0];
// Other ways of randomly picking a pivot
// pivot = 0;
// pivot = size-1;
// pivot = size/2;
assert(size > 0);
pivot = rand() % size;
for (i = 0; i < size; ++i)
{
if (A[i] < A[pivot])
{
lows[lowsLen] = A[i];
lowsLen++;
}
else if (A[i] > A[pivot])
{
highs[highsLen] = A[i];
highsLen++;
}
else
{
pivots[pivotsLen] = A[i];
pivotsLen++;
}
}
if (k < lowsLen)
median = medianSearch(lows, lowsLen, k);
else if (k < lowsLen + pivotsLen)
median = A[pivot];
else
median = medianSearch(highs, highsLen, k - lowsLen - pivotsLen);
free(lows);
free(highs);
free(pivots);
return median;
}
int compare(const void *a, const void *b)
{
return ( *(int *)a - *(int *)b );
}
int medianSorted(int A[], int size, int k)
{
qsort(A, size, sizeof(int), compare);
return A[k];
}
#define N 1000
int main()
{
int arr[N];
int brr[N];
int n = sizeof(arr) / sizeof(arr[0]);
int k = 200;
int x;
int y;
for (int i = 0; i < n; ++i)
arr[i] = brr[i] = rand();
x = medianSearch(arr, n, (k-1)%n);
y = medianSorted(brr, n, (k-1)%n);
string suffix;
switch (k % 10)
{
case 1: suffix = "st"; break;
case 2: suffix = "nd"; break;
case 3: suffix = "rd"; break;
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:
case 0: suffix = "th"; break;
}
cout << k << suffix << " smallest is: " << x << endl;
cout << k << suffix << " smallest is: " << y << endl;
}
https://onlinegdb.com/HJc2V6Lbu

How can I fix the error "expression must have pointer-to-object type" (multifile project)?

I'm writing the program with 2 .cpp files and 1 .h file (direct.h). The main function is:
#include <iostream>
#include <direct.h>
using namespace std;
int direct(const int rows, const int cols, int ARR);
int main()
{
const int rows = 9;
const int cols = 9;
int ARR[rows][cols];
direct(const int rows, const int cols, int ARR);
}
My function (that fills the array in the spiral way) is:
int direct(const int rows, const int cols, int ARR)
{
int val;
// Initialize the array to 0 values
for (int i = 0; i < rows;i++)
{
for (int j = 0; j < cols;j++)
{
val = 0;
}
}
// Use symbols for directions
enum dir
{
left = 0,
down,
up,
right,
}
dir = left;
// Define the starting point and starting value
int x = rows / 2;
int y = cols / 2;
int val = 1;
// A flag to know when to stop
bool stop = false;
// Start
for (;;)
{
ARR[x][y] = val++;
switch (dir)
{
case left:
y -= 1;
if (y < 0) stop = true;
else if (ARR[x + 1][y] == 0) dir = down;
break;
case down:
x += 1;
if (x > rows) stop = true;
else if (ARR[x][y + 1] == 0) dir = right;
break;
case right:
y += 1;
if (y >= rows) stop = true;
else if (ARR[x - 1][y] == 0) dir = up;
break;
case up:
x -= 1;
if (x < 0) stop = true;
else if (ARR[x][y - 1] == 0) dir = left;
}
if (stop) break;
}
}
In the main.cpp file everything is OK. However, in direct.cpp file I get the errors that say "expression must have pointer-to-object type" and the variables "x" and "y" are underlined in the loop "for", so the problem is in them.
What am I doing wrong? And how can I fix it?
Start to Replace
int direct(const int rows, const int cols, int ARR)
by
int direct(const int rows, const int cols, int ARR[][])
in the main
call the function :
direct( rows, cols, ARR);
When you init the tab :
for (int i = 0; i < rows;i++)
{
for (int j = 0; j < cols;j++)
{
ARR[i][j]= 0;
}
}

Program crashed after end of scope

I was confused from this following codes, it's creating crash that I fully don't understand.
#include <stdio.h>
#include <string.h>
#include <vector>
using namespace std;
struct Store
{
int pos;
char character;
};
vector<struct Store> v_store;
void swap_inside_vector(vector<struct Store> &v_store, int a, int b)
{
struct Store tmp = v_store[b];
v_store[b] = v_store[a];
v_store[a] = tmp;
}
int find_inside_vector(vector<struct Store> &v_store, int pos)
{
for(int i = 0; i < v_store.size(); i++)
{
if(v_store[i].pos == pos)
return i;
}
return -1;
}
void swap_most_right_to_most_left(vector<struct Store> &v_store)
{
struct Store tmp = v_store[v_store.size() - 1];
for(int i = v_store.size(); i > 0; i--)
{
v_store[i] = v_store[i-1];
}
v_store[0] = tmp;
}
void print_char_inside_vector(vector<struct Store> &v) // used for debugging
{
for(int i = 0; i < v.size(); i++)
{
printf("%C", v[i].character);
}
}
int check_vector_original_state(vector<struct Store> &v_store)
{
for(int i = 1; i <= v_store.size(); i++)
{
if(v_store[i-1].pos != i)
return 0;
}
return 1;
}
int main()
{
int n;
char input_str[100];
for(int q = 1; scanf("\n%d", &n), n; q++)
{
scanf("%s", input_str);
vector<struct Store> original_store, tmp_origin_store, v_store;
vector<vector<struct Store> > store_vector;
original_store.clear();
tmp_origin_store.clear();
v_store.clear();
store_vector.clear();
for(int i = 1; i <= strlen(input_str); i++)
{
struct Store s = {.pos = i, .character = input_str[i-1]};
original_store.push_back(s);
}
tmp_origin_store = original_store;
v_store = tmp_origin_store;
for(int i = 1, current_pos = 0; i <= n; i++, current_pos++)
{
int vector_index = find_inside_vector(v_store, tmp_origin_store[current_pos].pos);
//printf("Processing -> [%d], Current Pos -> [%d]\n", i, current_pos);
for(int z = 0; z < (current_pos + 1); z++)
{
if(vector_index == (v_store.size() - 1))
{
swap_most_right_to_most_left(v_store);
vector_index = 0;
}
else
{
swap_inside_vector(v_store, vector_index, vector_index + 1);
vector_index++;
}
//print_char_inside_vector(v_store);
//puts("");
}
//puts("");
store_vector.push_back(v_store);
if(check_vector_original_state(v_store))
{
store_vector.push_back(v_store);
break;
}
if(current_pos == (v_store.size() - 1))
{
tmp_origin_store = v_store;
current_pos = -1;
}
}
// debugging
/*for(int x = 0; x < store_vector.size(); x++)
{
printf("[%d] -> ", x + 1);
print_char_inside_vector(store_vector[x]);
puts("");
}*/
int target_pos;
if(store_vector.size() < n)
{
target_pos = n % store_vector.size();
}
else
{
target_pos = store_vector.size();
}
if(target_pos == 0)
{
printf("%d. ", q);
print_char_inside_vector(store_vector[0]);
puts("");
}
else
{
printf("%d. ", q);
print_char_inside_vector(store_vector[target_pos - 1]);
puts("");
}
}
}
What this program does is accepting input from STDIN, process it, and output it on STDOUT.
My expecting input is
3 ABCD
13 ACM
3 DAEQD
4 FAEQS
Expected output is
1. CABD
2. CAM
3. DAQDE
4. FQASE
My problem is, after inputing fourth input into STDIN, and after output is being shown, crash occured.
C:\Study>h.exe
3 ABCD
1. CABD
13 ACM
2. CAM
3 DAEQD
3. DAQDE
4 FAEQS
4. FQASE
0 [main] h 9092 cygwin_exception::open_stackdumpfile: Dumping stack trace to h.exe.stackdump
From my observation, I think the problem is at the vector, but it's just a guess.
Your code didn't compile :
//struct Store s = { .pos = i, .character = input_str[i - 1] }; // syntax not recongnized
Store s = { i, input_str[i - 1] }; // replaced with this.
After fixing this, the debugging immediatly identified an out of bound problem on a vector, which could lead to memory corruption issue. It's in swap_most_right_to_most_left():
for (int i = v_store.size(); i > 0; i--) { // you start with i=v_store.size()
v_store[i] = v_store[i - 1]; // and you immediately get out of bounds !
}
If you correct this instruction to :
for (int i = v_store.size()-1; i > 0; i--) {
v_store[i] = v_store[i - 1];
}
you'll get the expected output for the given input.