I have attempted to run this code. Prior to running this, no warnings or errors exist but once it is executed I have an exception thrown and it stops the program from compiling. Here is my code and the error is in the subject line. The CDA file is being used as header file to create a Circular Dynamic Array that is going to be manipulated in Heaps.cpp. The heaps.cpp is to create a binary heap that is to be used in to create Binomial heaps, but that code has not been developed yet.
#include <iostream>
using namespace std;
template <class T>
class CDA
{
private:
int rear;
int size;
int capacity;
T* circArray;
int front;
bool ordered;
T placeHolder;
public:
CDA();
CDA(int s);
~CDA();
int Front();
T Data(int n);
T& operator[](int i);
void AddEnd(T v);
void AddFront(T v);
void DelEnd();
void DelFront();
int Length();
int Capacity();
int Clear();
bool Ordered();
int SetOrdered();
int S01(int n);
T Select(int k);
void InsertionSort();
void QuickSort();
void QuickSort1(int low, int high);
void CountingSort(int m);
int Search(T e);
void reSize();
void Shrink();
int BinarySearch(int left, int right, T e);
int QSortPartition(int low, int high);
void Swap(int* x, int* y);
int QSelPartition(int front, int rear);
T QuickSelect(int front, int rear, int k);
CDA<T>& operator=(const CDA& a);
CDA(const CDA& old);
int Median(int low, int high);
};
template <class T>
CDA<T>::CDA()
{
capacity = 1;
circArray = new T[capacity];
size = 0;
rear = size - 1;
front = -1;
ordered = false;
placeHolder = 0;
}
template <class T>
CDA<T>::CDA(int s)
{
size = s;
capacity = s;
circArray = new T[capacity];
front = 0;
rear = size - 1;
ordered = false;
}
template <class T>
CDA<T>::CDA(const CDA& a)
{
size = a.size;
capacity = a.capacity;
circArray = new T[a.capacity];
front = a.front;
rear = a.size - 1;
ordered = a.ordered;
for (int i = a.front; i < a.front + (a.size); i++)
{
circArray[i % capacity] = a.circArray[i % capacity];
}
}
template <class T>
CDA<T>::~CDA()
{
delete[]circArray;
}
template <class T>
T& CDA<T>::operator[](int i)
{
if (i > capacity)
{
cout << "Array index is out of bounds; exiting." << endl;
placeHolder = i;
cout << endl;
return placeHolder;
exit(0);
}
else
{
return circArray[(front + i) % capacity];
}
}
template <class T>
void CDA<T>::AddEnd(T v)
{
size++;
if (front == -1)
{
circArray[0] = v;
front++;
rear++;
return;
}
if (size > capacity)
{
reSize();
}
else if (front == -1)
{
front = 0;
rear = size - 1;
}
else
{
rear = (rear + 1) % capacity;
}
circArray[rear] = v;
}
template <class T>
void CDA<T>::AddFront(T v)
{
size++;
if (size > capacity)
{
reSize();
}
if (front == -1) //means the array is empty
{
front = 0;
rear = capacity % size;
}
else if (front == 0) //means something is in spot 0
{
front = capacity - 1; //puts front at the end and places the input there
}
else //go until it is back at zero
{
front--;
}
circArray[front] = v;
}
template <class T>
void CDA<T>::DelEnd()
{
size--;
if (size <= capacity / 4)
{
Shrink();
}
else if (rear == front)
{
front = -1;
rear = -1;
}
else
{
rear--;
}
}
template <class T>
void CDA<T>::DelFront()
{
size--;
double shrMeasure;
shrMeasure = capacity / 4.0;
if (size <= shrMeasure) // make an empty and shrink function
{
Shrink();
}
/*
else if (front == rear)
{
if (front == 0)
front = size - 1;
else
front++;
}
*/
else
{
if (front == size) //brings it full circle
{
front = 0;
}
else
{
front++;
}
}
if (front > capacity)
front = front % capacity;
}
template <class T>
int CDA<T>::Length()
{
return size;
}
template <class T>
int CDA<T>::Capacity()
{
return capacity;
}
template <class T>
int CDA<T>::Clear()
{
~CDA();
size = 1;
circArray[size] = NULL;
}
template <class T>
bool CDA<T>::Ordered()
{
return ordered;
}
template <class T>
int CDA<T>::SetOrdered()
{
for (int i = 1; i < size - 1; i++)
{
if (circArray[(i - 1)] > circArray[i])
{
ordered = false;
return -1;
}
}
ordered = true;
return 1;
}
template <class T>
T CDA<T>::Select(int k)
{
if (ordered == true)
{
return circArray[(front + k - 1) % capacity];
}
else
QuickSelect(front, front + (size - 1), k);
}
template <class T>
int CDA<T>::QSelPartition(int left, int right)
{
int pivot = circArray[right % capacity];
int x = left - 1;
//Swap(&circArray[pivIndex], &circArray[right]);
for (int i = left; i <= right - 1; i++)
{
if (circArray[i % capacity] <= pivot)
{
x++;
Swap(&circArray[x % capacity], &circArray[i % capacity]);
}
}
Swap(&circArray[(x + 1) % capacity], &circArray[right % capacity]);
return (x + 1);
}
template <class T>
T CDA<T>::QuickSelect(int left, int right, int k)
{
if (k > 0 && k <= (right - left) + 1)
{
int index = QSelPartition(left, right);
if (index - 1 == k - 1)
return circArray[index % capacity];
else if (index - 1 > k - 1)
return QuickSelect(left, index - 1, k);
else
return QuickSelect(index - 1, right, k - index + left - 1);
}
return -1;
}
template <class T>
void CDA<T>::InsertionSort() //must be utilized in quicksort
{
for (int i = front + 1; i < (front + size); i++)
{
int val = circArray[i % capacity];
int inc = (i - 1) % capacity;
while (inc >= 0 && circArray[inc] > val)
{
circArray[(inc + 1) % capacity] = circArray[inc];
inc--;
if (inc == -1)
{
inc = capacity - 1;
}
}
circArray[(inc + 1) % capacity] = val;
}
ordered = true;
}
template <class T>
void CDA<T>::QuickSort() // change to other quicksort before leaving the ferg
{
QuickSort1(front, front + (size - 1));
}
template <class T>
void CDA<T>::QuickSort1(int low, int high)
{
while (low < high)
{
if (high - low < 900)
{
InsertionSort();
break;
}
else
{
int pivot = QSortPartition(low, high);
if (pivot - low < high - pivot)
{
QuickSort1(low, pivot--);
low = pivot + 1;
}
else
{
QuickSort1(pivot++, high);
high = pivot - 1;
}
}
}
}
template <class T>
int CDA<T>::QSortPartition(int low, int high)
{
int pivot = circArray[Median(low, high) % capacity];
Swap(&circArray[(Median(low, high)) % capacity], &circArray[(high) % capacity]);
int index = low % capacity;
for (int i = low; i < high; i++)
{
if (circArray[i % capacity] <= pivot)
{
T t = circArray[i % capacity];
circArray[i % capacity] = circArray[index % capacity];
circArray[index % capacity] = t;
index++;
}
}
Swap(&circArray[index % capacity], &circArray[high % capacity]);
return index;
}
template <class T>
int CDA<T>::Median(int low, int high)
{
T left, mid, right;
left = circArray[low % capacity];
mid = circArray[((low + high) / 2) % capacity];
right = circArray[high % high];
if (left < right && left > mid)
return low % capacity;
if (left < mid && left > right)
return low % capacity;
if (right < left && right > mid)
return high % capacity;
if (right < mid && right > left)
return high % capacity;
if (mid < left && mid > right)
return ((low + high) / 2 % capacity);
if (mid < right && mid > left)
return ((low + high) / 2 % capacity);
}
template <class T>
void CDA<T>::Swap(int* x, int* y)
{
int temp = *x;
*x = *y;
*y = temp;
}
template <class T>
void CDA<T>::CountingSort(int m) ////NEED TO FIX THIS
{
int* OP = new int[size];
int* Counter = new int[m + 1];
for (int i = front; i <= rear; i++)
{
cout << "CircArray[" << i << "] is " << circArray[i] << endl;
}
for (int i = 0; i <= m; i++)
{
Counter[i] = 0;
}
for (int i = front; i < front + (size); i++)
{
Counter[circArray[i % capacity]]++;
}
for (int i = 1; i <= m; i++)
{
Counter[i] += Counter[i - 1];
}
for (int i = rear - 1; i > 0; i--)
{
OP[Counter[circArray[i]] - 1] = circArray[i];
cout << "Circular array at " << i << " is " << circArray[i] << endl;
Counter[circArray[i]] -= 1;
if (i == front % capacity)
break;
if (i == 0)
i = capacity;
}
for (int i = 0; i < size; i++)
circArray[i] = OP[i];
ordered = true;
front = 0;
}
template <class T>
int CDA<T>::Search(T e)
{
if (ordered == true) //binary search of item e
{
return BinarySearch(front, front + (size - 1), e);
}
else if (ordered == false)
{
for (int i = 0; i < size - 1; i++)
{
if (circArray[i] == e)
return i;
}
}
return -1;
}
template <class T>
int CDA<T>::BinarySearch(int left, int right, T e)
{
while (left <= right)
{
int mid = (left + right) / 2;
int value = circArray[mid % capacity];
if (value == e)
return (mid - front) % capacity;
else if (value < e)
return BinarySearch(mid + 1, right, e);
else if (value > e)
return BinarySearch(left, mid - 1, e);
}
return -1;
}
template <class T>
void CDA<T>::reSize()
{
capacity = capacity * 2;
T *nArray = new T[capacity];
for (int i = 0; i < size - 1; i++)
{
int l = (front + i) % (size-1);
nArray[i] = circArray[l];
}
//delete[]circArray;
circArray = nArray;
front = 0;
rear = (size - 1);
}
template <class T>
void CDA<T>::Shrink()
{
int tFront = front;
capacity = capacity / 2;
T* bArr = new T[capacity];
int index = 0;
while (front <= rear)
{
bArr[index] = circArray[(front + index) % capacity];
index++;
}
T* circArray = bArr;
front = 0;
rear = (size - 1);
}
template <class T>
CDA<T>& CDA<T>::operator=(const CDA<T>& a)
{
if (this != &a)
{
delete[]circArray;
size = a.size;
capacity = a.capacity;
circArray = new T[a.capacity];
front = a.front;
rear = a.size - 1;
ordered = a.ordered;
for (int i = a.front; i < a.front + (a.size); i++)
{
circArray[i % capacity] = a.circArray[i % capacity];
}
}
return *this;
}
template <class T>
int CDA<T>::Front()
{
return front;
}
template <class T>
T CDA<T>::Data(int n)
{
return circArray[n];
}
#include <iostream>
#include "CDA-1.cpp"
using namespace std;
template<class keytype, class valuetype>
class Heap
{
private:
CDA<keytype>* K;
CDA<valuetype>* V;
int size;
public:
Heap()
{
this->K = new CDA<keytype>();
this->V = new CDA<valuetype>();
size = 0;
}
Heap(keytype k[], valuetype v[], int s)
{
//allocate two different arrays for each type
//fill those arrays concurrently using insert
//sort concurrently using heapafy recursively
this->K = new CDA<keytype>(s);
this->V = new CDA<valuetype>(s);
this->size = s;
for (int i = 0; i < s; i++)
{
insert(k[i], v[i]);
}
heapify(s, K->Front());
}
void heapify(int s, int i)
{
//Errors for evans to fix: swap the n's with s.
//Fix the left and right variable logic. Hepaify smallest not small at the bottom.
//Also we need to pass V[] in a parameter so we can edit it in this.
//How to better swap V with K and not just K.
int smallest = i;
int left = 2*i +(-i+1);
int right = 2*i + (-i+2);
keytype kl = K->Data(left);
keytype kr = K->Data(right);
keytype ks = K->Data(smallest);
if (left < s && kl < ks) //FIX
smallest = left;
if (right < s && kr < ks) //FIX
smallest = right;
if (smallest != i)
{
swap(K[i], K[smallest]);
swap(V[i], V[smallest]); //FIX
heapify(s, smallest);
}
}
~Heap() {
return;
}
//items should be inserted using bottom up heap building method
void insert(keytype k, valuetype v)
{
K->AddEnd(k);
V->AddEnd(v);
heapify(size, K->Front());
}
keytype peekKey()
{
int f = K->Front();
return K->Data(f);
}
valuetype peekValue()
{
int f = V->front();
return V->Data(f);
}
keytype extractMin()
{
keytype temp = K->Data(K->Front());
K->DelFront();
V->DelFront();
heapify(size, K->Front());
return temp;
}
void printKey()
{
ActualPrintKey(K->Front());
}
void ActualPrintKey(int n)
{
keytype rt = K->Data(n);
if (rt != size)
{
cout << K->Data(rt) << " ";
ActualPrintKey((2 * n) + (-n + 1));
ActualPrintKey((2 * n) + (-n + 2));
}
}
};
/*
template <class keytype, class valuetype>
class BHeap
{
BHeap();
BHeap(keytype k[], valuetype v[], int s);
~BHeap();
keytype peekKey();
valuetype peekValue();
keytype extractMin();
//items should be inserted using repeated insertion
void insert(keytype k, valuetype v);
void merge(BHeap<keytype, valuetype>& H2);
void printKey();
};
*/
#include <iostream>
#include "Heaps.cpp"
using namespace std;
int main() {
string K[10] = { "A", "B", "C", "D", "E", "F", "G", "H", "I", "K" };
int V[10] = { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 };
Heap<string, int> T1, T2(K, V, 10);
cout << T2.peekKey() << endl;
cout << endl;
system("pause");
return 0;
}
In general "Access violation reading location", means you are trying to read virtually memory address space to a process which does not belong to your application and the operating system protective mechanism is kicking in to protect the rest of the loaded applications and resource from been accessed (read or write) by your application "memory leak vulnerability". If I was at your place I would review the code and all variables and arrays if they are properly initialized before use. Another thing which needs to be taken in consideration is the operating system and the permissions required by your application (Windows run as Administrator / GNU/Linux sudo).
Cheers
I have to compile existing C code using CNG (Cryptography API: Next Generation) functions for Windows Embedded Compact 2013. This code is using BCryptDeriveKeyPBKDF2, which is not available under Windows Embedded Compact 2013.
That means I need a replacement for the function below to implement the PBKDF2 key derivation algorithm as defined in RFC 2898 section 5.2, but without using BCryptDeriveKeyPBKDF2.
I found some C code which is using CryptoAPI functions here, but i don't want to use a 2nd, deprecated API if possible.
BOOL pbkdf2(
PUCHAR pbPassword, ULONG cbPassword,
PUCHAR pbSalt, ULONG cbSalt,
ULONGLONG cIterations,
PUCHAR pbDerivedKey, ULONG cbDerivedKey)
{
NTSTATUS status;
BCRYPT_ALG_HANDLE hAlgorithm;
status = BCryptOpenAlgorithmProvider(&hAlgorithm, BCRYPT_SHA1_ALGORITHM, NULL, BCRYPT_ALG_HANDLE_HMAC_FLAG);
if (BCRYPT_SUCCESS(status))
{
status = BCryptDeriveKeyPBKDF2(hAlgorithm, pbPassword, cbPassword, pbSalt, cbSalt, cIterations, pbDerivedKey, cbDerivedKey, 0);
BCryptCloseAlgorithmProvider(hAlgorithm, 0);
}
return BCRYPT_SUCCESS(status);
}
You could use CNG primitive such as BCryptCreateHash to implement algorithm. The most important is to use flag BCRYPT_ALG_HANDLE_HMAC_FLAG in BCryptOpenAlgorithmProvider:
void pbkdf2()
{
BCRYPT_ALG_HANDLE hAlg = NULL;
BCRYPT_HASH_HANDLE hHash = NULL;
std::vector<BYTE> pass = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 };
std::vector<BYTE> salt = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 };
std::vector<BYTE> derived_key(32);
std::vector<BYTE> dig(32);
byte t[] = { 0x00, 0x00, 0x00, 0x01 };
DWORD itcount = 10000;
SECURITY_STATUS status = BCryptOpenAlgorithmProvider(&hAlg, BCRYPT_SHA256_ALGORITHM,
nullptr, BCRYPT_ALG_HANDLE_HMAC_FLAG);
if (status != ERROR_SUCCESS) {
goto Exit;
}
status = BCryptCreateHash(hAlg, &hHash, nullptr, 0, pass.data(), pass.size(), 0);
if (status != ERROR_SUCCESS) {
goto Exit;
}
status = BCryptHashData(hHash, salt.data(), salt.size(), 0);
if (status != ERROR_SUCCESS) {
goto Exit;
}
status = BCryptHashData(hHash, t, 4, 0);
if (status != ERROR_SUCCESS) {
goto Exit;
}
status = BCryptFinishHash(hHash, dig.data(), dig.size(), 0);
if (status != ERROR_SUCCESS) {
goto Exit;
}
derived_key = dig;
BCryptDestroyHash(hHash);
for (DWORD i = 1; i < itcount; ++i)
{
status = BCryptCreateHash(hAlg, &hHash, nullptr, 0, pass.data(), pass.size(), 0);
if (status != ERROR_SUCCESS) {
goto Exit;
}
status = BCryptHashData(hHash, dig.data(), dig.size(), 0);
if (status != ERROR_SUCCESS) {
goto Exit;
}
status = BCryptFinishHash(hHash, dig.data(), dig.size(), 0);
if (status != ERROR_SUCCESS) {
goto Exit;
}
BCryptDestroyHash(hHash);
for (DWORD j = 0; j < dig.size(); ++j) {
derived_key[j] ^= dig[j];
}
}
Exit:
if (hHash) {
BCryptDestroyHash(hHash);
}
if (hAlg) {
BCryptCloseAlgorithmProvider(hAlg, 0);
}
return;
}
EDIT: to clarify meaning of t[].
According to RFC (5.2):
For each block of the derived key apply the function F defined
below to the password P, the salt S, the iteration count c, and
the block index to compute the block:
T_1 = F (P, S, c, 1) ,
T_2 = F (P, S, c, 2) ,
...
T_l = F (P, S, c, l) ,
where the function F is defined as the exclusive-or sum of the
first c iterates of the underlying pseudorandom function PRF
applied to the password P and the concatenation of the salt S
and the block index i: F (P, S, c, i) = U_1 \xor U_2 \xor ... \xor U_c
where
U_1 = PRF (P, S || INT (i)) ,
U_2 = PRF (P, U_1) ,
...
U_c = PRF (P, U_{c-1}) .
Here, INT (i) is a four-octet encoding of the integer i, most
significant octet first.
So, in my code t[] - is a four-octet encoding of the integer 1 (for the first iteration), most significant octet first.
I took this code, converted the deprecated wincrypt calls to the new CNG API, refactored it and removed the stuff which i don't need.
Although i don't understand what the code is doing, it seems that it is producing the same result than the function in my question which is using BCryptDeriveKeyPBKDF2.
#define NOCRYPT
#include <windows.h>
#include <bcrypt.h>
#include <math.h>
#include <assert.h>
#define DIGEST_SIZE 20
#define BLOCK_SIZE 64
typedef struct
{
BCRYPT_ALG_HANDLE hAlgorithm;
BCRYPT_HASH_HANDLE hInnerHash;
BCRYPT_HASH_HANDLE hOuterHash;
} PRF_CTX;
static void hmacFree(PRF_CTX* pContext)
{
if (pContext->hOuterHash) BCryptDestroyHash(pContext->hOuterHash);
if (pContext->hInnerHash) BCryptDestroyHash(pContext->hInnerHash);
if (pContext->hAlgorithm) BCryptCloseAlgorithmProvider(pContext->hAlgorithm, 0);
}
static BOOL hmacPrecomputeDigest(BCRYPT_HASH_HANDLE hHash, PUCHAR pbPassword, DWORD cbPassword, BYTE mask)
{
BYTE buffer[BLOCK_SIZE];
DWORD i;
assert(cbPassword <= BLOCK_SIZE);
memset (buffer, mask, sizeof(buffer));
for (i = 0; i < cbPassword; ++i)
{
buffer[i] = (char) (pbPassword[i] ^ mask);
}
return BCRYPT_SUCCESS(BCryptHashData(hHash, buffer, sizeof(buffer), 0));
}
static BOOL hmacInit(PRF_CTX* pContext, PUCHAR pbPassword, DWORD cbPassword)
{
BCRYPT_HASH_HANDLE hHash = NULL;
BOOL bStatus = FALSE;
BYTE key[DIGEST_SIZE];
if (!BCRYPT_SUCCESS(BCryptOpenAlgorithmProvider(&pContext->hAlgorithm, BCRYPT_SHA1_ALGORITHM, NULL, 0)) ||
!BCRYPT_SUCCESS(BCryptCreateHash(pContext->hAlgorithm, &pContext->hInnerHash, NULL, 0, NULL, 0, 0)) ||
!BCRYPT_SUCCESS(BCryptCreateHash(pContext->hAlgorithm, &pContext->hOuterHash, NULL, 0, NULL, 0, 0)))
{
goto hmacInit_end;
}
if (cbPassword > BLOCK_SIZE)
{
ULONG cbResult;
if (!BCRYPT_SUCCESS(BCryptCreateHash(pContext->hAlgorithm, &hHash, NULL, 0, NULL, 0, 0)) ||
!BCRYPT_SUCCESS(BCryptHashData(hHash, pbPassword, cbPassword, 0)) ||
!BCRYPT_SUCCESS(BCryptGetProperty(hHash, BCRYPT_HASH_LENGTH, (PUCHAR)&cbPassword, sizeof(cbPassword), &cbResult, 0)) ||
!BCRYPT_SUCCESS(BCryptFinishHash(hHash, key, cbPassword, 0)))
{
goto hmacInit_end;
}
pbPassword = key;
}
bStatus =
hmacPrecomputeDigest(pContext->hInnerHash, pbPassword, cbPassword, 0x36) &&
hmacPrecomputeDigest(pContext->hOuterHash, pbPassword, cbPassword, 0x5C);
hmacInit_end:
if (hHash) BCryptDestroyHash(hHash);
if (bStatus == FALSE) hmacFree(pContext);
return bStatus;
}
static BOOL hmacCalculateInternal(BCRYPT_HASH_HANDLE hHashTemplate, PUCHAR pbData, DWORD cbData, PUCHAR pbOutput, DWORD cbOutput)
{
BOOL success = FALSE;
BCRYPT_HASH_HANDLE hHash = NULL;
if (BCRYPT_SUCCESS(BCryptDuplicateHash(hHashTemplate, &hHash, NULL, 0, 0)))
{
success =
BCRYPT_SUCCESS(BCryptHashData(hHash, pbData, cbData, 0)) &&
BCRYPT_SUCCESS(BCryptFinishHash(hHash, pbOutput, cbOutput, 0));
BCryptDestroyHash(hHash);
}
return success;
}
static BOOL hmacCalculate(PRF_CTX* pContext, PUCHAR pbData, DWORD cbData, PUCHAR pbDigest)
{
return
hmacCalculateInternal(pContext->hInnerHash, pbData, cbData, pbDigest, DIGEST_SIZE) &&
hmacCalculateInternal(pContext->hOuterHash, pbDigest, DIGEST_SIZE, pbDigest, DIGEST_SIZE);
}
static void xor(LPBYTE ptr1, LPBYTE ptr2, DWORD dwLen)
{
while (dwLen--)
*ptr1++ ^= *ptr2++;
}
BOOL pbkdf2(
PUCHAR pbPassword, ULONG cbPassword,
PUCHAR pbSalt, ULONG cbSalt,
DWORD cIterations,
PUCHAR pbDerivedKey, ULONG cbDerivedKey)
{
BOOL bStatus = FALSE;
DWORD l, r, dwULen, i, j;
BYTE Ti[DIGEST_SIZE];
BYTE V[DIGEST_SIZE];
LPBYTE U = malloc(max((cbSalt + 4), DIGEST_SIZE));
PRF_CTX prfCtx = { 0 };
assert(pbPassword != NULL && cbPassword != 0 && pbSalt != NULL && cbSalt != 0);
assert(cIterations > 0 && pbDerivedKey > 0 && cbDerivedKey > 0);
if (!hmacInit(&prfCtx, pbPassword, cbPassword))
{
goto PBKDF2_end;
}
l = (DWORD) ceil((double) cbDerivedKey / (double) DIGEST_SIZE);
r = cbDerivedKey - (l - 1) * DIGEST_SIZE;
for (i = 1; i <= l; i++)
{
ZeroMemory(Ti, DIGEST_SIZE);
for (j = 0; j < cIterations; j++)
{
if (j == 0)
{
// construct first input for PRF
memcpy(U, pbSalt, cbSalt);
U[cbSalt] = (BYTE) ((i & 0xFF000000) >> 24);
U[cbSalt + 1] = (BYTE) ((i & 0x00FF0000) >> 16);
U[cbSalt + 2] = (BYTE) ((i & 0x0000FF00) >> 8);
U[cbSalt + 3] = (BYTE) ((i & 0x000000FF));
dwULen = cbSalt + 4;
}
else
{
memcpy(U, V, DIGEST_SIZE);
dwULen = DIGEST_SIZE;
}
if (!hmacCalculate(&prfCtx, U, dwULen, V))
{
goto PBKDF2_end;
}
xor(Ti, V, DIGEST_SIZE);
}
if (i != l)
{
memcpy(&pbDerivedKey[(i-1) * DIGEST_SIZE], Ti, DIGEST_SIZE);
}
else
{
// Take only the first r bytes
memcpy(&pbDerivedKey[(i-1) * DIGEST_SIZE], Ti, r);
}
}
bStatus = TRUE;
PBKDF2_end:
hmacFree(&prfCtx);
free(U);
return bStatus;
}
I had an interview today. This question was to optimize the code below. if we will see the code below after for loop there are four steps of "if-else" follows. So, interviewer asked me optimize it to 3 if-else line. I have tried a lot. But could not able to find the solution. Even he told me if you know scripting language then, you can use them also.
Please help me in optimizing the same.
int main()
{
int i = 1;
for(i; i <= 100; i++)
{
if((i % 3 == 0 && i % 5 == 0))
{cout << "PR\n";}
else if(i % 3 == 0)
{cout << "P\n";}
else if(i % 5 == 0)
{cout << "R\n";}
else
{cout << i <<"\n";}
}
system("pause");
return 0;
}
This is a well known question... the "FizzBuzz".
You can even solve it without any explicit IFs
const char *messages[] = {"%i\n", "P\n", "R\n", "PR\n"};
for (i=1; i<=100; i++) {
printf(messages[((i % 3)==0) + 2*((i % 5)==0))], i);
}
Here's one way, in Python:
for i in range(1, 101):
s = ''
if i % 3 == 0:
s += 'P'
if i % 5 == 0:
s += 'R'
if i % 3 != 0 and i % 5 != 0:
s = i
print(s)
Equivalently: using a flag, as shown in your own answer:
for i in range(1, 101):
s, flag = '', False
if i % 3 == 0:
flag = True
s += 'P'
if i % 5 == 0:
flag = True
s += 'R'
if not flag:
s = i
print(s)
Just for fun, a Python version of #6502's answer:
messages = ['{}', 'P', 'R', 'PR']
for i in range(1, 101):
print(messages[(i%3 == 0) + 2*(i%5 == 0)].format(i))
And finally, my personal favorite (because it's the shortest) - using the Greatest Common Divisor function and a lookup table:
from fractions import gcd
messages = {3:'P', 5:'R', 15:'PR'}
for i in range(1, 101):
print(messages.get(gcd(i, 15), i))
I found a solution.
Please let me know whether it is good or not?
int main()
{
int i = 1;int stat=0;
for(i; i <= 100; i++)
{
stat=0;
if(i%3 == 0){stat++; cout << "P";}
if(i%5 == 0){stat++; cout << "R";}
if(stat == 0)cout << i;
cout << "\n";
}
system("pause");
return 0;
}
I really like 6502's answer, but here is a simple solution without extra variables:
for(i = 1; i <= 100; i++)
{
if(i % 3 != 0 && i % 5 != 0)
{
printf("%d\n", i);
continue;
}
if(i % 3 == 0)
printf("P");
if(i % 5 == 0)
printf("R");
printf("\n");
}
this way only use 3 if
#include <iostream>
using namespace std;
int main()
{
for (int i = 0; i <= 100; ++i)
{
bool fizz = (i % 3) == 0;
bool buzz = (i % 5) == 0;
if (fizz)
cout << "Fizz";
if (buzz)
cout << "Buzz";
if (!fizz && !buzz)
cout << i;
cout << endl;
}
return 0;
}
Is there a way of modifing the algorithm in
Finding all cycles in undirected graphs
to consider edges as directed and only cycles of length <= k ?
I reply by myself
static void Main(string[] args)
{
int k = 4;
for (int i = 0; i < graph.GetLength(0); i++)
for (int j = 0; j < graph.GetLength(1); j++)
{
findNewCycles(new int[] { graph[i, j] },k);
}
foreach (int[] cy in cycles)
{
string s = "" + cy[0];
for (int i = 1; i < cy.Length; i++)
s += "," + cy[i];
Console.WriteLine(s);
}
}
static void findNewCycles(int[] path, int k)
{
int n = path[0];
int x;
int[] sub = new int[path.Length + 1];
if (path.Length < k + 1)
{
for (int i = 0; i < graph.GetLength(0); i++)
for (int y = 0; y <= 1; y = y + 2)
if (graph[i, y] == n)
// edge referes to our current node
{
x = graph[i, (y + 1) % 2];
if (!visited(x, path))
// neighbor node not on path yet
{
sub[0] = x;
Array.Copy(path, 0, sub, 1, path.Length);
// explore extended path
findNewCycles(sub,k);
}
else if ((path.Length > 2) && (x == path[path.Length - 1]))
// cycle found
{
int[] p = normalize(path);
int[] inv = invert(p);
if (isNew(p) && isNew(inv))
cycles.Add(p);
}
}
}
}
static bool equals(int[] a, int[] b)
{
bool ret = (a[0] == b[0]) && (a.Length == b.Length);
for (int i = 1; ret && (i < a.Length); i++)
if (a[i] != b[i])
{
ret = false;
}
return ret;
}
static int[] invert(int[] path)
{
int[] p = new int[path.Length];
for (int i = 0; i < path.Length; i++)
p[i] = path[path.Length - 1 - i];
return normalize(p);
}
// rotate cycle path such that it begins with the smallest node
static int[] normalize(int[] path)
{
int[] p = new int[path.Length];
int x = smallest(path);
int n;
Array.Copy(path, 0, p, 0, path.Length);
while (p[0] != x)
{
n = p[0];
Array.Copy(p, 1, p, 0, p.Length - 1);
p[p.Length - 1] = n;
}
return p;
}
static bool isNew(int[] path)
{
bool ret = true;
foreach (int[] p in cycles)
if (equals(p, path))
{
ret = false;
break;
}
return ret;
}
static int smallest(int[] path)
{
int min = path[0];
foreach (int p in path)
if (p < min)
min = p;
return min;
}
static bool visited(int n, int[] path)
{
bool ret = false;
foreach (int p in path)
if (p == n)
{
ret = true;
break;
}
return ret;
}
}