Convert Lua table to C array? - c

What I'm looking for is something like:
lua script
MY_ARRAY = {
00, 10, 54, 32,
12, 31, 55, 43,
34, 65, 76, 34,
53, 78, 34, 93
}
c code
lua_Number array[] = lua_getarray("MY_ARRAY");
Is this possible? Is there anything similar to make dealing with lua tables in C easier.

You can write such function yourself! It shouldn't be too many lines. But it's better to use pointers than arrays, because they can point to any number of elements. The interface could be something like this:
lua_Number *values;
size_t nvalues;
values = luaGetNumbers("MY_ARRAY", &nvalues);
/* the number of values is now nvalues */
for (int i=0; i<nvalues; i++) {
/* do something with values[i] */
}
free(values);
And the implementation should use the following functions (from http://www.lua.org/manual/5.2/manual.html):
void lua_getglobal (lua_State *L, const char *name);
Pushes onto the stack the value of the global name.
void lua_gettable (lua_State *L, int index);
Pushes onto the stack the value t[k], where t is the value at the
given valid index and k is the value at the top of the stack.
This function pops the key from the stack putting the resulting value
in its place). As in Lua, this function may trigger a metamethod for
the "index" event (see §2.4).
lua_Number lua_tonumberx (lua_State *L, int index, int *isnum);
Converts the Lua value at the given acceptable index to the C type
lua_Number (see lua_Number). The Lua value must be a number or a
string convertible to a number (see §3.4.2); otherwise, lua_tonumberx
returns 0.
If isnum is not NULL, its referent is assigned a boolean value that
indicates whether the operation succeeded.
void lua_len (lua_State *L, int index);
Returns the "length" of the value at the given acceptable index; it is
equivalent to the '#' operator in Lua (see §3.4.6). The result is
pushed on the stack.

Related

How can I change a structure array in C

I need to change the properties of the structure within a function, so I could do a calculation with the properties and set new values,but when i try to change the value of a structure i am getting the following error: cannot convert 'data specs (*) [2]' to 'data specs' for argument '1' to 'void changeValues ​​(data specs)' changeValues ​​(& stats);
Does anyone know how to fix it?
typedef struct
{
char nome;
int vida;
int dano;
int x;
int y;
} dadospecas;
void changeValues(dadospecas *a[]){
a[1]->vida = 5;
printf("%i", a[1]->vida);
}
int main() {
dadospecas stats[2];
stats[1].nome = 'W';
stats[1].vida = 3;
stats[1].dano = 1;
stats[1].x = 4;
stats[1].y = 1;
stats[2].nome = 'F';
stats[2].vida = 33;
stats[2].dano = 11;
stats[2].x = 44;
stats[2].y = 14;
changeValues(&stats);
return 0;
}
In addition to the great answer by #Stuart, you seem to be a little confused on how to handle sending values to your function to be changed, (here you are changing the vida member only). As noted in the other answer, on access, an array is converted to a pointer to its first element. C11 Standard - 6.3.2.1 Other Operands - Lvalues, arrays, and function designators(p3).
To make your function useful (as it is it hardcodes the entire operation), you should provide parameters for a pointer to dadospecas, the index to change and the new value to assign to the vida member. The caller is responsible for ensuring the index to change is within bounds (you can pass the number of elements as an additional index if desired)
If you put those pieces together and change the name of the function to reflect the fact you are only changing the vida member, you could do:
/* pass a pointer to the array as your parameter (inlcude index and value) */
void changeVida (dadospecas *a, int index, int newvida)
{
a[index].vida = newvida;
}
A short example showing the use, and fixing your indexing problem, could be written as:
#include <stdio.h>
#define NSTRUCT 2 /* if you need a constant, #define one (or more) */
typedef struct {
char nome;
int vida,
dano,
x,
y;
} dadospecas;
/* pass a pointer to the array as your parameter (inlcude index and value) */
void changeVida (dadospecas *a, int index, int newvida)
{
a[index].vida = newvida;
}
int main (void)
{
dadospecas stats[NSTRUCT] = {{'W', 3, 1, 4, 1}, {'F', 33, 11, 44, 14}};
for (int i = 0; i < NSTRUCT; i++) { /* loop over each struct */
changeVida (stats, i, stats[i].vida + 5); /* increment vida by 5 */
printf ("stats[%d].vida = %d\n", i, stats[i].vida); /* output new vida */
}
}
Example Use/Output
Where the example simply adds 5 to the existing value of the vida member:
$ ./bin/dadospecas
stats[0].vida = 8
stats[1].vida = 38
If You Pass The Address of stats
While there is no need to pass the address of stats, there is nothing to prevent you from doing it -- it is perfectly fine -- just unnecessary. For sake of argument, let's say you did. Continuing from my comment, in main stats is an array of type dadospecas [2], so when you take the address your type is pointer to array of dadospecas [2]. The formal type is dadospecas (*)[2]
So passing the pointer your function parameter would become: dadospecas (*a)[2].
Within your function to operate on your array, you would first need to dereference the parameter to allow you to operate on the elements of the array, e.g. (*a)[index] and finally to change the vida member you would have:
(*a)[index].vida = newvida;
The changes to the example above to pass the address of stats would be:
/* pass a pointer to array[NSTRUCT] as your parameter (inlcude index and value) */
void changeVida (dadospecas (*a)[NSTRUCT], int index, int newvida)
{
(*a)[index].vida = newvida;
}
int main (void)
{
dadospecas stats[NSTRUCT] = {{'W', 3, 1, 4, 1}, {'F', 33, 11, 44, 14}};
for (int i = 0; i < NSTRUCT; i++) { /* loop over each struct */
changeVida (&stats, i, stats[i].vida + 5); /* increment vida by 5 */
printf ("stats[%d].vida = %d\n", i, stats[i].vida); /* output new vida */
}
}
(same output)
It is simply a matter of keeping the levels of pointer indirection straight and observing C operator precedence.
Look things over and let me know if you have further questions.
I think there are two things you don't understand about arrays in C.
Arrays are indexed starting from 0 and not 1.
The first element of your stats array is stats[0] and the second is stats[1]. You need to change the assignments in your main function, and in your changeValues function if you want it to change the first element of the array.
Arrays are const pointers (i.e. pointers that have a fixed value).
The stats array is really a const pointer to dadospecas. It's a const pointer meaning you can't change the value of stats. You can change the values contained by (i.e. pointed to) by stats.
If you want to define a function that will modify the contents of an array, you don't need to pass a pointer to the array, you can just pass the array.
Your changeValues function should be defined like this:
void changeValues(dadospecas *a){
//put code here.
}
or
void changeValues(dadospecas a[]){
//put code here.
}
In either case, your main function would call changeValues like this
changeValues(stats);
By the way, if you want to check that changeValues has modified the vida member of the first element of stats, I would remove the printf call from the changeValues function and replace it with
printf("%i", stats[0].vida);
in your main function (after the call to changeValues of course).

What, if any, is a technical reason to lead with a function pointer argument and then arguments for that function or the other way around?

Perhaps based deeper on VLAs, debuggers, _Geneirc_, some presently proposed feature of the next C, or some other corner of C, the question:
Is there a coding advantage (objective reason) that prefers one function signature over the other when functions pointers are involved?
I have found none.
Typically the order of arguments in a function signature is simply a style choice.
I am looking though for a reason why in a non-(...) function with a function pointer argument an advantage may exist for a certain order.
I could define a function containing a function pointer as
// Function pointer before its arguments a1,b1 it will eventually use
void foo1(void (*fun)(int a0, double b0), int a1, double b1) {
fun(a1, b1);
fun(a1,-b1);
}
or
// Function pointer after the a2,b2 arguments
void foo2(int a2, double b2, void (*fun)(int a0, double b0)) {
fun(a2, b2);
fun(a2, -b2);
}
Researching the standard C library offers 2 opposite examples.
// Function pointer before `context`.
errno_t qsort_s(void *base, rsize_t nmemb, rsize_t size,
int (*compar)(const void *x, const void *y, void *context), void *context);
// Function pointer last.
void (*signal(int sig, void (*func)(int)))(int);
So far, this certainly is a style choice.
Order is important with VLA
I considered VLAs where the arguments before arr2 are needed and somehow the signature of fun2() might be based on row2, col2, arr2 and derive some benefit. This would offer an advantage for the function pointer to trail.
int foo2(int row2, int col2, char arr2[row2][col2], void (*fun2)(TBD_Signature);
But I came up with no useful example.
[Edit]
Perhaps another way to look at one aspect of this question:
Can the signature of the function pointer derive from prior arguments of the function in a useful manner?
int bar(int some_arg, other_args,
(*f)(signature based on some_arg, other_args or their type));
GCC lets you write:
int function1(int arg1, int arg2, int (*function)(int array1[arg1], int array2[arg2]));
which declares a function taking a pointer to function with VLA arguments — but I don't think that pointer to function is usable because the size information isn't available to the actual function, so it has no idea about the size of the two VLAs purportedly passed to it. So you can't write the code for the function to be passed as a pointer.
Now, you could perhaps use:
int function2(int arg1, int arg2, int (*function)(int, int, int array1[arg1], int array2[arg2]));
But that is equivalent to:
int function2(int arg1, int arg2, int (*function)(int, int, int array1[*], int array2[*]));
which you can verify by including both those declarations in a single file and noting that there is no conflict reported. The * notation in subscripts is only allowed in function declarations (not in function definitions).
In the same way, the declaration of function1() above is equivalent to:
int function1(int arg1, int arg2, int (*function)(int array1[*], int array2[*]));
And it isn't really clear that it is different from:
int function1(int arg1, int arg2, int (*function)(int array1[], int array2[]));
All three declarations can coexist in a single source file. The function called via the pointer must have some way to determine the size of the two arrays it is given.
An attempt to use [*] in a function definition yields:
error: ‘[*]’ not allowed in other than function prototype scope
Here's a demonstration of the second function (at work:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int function1(int arg1, int arg2, int (*funcptr)(int array1[arg1], int array2[arg2]));
int function2(int arg1, int arg2, int (*funcptr)(int, int, int array1[arg1], int array2[arg2]));
int function2(int arg1, int arg2, int (*funcptr)(int, int, int array1[*], int array2[*]));
static void dump_array(const char *tag, int n, int array[n])
{
printf("%s (%d):\n", tag, n);
int length = 0;
const char *pad0 = " ";
const char *pad = pad0;
for (int i = 0; i < n; i++)
{
length += printf("%s%d", pad, array[i]);
if (length > 70)
{
length = 0;
pad = pad0;
putchar('\n');
}
else
pad = ", ";
}
if (length > 0)
putchar('\n');
}
static int function(int s1, int s2, int array1[s1], int array2[s2])
{
dump_array("array1", s1, array1);
dump_array("array2", s2, array2);
return s1 + s2;
}
int function2(int arg1, int arg2, int (*funcptr)(int, int, int array1[*], int array2[*]))
{
int a1[arg1];
for (int i = 0; i < arg1; i++)
a1[i] = rand() % 100;
int a2[arg2];
for (int i = 0; i < arg2; i++)
a2[i] = rand() % 100 + 100;
return (*funcptr)(arg1, arg2, a1, a2);
}
int main(void)
{
srand(time(0));
function2(32, 16, function);
return 0;
}
When run, it might produce:
array1 (32):
47, 23, 52, 60, 42, 48, 54, 55, 65, 6, 66, 57, 63, 77, 22, 96, 72, 98
75, 0, 50, 33, 39, 30, 62, 82, 1, 87, 73, 24, 55, 20
array2 (16):
148, 159, 133, 142, 107, 187, 197, 172, 145, 163, 130, 160, 141, 104
156, 165
You are excluding varargs functions, but I'm not sure why. Also, I'm not sure if you meant to exclude them as an implementation detail, or as a matter of theory.
Regardless, one reason would be for performance. If your calling convention puts the arguments on the stack from right to left, then putting the function-pointer parameter on the left might leave the arguments to the function already on-stack in the correct order:
int call_fn(int (*fn)(void * ignored, A_TYPE a, B_TYPE b), A_TYPE a, B_TYPE b);
In this scenario, the code might simply fetch the function pointer and jump to that address, with the arguments already in the correct location. Alternatively, you might do this to implement a thunk where the virtual table pointer was replaced and then execution continued at a new address.
I doubt there is any technical reason. Rather, there is a very good semantic reason.
When an object gets conceptually "attached" to another, by way of an assignment or, in the case of function pointers, a call, then we tend to put that object after the one it's attached to. For example, when using a map data structure, you need a function to associate a value with a key: you "attach" that value to the key. That function will almost certainly accept the key parameter first, and the value parameter second. The same kind of order is seen in the language itself when defining a function: the name of the function comes before the names of its parameters, because the parameters are "attachments" to the function, not the other way around.
The qsort_s case is where the function pointer comes first: compar comes before context. Here, the function pointer is a functor, in the sense that it is passed as some kind of object (a pointer) to the main function (qsort_s), which can call it straight away. Its arguments (context) come after, because they are attachments to the functor.
The signal (also sigaction) case is where the function pointer comes last: func comes after sig. Here, the function pointer is a handler, or callback, saved for later use. It isn't called directly; instead, it gets "assigned", or "attached", to some event object (here represented by sig, a signal number), and so comes after it, even if it's then called with that event object as argument. It's like the map function associating a value to a key: the value is the handler, and the key is the event.
In the particular case of qsort_s, compar gets passed values from base as well, but base itself isn't an argument to compar.
This corresponds to a third case where the function pointer comes last but is meant to act on parts of the previous arguments. It often happens in generic algorithms that require some kind of functor, often a predicate, to act on data (the C++ standard library is full of such examples). In this case, the data comes first, even though the function pointer gets called with individual pieces of that data. Conceptually, the functor gets attached to the data to act on it piece by piece.
Plain old qsort (without a context parameter) also qualifies for that case.
As for your last question (Can the signature of the function pointer derive from prior arguments of the function in a useful manner?), I would say no.
It certainly can't change based on the runtime values of the arguments, since the signature is a compile-time thing (at least in C). You could always have void* parameters and change their interpretation based on runtime values, but that's not the same thing.
I don't think it can change based on the types of the other arguments, at least not in C. Other languages have mechanisms that make this possible, but they are usually complicated and not worth it anyway.

Invoke function with 2D array as parameter [duplicate]

This question already has answers here:
Passing a multidimensional array of variable size
(2 answers)
How to pass 2D array (matrix) in a function in C?
(4 answers)
Closed 4 years ago.
I'm Java developer, not a C programmer. I'm trying to invoke some function that receives a 2D array, tried like:
#include <stdio.h>
int foo(int mat[][N])
{
printf("%d",N); /* <--- here error */
}
int main()
{
int a[5][5] =
{
{1, 2, 3, 4,5},
{1, 5, 5, 5,2},
{1, 4, 30,4,2},
{1, 2, 2,2, 2},
{1,1, 1,1, 2 }
};
foo(a);
return 0;
}
But the compiler says:
'N' undeclared (first use in this function)
I must have the signature: int foo(int mat[][N])
How should I pass the 2D array then?
You can use macros to define constant numbers, i.e. #define N 5. At compile time each appearance of the defined macro name will be replaced with the given value. In our case each N would be replaced with 5.
But this would not solve your problem, because it would print 5 every time, even if you change the dimensions of your array.
Pass the dimensions of the array as parameters.
You can pass the 2D array as a pointer.
I created a printing function, with what I can show you accessing the elements from the array. So the function's prototype would look like:
void print2DMatrix(int *matrix2D, const int rowLength, const int columnLength);
where matrix2D is a pointer, there will be passed the address of the array. The other two parameters tell us the dimensions of the array.
We can access the elements in a selected row and in a selected column with matrix2D[selectedRow * maxRowLength + selectedColumn].
When you call the function, you can pass the name of the array, like print2DMatrix(*myMatrix, myRowLength, myColumnLength);, of course you shall declare and initialize it before using.
print2DMatrix(myMatrix, myRowLength, myColumnLength); would cause warning, because the passed argument and the waited one have different types, but it will run correctly. The passed one is a double pointer, when the waited one is a single pointer. Because of that you have to use print2DMatrix(*myMatrix, myRowLength, myColumnLength);, where *myMatrix will point to the first row of our array.
I would like to mention that myMatrix and *myMatrix point to the same address, the difference is: myMatrix is looked as a double pointer to an integer, when *myMatrix is looked as a pointer to an integer. Run printf("%d %d %d", myMatrix, *myMatrix, **myMatrix); to see the result. **myMatrix will point to the first element of the first row, what is 11. See the entire code below...
#include <stdio.h>
#define ROW_LENGTH 5
#define COLUMN_LENGTH 5
void print2DMatrix(int *matrix2D, const int rowLength, const int columnLength)
{
int i;
for (i = 0; i < rowLength; i++)
{
int j;
for (j = 0; j < columnLength; j++)
{
printf("%d ", matrix2D[i * rowLength + j]);
}
printf("\n");
}
}
int main(void)
{
const int myRowLength = ROW_LENGTH;
const int myColumnLength = COLUMN_LENGTH;
int myMatrix[ROW_LENGTH][COLUMN_LENGTH] =
{
{11, 12, 13, 14, 15},
{21, 22, 23, 24, 25},
{31, 32, 33, 34, 35},
{41, 42, 43, 44, 45},
{51, 52, 53, 54, 55}
};
print2DMatrix(*myMatrix, myRowLength, myColumnLength);
return 0;
}
You are trying to print a non existent value. N is not a declared variable.
The function foo is receiving a pointer. Unlike java, C deals with pointers, not objects, it does not have any information about what it received, except that it is a pointer that contains addresses to ints. Therefore, the function does not know (or care) about your array being of size N (regardless of you mentioning N) .
When you call printf there's nothing in memory called N, which explains the error.
You could always send a second argument which is an int specifying the size and print that one.
void foo(int[][] mat, int matSize){
printf("%d\n",matSize);
}
Notice how I used int[][] this is to simplify and illustrate the fact that is just a pointer.

How to find the insertion point in an array bsearch() works on?

using bsearch() in C (standard library) one can quickly find an entry in a sorted array.
However, how do I calculate where to insert a new entry (using the standard library)?
bsearch() specifically checks whether the found item's key is equal to the passed key and if it isn't, it returns NULL - so can't use that.
Its not clear from the question but possibly this is what you want:
You can do something like this to find the index in the array where bsearch () found the match.
if (bsearch_returned_address != NULL)
index = (bsearch_returned_address - array_base_address)
EDIT
To know the location which the bsort last visited, check the below stuff out.
The good thing is that the manual says:
The compar routine is expected to have two arguments which point to the key object and to an array member, in that order, and should return an integer less than,
equal to, or greater than
zero if the key object is found, respectively, to be less than, to match, or be greater than the array member.
Therefore you can store the second argument inside the comparison function in a global variable, and in a case of the fail use the address in this variable, which points to the last location the bsearch function visited to find for a match.
For example:
A list with address and value:
[0x8d6010: 0][0x8d6014: 4][0x8d6018: 8][0x8d601c: 12][0x8d6020: 16][0x8d6024: 20][0x8d6028: 24][0x8d602c: 28][0x8d6030: 32][0x8d6034: 36]
Value to search
13
output
fmem: (nil) //this is the memory location where it was found
last_mem1: 0x7fff8c8e6c54 //last val of 1st param of compare
last_mem2: 0x8d601c //last val of 2nd param of compare
*last_mem1: 13, *last_mem2: 12
The sample compare function code is
static const int *last_mem1, *last_mem2;
static int
compmi(const void *a, const void *b)
{
last_mem1 = a; last_mem2 = b;
return *(int *)a - *(int *)b;
}
So you can insert after the address in last_mem2. Although there are terminal cases, if you find a key which is less than the first element, then last_mem2 will also have the address of the first element.
But how ever you have to shift the array elements to make place for the insertion, which will make the insertion complexity to O(n). You might want to improve performance by introducing some kind of lazy insertion, like make a separate unordered list, which is much smaller than your original list, and dump new elements there. When searching, perform bsearch in original list, and linear search in the dump. When the dump list grows past a certain threshold, you can merge the list by performing an insertion sort. But still, you can't be O(lg n).
Here's an improvement upon #phoxis's answer that will make the code thread-safe and reentrant by avoiding any global variables. The trick is to use the key itself to store the last visited address.
bsearch_insertion.h
#include <stdlib.h>
#ifndef BSEARCH_INSERTION_H
#define BSEARCH_INSERTION_H
/* Just like bsearch(3), but return a pointer to the element after which
* the key would need to be inserted in order to maintain sorted order. */
void *bsearch_insertion(
const void *key, const void *base, size_t nel,
size_t width, int (*compar)(const void *, const void *));
#endif /* BSEARCH_INSERTION_H */
bsearch_insertion.c
#include "bsearch_insertion.h"
typedef struct
{
const void *key;
int (*const compar)(const void *, const void *);
void *last_visited;
} bsearch_insertion_state;
static int bsearch_insertion_compare(const void *a, const void *b)
{
bsearch_insertion_state *state = (bsearch_insertion_state *) a;
state->last_visited = (void *) b;
return state->compar(state->key, b);
}
void *bsearch_insertion(
const void *key, const void *base, size_t nel,
size_t width, int (*compar)(const void *, const void *))
{
bsearch_insertion_state state = {key, compar, NULL};
bsearch(&state, base, nel, width, bsearch_insertion_compare);
return state.last_visited;
}
Example: test.c
#include <stdio.h>
#include "bsearch_insertion.h"
static int cmp(const void *a, const void *b)
{
int aint = *(const int *)a;
int bint = *(const int *)b;
return aint - bint;
}
int main(int argc, char **argv)
{
int data[] = {0, 1, 2, 3, 5};
int key = 4;
void *result = bsearch_insertion(
&key, data, sizeof(data) / sizeof(data[0]), sizeof(data[0]), cmp);
/* Should print "Insertion point: 3" */
printf("Insertion point: %d\n", (int *)result - data);
return 0;
}
Not sure what you mean by "calculate insertion place"; you build an array, then sort it using qsort(), then do (many) searches using bsearch().
In other words: for typical usage, you don't need to implement the array-sorting, since the standard library contains functionality for that, too.
Not sure about the connection to bisecting, here.
UPDATE: From the comment, it seems you're concerned about doing inserts into an array that you're also doing searches from. I would recommend looking at some other data structure that is more friendly towards inserts, such as a hash table for instance. By not relying on sorting to keep searches fast, a hash table might perform better. Inserting into an array involves moving all the subsequent elements, which is also quite costly and which is not needed for e.g. a hash table.
UPDATE 2: To actually try to answer your question, assuming you have a bsearch()-comparible comparator() function for your array of n entries, the index for the new item ni should be given by something like this:
size_t i;
for( i = 0; i < n && comparator(&ni, array + i) >= 0; ++i )
;
/* Grow array, copy i..n to (i+1)..(n+1), insert ni at i. */
Because insert causes copying of tail of array, time is O(n). So simple linear search won't slow down your code dramatically. You can even copy items during searching, if you start searching from the end of array.

sort arrays of double in C

if I have an array
double i[5] = {1.023, 1.22, 1.56, 2, 5, 3.331};
how do i sort the values so that they look like this:
double i[5] = {1.023, 1.22, 1.56, 2, 3.331, 5};
i've tried qsort() with no luck, after trying some examples, i came up with:
qsort(i, 5, sizeof(double), sort);
int sort(const void *x, const void *y)
{
return (*(double*)x - *(double*)y);
}
with => error: incompatible type for argument 1
not sorting the array.....
The first argument to qsort is the pointer to the start of the array to be sorted. Instead of
qsort(i[5], 5, sizeof(double), sort);
it should read
qsort(i, 5, sizeof(double), sort);
Some further observations:
The length of i's initializer is incorrect (i has five elements, yet the initializer has six).
Hard-coding the 5 into the qsort call is asking for trouble later on.
The name "i" is most commonly used for loop counters and the like.
Calling the comparison function sort is confusing.
Your comparison function is wrong. Consider how it would compare the numbers 1.1 and 1.2. Also think about what would happen if the difference between the two values doesn't fit in an int.
I would rewrite your entire example like so:
double arr[] = {1.023, 1.22, 1.56, 2, 5, 3.331};
int cmp(const void *x, const void *y)
{
double xx = *(double*)x, yy = *(double*)y;
if (xx < yy) return -1;
if (xx > yy) return 1;
return 0;
}
int main() {
qsort(arr, sizeof(arr)/sizeof(arr[0]), sizeof(arr[0]), cmp);
}
Note that the above comparison function still doesn't correctly handle NaNs; I leave it as an exercise for the reader to fix that.

Resources