I'm trying to understand how to create & handle an array of unsigned char arrays in C++. Such as:
Array[0] = { new array of unsigned chars }
Array[1] = { new array of unsigned chars }
Array[2] = { new array of unsigned chars }
....and so on
I've written the next code but I have the feeling that I'm doing something wrong. The code works correctly, but I don't know if the way I declare the "buffer" and how I delete the cache is the correct way, or if it can produce a memory leak.
#define MAX_BUFFER 10
unsigned char* cache[MAX_BUFFER];
bool cache_full = false;
void AddToCache(unsigned char *buffer, const size_t buffer_size)
{
if (cache_full == true)
{
return;
}
for (int index = 0; index < MAX_BUFFER; index++)
{
if (cache[index] == NULL)
{
cache[index] = new unsigned char[buffer_size];
memcpy(cache[index], buffer, buffer_size);
}
if (index < MAX_BUFFER - 1)
{
cache_full = true;
}
}
}
void ClearCache()
{
for (int index = 0; index < MAX_BUFFER; index++)
{
if (cache[index] != NULL)
{
delete[] cache[index];
cache[index] = NULL;
}
}
cache_full = false;
}
bool IsCacheFull()
{
return cache_full;
}
This works?
memcpy(cache, buffer, buffer_size);
It shouldn't. That's overwriting all the pointers in cache with the contents of buffer. In context, this should probably be:
memcpy(cache[index], buffer, buffer_size);
Also, you'll be setting cache_full to true, repeatedly, every time you add to the cache. Try:
AddToCache(unsigned char *buffer, const size_t buffer_size)
{
for (int index = 0; index < MAX_BUFFER; index++)
{
if (cache[index] == NULL)
{
cache[index] = new unsigned char[buffer_size];
memcpy(cache[index], buffer, buffer_size);
return(index); // in case you want to find it again
}
}
// if we get here, we didn't find an empty space
cache_full = true;
return -1;
}
Related
EDIT: Clarification:
If I have an array int* a = new int[10], I want to get a pointer to a, but only the values from 0 to 5, without having to allocate another array for those values.
Original post:
I created a small class to fuzz my functions, but the thing is that it is painfully slow. It takes roughly 10-20 seconds to run my function 1000 times.
I decided to improve my code by allocating a very large array at first, then filling it from 0 to a randomly generated number and then just returning a pointer to that range to use in my function instead of allocating memory and deleting it each time.
Below is my code.
I attempt to allocate 1 million bytes at first, then I want to return a range from 0 to whatever size my class generated. Currently I allocate memory once more for returning it, but that's not efficient.
I use Xorshift to generate random numbers, which should be much faster than rand() so I think besides memory allocation it's pretty good, but any suggestions are very much welcome!
Note: if you do not understand part of my code ask me (it's written quickly, so it might be unintelligible at certain parts) ;)
class fuzz {
public:
fuzz() {
this->alloc_init_buff();
}
~fuzz() {
this->dealloc_init_buff();
}
int fill_buff(unsigned int size) {
if (size > this->m_buffsize) { size = this->m_buffsize; }
for (int i = 0; i < size; ++i) {
this->m_buff[i] = this->rand_xor();
}
return size;
}
int fill_buff() {
int size = this->rand_xor(1, this->m_buffsize);
if (size > this->m_buffsize) { size = this->m_buffsize; }
for (int i = 0; i < size; ++i) {
this->m_buff[i] = this->rand_xor();
}
return size;
}
unsigned char*& get_buff(int size) {
unsigned char* temp = new unsigned char[size];
memcpy((void*)temp, (void*)this->m_buff, size);
return temp;
}
private:
struct xr_xorshift_state {
unsigned int a = 123456789, b = 362436069, c = 521288629, d = 88675123;
};
unsigned int xorshift(xr_xorshift_state* state) {
unsigned int res = 0;
res = state->a ^ (state->a << 11);
state->a = state->b; state->b = state->c; state->c = state->d;
state->d = state->d ^ (state->d >> 19) ^ (res ^ (res >> 8));
res &= 0x7fffffff;
return res;
}
unsigned int rand_xor() {
return this->xorshift(&this->m_state);
}
unsigned int rand_xor(unsigned int min, unsigned int max) {
return (min + (this->rand_xor() % (max - min)));
}
void alloc_init_buff() {
this->m_buff = new unsigned char[this->m_buffsize];
}
void dealloc_init_buff() {
delete[] this->m_buff;
}
xr_xorshift_state m_state = { 0 };
unsigned char* m_buff = { 0 };
unsigned int m_buffsize = { 1000000 };
};
int find_newline(const char* text, int size) {
int pos = 0;
while (*text != '\n') {
if (pos == size) { return 0; }
++text; ++pos;
}
return pos;
}
int main() {
fuzz fz = {};
unsigned char* randdata = nullptr;
int lap = 0;
int th = 0;
for (;;) {
if (lap == 1000) {
lap = 0;
++th;
printf("%d thousand laps done!\n", th);
}
try {
int size = fz.fill_buff();
randdata = fz.get_buff(size);
const char* d = (const char*)randdata;
find_newline(d, size);
delete[] randdata;
++lap;
}
catch (...) {
printf("error!\n");
++lap;
}
}
getchar();
return 0;
}
I am implementing my version of the basic String class, however I am running into an issue that I have never seen before and have no idea how to properly debug. My code is pasted below. All functions have their header counterparts. My test is simply creating one object using the convert constructor.
A4String obj1("this");
My problem is I get an Access violation reading location exception thrown. My research has indicated that I may be trying to access memory outside of Visual Studio's allotment. I'm having trouble finding where this pointer error exists though. I have placed breakpoints through every step of the convert constructor and subsequent function calls within however my program doesn't throw the exception until it returns to main, seemingly after my program has executed completely.
#include "A4String.h"
A4String::A4String() {
data = new char[5];
data[0] = '\0';
capacity = 5;
}
A4String::~A4String() {
if (capacity != 0)
delete[] data;
}
//Copy Constructor
A4String::A4String(const A4String &right) {
cout << "copy" << endl;
data = new char[right.capacity + 1];
strcpy(data, right.data, capacity);
capacity = right.capacity;
}
//Convert Constructor
A4String::A4String(const char *sptr) {
cout << "convert" << endl;
capacity = (strlen(sptr)) + 1;
data = new char[capacity + 1];
strcpy(sptr, data, capacity);
}
//Assignment
A4String& A4String::operator = (const A4String & right) {
//if (capacity != 0) delete[] data;
data = new char[right.capacity + 1];
strcpy(data, right.data, capacity);
capacity = right.capacity;
return *this;
}
//Equivalence
bool A4String::operator == (const A4String &right) const {
return (strcmp(data, right.data)) == 0;
}
int A4String::length() const {
return capacity;
}
void A4String::addChar(char) {
//Not implemented yet
}
string A4String::toString() {
string str = "";
int i = 0;
while (data[i] != '\0') {
str += data[i];
i++;
}
return str;
}
void A4String::strcpy(const char *source, char* destination, int size)
{
for (int i = 0; i < 20; i++)
destination[i] = '\0';
int index = 0;
while (source[index] != '\0')
{
destination[index] = source[index];
index++;
}
destination[index] = '\0';
}
int A4String::strcmp(char *str1, char *str2)
{
if (*str1 < *str2)
return -1;
if (*str1 > *str2)
return 1;
if (*str1 == '\0')
return 0;
return strcmp(str1 + 1, str2 + 1);
return 0;
}
int A4String::strlen( char *s)
{
char *start;
start = s;
while (*s != 0)
{
++s;
}
return s - start;
}
The problem is your A4String::strcpy, the line
for (int i = 0; i < 20; i++)
destination[i] = '\0';
The destination has less than 20 characters, so it crashes.
Use of the hard code number 20 in the A4String::strcpy is not right. I suggest changing it to size.
void A4String::strcpy(const char *source, char* destination, int size)
{
// for (int i = 0; i < 20; i++)
for (int i = 0; i < size; i++)
destination[i] = '\0';
int index = 0;
// Add an additional check here also.
// while (source[index] != '\0' )
while (source[index] != '\0' && index < size)
{
destination[index] = source[index];
index++;
}
destination[index] = '\0';
}
Disclaimer Fixing the above function may not fix your crashing problem even though the use of 20 is most likely crashing your program. In other words, there might be other problems in your code too.
I'm at a loss here. I'm new to C/C++, moving from Java, so I'm not too knowledgable on the ins and outs of memory in C, which I think is the issue here.
The following is a class for a custom string, and a set of methods to determine anagrams of said string.
//Constructor
MyString::MyString(const char* input) {
m_c = new char[strlen(input + 1)];
strcpy(m_c, input);
}
bool MyString::IsAnagram(char* in) {
int* a = BuildFreqTable(m_c);
int* b = BuildFreqTable(in);
if (strlen(m_c) != strlen(in))
return false;
for (int i = 0; i<256; i++)
{
if (a[i] != b[i])
return false;
}
return true;
int* MyString::BuildFreqTable(const char* s) {
int* table = new int[256];
for (int i = 0; i < 256; i++)
table[i] = 0;
while (*s)
{
table[(unsigned char)*s]++;
s++;
}
return table;
}
And in main I call the following:
int strtptr = 0;
getline(cin, cmd);
MyString tmp = cmd.c_str();
char* buf = new char[tmp.Length()];
buf[0] = '\0';
do
{
int endptr = tmp.IndexOf(",", strtptr);
if (endptr == -1) {
endptr = tmp.Length();
char* temp = (tmp.Substring(strtptr, endptr - strtptr).GetString());
if (data.IsAnagram(temp))
strcat(buf, temp);
break;
}
else {
char* temp = (tmp.Substring(strtptr, endptr - strtptr).GetString());
if (data.IsAnagram(temp)) {
strcat(buf, temp);
strcat(buf, ",");
}
strtptr = endptr;
strtptr++;
}
} while (true);
cout << buf;
}
This works for singular input strings, but when some number of strings (unsure if number of characters or string delimiters), a SIGABRT comes up. The code for that is:
0x00007ffff7531cc9 in __GI_raise (sig=sig#entry=6)
at ../nptl/sysdeps/unix/sysv/linux/raise.c:56
56 ../nptl/sysdeps/unix/sysv/linux/raise.c: No such file or directory.
I'm really at a loss here.
How can I read and access Unicode characters with standard C. Previously I was using C++ and std::wstring for whole word and 'const wchar_t' for a single characters, which works perfectly( below is example code).
But now I am not allowed to use C++. How can I replace the 'wstring' in C? How can I convert my code to standard C?
...
...
const wchar_t small_char[10]={ L'锕',L'吖',L'啊',L'阿',L'呵',L'嗄',L'埃',L'哀',L'哎'};
std::wstring strIn=L"锕吖哎";
std::wstring s_temp=L"";
int length= strIn.length();
for(int i=0;i<length;i++){
if(strIn[i]==small_char[2]){
s_temp=s_temp+L"ba";
}
else if(strIn[i]==small_char[5]){
s_temp=s_temp+L"pe";
}
else{
s_temp=s_temp+strIn[i];
}
}
...
...
How can I replace the 'wstring' in C? How can I convert my code to standard C?
std::wstring is just a wrapper for wchar_t*. You can use wchar_t directly, you just have to manage the string memory and concatenations manually.
Try this:
...
const wchar_t small_char[10] = { L'锕', L'吖', L'啊', L'阿', L'呵', L'嗄', L'埃', L'哀', L'哎'};
wchar_t *strIn = L"锕吖哎";
int length = wcslen(strIn);
wchar_t *s_temp = (wchar_t*) calloc((length*2)+1, sizeof(wchar_t));
int s_temp_len = 0;
for(int i = 0; i < length; i++)
{
if (strIn[i] == small_char[2])
{
memcpy(&s_temp[s_temp_len], L"ba", 2*sizeof(wchar_t));
s_temp_len += 2;
s_temp[s_temp_len] = L'\0';
}
else if (strIn[i] == small_char[5])
{
memcpy(&s_temp[s_temp_len], L"pe", 2*sizeof(wchar_t));
s_temp_len += 2;
s_temp[s_temp_len] = L'\0';
}
else
{
s_temp[s_temp_len] = strIn[i];
s_temp_len += 1;
s_temp[s_temp_len] = L'\0';
}
}
// use s_temp up to s_temp_len characters as needed...
free(s_temp);
...
If you want something more like std::wstring, you should pre-allocate a small buffer and resize it whenever you are going to exceed its capacity during concatenations. A struct is useful for keeping track of that:
struct my_wstring
{
wchar_t *data;
int length;
int capacity;
};
void wstring_init(struct my_wstring *str)
{
str->data = NULL;
str->length = 0;
str->capacity = 0;
};
void wstring_clear(struct my_wstring *str)
{
free(str->data);
str->data = NULL;
str->length = 0;
str->capacity = 0;
};
// allocate in multiples of 32
const int delta = 32;
void wstring_append_str_len(struct my_wstring *str, const wchar_t *value, int valueLen)
{
if ((!str) || (!value) || (valueLen < 1)) return;
int newLen = str->length + valueLen;
if ((newLen + 1) > str->capacity)
{
// round to next highest multiple of 32
int newCap = ((newLen + 1) + (delta - 1)) & ~delta;
wchar_t *newData = (wchar_t*) realloc(str->data, newCap * sizeof(wchar_t));
if (!newData)
{
// memory allocation error, do something!
return;
}
str->data = newData;
str->capacity = newCap;
}
memcpy(&(str->data[str->length]), value, valueLen * sizeof(wchar_t));
str->length = newLen;
str->data[newLen] = L'\0';
}
void wstring_append_str(struct wstring *str, const wchar_t *value)
{
wstring_append_str_len(str, value, wcslen(value));
}
void wstring_append_chr(struct wstring *str, const wchar_t value)
{
wstring_append_str_len(str, &value, 1);
}
...
const wchar_t small_char[10] = { L'锕', L'吖', L'啊', L'阿', L'呵', L'嗄', L'埃', L'哀', L'哎'};
wchar_t *strIn = L"锕吖哎";
struct my_wstring s_temp;
wstring_init(&s_temp);
int length = wcslen(strIn);
for(int i = 0; i < length; i++)
{
if (strIn[i] == small_char[2])
{
wstring_append_str(&s_temp, L"ba");
}
else if (strIn[i] == small_char[5])
{
wstring_append_str(&s_temp, L"pe");
}
else
{
wstring_append_chr(&s_temp, strIn[i]);
}
}
// use s_temp.data up to s_temp.length characters as needed...
wstring_clear(&s_temp);
...
The equivalent C routines are
== wcscmp or wcsncmp
+= wcscat or wcscat_s
= wcscpy or wcsncpy or wcscpy_s
.size() or length() wcslen
In your case since you are comparing one character at a time, you do not need wcscmp. Make sure all your strings are null terminated otherwise the non _s versions won't work.
This question already has answers here:
How to replicate vector in c?
(6 answers)
Closed 2 years ago.
I have a code (C++) that looks like this
vector<int> values[10000];
int i, j;
while (.....) {
scanf("%d%d", &i, &j);
values[i].push_back(j);
values[j].push_back(i);
}
but I want to rewrite this code to C. How can I do this?
I researched the opportunity to make the own stack, but maybe have more lightweight way to rewrite this code, maybe two-dimensional arrays. So far I can not think how this remake, I hope that someone more experienced tell me how to do it :)
Sorry guys, added a more advanced example...
Instead of rolling your own, you may want to try a C container library, e.g. http://code.google.com/p/ccl/
You can use Gena library. It closely resembles stl::vector in pure C89.
You can check it out here:
https://github.com/cher-nov/Gena
Something like this:
#include <stdio.h>
#include <stdlib.h>
typedef struct _darray
{
size_t size;
size_t actual_size;
int *content;
} darray;
void darray_create(darray *d)
{
d->actual_size = d->size = 0;
d->content = NULL;
}
void darray_append(darray *d, int v)
{
if (d->size+1 > d->actual_size)
{
size_t new_size;
if (!d->actual_size)
{
new_size = 1;
}
else
{
new_size = d->actual_size * 2;
}
int *temp = realloc(d->content, sizeof(int) * new_size);
if (!temp)
{
fprintf(stderr, "Failed to extend array (new_size=%zu)\n", new_size);
exit(EXIT_FAILURE);
}
d->actual_size = new_size;
d->content = temp;
}
d->content[d->size] = v;
d->size++;
}
const int* darray_data(darray *d)
{
return d->content;
}
void darray_destroy(darray *d)
{
free(d->content);
d->content = NULL;
d->size = d->actual_size = 0;
}
size_t darray_size(darray *d)
{
return d->size;
}
int main()
{
int i;
darray myarray;
const int *a;
darray_create(&myarray);
for(i = 0; i < 100; i++)
{
darray_append(&myarray, i);
}
a = darray_data(&myarray);
for(i = 0; i < darray_size(&myarray); i++)
{
printf("i=%d, value=%d\n", i, a[i]);
}
darray_destroy(&myarray);
}
You can try something like this:
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct vector
{
int len;
int allocated;
int step;
int *data;
};
#define INIT_SIZE 1
void init_vector(struct vector *v)
{
v->len = 0;
v->allocated = 0;
v->step = 2;
v->data = NULL;
}
int append(struct vector *v, int item)
{
if (!v->data)
{
v->data = malloc(INIT_SIZE * sizeof(int));
if (!v->data)
return -1;
v->allocated = INIT_SIZE;
}
else
if (v->len >= v-vallocated)
{
int *tmp = realloc(v->data,
v->allocated * v->step * sizeof(int));
if (!tmp)
return -1;
v->data = tmp;
v->allocated *= v->step;
}
v->data[v->len] = item;
v->len++;
return 0;
}
int delete(struct vector *v, int index)
{
if (index < 0 || index >= v->len)
return -1;
memmove(v->data + index, v->data + index + 1,
(v->len - index - 1) * sizeof(int));
v->len--;
return 0;
}
void print(const struct vector *v)
{
printf("Array:\n");
for (int i = 0; i < v->len; i++)
printf("%d ", v->data[i]);
printf("\n");
}
int main(void)
{
struct vector v;
int rc;
init_vector(&v);
rc = append(&v, 1);
assert(rc == 0);
rc = append(&v, 2);
assert(rc == 0);
rc = append(&v, 3);
assert(rc == 0);
rc = append(&v, 4);
assert(rc == 0);
rc = append(&v, 5);
assert(rc == 0);
print(&v);
rc = delete(&v, 2);
assert(rc == 0);
print(&v);
free(v.data);
return 0;
}
A rough equivalent of a C++ vector would be a resizing C array (to account for more elements than available).
Ergo, the equivalent of an array of vectors would be an array of pointers (an array of arrays wouldn't cut it because of the resizing constraint).
int* values[1000];
You'll need to account for the sizes though, so you could either do that externally or wrap the logic inside a structure.
int sizes[1000];
int noElements[1000];
// all sizes and noElements initially 0
for (int i = 0; i < 10; i++) {
if ( noElements[i] >= sizes[i] )
{
// allocate more memory for values[i];
// copy old contents into the new memory
// update sizes[i]
}
values[i][noElements] = 10;
noElements++;
}
There is no C standard equivalent to the c++ vector, though you could create a struct based off of the vector in c++. The struct would
Resize itself if the array bounds are passed the max size
perform the operations similar to that of a vector
OR
Create a linked list stack struct that simulates that of a c++ vector
I'm affraid you'll have to work with heap memory in 80's fashion in the plain C.
typedef struct tagArrayDesc {
int* arr;
size_t top;
size_t reserved;
} ArrayDesc;
#define EC(NAME, T) size_t ensure_capacity##NAME##(size_t size, \
T** vec, \
size_t reserved) \
{ \
size_t new_reserved; \
new_reserved = reserved; \
if (reserved < size) { \
if (reserved != 0) { \
new_reserved *= 2; \
} else { \
new_reserved = 0x10; \
} \
} \
if (new_reserved < size) { \
new_reserved = (size * 4) / 3; \
} \
if (new_reserved > reserved) { \
*vec = realloc(*vec, sizeof(**vec) * new_reserved); \
memset((*vec) + reserved, 0, sizeof(T) * (new_reserved - reserved)); \
} \
return new_reserved; \
}
EC(_int, int)
EC(_array_desc, ArrayDesc)
int main()
{
ArrayDesc* rows = NULL;
size_t rows_size = 0;
size_t rows_reserved = 0;
while (true) {
int i, j;
scanf("%d%d", &i, &j);
rows_reserved = ensure_capacity_array_desc(i + 1, &rows, rows_reserved);
rows[i].reserved = ensure_capacity_int(j + 1, &rows[i].arr, rows[i].reserved);
rows[i].arr[j] = 42;
}
return 0;
}
You have to work with dynamic memory allocation. It's not hard. Every time when a new item must be inserted just use realloc. Somethink that looks like this:
#include <cstdlib>
typedef struct { } UserType;
int currentSize = 0;
UserType* values;
/// Add new value to values method
void addValue(const UserType& newValue)
{
++currentSize;
values = static_cast<UserType*>(realloc(values, currentSize));
if (values == NULL)
// memory allocation filed, place fix code here
*(values + currentSize) = newValue;
}
Remember, u have to use free for free memory of the values. Also, you may don't free allocated memory if will end work right now.