i use strtok to split a string into different pieces and assemble them as a struct. This is my code:
object* parseJSON(size_t length, char* json, size_t jsonLen){
char *finalString = prepareJSON(json,jsonLen);
cout << finalString << "\n";
char delimiter[] = ",:";
char *token = strtok(finalString, delimiter);
object *retObj = (struct object *)malloc(length);
size_t returnObjectIndex = 0;
size_t index = 0;
bool firstTime = true;
struct object item;
while(token != NULL){
if((index % 2) != 0){
if(firstTime){
item.Type = token;
firstTime = false;
} else {
item.ID = token;
retObj[returnObjectIndex] = item;
returnObjectIndex++;
firstTime = true;
}
}
token = strtok(NULL,delimiter);
index++;
}
return retObj;
}
This is the finalString:
Type:temp,id:3,Type:temp,id:1
In my mind this should come out with this code:
for(int n = 0; n < 5; n++){
cout << returnObject[n].Type << " " << returnObject[n].ID << "\n";
}
as:
temp 3
temp 1
but instead i get this on the console:
temp 3
temp 1
h"° Ó*°
C
Is this because i loop 5 times even though there should be only 2 elements in the array? I loop 5 times because i can't get the number of elements of the array in the pointer (atleast i think that this is not possible).
Any help is very much appreciated
Best regards
Edit: This is my prepareJSON function:
char* prepareJSON(char* json, size_t jsonLen){
char forbiddenChars[] = {'[', '{','\"', '}', ']'};
bool isForbbidenChar = false;
char* finalString = (char*)malloc(jsonLen);
size_t finalStringIndex = 0;
for(size_t i = 0; i < jsonLen; i++){
char c = json[i];
isForbbidenChar = false;
for(int k = 0; k < 5; k++){
if(c == forbiddenChars[k]){
isForbbidenChar = true;
break;
}
}
if(isForbbidenChar){
continue;
}
else{
finalString[finalStringIndex] = c;
finalStringIndex++;
}
}
return finalString;
}
and this my main function:
int main(){
object *returnObject;
char json[] = "[{\"Type\":\"temp\",\"id\":\"3\"},{\"Type\":\"temp\",\"id\":\"1\"}]";
returnObject = parseJSON(5,json, strlen(json));
for(int n = 0; n < 5; n++){
cout << returnObject[n].Type << " " << returnObject[n].ID << "\n";
}
}
Solution:
I did indeed allocate too little memory, changed it:
object *retObj = (struct object *)malloc(sizeof(struct object) * length);
Now it works!
Related
I have an implementation of the Long Integer class, which should provide the ability to perform arithmetic operations with instances of the class.
It works in 95% of situations, but sometimes it shows wrong results.
The screen with wrong answers is located below the code.
HugeInt.h:
#ifndef _HUGEINGH
#define _HUGEINGH
#include <iostream>
#include <list>
#include <string>
#include <math.h>
using namespace std;
class HugeInt {
private:
char* listNumber;
int maxLength, length;
bool plus;
void expansion_size_length();
void updatingLength();
void set_listNumber(int position, char num);
char get_listNumber(int position);
char symbol_in_numeral(char symbol);
char numeral_in_symbol(char numeral);
public:
string toString();
void setNumber(string str);
HugeInt operator-(HugeInt HugeInt);
HugeInt operator+(HugeInt HugeInt);
HugeInt operator*(HugeInt HugeInt);
HugeInt(string str);
HugeInt();
HugeInt(const HugeInt &lg);
~HugeInt();
};
#endif
Hugeint.cpp:
#include "stdafx.h"
#include "HugeInt.h"
void HugeInt::expansion_size_length() {
char* tmp = new char[maxLength * 2];
for (int i = 0; i < maxLength; i++) {
tmp[i] = listNumber[i];
}
delete[] listNumber;
listNumber = tmp;
maxLength *= 2;
}
void HugeInt::updatingLength() {
while (length > 1) {
int tmp = listNumber[length - 1];
if (listNumber[length - 1] == 0) {
length--;
}
else {
return;
}
}
}
void HugeInt::set_listNumber(int position, char num) {
if (position < maxLength) {
listNumber[position] = num;
if (position >= length)
length = position + 1;
}
else {
while (position > maxLength)
expansion_size_length();
length = position + 1;
}
}
char HugeInt::get_listNumber(int position) {
if (position < length) {
return listNumber[position];
}
return 0;
}
char HugeInt::symbol_in_numeral(char symbol) {
return symbol - '0';
}
char HugeInt::numeral_in_symbol(char numeral) {
return numeral + '0';
}
string HugeInt::toString() {
string str = string();
if (!plus)
str.insert(str.size(), 1, '-');
for (int i = length - 1; i >= 0; i--) {
str.insert(str.size(), 1, numeral_in_symbol(listNumber[i] / 10));
str.insert(str.size(), 1, numeral_in_symbol(listNumber[i] % 10));
}
return str;
}
void HugeInt::setNumber(string str) {
//plus = true;
//maxLength = 10;
//listNumber = new char[maxLength];
length = 0; // дело в этом
delete[] listNumber;
listNumber = new char[str.length() + 1];
maxLength = str.length() + 1;
for (int i = length; i < maxLength; i++)
listNumber[i] = 0;
length = maxLength;
if (str.size() != 0) {
int k = 0;
if (str[0] == '-') {
plus = false;
for (int i = str.size() - 1; i > 0; i -= 2) {
if (i - 1 > 0)
listNumber[k] = symbol_in_numeral(str[i]) + symbol_in_numeral(str[i - 1]) * 10;
else listNumber[k] = symbol_in_numeral(str[i]);
k++;
}
}
else if (str[0] == '+') {
plus = true;
for (int i = str.size() - 1; i > 0; i -= 2) {
if (i - 1 > 0)
listNumber[k] = symbol_in_numeral(str[i]) + symbol_in_numeral(str[i - 1]) * 10;
else listNumber[k] = symbol_in_numeral(str[i]);
k++;
}
}
else {
plus = true;
for (int i = str.size() - 1; i >= 0; i -= 2) {
if (i - 1 >= 0)
listNumber[k] = symbol_in_numeral(str[i]) + symbol_in_numeral(str[i - 1]) * 10;
else listNumber[k] = symbol_in_numeral(str[i]);
k++;
}
}
}
updatingLength();
}
HugeInt HugeInt::operator-(HugeInt _HugeInt) {
HugeInt result = HugeInt();
if (_HugeInt.plus == this->plus) {
int length_tmp = _HugeInt.length > this->length ? _HugeInt.length : this->length;
char part_sub = 0;
int sub;
char tmp1, tmp2;
for (int i = 0; i < length_tmp; i++) {
tmp1 = listNumber[i];
tmp2 = _HugeInt.listNumber[i];
sub = ((int)listNumber[i] - (int)_HugeInt.listNumber[i] - (int)part_sub);
part_sub = 0;
if (sub < 0) {
sub += 100;
part_sub = 1;
}
//else if (sub == 0) //
//part_sub = 1; //
result.set_listNumber(i, sub);
}
if (part_sub != 0) {
part_sub = 0;
result.plus = !this->plus;
for (int i = 0; i < length_tmp; i++) {
sub = ((int)result.listNumber[i] + (int)part_sub - 100);//
part_sub = 0;
if (sub < 0) {
sub = abs(sub);
part_sub = 1;
}
//else if (sub == 0) //
//part_sub = 1; //
result.set_listNumber(i, sub % 100);
}
}
result.updatingLength();
return result;
}
else {
HugeInt lg1 = HugeInt(_HugeInt);
HugeInt lg2 = HugeInt(*this);
lg1.plus = !lg1.plus;
//HugeInt.plus = !HugeInt.plus;
return lg2 + lg1;
}
}
HugeInt HugeInt::operator+(HugeInt _HugeInt) {
HugeInt result = HugeInt();
if (_HugeInt.plus == this->plus) {
int length_tmp = _HugeInt.length > this->length ? _HugeInt.length : this->length;
char part_sum = 0;
char tmp1, tmp2;
for (int i = 0; i < length_tmp; i++) {
tmp1 = _HugeInt.listNumber[i];
tmp2 = listNumber[i];
result.set_listNumber(i, (_HugeInt.listNumber[i] + listNumber[i] + part_sum) % 100);
part_sum = (_HugeInt.listNumber[i] + listNumber[i] + part_sum) / 100;
}
if (part_sum != 0) {
result.set_listNumber(length_tmp, part_sum);
}
result.plus = plus;
result.updatingLength();
return result;
}
else {
if (_HugeInt.plus) {
//plus = !plus;
HugeInt lg1 = HugeInt(_HugeInt);
HugeInt lg2 = HugeInt(*this);
lg2.plus = !lg2.plus;
return lg1 - lg2;
}
else {
HugeInt lg1 = HugeInt(_HugeInt);
HugeInt lg2 = HugeInt(*this);
lg1.plus = !lg1.plus;
//HugeInt.plus != HugeInt.plus;
return lg2 - lg1;
}
}
}
HugeInt HugeInt::operator*(HugeInt _HugeInt) {
HugeInt result = HugeInt();
int part_mul;
int iter = 0;
HugeInt tmpHugeInt;
int tmp1, tmp2;
for (int i = 0; i < _HugeInt.length; i++) {
part_mul = 0;
tmpHugeInt = HugeInt();
for (int j = 0; j < length; j++) {
tmp1 = _HugeInt.listNumber[i];
tmp2 = listNumber[j];
iter = (int)_HugeInt.listNumber[i] * (int)listNumber[j] + (int)part_mul;
part_mul = iter / 100;
tmpHugeInt.set_listNumber(j + i, iter % 100);
}
if (part_mul != 0) {
tmpHugeInt.set_listNumber(tmpHugeInt.length, part_mul);
}
result = result + tmpHugeInt;
}
if (_HugeInt.plus != plus)
result.plus = false;
result.updatingLength();
return result;
}
HugeInt::HugeInt(string str) {
plus = true;
maxLength = 10;
listNumber = new char[maxLength];
length = 0;
setNumber(str);
}
HugeInt::HugeInt() {
plus = true;
maxLength = 10;
listNumber = new char[maxLength];
length = 0;
for (int i = length; i < maxLength; i++)
listNumber[i] = 0;
}
HugeInt::HugeInt(const HugeInt &lg) {
plus = lg.plus;
maxLength = lg.maxLength;
listNumber = new char[maxLength];
length = lg.length;
for (int i = 0; i < maxLength; i++)
if (i < lg.length){
listNumber[i] = lg.listNumber[i];
}
else{
listNumber[i] = 0;
}
}
HugeInt::~HugeInt() {
//delete[] listNumber;
}
main.cpp:
#include "stdafx.h"
#include "HugeInt.h"
int _tmain(int argc, _TCHAR* argv[])
{
/*
string num1, num2;
cout << "Enter the first number:" << endl;
cin >> num1;
cout << "Enter the second number:" << endl;
cin >> num2;
HugeInt hugeNum1 = HugeInt(num1);
HugeInt hugeNum2 = HugeInt(num2);
cout << "Entered the following numbers:" << endl;
cout << "First number: " << num1 << endl;
cout << "Second number: " << num2 << endl;
HugeInt sum = hugeNum1 + hugeNum2;
HugeInt sub = hugeNum1 - hugeNum2;
HugeInt mul = hugeNum1 * hugeNum2;
cout << "Summary = " << sum.toString() << endl;
cout << "Substruction = " << sub.toString() << endl;
cout << "Multiplacation = " << mul.toString() << endl;
*/
HugeInt longNumber1;
HugeInt longNumber2;
HugeInt longNumberRes;
/*
int firstTrue = 1837;
int secondTrue = -8108;
char buf[32];
itoa(firstTrue, buf, 10);
string firststr(buf);
itoa(secondTrue, buf, 10);
string secstr(buf);
longNumber1.setNumber(firststr);
longNumber2.setNumber(secstr);
longNumberRes = longNumber1 + longNumber2;
int res = atoi(longNumberRes.toString().c_str());
cout << "Good " << firstTrue << "+" << secondTrue << "=" << res << endl;
int firstFalse = 312;
int secondFalse = 712;
char buf2[32];
itoa(firstFalse, buf2, 10);
string firststr2(buf2);
itoa(secondFalse, buf2, 10);
string secstr2(buf2);
longNumber1.setNumber(firststr2);
longNumber2.setNumber(secstr2);
longNumberRes = longNumber1 - longNumber2;
int res2 = atoi(longNumberRes.toString().c_str());
cout << "Bad " << firstFalse << "-" << secondFalse << "=" << res2 << endl;
*/
for (int i = 0; i < 1000; i++)
{
int first = rand() % 20000 - 10000;
int second = rand() % 20000 - 10000;
char buf[32];
itoa(first, buf, 10);
string firststr(buf);
itoa(second, buf, 10);
string secstr(buf);
longNumber1.setNumber(firststr);
longNumber2.setNumber(secstr);
longNumberRes = longNumber1 - longNumber2;
int res = atoi(longNumberRes.toString().c_str());
if (res != first - second)
cout << i << " = "<< first << "+" << second << "=" << res << endl;
}
system("pause");
return 0;
}
It prints the following results when i am doing the test with 1000 random numbers (5 of 1000 results are incorrect):
48 = 6118+-7918=-1700
268 = -8887+4887=-3900
326 = 3169+-6169=-2900
474 = 212+-712=-400
492 = 1333+-7133=-5700
545 = 8352+-9552=-1100
617 = -4395+195=-4100
Looks like something wrong with minus operation, but i can not uderstand what exactly. Please, help, what is wrong in the implementation and how to fix it?
#ifndef _LIBCPP_HASH
#define _LIBCPP_HASH
#include <iostream>
#include <string>
#include <string.h>
#include <iomanip>
#define PERTERB_SHIFT 5
using namespace std;
int FAIL = 0;
template <typename myType>
class HashMap
{
public:
HashMap()
{
Size = 8;
Resize = 2;
Keys = new int[8];
Values = new myType[8];
typesize = sizeof(myType);
Fill = 0;
memset(Keys, -1, 32);
memset(Values, 0, 8 * typesize);
}
~HashMap()
{
delete[] Keys;
delete[] Values;
}
HashMap(const HashMap &table)
{
Size = table.Size;
Keys = table.Keys;
Values = table.Values;
}
int GetSize() { return Size; }
// can't return get(key) because no binding of reference int to temporary int, so has the same body as get..
myType &operator[] (int hash)
{
register size_t perterb = hash;
register unsigned long j = 0;
register int temp = 0;
register int index = 0;
while ( Keys[index] != hash && Keys[index] != -1)
{
j = 5 * j + 1 + perterb;
perterb >>= PERTERB_SHIFT;
index = j % (2 << Resize);
//cout << "j : " << j << " temp: " << temp << " hash: " << hash << " index: " << index << endl;
}
if (Fill == (int)(Size * 2 / 3))
{
cout << "here" << endl;
Resize <<= 1;
int* tempkey = new int[Size*2];
myType* tempvalue = new myType[Size*2];
memset(tempkey, -1, Size*8);
memset(tempvalue, 0, Size*2*typesize);
copy(Keys, Keys + Size, tempkey);
copy(Values, Values + Size, tempvalue);
delete[] Values; delete[] Keys;
Keys = tempkey; Values = tempvalue;
Size <<= 1;
}
if (Keys[index] != hash) Fill ++;
Keys[index] = hash;
return Values[index];
}
bool insert(int key, myType value)
{
int index = key % Size;
short temp = 0;
while ((Keys[index] != key) && (Keys[index] != -1) && temp < Size)
{
index ++;
temp ++;
}
if (temp == Size)
{
int s = static_cast<int>(Size*4);
int* tempkey = new int[s];
myType* tempvalue = new myType[s];
for (int i = Size; i < s; i++)
{
tempkey[i] = -1;
tempvalue[i] = 0;
}
copy(Keys, Keys + Size, tempkey);
copy(Values, Values + Size, tempvalue);
delete[] Values; delete[] Keys;
Size *= 4;
Keys = tempkey;
Values = tempvalue;
}
Keys[index] = key;
Values[index] = value;
return true;
}
myType get(int key)
{
int index = key % Size;
short count = 0;
while (Keys[index] != key && count < Size)
{
index ++;
count ++;
}
if (count == Size)
{
try
{
throw key;
}
catch (int er)
{
cout << "KeyError: " << er << endl;
}
return FAIL;
}
return Values[index];
}
myType pop(int key)
{
int index = key % Size;
short count = 0;
while (Keys[index] != key && count < Size)
{
index ++;
count ++;
}
if ( count == Size )
{
try
{
throw key;
}
catch (int er)
{
cout << "KeyError: " << er << endl;
}
return FAIL;
}
myType temp = Values[index];
Values[index] = 0;
Keys[index] = -1;
return temp;
}
void Print()
{
cout << "index\t" << "key\t" << "value\t" << endl;
for (int i = 0; i < Size; i++)
{
cout << i << "\t" << Keys[i] << "\t" << Values[i] << "\t" << endl;
}
}
private:
int Size;
int Resize;
int* Keys;
myType* Values;
short typesize;
int Fill;
};
#endif
This is my code currently. The hash function is based off of Python dictionaries. The issue arises when trying to reference a hashmap entry after it has been inserted. If there was a collision during insertion, the [] operator will treat the reference as if it is trying to insert the value again and will stop at the first key = -1, instead of iterating until it finds the hash value in the key array. I'm able to address this issue with insert(), pop(), and get(), but I don't know how to deal with it for the [] operator, since it is used for both reference and assignments. It needs to know if it is followed by an assignment operator before it tries to either insert or get the hash.
I spent some time in the Python source code trying to figure out how they dealt with this issue but I couldn't figure it out.
I know this is a strange question, but I would really appreciate any help.
Your [] can return a proxy type, which in turn has an operator int()&& for reading and operator =(int const&)&& for writing.
There are issues with this in that it interacts with auto poorly, but it does work.
This is what std vector bool does to support bit compressed data. It was viewed as a mistake, but partly for unrelated reasons.
I have two examples, which of these two is better and why? In both cases, I got the same result. I have chosen container simply to hold strings.
Example 1:
char *c_ptr[] = {};
int num;
if (fill_array(c_ptr, &num) != 0) {
cout << "Error" << endl;
}
for (int i = 0; i < num; i++) {
cout << "Str[" << i << "] = " << c_ptr[i] << endl;
}
// free pointer..
// Function implementation
int fill_array(char *c_ptr[], int *count) {
vector<string> v = {"haha", "hehe", "omg", "happy, learning!"};
*count = v.size();
int i = 0;
for (vector<string>::iterator it = v.begin(); it != v.end(); it++, i++) {
c_ptr[i] = (char*)malloc((*it).size() + 1);
strncpy(c_ptr[i], (*it).c_str(),(*it).size() + 1);
}
return 0;
}
Example 2:
char **c_ptr = NULL;
int num;
if (fill_array(&c_ptr, &num) != 0) {
cout << "Error" << endl;
}
for (int i = 0; i < num; i++) {
cout << "Str[" << i << "] = " << c_ptr[i] << endl;
}
// free double pointer..
// Function implementation
int fill_array(char ***c_ptr, int *num) {
vector<string> v = {"haha", "hehe", "omg", "happy, learning!"};
*num = v.size();
int i = 0;
*c_ptr = (char **)malloc(*num * sizeof(char *));
for (vector<string>::iterator it = v.begin(); it != v.end(); it++, i++) {
c_ptr[i] = (char*)malloc((*it).size() + 1);
strncpy(*c_ptr[i], (*it).c_str(),(*it).size() + 1);
}
return 0;
}
Result:
Str[0] = haha
Str[1] = hehe
Str[2] = omg
Str[3] = happy, learning!
Also What is the use of empty bracket in array? Is it good programming habit vs dynamic allocation?
** is pointer to a pointer or simply we can say it a double pointer.
Double pointers are better to use when we are passing a pointer variable from main() or simply a function to another function.
By looking at your code, I would like to suggest you one thing and that is, avoid using global variables.
so I was writing a program which has to check if the input sting is a palindrome or not. And it's actually working but a problem with deleting the array I created during the course of it arouse.
#include <iostream>
using namespace std;
bool checkPalindrome(char* text);
char* clearString(char* src);
int main()
{
char buffer[1000];
cin.getline(buffer, 1000);
cout << boolalpha << checkPalindrome(buffer) << endl;
return 0;
}
bool checkPalindrome(char* text)
{
char* newStr = clearString(text);
if (!newStr)
return false;
int newLen = strlen(newStr);
for (int i = 0; i < newLen / 2; i++) {
if (newStr[i] == newStr[newLen - i - 1])
continue;
else
return false;
}
//delete[] newStr;
return true;
}
char* clearString(char* src)
{
unsigned len = strlen(src);
unsigned counter = 0;
for (int i = 0; i < len; i++) {
if (src[i] == ' '||src[i] == '.'||src[i] == ','||src[i] == '!')
counter++;
}
unsigned newSize = len - counter + 1;
char* dest = new(nothrow) char[newSize];
if (!dest) {
cout << "not enoough memory\n";
return NULL;
}
int i, j;
for(i = j = 0; j < newSize; ++i, ++j) {
if(src[i]==' '||src[i]=='.'||src[i]==','||src[i]=='!'||src[i]=='?')
i++;
else
dest[j] = src[i];
}
dest[j] = '\0';
return dest;
}
So the commentated delete in the checkPalindrome function causes a crash if executed and I get the "Heap corruption detected" error. I tried changing the function type to void and delete there and the same thing happened. Any ideas what causes it?
Your loop copies the '\0' at the end of the string, but then you add another '\0', using one more byte of memory than you allocated.
I have defined the struct chararray as follows.
struct chararray
{
char* lhs;
char* rhs;
};
Now, I have two arrays la[l] and ra[l](both have all l values defined). I assign that to the struct,and return the function.
chararray s;
s.lhs = new char[l];
s.rhs = new char[l];
s.lhs = &la[0];
s.rhs = &ra[0];
return s;
In main , I ouptut
for(int i = 1; i < l;i++){
cout << *(s.rhs + i);
}
Now,I get gibberish as output.
But if I output *(s.rhs + 0) and *(s.rhs + 1) and ... [ the values 0,1,.. are explicitly included ], I get correct output!
Why doesnt the for loop work?
PS - My entire code is -
#include <iostream>
#include <cstring>
#include <vector>
#include <cmath>
using namespace std;
struct chararray
{
char* lhs;
char* rhs;
};
chararray getcenter(char in[],int l){
int open_count = 0;
int open = 0;
int first = 0;
int last = 0;
int limit;
int close_count = 0;
char lhs[l],rhs[l];
for(int i = 0; i < l;i++){
lhs[i] = ' ';
rhs[i] = ' ';
}
for(int i = 0; in[i]!='\0';i++){
int flag = 0;
if(in[i] == '('){
if(flag == 0){first = i;flag = 1;}
open++;
}
if(in[i] == '('){
last = i;
}
limit = i;
}
for(int i = 0; in[i]!='\0';i++)
{
//cout << "entrt" << endl;
int temp;
if(in[i] == '(') { open_count++; }
if(in[i] == ')') { close_count++; }
if((open_count == close_count) && (open_count != 0) && (open_count != open))
{
//cout << open_count << endl;
for(int j = 0;j < i+1;j++)
{
lhs[j] = in[j];
}
lhs[i+1] = ' ';
lhs[i+2] = ' ';
for(int j = i+3; in[j]!='\0';j++)
{
lhs[j] = ' ';
rhs[j-i-3] = in[j];//Assuming no space between -> and rhs
temp = j;
}
for(int j = temp;rhs[j] != '\0';j++){
rhs[j] = ' ';
}
for(int j = temp;lhs[j] != '\0';j++){
lhs[j] = ' ';
}
break;
}
}
chararray s;
s.lhs = new char[l];
s.rhs = new char[l];
s.lhs = &lhs[0];
s.rhs = &rhs[0];
return s;
}
int main()
{
string input;
cin >> input;
int l=input.length()+1;
char in[l];
strcpy(in, input.c_str());
chararray s = getcenter(in,l);
for(int i = 1; i < l;i++){
//cout << *(s.rhs + i); - Doesnt work
}
cout << *(s.lhs + 5); // Works!
return 0;
}
Your for loop is starting at i=1, and when you explicitly set the values you are using 0 and 1. Decide where you want to start, and try it again.
Try this:
for(int = 0 ; i < l; i++)
cout << *(s.rhs + i);
Note that you are actually risking a memory leak with these lines of code:
s.lhs = new char[l];
s.rhs = new char[l];
s.lhs = &lhs[0];
s.rhs = &rhs[0];
You are allocating 1 char and storing its address in s.lhs, then resetting s.lhs to the address of lhs[0]. There is no need for the two first lines with the new in them. So replace that code with this: (also note that &lhs[0] is the same as lhs)
s.lhs = lhs;
s.rhs = rhs;