so basically i am trying to solve a leet code problem called [two sum II] using hashing
but i am getting error in this test case 1,2,3,4,4,9,56,90 where i have to find two index those elements sum is equal to target 8
well the answer of this test case is 4,5 because the sum of index4 and index5 in array[1-8] is 8
Here the problem is when i compiled this below code in vs code it works perfectly fine and gives correct output 4,5
but during leet code submission it throws wrong answer and showing output 1,3 instead of 4,5
// here is my hash implemention code
#include <stdio.h>
#include <stdlib.h>
typedef struct Hash {
int value;
int index;
struct Hash *next;
} hash;
hash *Hashes[10];
int hashify(int value) { return abs(value) % 10; }
void insert(int value, int index) {
int key = hashify(value);
if (Hashes[key] == NULL) {
Hashes[key] = malloc(sizeof(hash));
Hashes[key]->value = value;
Hashes[key]->index = index;
Hashes[key]->next = NULL;
return;
}
hash *ptr = Hashes[key];
while (ptr->next != NULL) ptr = ptr->next;
ptr->next = malloc(sizeof(hash));
ptr->next->value = value;
ptr->next->index = index;
ptr->next->next = NULL;
return;
}
int search(int value) {
int key = hashify(value);
if (Hashes[key] == NULL) return -1;
if (Hashes[key]->value == value)
return Hashes[key]->index;
else {
hash *ptr = Hashes[key]->next;
while (ptr != NULL) {
if (ptr->value == value) return ptr->index;
ptr = ptr->next;
}
return -1;
}
}
// here is hash_free function
void Hash_free() {
for (int i = 0; i < 10; i++) {
if (Hashes[i] == NULL)
continue;
else {
if (Hashes[i]->next == NULL) {
free(Hashes[i]);
Hashes[i] = NULL;
} else {
hash *ptr;
while (ptr != NULL) {
ptr = Hashes[i]->next;
free(Hashes[i]);
Hashes[i] = ptr;
}
}
}
}
}
// here is two sum function code
int *twoSum(int *numbers, int numbersSize, int target, int *returnSize) {
int *result;
if (numbersSize == 2) {
result = malloc(2 * sizeof(int));
result[0] = 1;
result[1] = 2;
*returnSize = 2;
return result;
} else {
int val, element;
for (int i = 0; i < numbersSize; i++) {
val = target - numbers[i];
element = search(val);
if (element != -1) {
result = malloc(2 * sizeof(int));
if (element < i) {
result[0] = element + 1;
result[1] = i + 1;
} else {
result[0] = i + 1;
result[1] = element + 1;
}
*returnSize = 2;
Hash_free();
return result;
}
insert(numbers[i], i);
}
}
return NULL;
}
// here is main code
int main() {
int numbers[] = {1, 2, 3, 4, 4, 9, 56, 90};
int target = 8;
int numberSize = sizeof(numbers) / sizeof(int);
int returnSize;
int *res = twoSum(numbers, numberSize, target, &returnSize);
for (int i = 0; i < returnSize; i++) {
printf("%d ", res[i]);
}
free(res);
return 0;
}
Your "hash" variable is global, so it keeps preserving data of previous testcase executed. I have faced the same when using global variable.
Solution:
Just clear your hash or initialize it, in your main function( or the entry point function), so that it will ensure a fresh start for each of the test cases those are executed.
I have a custom implementation for _strdup. It shouldn't have any dependencies, which means I cannot use CRT or anything built-in. The code below works fine. The only problem is that it depends on malloc. Therefore I can't use it with /NODEFAULTLIB, unless I implement my own malloc.
Any ideas for non-dependent implementations? Or at least a malloc/free implementation. I would even accept a shellcode implementation.
size_t __strlen(const char* str)
{
const char* s;
for (s = str; *s; ++s)
;
return (s - str);
}
void* __memcpy(void* to, const void* from, size_t count)
{
register char* f = (char*)from;
register char* t = (char*)to;
register size_t i = count;
while (i-- > 0)
*t++ = *f++;
return to;
}
char* __strdup(const char* str)
{
size_t len;
char* copy;
len = __strlen(str) + 1;
if (!(copy = (char*)malloc(len)))
return nullptr;
__memcpy(copy, str, len);
return copy;
}
I found a broken malloc implementation:
#define MEMORY_CAPACITY 20000
void* mov_sbrk(int increment)
{
static char global_mem[MEMORY_CAPACITY] = { 0 };
static char* p_break = global_mem;
char* const limit = global_mem + MEMORY_CAPACITY;
char* const original = p_break;
if (increment < global_mem - p_break || increment >= limit - p_break)
{
errno = ENOMEM;
return (void*)-1;
}
p_break += increment;
return original;
}
//=======================================================================
#define ALIGNMENT 8
#define ALIGN(size) (((size) + (ALIGNMENT-1)) & ~(ALIGNMENT-1))
typedef struct list_t list_t;
struct list_t
{
unsigned in_use : 1; /* if the block is used or not */
size_t order; /* current order of block (2^order) */
list_t* succ; /* right child block in tree */
list_t* pred; /* left child block in tree */
};
#define K_MAX 22
#define K_MAX_SIZE (1 << K_MAX)
#define ORDER_0 4
// Size of the node metadata
#define META_SIZE (ALIGN(sizeof(list_t)))
static list_t* find_block(size_t);
static size_t get_order(size_t);
static list_t* split(list_t*, size_t);
/* Array of pointers to first block of order k at free_list[k] */
static list_t* freelist[K_MAX + 1];
static void* start = NULL;
static void print_freelist()
{
for (int i = ORDER_0; i <= K_MAX; i++)
{
int f = 0;
int j = 0;
list_t* current = freelist[i];
while (current)
{
if (!current->in_use)
{
f++;
}
j++;
current = current->succ;
}
}
}
void* malloc(size_t requested_size)
{
print_freelist();
if (requested_size <= 0)
{
return NULL;
}
if (!start)
{
// First allocation ever, grab memory and root the tree
start = mov_sbrk(K_MAX_SIZE);
list_t* top = reinterpret_cast<list_t*>(start);
top->order = K_MAX;
top->in_use = 0;
top->succ = NULL;
top->pred = NULL;
freelist[K_MAX] = top;
}
/* E.g. if requested size is 56 bytes, k = 6 (2^6=64)*/
size_t k = get_order(ALIGN(requested_size + META_SIZE));
list_t* r = find_block(k);
if (r) {
r->in_use = 1;
print_freelist();
return (r + 1);
}
else {
return NULL;
}
}
/* Find the smallest power of 2 larger than k */
static size_t get_order(size_t v)
{
int k = ORDER_0;
while ((1 << k) < v) {
k++;
}
return k;
}
// finds a suitable block of order k. if not found return null
static list_t* find_block(size_t k)
{
if (k > K_MAX)
return NULL;
list_t* current = freelist[k];
while (current) {
if (!current->in_use)
return current;
current = current->succ;
}
list_t* big_block = find_block(k + 1);
if (big_block) {
current = split(big_block, k);
}
return current;
}
static void remove_from_freelist(list_t* item)
{
size_t k = item->order;
if (freelist[k] == item)
freelist[k] = item->succ;
if (item->pred)
item->pred->succ = item->succ;
if (item->succ)
item->succ->pred = item->pred;
item->pred = NULL;
item->succ = NULL;
}
static void add_to_freelist(list_t* item)
{
size_t k = item->order;
if (!freelist[k])
{
freelist[k] = item;
item->succ = NULL;
item->pred = NULL;
return;
}
item->pred = NULL;
item->succ = freelist[k];
freelist[k]->pred = item;
freelist[k] = item;
}
static list_t* split(list_t* src, size_t new_order)
{
while (src->order > new_order)
{
/* src becomes left buddy */
remove_from_freelist(src);
// set new order
src->order = src->order - 1;
// calculate half size of old block, aka size of new order.
size_t size = 1 << src->order;
list_t* right = reinterpret_cast<list_t*>(src + size);
right->order = src->order;
right->in_use = 0;
add_to_freelist(right);
add_to_freelist(src);
}
return src;
}
static void merge(list_t* block)
{
if (block->in_use || block->order == K_MAX)
return;
list_t* buddy = (list_t*)((uint64_t)start + (block - start) ^ (1 << block->order));
if (buddy->in_use || buddy->order != block->order)
return;
list_t* left = block;
list_t* right = buddy;
if (block > buddy) {
left = buddy;
right = block;
}
remove_from_freelist(right);
remove_from_freelist(left);
left->order++;
add_to_freelist(left);
merge(left);
}
void free(void* ptr)
{
print_freelist();
if (!ptr)
return;
list_t* block = (((list_t*)ptr) - 1);
block->in_use = 0;
merge(block);
print_freelist();
}
void* calloc(size_t nbr_elements, size_t element_size)
{
size_t size = nbr_elements * element_size;
void* ptr = malloc(size);
if (ptr == NULL)
return NULL;
memset(ptr, 0, size);
return ptr;
}
void* realloc(void* ptr, size_t size)
{
if (!ptr) {
return malloc(size);
}
list_t* block = (((list_t*)ptr) - 1);
if ((1 << block->order) - META_SIZE >= size) {
return ptr;
}
void* new_ptr = malloc(size);
if (!new_ptr) {
return NULL;
}
memcpy(new_ptr, ptr, (1 << block->order) - META_SIZE);
free(ptr);
return new_ptr;
}
Since you have mentioned /nodefaultlib option, seems like you are on Windows. Then instead of using malloc() you can directly use Windows API function HeapAlloc() and then HeapFree() to free copy of the string later. You may want to wrap them into you own __malloc() and __free(), like this:
void* __malloc(size_t size)
{
return HeapAlloc(GetProcessHeap(), 0, size);
}
void __free(void* p)
{
if (p) HeapFree(GetProcessHeap(), 0, p);
}
I compiled in C with -O3 and as share library on Linux Fedora x64. I used some mallocs after one. It seems when I work with wmemcpy and other functions in this family the change in one memory makes change in other...
I may violate size of memory? Or the problem is in my implementation?
Thanks in advance!
char* ur_free_available(struct memory_pool* pool, uint64_t sz)
{
uint64_t size = sz + sizeof(struct _MyPage);
if(pool->free_pos > 0)
{
if(pool->free_blocks[pool->free_pos - 1].pNext - pool->free_blocks[0].pNext > size)
{
uint64_t i, j;
char *addr;
struct _MyPage mpg;
for(i = 1; i < pool->free_pos; ++i)
{
if(pool->free_blocks[i].pNext - pool->free_blocks[0].pNext > size)
{
mpg.pPrev = NULL;
mpg.pNext = pool->free_blocks[i-1].pNext;
break;
}
}
pool->free_blocks[0].pPrev = NULL;
for(j = i; j < pool->free_pos; ++j)
{
if(j > 0)
pool->free_blocks[j-i].pPrev = pool->free_blocks[j-1].pPrev;
pool->free_blocks[j-i].pNext = pool->free_blocks[j].pNext;
}
pool->free_pos -= i;
pool->free_pos++;
memcpy(addr,(char*)&mpg, sizeof(mpg));
return &addr[0] + sizeof(struct _MyPage);
}
}
return NULL;
}
char* ur_mem_alloc(struct memory_pool* pool, uint64_t sz)
{
char *addr;
struct _MyPage mpg;
uint64_t size = sz + sizeof(mpg);
uint64_t j = 0, c, op;
if(pool->init_pos_is != 7)
{
//bzero(pool, sizeof(pool));
pool->init_pos_is = 7;
pool->free_pos = 0;
pool->hp_position = 0;
pool->st_position = 0;
mpg.pPrev = NULL;
for(c = 0; c < HP_CNT; c++)
pool->_extramem[c] = NULL;
pool->free_blocks[0].pNext = NULL;
//pool->_bytes = malloc(ST_MYPAGE_NO*ST_MYPAGE_SIZE);
//pthread_mutex_lock(&llk1);
_mpool = pool;
//pthread_mutex_unlock(&llk1);
atexit(equit);
}
if((addr = ur_free_available(pool, size)) != NULL)
{
return &addr[0];
}
op = pool->hp_position;
if(size + (ST_MYPAGE_SIZE * pool->st_position) > ST_MYPAGE_NO * ST_MYPAGE_SIZE)
{
uint64_t i;
for(i = 0; i < HP_CNT; ++i)
{
if(size < (pow(8, i)-pool->hp_position)*HP_MYPAGE_SIZE)
{
j = i;
if(pool->_extramem[i] == NULL)
{
pool->hp_position = 0;
pthread_mutex_lock(&llk2);
pool->_extramem[i] = (char*)malloc((uint64_t)pow(8, i) * HP_MYPAGE_SIZE);
pthread_mutex_unlock(&llk2);
}
break;
}
}
addr = &pool->_extramem[j][pool->hp_position*HP_MYPAGE_SIZE];
mpg.pPrev = (struct _MyPage*)&pool->_extramem[j][op*HP_MYPAGE_SIZE];
//printf("j %u %u %u\n", j, (uint64_t)size, (uint64_t)(pow(8, i-1))*HP_MYPAGE_SIZE);
pool->hp_position += floor(size/HP_MYPAGE_SIZE) + 1;
mpg.pNext = (struct _MyPage*)&pool->_extramem[j][pool->hp_position*HP_MYPAGE_SIZE];
memcpy(addr,(char*)&mpg, sizeof(mpg));
return &addr[0] + sizeof(struct _MyPage);
//
}
else
{
if(pool->st_position != 0)
{
mpg.pPrev = (struct _MyPage*)&pool->_extramem[j][(pool->hp_position)];
}
mpg.pNext = NULL;
pool->st_position += floor(size/ST_MYPAGE_SIZE);
addr = &pool->_bytes[(uint64_t)(pool->st_position-floor(size/ST_MYPAGE_SIZE)) * ST_MYPAGE_SIZE];
memcpy(addr,(char*)&mpg, sizeof(mpg));
return &addr[0] + sizeof(struct _MyPage);
}
}
void ur_mem_free(struct memory_pool* pool, char *addr)
{
if(addr == NULL) return;
pool->free_blocks[pool->free_pos].pPrev = pool->free_blocks[pool->free_pos].pNext;
pool->free_blocks[pool->free_pos].pNext = (struct _MyPage*)(addr - sizeof(struct _MyPage));
pool->free_pos++;
}
Breafly looking into function ur_free_available, the variable addr is not initialized, but you memcpy to it corrupting a random memory region. Then you try to return something using the same non-initialized pointer.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
its a very very anoing problem what i get. My problem is, gcc seems not allocate enough space to my int pointer.
Here is the code:
fns = (int*)calloc(c,sizeof(int));
So, after then i fill up this in a simple loop ones and zeros:
offset = seekToFirstParam(fnString,n);
i = 0;
while(i<c) {
tmp[i] = readNextParam(fnString,n,offset,&s);
if (isFunctionString(tmp[i])) {
fns[i] = 1;
} else {
fns[i] = 0;
}
i++;
}
So this is a "flag" array, but when i debug this, and print the elements i get:
156212102, 0, 0, 0, 1, 1
Or som. like this. I don't get it, because if in the calloc method i write 1000 like this:
fns = (int*)calloc(1000,sizeof(int));
After works fine.
Ok, this is a hole function:
char **readFnParams(char *fnString, int n, int *count, int **func) {
char **tmp;
int *fns = NULL;
int c,i = 0,offset,s;
c = getParamsCount(fnString,n);
if (!c) {
return NULL;
}
tmp = (char**)calloc(c,sizeof(char));
fns = (int*)calloc(c,sizeof(int*));
offset = seekToFirstParam(fnString,n);
while(i<c) {
tmp[i] = readNextParam(fnString,n,offset,&s);
if (isFunctionString(tmp[i])) {
tmp[i] = readNextFunctionParam(fnString,n,offset,&s);
offset = seekToNextParam(fnString,n,offset + s - 1);
fns[i] = 1;
} else {
fns[i] = 0;
offset = seekToNextParam(fnString,n,offset);
}
i++;
}
*func = fns;
*count = c;
return tmp;
}
:) Ok, this is a hole .c file. Yes my previous q. end this connected, becouse its a homework.
#ifndef exccel_builder_source
#define exccel_builder_source
#include "exccel_builder.h"
#include "exccel_utils.h"
#include "exccel_function.h"
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
table* _processing;
//A végére fűzi az új elemeket
void addProcess(cell_process **LIST, cell_process *new) {
if (*LIST == NULL) {
new->next = NULL;
*LIST = new;
return;
}
new->next = *LIST;
*LIST = new;
}
void build(table* table) {
int col = table->matrix->col;
int row = table->matrix->row;
int i,j;
table_cell *cellTemp;
_processing = table;
for (i = 1; i<=row; i++) {
for (j = 1; j<=col; j++) {
cellTemp = getCell(table,i,j);
if (cellTemp != NULL) {
buildCell(cellTemp);
}
}
}
}
void buildCell(table_cell *cell) {
//Begins with '='
if (isFunction(cell)) {
buildCellWithFunction(cell);
}
}
void printProcesses(cell_process *LIST, int tab) {
cell_process *tmp = NULL;
int i = 0;
tmp = LIST;
while(tmp != NULL) {
i = 0;
while(i++<tab) printf(" ");
printf("%s, %d, paramPos: %i\n",tmp->func->name,tmp->func->paramsCount,tmp->paramPos);
if (tmp->childs != NULL) {
i = 0;
while(i++<tab + 3) printf(" ");
printf("Childs\n");
printProcesses(tmp->childs, tab + 3);
}
tmp = tmp->next;
}
}
void buildCellWithFunction(table_cell *cell) {
cell_process *HEAD = NULL;
buildCellProcessList(cell,&HEAD);
cell->cp = HEAD;
printf("%d,%d - cella:\n",cell->row,cell->col);
printProcesses(HEAD,0);
}
void buildCellProcessList(table_cell *cell, cell_process **HEAD) {
char *fnString;
int size;
fnString = getCellStringValue(cell, &size);
readFn(fnString,size,1,cell,HEAD,-1);
}
int readFn(char *fnString, int n, int offset, table_cell *cell, cell_process **LIST, int paramPos) {
char *fnName, *fnParam;
int fnNameLength;
int *fnSig;
int fnSigN;
int fnSigI;
int sig;
exccel_var *vtmp;
exccel_function *ftmp;
cell_process *ptmp;
char **parameters;
int *fnIndexes;
int paramsCount;
int paramI;
int i;
fnName = readFnName(fnString,n,offset,&fnNameLength);
ftmp = getExccelFunction(fnName);
if (ftmp == NULL) {
return 0;
}
ptmp = (cell_process*)malloc(sizeof(cell_process));
ptmp->cell = cell;
ptmp->func = ftmp;
ptmp->paramPos = paramPos;
ptmp->t = _processing;
ptmp->childs = NULL;
addProcess(LIST,ptmp);
parameters = readFnParams(fnString,n,¶msCount,&fnIndexes);
allocParams(ptmp->func,paramsCount);
paramI = 0;
fnSig = ftmp->signature;
fnSigN = fnSig[0];
fnSigI = 1;
while(fnSigI <= fnSigN) {
sig = fnSig[fnSigI];
if (sig == FN_SIG_RANGE) {
fnParam = parameters[paramI];
vtmp = createExccelRangeVarFromString(fnParam);
//addParamToFunction(ftmp,vtmp);
addParamToFunctionAtPosition(ftmp,vtmp,paramI);
paramI++;
} else if (sig == FN_SIG_LITERAL) {
fnParam = parameters[paramI];
if (fnIndexes[paramI] == 1) {
readFn(fnParam,strlen(fnParam),0,cell,&((*LIST)->childs),paramI);
} else {
vtmp = createExccelVarFromString(fnParam);
//addParamToFunction(ftmp,vtmp);
addParamToFunctionAtPosition(ftmp,vtmp,paramI);
}
paramI++;
} else if (sig == FN_SIG_LIST) {
while(paramI<paramsCount) {
fnParam = parameters[paramI];
if (fnIndexes[paramI] == 1) {
readFn(fnParam,strlen(fnParam),0,cell,&((*LIST)->childs),paramI);
} else {
vtmp = createExccelVarFromString(fnParam);
//addParamToFunction(ftmp,vtmp);
addParamToFunctionAtPosition(ftmp,vtmp,paramI);
}
paramI++;
}
} else {
printf("Invalid signature %d\n",sig);
exit(1);
}
fnSigI++;
}
return 1;
}
char *readFnName(char *fnString, int n, int offset, int *size) {
char *fnName;
int nameBuffer, i, j;
i = offset;
j = 0;
nameBuffer = 8;
fnName = (char *)calloc(nameBuffer,sizeof(char));
while(*(fnString + i) != '(' && i<n) {
*(fnName + j++) = *(fnString + i++);
if (j>=nameBuffer) {
nameBuffer += 8;
fnName = (char *)realloc(fnName, nameBuffer);
}
}
*(fnName + j++) = '\0';
*size = j;
return fnName;
}
char **readFnParams(char *fnString, int n, int *count, int **func) {
char **tmp;
int *fns = NULL;
int c,i = 0,offset,s;
c = getParamsCount(fnString,n);
if (!c) {
return NULL;
}
tmp = (char**)calloc(c,sizeof(char));
fns = (int*)calloc(c,sizeof(*fns));
offset = seekToFirstParam(fnString,n);
while(i<c) {
tmp[i] = readNextParam(fnString,n,offset,&s);
if (isFunctionString(tmp[i])) {
tmp[i] = readNextFunctionParam(fnString,n,offset,&s);
offset = seekToNextParam(fnString,n,offset + s - 1);
fns[i] = 1;
} else {
fns[i] = 0;
offset = seekToNextParam(fnString,n,offset);
}
i++;
}
*func = fns;
*count = c;
return tmp;
}
int getParamsCount(char *fnString, int n) {
int i = 0, c = 0, jump = 0;
while(i<n) {
if (fnString[i] == '(') {
jump++;
} else if (fnString[i] == ',') {
if (jump == 1) c++;
} else if (fnString[i] == ')') {
jump--;
}
i++;
}
if (c > 0) {
return c + 1;
} else {
return 1;
}
}
int seekToFirstParam(char *fnString, int n) {
int i = 0;
while(fnString[i++] != '(' && i<n);
return i;
}
int seekToNextParam(char *fnString, int n, int offset) {
int i = offset;
while(fnString[i++] != ',' && i<n);
return i;
}
char *readNextParam(char *fnString, int n, int offset, int *size) {
char *params, c;
int paramBuffer, i, j;
i = offset;
j = 0;
paramBuffer = 8;
params = (char*)calloc(paramBuffer,sizeof(char));
while((c = fnString[i++]) != ',' && c != ')' && c != '(' && i<n) {
params[j++] = c;
if (j >= paramBuffer) {
paramBuffer += 8;
params = (char*)realloc(params,paramBuffer);
}
}
params[j] = '\0';
*size = j;
return params;
}
//Megfelelő számú nyitó ( - hez kell hogy legyen ugyanannyi )
char *readNextFunctionParam(char *fnString, int n, int offset, int *size) {
char *fn, c;
int fnBf, i, j, fnStarted = 0, fnClosed = 0;
i = offset;
j = 0;
fnBf = 8;
fn = (char*)calloc(fnBf, sizeof(char));
while((fnStarted != fnClosed || fnStarted == 0) && i<n) {
c = *(fnString + i++);
if (c == '(')
fnStarted++;
else if (c == ')')
fnClosed++;
*(fn + j++) = c;
if (j >= fnBf) {
fnBf += 8;
fn = (char*)realloc(fn, sizeof(char) * fnBf);
}
}
//*(fn + j++) = ')';
*(fn + j++) = '\0';
*size = j;
return fn;
}
#endif
And input like this:
=SZORZAT(MDETERM(A1:D4),NAGY(A1:D4,0),10,20,30)
It looks to me like you aren't allocating correctly, you have:
tmp = (char**)calloc(c,sizeof(char));
The first line, tmp, is allocating c elements of size char (c elements of 1 byte), I think you want c elements of size char * (c elements of size 4 or 8 bytes per element depending on if you are 32 or 64 bit platform). Since your routine readNextParam() is returning char * to store in this array, you need to change the calloc sizeof for tmp to:
tmp = calloc(c,sizeof(char*));
Because of this, I believe you have memory overwrites when you write into the tmp array that bleed into your other array. By making both "1000" elements, you've padded out that first calloc far enough that the overwrites are still in that same piece of memory.
in the following code when ran will produce a Segmentation Fault, due to a FILE* being passed to fclose which contains no address (NULL).
I'm wondering why this is happening, the FILE* isn't being used what so over.
The FILE* is named urandom and is passed to fclose in the main function.
Thanks
#include <stdio.h>
#include <stdlib.h>
struct property
{
char *name;
unsigned int value;
unsigned int owner;
unsigned int type;
};
struct player
{
unsigned int id;
unsigned int money;
unsigned int position;
};
int rollDice(FILE *);
int amountOfLines(FILE *);
int createArrayOfPtrs(int ,void ***);
int makeArryOfPropertyPtrs(int ,struct property **);
int FillArryPropertyData(struct property **,int ,FILE *);
int splitBuffer(char *,unsigned int *,char **);
int bufferPropertyFile(FILE *,char **,int );
i nt fillPropertyStruct(struct property *,unsigned int ,char *);
int main(void)
{
int linesInPropertyFile = 0;
struct property **arrayForProperties = 0;
//Open /dev/urandom for rollDice
FILE *urandom = fopen("/dev/urandom","rb");
FILE *propertyFile = fopen("/home/jordan/Documents/Programming/Monopoly Project/properties","rb");
if(propertyFile == NULL || urandom == NULL)
{
puts("ERROR: error in opening file(s)");
return 1;
}
linesInPropertyFile = amountOfLines(propertyFile);
//DEBUG
printf("%d is contained within \"linesInPropertyFile\"\n",linesInPropertyFile);
if(createArrayOfPtrs(linesInPropertyFile,(void ***)&arrayForProperties))
{
puts("ERROR: error from createArrayOfPointers()");
return 1;
}
//DEBUG
printf("Outside Pointer: %p\n",arrayForProperties);
if(makeArryOfPropertyPtrs(linesInPropertyFile,arrayForProperties))
{
puts("ERROR: error from createArrayOfPointersForProperties()");
return 1;
}
if(FillArryPropertyData(arrayForProperties,linesInPropertyFile,propertyFile))
{
puts("ERROR: error from FillArryPropertyData()");
}
//Close FILE stream for /dev/urandom
fclose(urandom);
fclose(propertyFile);
return 0;
}
int FillArryPropertyData(struct property **array,int amntOfProperties,FILE *fp)
{
int bufferUsed = 100;
int i = 0;
int returnValue = 0;
int returnValue2 = 0;
unsigned int money = 0;
char *name;
char *buffer;
rewind(fp);
while(returnValue == 0)
{
buffer = malloc(bufferUsed);
returnValue = bufferPropertyFile(fp,&buffer,bufferUsed);
if(returnValue && returnValue != -1)
{
puts("ERROR: error from bufferPropertyFile()");
return -1;
}
if(returnValue == -1)
{
break;
}
if(buffer[0] != '\0')
{
returnValue2 = splitBuffer(buffer,&money,&name);
}
if(returnValue2)
{
puts("ERROR: error in splitBuffer()");
return 1;
}
if(fillPropertyStruct(array[i],money,name))
{
puts("ERROR: error in fillPropertyStruct()");
return 1;
}
money = 0;
i++;
}
free(buffer);
return 0;
}
int fillPropertyStruct(struct property *array,unsigned int money,char *name)
{
int nameSize = 100;
int i = 0;
array->name = malloc(nameSize);
array->value = money;
while(1)
{
if(i >= nameSize)
{
void *tmp = realloc(array->name,nameSize * 2);
nameSize *= 2;
if(tmp)
{
array->name = tmp;
}
else
{
return -1;
}
}
if(name[i] == '\0')
{
break;
}
array->name[i] = name[i];
i++;
}
array->name[i] = '\0';
return 0;
}
int splitBuffer(char *buffer,unsigned int *money,char **name)
{
int i = 0;
int j = 1;
int nameSize = 100;
*name = malloc(nameSize);
while(1)
{
if(buffer[j] != '"')
{
(*name)[j-1] = buffer[j];
}
else
{
i++;
}
j++;
if(i)
{
break;
}
if(j >= nameSize)
{
void *tmp = 0;
tmp = realloc(*name,nameSize * 2);
nameSize = nameSize * 2;
if(tmp != NULL)
{
*name = tmp;
}
else
{
puts("ERROR: error in splitBuffer");
return -1;
}
}
}
name[j-1] = '\0';
while(buffer[j] != '$')
{
if(buffer[j] == '\0')
{
puts("ERROR: error in splitBuffer()");
return -2;
}
j++;
}
j++;
while(buffer[j] != '\0')
{
*money += (buffer[j] - '0');
if(buffer[j+1] != '\0')
{
*money *= 10;
}
j++;
}
printf("BUFFER: %s\n",buffer);
printf("NAME: %s\n",*name);
printf("MONEY: %d\n",*money);
return 0;
}
int bufferPropertyFile(FILE *fp,char **buffer,int i)
{
int j = (i - i);
if(feof(fp))
{
//-1 Returned if EOF detected
return -1;
}
char retr = 0;
while(1)
{
if(j + 1 >= i)
{
void *tmp = realloc(*buffer,i * 2);
if(tmp != NULL)
{
*buffer = tmp;
i = i * 2;
}
else
{
puts("ERROR: error in bufferPropertyFile()");
return -2;
}
}
retr = fgetc(fp);
if(retr == '\n' || feof(fp))
{
break;
}
(*buffer)[j] = retr;
j++;
}
(*buffer)[j] = '\0';
if(**buffer == '\0')
{
return -1;
}
return 0;
}
int rollDice(FILE *fp)
{
int seed = fgetc(fp);
srand(seed);
return (rand() % 6) + 1;
}
int amountOfLines(FILE *file)
{
int i = 0;
int retr = 0;
while(1)
{
retr = fgetc(file);
if(retr == EOF)
{
break;
}
if(retr == '\n' )
{
i++;
}
}
return i;
}
int createArrayOfPtrs(int numberOfPointers,void ***pointer)
{
void *tmp = malloc(numberOfPointers * sizeof (tmp));
if(tmp != NULL)
{
*pointer = tmp;
//DEBUG
printf("Pointer: %p\n",*pointer);
}
else
{
return 1;
}
return 0;
}
int makeArryOfPropertyPtrs(int numberOfPointers,struct property **pointer)
{
int i = 0;
void *tmp;
for(i = 0;i < numberOfPointers;i++)
{
tmp = malloc(sizeof(struct property));
if(tmp == NULL)
{
return 1;
}
pointer[i] = (struct property *)tmp;
}
return 0;
}
here it givest an access violation in splitBuffer on this line:
name[j-1]='\0';
which probably should be
(*name)[j-1]='\0';
indeed that memory is not allocated anywhere, in other words, undefined behaviour, which indeed in your case might overwrite the urandom variable: both urandom and name are allocated on stack so depending on value of j it might write over urandom..
apart from that, there might be more errors, the number and use of pointers/mallocs/reallocs and lack of frees is a bit scary
int createArrayOfPtrs(int ,void ***);
if(createArrayOfPtrs(linesInPropertyFile,(void ***)&arrayForProperties))
This is undefined behaviour, a (void***) is not compatible to a (struct property ***). Why do you even use it here, all the other functions use struct property pointers?
Since the array is located right before the file pointer in the local variables of main, maybe the problem is that the array creation/initialization overwrites urandom?