Create a Lua table from a CPP string - c++

I'm coding and artificial intelligence using Lua script. And I'd like to push my map in the Lua's stack which is stock in a std::string *. I show you :
My Lua script (just a sketch to display the map) :
function runIa(x, y, map)
table.foreach(map, print)
return 0
end
Which only displays "0" on stdout
Here is where I fill my std::string * :
int AI::update()
{
std::string *map = new std::string[2];
pos_x = 0;
pos_y = 10;
map[0] = "0101100";
map[1] = "1101001";
toot->getGlobal("runIa");
toot->pushPosToScript(pos_x, pos_y);
toot->pushMapToScript(map);
try {
toot->pcall(3, 1, 0);
}
catch (const LuaException & e){
std::cerr << e.what() << std::endl;
}
return 0;
}
And that's how I push it into the Lua's stack :
void Lua::pushMapToScript(std::string *map)
{
lua_newtable(_L);
for (unsigned int i = 0; i < 2; ++i)
{
lua_pushnumber(_L, i + 1);
lua_pushstring(_L, map[i].c_str());
lua_settable(_L, -3);
}
}
It works well for the position but not for the map. I can't display what is store in the var map in the Lua script. Does someone have any idea ?
Thanks a lot.

Related

How to inserta nd retreive Multidimension array with static data in it into database using **insert** function of mongo-cxx-driver?

I tried the conventional way of passing an array to a wrapper function in which I'm using insertOne to insert data using for loop. No build issues, but while running, I'm hitting this error: Microsoft C++ exception: mongocxx::v_noabi::bulk_write_exception at memory location 0x000000B26C12DF30. Here is my source code.
int main(void) {
char EUI[][20] = { "10205E3710014240", "10205e37100142cc" ,"10205E6910001E58", "10205E371001426C" };
char IP[][15] = { "192.168.85.117" , "192.168.85.114", "192.168.85.186", "192.168.85.168" };
int i = 4;
push_data(IP, EUI, i);
while (1);
}
void push_data(char IP[][15], char EUI[][20], int count)
{
mongocxx::instance inst{};
mongocxx::client conn{ mongocxx::uri{} };
auto collection = conn["new"]["collection"];
int a;
builder::stream::document builder{};
auto in_array = builder << "subdocs" << builder::stream::open_array;
for (a = 0; a<count; a++) {
in_array = in_array << builder::stream::open_document << EUI[a] << IP[a]
<< builder::stream::close_document;
}
auto after_array = in_array << builder::stream::close_array;
bsoncxx::document::value doc = after_array << builder::stream::finalize;
bsoncxx::document::view view = doc.view();
for (a = 0; a < count; a++) {
collection.insert_one(doc.view());
}
auto cursor = collection.find({});
for (auto&& doc : cursor) {
std::cout << bsoncxx::to_json(doc) << std::endl;
}
}
Almost certainly, an exception has been thrown from collection.insert_one(doc.view());. You should catch that exception (by using try, and catch), and inspect the contents of the exception, which should tell you more about what is going wrong.

c++ String returning with an extra char

I have tested my program and am certain right before being returned the string in my function equals "card001". But the returned value equals "card0011". I have no idea how this even happens. Help me before I lose my mind. ;)
std::string function_cardTexture(int card) {
//removes the last 1
card = card - 10000;
int ctr = 0;
card = floor(card / 10);
std::cout << card << std::endl;
//turn int card into a string
std::string a = static_cast<std::ostringstream*>(&(std::ostringstream() << card))->str();
//combines card and string a into one string
std::string nametext = "card00" + a;
std::cout << nametext << std::endl;
return (nametext);
}
void function_Battle(tempPlayer &Player, tempCard &card001) {
if (Player.Start == true) {
//Draw hand
for (int i = 0; i < Player.numDrawn; i++) {
int x = rand() % Player.deckSize + 0; ;
Player.Hand[i] = Player.Deck[x];
Player.Discarded[x] = 1;
}
Player.Start = false;
}
std::map<std::string, tempCard> Vars;
//draw hand
for (int i = 0; i < Player.handMax;i++) {
if (Player.Hand[i] != 0) {
sf::RectangleShape Card(sf::Vector2f(80.0f, 128.0f));
std::string nametext = function_cardTexture(Player.Hand[i]);
std::cout << nametext;
sf::Texture texture = Vars[nametext].Art;
Card.setTexture(&texture);
window.draw(Card);
}
}
}
Your problem is how you're printing things out without a newline in the function_Battle() function, so you're likely "smashing together" your new value with an old one. If you replace your main function with just a loop with clearer printing of values, you can see you don't have a problem:
http://coliru.stacked-crooked.com/a/8d1e4f51643b84b9
That link will go to an online compiler where I just replaced the calling function with a loop that makes numbers. It even supplies a negative one.

C++ Calculating Shortest Path in a Directed Graph

I am tasked with writing a program to maintain the representation of a simple network(weighted directed graph) and compute the best path between two given nodes upon request.
Currently, I am attempting to write a function to compute the simplest between two nodes, however, when attempting to run my program, I get two specific error
Severity Code Description Project File Line Suppression State
Error C3863 array type 'bool [openNode]' is not assignable P 127
and
Severity Code Description Project File Line Suppression State
Error C3863 array type 'int [openNode]' is not assignable
I am unable to debug since these two primary errors are not allowing my program to run. Is there any particular reason for these errors?
Thanks in advance!
This is the node structure defined in Graph.h
struct GraphNode
{
char ID;
std::string name;
int inNodes = 0;
int outNodes = 0;
std::vector<std::pair<GraphNode*, int>> connection;
int connections = 0;
};
And here is the particular code that causes the errors.
#include "Graph.h"
std::vector<GraphNode*> _graph;
int openNode = 0;
//Obligatory constructor
void Graph()
{
}
void shortestPath(char fromNode, char toNode)
{
bool known[openNode];
int distance[openNode];
GraphNode* previous[openNode];
int numbChecked = 0;
for (int i = 0; i < openNode; i++)
{
known[i] = false;
distance[i] = 999999;
previous[i] = nullptr;
}
distance[findNode(fromNode)] = 0;
while (numbChecked < openNode)
{
int smallestUnknown = 9999999;
int locationOfSmall = 0;
for (int i = 0; i < openNode; i++)
{
if (known[i] == false && distance[i] < smallestUnknown)
{
smallestUnknown = distance[i];
locationOfSmall = i;
}
}
if (distance[locationOfSmall] == 0)
{
previous[locationOfSmall] = nullptr;
}
known[locationOfSmall] = true;
numbChecked++;
if (_graph[locationOfSmall]->outNodes > 0)
{
for (int i = 0; i < _graph[locationOfSmall]->outNodes; i++)
{
int newDistanceLocation = findNode(_graph[locationOfSmall]->connection[i].first->ID);
if (known[newDistanceLocation] == false && (distance[locationOfSmall] + _graph[locationOfSmall]->connection[i].second) < distance[newDistanceLocation])
{
distance[newDistanceLocation] = distance[locationOfSmall] + _graph[locationOfSmall]->connection[i].second;
previous[newDistanceLocation] = _graph[locationOfSmall];
}
}
}
}
int destination = findNode(toNode);
std::string output;
std::string charTransfer;
charTransfer = toNode;
output = charTransfer;
while (previous[destination] != nullptr)
{
destination = findNode(previous[destination]->ID);
charTransfer = _graph[destination]->ID;
output = charTransfer + "->" + output;
}
if (_graph[destination]->ID != fromNode)
{
std::cout << "The nodes are not connected." << std::endl;
}
else
{
std::cout << "The path is: " << output << std::endl;
std::cout << "The distance is: " << distance[findNode(toNode)] << std::endl;
}
}
Any change suggestions would be much appreciated!
You have invalid code at the beginning of your shortestPath function:
bool known[openNode];
int distance[openNode];
GraphNode* previous[openNode];
You cannot use variables to create arrays on the stack (which is what you are trying to do there), because the compiler doesn't know the value of openNode at compile time (which is needed to determine the stack size).
Why don't you use a vector, like:
std::vector<bool> known(openNode, false);
std::vector<int> distance(openNode, 999999);
std::vector<GraphNode*> previous(openNode, nullptr);
Using this method makes the for loop below obsolete aswell.

How to prepare statements and bind parameters in Postgresql for C++

I'm quite new to C++ and know a little bit about pqxx library. What I want to implement is to prepare statements and bind parameters. In PHP I'm used to doing this in such a nice and concise manner:
$s = $db->prepare("SELECT id FROM mytable WHERE id = :id");
$s->bindParam(':id', $id);
$s->execute();
or using tokens:
$data = array();
$data[] = 1;
$data[] = 2;
$s = $db->prepare("SELECT id FROM mytable WHERE id = ? or id = ?");
$s->execute($data);
I tried to fugure out from pqxx documentation how to implement this, but to me documentation looks like a mess and lacks short and simple examples (like I provided above). I hope someone can also provide such simple examples (or of comparable simplicity - without having to write some behemoth code) when dealing with Postgresql in C++.
A simple example. This just prints the number of entries with id value 0.
#include<pqxx/pqxx>
#include<iostream>
int main()
{
std::string name = "name";
int id = 0;
try {
//established connection to data base
pqxx::connection c("dbname=mydb user=keutoi");
pqxx::work w(c);
//statement template
c.prepare("example", "SELECT id FROM mytable WHERE id = $1");
//invocation as in varible binding
pqxx::result r = w.prepared("example")(id).exec();
w.commit();
//result handling for accessing arrays and conversions look at docs
std::cout << r.size() << std::endl;
}
catch(const std::exception &e)
{
std::cerr << e.what() << std::endl;
return 1;
}
return 0;
}
The function w.prepared() is a bit convoluted. It's similar to a curried(curry) function in haskell, as in it takes a parameter and returns another function which in turn takes another parameter. That kind of thing.
Documentation says:
How do you pass those parameters? C++ has no good way to let you pass an unlimited, variable number of arguments to a function call, and the compiler does not know how many you are going to pass. There's a trick for that: you can treat the value you get back from prepared as a function, which you call to pass a parameter. What you get back from that call is the same again, so you can call it again to pass another parameter and so on.
Once you've passed all parameters in this way, you invoke the statement with the parameters by calling exec on the invocation
If there are more parameters use $1 $2 and so on in the prepare function.
c.prepare("SELECT id name FROM mytable WHERE id = $1 AND name = $2")
and give the varibles as
w.prepared("example")(dollar1_var)(dollar2_var).exec()
An Example for dynamic preparation
#include<pqxx/pqxx>
#include<iostream>
#include<vector>
//Just give a vector of data you can change the template<int> to any data type
pqxx::prepare::invocation& prep_dynamic(std::vector<int> data, pqxx::prepare::invocation& inv)
{
for(auto data_val : data)
inv(data_val);
return inv;
}
int main()
{
std::string name = "name";
//a data array to be used.
std::vector<int> ids;
ids.push_back(0);
ids.push_back(1);
try {
pqxx::connection c("dbname=mydb user=keutoi");
pqxx::work w(c);
c.prepare("example", "SELECT id FROM mytable WHERE id = $1 or id = $2");
pqxx::prepare::invocation w_invocation = w.prepared("example");
//dynamic array preparation
prep_dynamic(ids, w_invocation);
//executing prepared invocation.
pqxx::result r = w_invocation.exec();
w.commit();
std::cout << r.size() << std::endl;
}
catch(const std::exception &e)
{
std::cerr << e.what() << std::endl;
return 1;
}
return 0;
}
if you want to handle other data types use this function definition
template<class T> pqxx::prepare::invocation& prep_dynamic(std::vector<T> data, pqxx::prepare::invocation& inv)
{
for(auto data_val : data)
inv(data_val);
return inv;
}
Use pqxx::prepare::invocation where you can, and bind more values before execution, because it's more stable and error preventative, but there is a faster way as I describe it below.
I.
With invocation:
pqxx::nontransaction W(C);
std::string m_insertCommand = "INSERT INTO tableforperftest(column1, column2) VALUES";
unsigned int m_nCurrentRow = 32767;
for (size_t i = 0; i < m_nCurrentRow; i++)
{
unsigned int countOf$ = i * 2;
for (unsigned int i = 0; i < 2; ++i)
{
if (i == 0)
{
m_insertCommand += "(";
}
else
{
m_insertCommand += ", ";
}
m_insertCommand += "$";
std::stringstream ss;
ss << countOf$ + i + 1;
m_insertCommand += ss.str();
}
if(i < m_nCurrentRow - 1)
m_insertCommand += ") ,";
}
m_insertCommand += ")";
C.prepare("insert_into_db", m_insertCommand);
pqxx::prepare::invocation inv = W.prepared("insert_into_db");
for (size_t i = 0; i < m_nCurrentRow; i++)
{
inv(i)(i);
}
inv.exec();
II.
With stored procedure which gets more values for parameters:
CREATE OR REPLACE FUNCTION insertintoboosted(valuesforinsert TEXT) RETURNS VOID AS
$$
BEGIN
EXECUTE 'INSERT INTO tableforperftestproof(column1, column2) VALUES (' || valuesforinsert || ')';
END;
$$
LANGUAGE plpgsql;
Code:
for (size_t i = 0; i < m_nCurrentRow; i++)
{
if (i == 0)
ss << i << "," << i;
else
ss << "(" << i << "," << i;
if (i < m_nCurrentRow - 1)
ss << "),";
}
C.prepare("prep2", "select insertintoboosted($1::text)");
W.prepared("prep2")(ss).exec();
III.
With parameter bindings and execution for each time:
std::string m_insertCommand3 = "INSERT INTO tableforperftest(column1, column2) VALUES ($1, $2)";
C.prepare("insert_into_db3", m_insertCommand3);
for (size_t i = 0; i < m_nCurrentRow; i++)
{
W.prepared("insert_into_db3")(i)(i).exec();
}
To compare the solutions with 32767 inserts:
Invocation: --> Elapsed: 0.250292s
Stored Proc: --> Elapsed: 0.154507s
Parameter binding + execution each time: --> Elapsed: 29.5566s

C++ Returning results from several threads into an array

I've a pattern-matching program which takes as input a string and returns a string closely matched by a dictionary. Since the algorithm takes several seconds to run one match query, I am attempting to use multi-threading to run batch queries.
I first read in a file containing a list of queries and for each query dispatch a new thread to perform the matching algorithm, returning the results into an array using pthread_join.
However, I'm getting some inconsistent results. For example, if my query file contains the terms "red, green, blue", I may receive "red, green, green" as the result. Another run may generate the correct "red, green, blue" result. It appears to sometimes be writing over the result in the array, but why would this happen since the array value is set according to the thread id?
Dictionary dict; // global, which performs the matching algorithm
void *match_worker(void *arg) {
char* temp = (char *)arg;
string strTemp(temp);
string result = dict.match(strTemp);
return (void *)(result.c_str());
}
void run(const string& queryFilename) {
// read in query file
vector<string> queries;
ifstream inquery(queryFilename.c_str());
string line;
while (getline(inquery, line)) {
queries.push_back(line);
}
inquery.close();
pthread_t threads[queries.size()];
void *results[queries.size()];
int rc;
size_t i;
for (i = 0; i < queries.size(); i++) {
rc = pthread_create(&threads[i], NULL, match_worker, (void *)(queries[i].c_str()));
if (rc) {
cout << "Failed pthread_create" << endl;
exit(1);
}
}
for (i = 0; i < queries.size(); i++) {
rc = pthread_join(threads[i], &results[i]);
if (rc) {
cout << "Failed pthread_join" << endl;
exit(1);
}
}
for (i = 0; i < queries.size(); i++) {
cout << (char *)results[i] << endl;
}
}
int main(int argc, char* argv[]) {
string queryFilename = arg[1];
dict.init();
run(queryFilename);
return 0;
}
Edit: As suggested by Zac, I modified the thread to explicitly put the result on the heap:
void *match_worker(void *arg) {
char* temp = (char *)arg;
string strTemp(temp);
int numResults = 1;
cout << "perform match for " << strTemp << endl;
string result = dict.match(strTemp, numResults);
string* tmpResult = new string(result);
return (void *)((*tmpResult).c_str());
}
Although, in this case, where would I put the delete calls? If I try putting the following at the end of the run() function it gives an invalid pointer error.
for (i = 0; i < queries.size(); i++) {
delete (char*)results[i];
}
Without debugging it, my guess is that it has something to do with the following:
void *match_worker(void *arg)
{
char* temp = (char *)arg;
string strTemp(temp);
string result = dict.match(strTemp); // create an automatic
return (void *)(result.c_str()); // return the automatic ... but it gets destructed right after this!
}
So when the next thread runs, it writes over the same memory location you are pointing to (by chance), and you are inserting the same value twice (not writing over it).
You should put the result on the heap to ensure it does not get destroyed between the time your thread exits and you store it in your main thread.
With your edit, you are trying to mix things up a bit too much. I've fixed it below:
void *match_worker(void *arg)
{
char* temp = (char *)arg;
string strTemp(temp);
int numResults = 1;
cout << "perform match for " << strTemp << endl;
string result = dict.match(strTemp, numResults);
string* tmpResult = new string(result);
return (void *)(tmpResult); // just return the pointer to the std::string object
}
Declare results as
// this shouldn't compile
//void* results[queries.size()];
std::string** results = new std::string[queries.size()];
for (int i = 0; i < queries.size(); ++i)
{
results[i] = NULL; // initialize pointers in the array
}
When you clean up the memory:
for (i = 0; i < queries.size(); i++)
{
delete results[i];
}
delete [] results; // delete the results array
That said, you would have a much easier time if you used the C++11 threading templates instead of mixing the C pthread library and C++.
The problem is caused by the lifetime of the local variable result and the data returned by the member function result.c_str(). You make this task unnecessary difficult by mixing C with C++. Consider using C++11 and its threading library. It makes the task much easier:
std::string match_worker(const std::string& query);
void run(const std::vector<std::string>& queries)
{
std::vector<std::future<std::string>> results;
results.reserve(queries.size());
for (auto& query : queries)
results.emplace_back(
std::async(std::launch::async, match_worker, query));
for (auto& result : results)
std::cout << result.get() << '\n';
}