I'm working on this and have a problem that I cant figure out.
I got this in the header
class PGEnemy : Public CCSprite
{
private:
int pHP;
int pLoot;
int pAttack;
int pSpeed;
PGEnemy();
~PGEnemy();
public:
bool setSpeed (int speed);
static PGEnemy* factory(eType type); //create an enemy
void init(int type); //read info from json (json cpp)
};
And in the code I got this
void PGEnemy::init(int type)
{
try
{
Reader reader;
Value initial;
unsigned long size = 0;
unsigned char *config_doc = CCFileUtils::sharedFileUtils()->getFileData("enemy.json", "r", &size);
bool parsingSuccessful = reader.parse((char*)config_doc, initial);
string s = TO_STRING(type);
cout << s << endl;
if(parsingSuccessful)
{
this->pHP = initial[TO_STRING(type)]["hp"].asInt();
this->pLoot = initial[TO_STRING(type)]["loot"].asInt();
this->pAttack = initial[TO_STRING(type)]["attack"].asInt();
this->pSpeed = initial[TO_STRING(type)]["speed"].asInt();
}
}
catch (exception)
{
this->pHP = 100*type;
this->pAttack = 100*type;
this->pSpeed = 100*type;
this->pLoot = 100*type;
}
//*/
}
In the moment of doing this->pHP = initial[TO_STRING(type)]["hp"].asInt();
or any other that I shall put a value in those integers (even in the catch), it crash with the error
Access violation writing location 0x000001C0.
from a open source code for using json, file Json_value.cpp
Value::asInt() const
{
switch ( type_ )
{
case nullValue:
return 0;
case intValue:
JSON_ASSERT_MESSAGE( value_.int_ >= minInt && value_.int_ <= maxInt, "unsigned integer out of signed int range" );
return Int(value_.int_);
case uintValue:
JSON_ASSERT_MESSAGE( value_.uint_ <= UInt(maxInt), "unsigned integer out of signed int range" );
return Int(value_.uint_);
case realValue:
JSON_ASSERT_MESSAGE( value_.real_ >= minInt && value_.real_ <= maxInt, "Real out of signed integer range" );
return Int( value_.real_ );
case booleanValue:
return value_.bool_ ? 1 : 0;
case stringValue:
case arrayValue:
case objectValue:
JSON_FAIL_MESSAGE( "Type is not convertible to int" );
default:
JSON_ASSERT_UNREACHABLE;
}
return 0; // unreachable;
}
The most "unknow" is that the error also happened when I simply try to do this->pHP = anyIntegerValue
PGEnemy* PGEnemy::factory(eType type)
{
PGEnemy* enemy = (PGEnemy*)CCSprite::create("Target.png");
enemy->init(type);
return enemy;
}
Related
As I understood this char* is a valid json-string.
const char* json = { "array":[14, -15, 3.17], "array_type": ["uint", "int", "float"] }
All numbers in the array shall be 4 bytes.
How could one loop through the array using rapidjson?
This is my code so far:
#include "rapidjson/document.h"
using namespace rapidjson;
int main(void)
{
int i_val; unsigned int ui_val; float f_val;
const char* json = "{ \"array\":[14, -15, 3.17], \"array_type\" : [\"uint\", \"int\", \"float\"] }";
Document d;
d.Parse<0>(json);
Value& a = d["array"];
Value& at = d["array_type"];
for (SizeType i = 0; i<a.Size(); i++)
{
if (a[i].IsInt() && (std::string)at[i].GetString() == "int")
{
i_val = a[i].GetInt();
//Do anything
}
if (a[i].IsUint() && (std::string)at[i].GetString() == "uint")
{
ui_val = a[i].GetUint();
//Do anything
}
if (a[i].IsDouble() && (std::string)at[i].GetString() == "float")
{
f_val = (float)a[i].GetDouble();
//Do anything
}
}//end for
return 0;
}
ERROR:
TestApp: /workspace/TestApp/src/include/rapidjson/document.h:1277: rapidjson::GenericValue<Encoding, Allocator>& rapidjson::GenericValue<Encoding, Allocator>::operator[](rapidjson::SizeType) [with Encoding = rapidjson::UTF8<>; Allocator = rapidjson::MemoryPoolAllocator<>; rapidjson::SizeType = unsigned int]: Assertion `index < data_.a.size' failed.
The code crashes at the function a.Size(), when it is executed after GetDouble. How could one solve this?
I know the last "if" is wrong and thats probably why the program crashes. Double is 8 bytes and the SizeType is 4 bytes by default.
Is there a solution to loop though the array?? If not I also would be good with other libs.. I need to transport these three different types of values by json. By the way the length of the array could be 1 to 500.
(There is no GetFloat() function.)
Thanks for any kind of help.
Regards
You can use JSONLint to validate json string.
Your example fixed:
int i_val; unsigned int ui_val; float f_val;
const char* json = "{ \"array\":[14, -15, 3.17], \"array_type\" : [\"uint\", \"int\", \"float\"] }";
rapidjson::Document d;
d.Parse<0>(json);
rapidjson::Value& a = d["array"];
rapidjson::Value& at = d["array_type"];
for (rapidjson::SizeType i = 0; i<a.Size(); i++)
{
if (a[i].IsInt() && (std::string)at[i].GetString() == "int")
{
i_val = a[i].GetInt();
//Do anything
}
if (a[i].IsUint() && (std::string)at[i].GetString() == "uint")
{
ui_val = a[i].GetUint();
//Do anything
}
if (a[i].IsDouble() && (std::string)at[i].GetString() == "float")
{
f_val = (float)a[i].GetDouble();
//Do anything
}
}
Ok, I added the following code to a mod menu for a game and everything works fine for me in Windows 7. But when I send it to my friend on Windows 8, he tries to select a button (which calls the GetClients() function) and the game just crashes. Any idea why?
char* playerNames[31] = {};
int getUID(char* pName)
{
int i = 0;
while (i < 31) {
char* pNamesec = (char*)PLAYER::GET_PLAYER_NAME((Player)(i));
if (pNamesec == pName) {
return i;
}
//else { break; }
i++;
}
}
char* getPnameAt(int id) {
for (int i = 0; i < 30; i++) {
if (i == id) {
return (char*)PLAYER::GET_PLAYER_NAME((Player)(i));
}
}
}
void GetClients()
{
playerNames[31] = {};
int i = 0;
while (i < 100) {
char* pName = (char*)PLAYER::GET_PLAYER_NAME((Player)(i));
if (wcslen((WCHAR*)pName) > 3) {
if (getUID(pName) == i) {
playerNames[i] = pName;
} else {
getPnameAt(i);
}
}
i++;
}
i = 0;
}
Error message that pops up says:
CORE: An exception occurred while executing modmenu.asi, press ok to continue
You have created an array of length 31. So you can access array playerName from index 0 to index 30. In GetClients()
playerNames[31] = {}; //Observe this line
while (i < 100) {
// Indexes greater than 30 are being used to access playerNames array
}
31 or beyond is not a valid index for playerNames array and you are getting undefined behavior.
So if you want to add in playerNames in runtime. Below is the small example that might help you..
int main()
{
vector<string> playerNames;
playerNames.push_back("XYZ");
playerNames.push_back("ABC");
// To access from vector
vector<string>::iterator itr = vec.begin();
for(;itr!=vec.end();itr++)
{
cout<<*itr<<endl;
}
}
Read more here
Here's my solution, which requires a test run to compute the const values before it is functional. That's awkward, do you have a more graceful solution? I was thinking I'd avoid calling 100 string comparisons doing it this way.
//find these values before hand
char a[] = "SHET"; //1413826643
char b[] = "ANIM"; //1296649793
char c[] = "RGST"; //1414743890
int* get_word_value[] = { (int*)a, (int*)b, (int*)c };
//enum in header file makes it externally linked and compatible with switch statement
enum str_command{ SHET = 1413826643, ANIM = 1296649793, RGST = 1414743890 } ;
//cpp:
char* file = readTXT( "text.txt" );
int* command = (int*)file;
switch( command ) {
case SHET: SHETfunc( file ); break;
case ANIM: ANIMfunc( file ); break;
case RGST: RGSTfunc( file ); break;
}
Why not
std::map<std::string, std::function<here goes what the return types etc are>> dispatch;
Then
dispatch["a string"](args);
You can initialise the list with map_list_of from boost
Another popular method is to use a look up table:
typedef void (*Function_Pointer)(/* input parameters*/);
struct Name_Function_Entry
{
std::string name;
Function_Pointer function;
};
void Shet(void);
void Anim(void);
void Rgst(void);
const Name_Function_Entry function_table[] =
{
{"SHET", Shet},
{"ANIM", Anim},
{"RGST", Rgst},
};
const unsigned int number_of_entries =
sizeof(function_table) / sizeof(function_table[0]);
// ...
for (unsigned int i = 0; i < number_of_entries; ++i)
{
if (name == function_table[i].name)
{
(function_table[i].function)();
break;
}
}
I have this function in c++ that should add a member to a linked list, but when it's executed it throw an exception:
Unhandled exception at 0x5b9414cf (msvcr100d.dll) in Sample.exe: 0xC0000005: Access violation reading location 0x00000001
This happen when some variable isn't definite...but I can't figure out where is this variable...also with breakpoints.
Here the entire code (except for the .h file...but it only contains declaration)
#include "stdafx.h"
#include "winsock.h"
#include "windows.h"
#include <string.h>
#include <iostream>
#include "Sample.h"
using namespace std;
struct BUNNY
{
public:
int sex;
int name;
int age;
bool colour;
int radioactive_mutant_vampire_bunny;
BUNNY *nextBunny;
};
int returnSex();
int returnName (int sex);
int returnColour ();
bool radioactiveBunny ();
string translateName(int name);
string translateSex(int sex);
string translateColour(int colour);
BUNNY * AddBunny(BUNNY * head,int sex,int name,int colour,bool radioactive_mutant_vampire_bunny);
BUNNY * travereseBunny(BUNNY * head);
BUNNY * displayBunny();
int _tmain(int argc, _TCHAR* argv[])
{
bool flag = true;
int turn = 0;
BUNNY * head = new BUNNY;
head = NULL;
while (flag)
{
++turn;
if (turn == 1)
{
for (int i = 1; i <= 5; i++)
{
int sex = returnSex();
int name = returnName(sex);
int colour = returnColour();
bool radioactive = radioactiveBunny();
head = AddBunny(head,sex,name,colour,radioactive);
printf("A new bunny is born: sex %s , name %s , colour %s , radioactive %d",head->sex,head->name,head->colour,head->radioactive_mutant_vampire_bunny);
system("pause");
}
}
}
return 0;
}
int returnSex()
{
int random = rand() % 100 + 1;
if(random > 50)
return MALE;
else
return FEMALE;
}
int returnName(int sex)
{
if (sex == MALE)
{
int random = (rand() % 100 + 1) / 5;
if(random < 20)
return BU;
else if (random > 20 && random <40)
return CRYSTAL;
else if(random > 40 && random < 60)
return JASON;
else if(random > 60 && random < 80)
return ERO;
else if(random > 80)
return METH;
}
else
{
int random1 = rand() % 100 + 1;
if (random1 < 50 )
{
return MARIA;
}
else if (random1 > 50)
return JAMIE;
}
}
int returnColour ()
{
int random = rand() % 4 + 1;
if(random == 1)
return WHITE;
else if(random > 1 && random <= 2)
return BROWN;
else if(random > 2 && random <= 3)
return BLACK;
else if(random > 3 && random <= 4)
return SPOTTED;
}
bool radioactiveBunny()
{
int random = rand() % 100 + 1;
if(random > 0 && random <= 2)
return true;
else
return false;
}
BUNNY * AddBunny(BUNNY * head,int sex,int name,int colour,bool radioactive_mutant_vampire_bunny)
{
BUNNY * newBunny = new BUNNY;
newBunny->age = 0;
newBunny->colour = colour;
newBunny->sex = sex;
newBunny->name = name;
newBunny->radioactive_mutant_vampire_bunny = radioactive_mutant_vampire_bunny;
newBunny->nextBunny = head;
return newBunny;
}
string translateName (int name)
{
switch (name)
{
case CRYSTAL: return "CRYSTAL";
break;
case BU: return "BU";
break;
case JASON: return "JASON";
break;
case ERO: return "ERO";
break;
case METH: return "METH";
break;
case MARIA: return "MARIA";
break;
case JAMIE: return "JAMIE";
break;
}
}
string translateColour (int colour)
{
switch (colour)
{
case WHITE: return "WHITE";
break;
case BLACK: return "BLACK";
break;
case BROWN: return "BROWN";
break;
case SPOTTED: return "SPOTTED";
break;
}
}
string translateSex (int sex)
{
switch (sex)
{
case MALE: return "MALE";
break;
case FEMALE: return "FEMALE";
break;
}
}
this is the entire code...hope it will help.
thanks for your time :)
Whether there is a probelm or no depends on how you call the function
It should be called the following way
head = AddBunny( /* some arguments */ );
If you call it such a way then there is no problem with the function.
If you call it as for example
AddBunny( /* some arguments */ );
that is without assigning head by the returning pointer then head will be always equal to NULL.
EDIT: After you showed additional code then I would like to point out that these statements
BUNNY * head = new BUNNY;
head = NULL;
are invalid. There is a memory leak. You at first allocate memory and head gets the address of the memory and then you reassign the head.
There must be
BUNNY * head = NULL;
Also it seems your code has a typo. You defined private data members as
bool colour;
int radioactive_mutant_vampire_bunny;
but corresponding parameters of function AddBunny are defined diffirently
BUNNY * AddBunny(BUNNY * head,int sex,int name,int colour,bool radioactive_mutant_vampire_bunny);
The abend was due to incorrect formating symbol. You defined colour as bool but trying to output it as a string literal.
printf("A new bunny is born: sex %s , name %s , colour %s , radioactive %d",head->sex,head->name,head->colour,head->radioactive_mutant_vampire_bunny);
You wrote colour %s while head->colour has type bool
By the way the address 0x00000001 shown in the message
Access violation reading location 0x00000001
is the value of colour that is equal to boolean literal true that is to 1.
Your problem is the printf statement, consider the following:
printf("Test: %s", 2);
This will produce a crash, as printf is assuming a string, but you pass an integer. The integer will thus be interpreted as char* and therefor result in an access violation as soon as printf tries to print any char (which requires dereferencing the pointer).
But this is exactly what happens if you do:
printf("A new bunny is born: sex %s", head->sex);
As BUNNY::sex is declared as int.
I'm writing a program that print the full english name of the number inputted by the user. it's not a complete program but i keep getting an error:
First-chance exception at 0x00b02c76 in Programming Challenge 14.1.exe: 0xC0000005: Access violation reading location 0xcccccd80.
Unhandled exception at 0x00b02c76 in Programming Challenge 14.1.exe: 0xC0000005: Access violation reading location 0xcccccd80.
I've tried looking around and couldn't find anything of use to me. here this the program:
header file:
#ifndef NUMBERS_H
#define NUMBERS_H
#include <string>
using namespace std;
const int SIZE1 = 18;
const int SIZE2 = 8;
class Numbers
{
private:
int number;
string hundred;
string thousand;
string * one;
string * ten;
public:
Numbers(int num)
{
number = num;
hundred = "hundred";
thousand = "thousand";
string * one = new string[SIZE1];
string * ten = new string[SIZE2];
}
void initializeArray()
{
// Intialize array "one"
one[0] = "zero";
one[1] = "one";
one[2] = "two";
one[3] = "three";
one[4] = "four";
one[5] = "five";
one[6] = "six";
one[7] = "seven";
one[8] = "eight";
one[9] = "nine";
one[10] = "eleven";
one[11] = "twelve";
one[12] = "thirteen";
one[13] = "fourteen";
one[14] = "fifteen";
one[15] = "sixteen";
one[16] = "seventeen";
one[17] = "eighteen";
one[18] = "nineteen";
// Initialize the ten array
ten[0] = "ten";
ten[1] = "twenty";
ten[2] = "thirty";
ten[3] = "forty";
ten[4] = "fifty";
ten[5] = "sixty";
ten[6] = "seventy";
ten[7] = "eighty";
ten[8] = "ninety";
}
string determine()
{
string name = "";
for (int i = 0; i <= number; i++)
{
if (number == i)
{
name = one[i];
}
}
return name;
}
~Numbers()
{
delete [] one;
delete [] ten;
}
};
#endif
and this is the main program, im just using a constructor to assign a value to number to make debugging a little faster
#include <iostream>
#include "Numbers.h"
using namespace std;
int main()
{
Numbers n(5);
string name = n.determine();
cout << "The number is " << name << endl;
cin.ignore();
cin.get();
return 0;
}
by the way this is vc++ for the compiler
ill answer any questions as this isnt really too organized
const int SIZE1 = 18;
Valid array index for the array of SIZE1 are 0 to 17. In general, valid indexes for an array of size N are 0 to N-1.
I recommend using std::vector<std::string>.
one holds 18 elements, but you put 19 elements in there.
Two things here:
You are not calling "initializeArray()" at all. So when you are trying to access the array there is nothing there. I would recommend calling it in the constructor. Like this:
Numbers(int num)
{
number = num;
hundred = "hundred";
thousand = "thousand";
one = new string[SIZE1];
ten = new string[SIZE2];
initializeArray();
}
Second, is what the guys above said. You have an incorrect value for the size of your array since you are trying to assign 19 values to an array of size 18. Just to be really sure lets make the size bigger than we expect and you can adjust later:
const int SIZE1 = 20;
const int SIZE2 = 20;
Additionally, See your determine()? instead of using a for loop why don't you go:
string name = one[number];
EDIT: Wow there was another thing I missed...you have declared your array pointer variable twice and so it's actually going out of scope thinking you want to make some local versions. Look at my adjusted implementation of your constructor above again. See how I've removed the "String *" from before the variable names.
The variable "one" and "ten" have been changed from string pointers to vectors holding strings. Called the initializeArray within the constructor. Changed the way the name string was being assigned the new string. Here is the working code.
class Numbers
{
private:
int number;
string hundred;
string thousand;
vector<string> one;
vector<string> ten;
public:
Numbers(int num)
{
number = num;
hundred = "hundred";
thousand = "thousand";
initializeArray();
}
void initializeArray()
{
one.push_back("zero");
one.push_back("one");
one.push_back( "two");
one.push_back("three");
one.push_back("four");
one.push_back("five");
one.push_back("six");
one.push_back("seven");
one.push_back("eight");
one.push_back("nine");
one.push_back("eleven");
one.push_back("twelve");
one.push_back("thirteen");
one.push_back("fourteen");
one.push_back("fifteen");
one.push_back("sixteen");
one.push_back("seventeen");
one.push_back("eighteen");
one.push_back("nineteen");
// Initialize the ten array
ten.push_back("ten");
ten.push_back("twenty");
ten.push_back("thirty");
ten.push_back("forty");
ten.push_back("fifty");
ten.push_back("sixty");
ten.push_back("seventy");
ten.push_back("eighty");
ten.push_back("ninety");
}
string determine()
{
string name("");
for (int i = 0; i <= number; i++)
{
if (number == i)
{
auto iter = one.begin();
iter += i;
name.assign(*iter);
}
}
return name;
}
~Numbers()
{
}
};
int main()
{
Numbers n(5);
string name = n.determine();
cout << "The number is " << name << endl;
cin.ignore();
cin.get();
return 0;
}