How to call a function with an array of strings - c

I've made a function, but I'm struggling with calling it.
This is the prototype of the function:
char *test(int argc, char **argv);
I've tried calling it this way but it doesn't work :
int main()
{
char tab[3][3] ={
"Yo",
"Hi"};
test(2, tab);
return (0);
}

For me this works:
char* test(int index, char** char2Darray)
{
return char2Darray[index];
}
int main()
{
char* tab[2] ={
"Yo",
"Hi"};
test(1, tab);
return (0);
}
I think there are two problems in your code :
the tab what you provided has only two item
your tab is a pointer which pointing to char[3] types and not char*

When you pass the 2D array
char tab[3][3]
to the function test(), it decays to a pointer of type:
char (*)[3]
which is a pointer to an array of 3 char elements.
This type is not compatible with char** which is a pointer-to-pointer to char. This is the source of your problem. You need to change the function test() to take char (*argv)[3] instead of char **argv.

Looking at function prototype:
char *test(int argc, char **argv);
char **argv is pointer of pointers and the variable char tab[3][3] is array of arrays so they are incompatible.
You can change function prototype to: char *test(int argc, char argv[][SOMECONSTANT]); or char *test(int argc, char (*argv)[3]);

This way
char * test(int argc,const char **argv);
int main()
{
const char * tab[3]=
{
"Yo",
"Hi",
0
};
test(2,tab);
return 0;
}
or
char * test(int argc,char **argv);
int main()
{
char arg1[]="Yo";
char arg2[]="Hi";
char * tab[3]=
{
arg1,
arg2,
0
};
test(2,tab);
return 0;
}

Related

How to call another function that utilizes argc, char *argv[] in main without passing things to it?

say there is a function in my code:
int getwords(int argc, char *argv[])
and I want to call this function in main().
How do I call this in main without erroring out?
`void main(void)
getwords();`
If you write main to provide access to argc and argv:
int main(int argv, char **argv) {
// ...
}
Then you can pass those to another function when you call it:
void foo(int argc, char **argv) {
// ...
}
int main(int argc, char **argv) {
foo(argc, argv);
}
argc will be copied, but argv is a pointer, so the pointer is copied
but not the data it points to.
if for some special reason you do not want to use parameters you can use global variables available in all program.
int gargc;
char **gargv;
int main(int argc, char *argv[])
{
gargc = argc;
gargv = argv;
getopt();
}

Block signature for block that takes a function pointer and returns a block

I am using clang on linux.
What is the correct way to format this block?
(int ^(int, char**)) (^f2b)(int, char**) = (int ^(int, char**)) ((int (*func)(int, char**)))
{
return int ^(int argc, char** argv){ func(argc, argv)};
};
I am getting an error
error: type-id cannot have a name
int (^f2b)(int, char**) = (int ^(int, char**)) ((int (*func)(int, char**)))
The error underlines (*func).
I am trying to create a block that takes in a function pointer named func as a parameter and returns a block that calls that func using the arguments it is passed.
The key is the Block_copy function from <Block.h>1. That puts a copy of a block on the heap, which allows the block to be returned.
#include <stdio.h>
#include <Block.h>
typedef int (^block_t)(int, char **);
typedef int (*func_t)(int, char **);
block_t (^createBlock)(func_t func) = ^(func_t func)
{
return Block_copy( ^(int argc, char **argv) { return func(argc, argv); } );
};
int showFirst(int argc, char *argv[])
{
printf("%s\n", argv[0]);
return argc;
}
int main(void)
{
int argc = 3;
char *argv[] = {"hello", "world", NULL};
block_t block1 = createBlock(showFirst);
int count = block1(argc, argv);
printf("count=%d\n", count);
Block_release(block1);
}
createBlock takes a function pointer as its argument, and returns a block with the signature int (^block)(int, char **).
showFirst is just one possible implementation of the function that can be passed to createBlock. It displays the first string in the argv array and returns the value in argc.
The main function creates a block from the showfirst function. It then invokes the block, prints the returned value, and releases the block.
The output from the code is:
hello
count=3
1 I was not aware of <Block.h> until reading OP's answer.
http://thirdcog.eu/pwcblocks/ helped a lot.
#include <stdlib.h>
#include <stdio.h>
#include <Block.h>
int fake_main(int argc, char** words)
{
printf("%s\n", (char*)words);
return argc;
}
int main(int argc, char* argv[])
{
typedef int(*main_type_func)(int, char**);
typedef int(^main_type)(int, char**);
typedef main_type(^f2b_type)(main_type_func);
f2b_type f2b = ^ (main_type_func func)
{
return Block_copy(^ (int apple, char** ban)
{
return func(apple, ban);
});
};
printf("%d\n", f2b(fake_main)(1, "words worked"));
}
This is a minimum example of accomplishing the goals I outlined in the question.
The trick is the typedefs. Simplify the type signature by creating typedefs to help. I recommend that you use these whenever you want to accept and/or return a function pointer/block pointer.
Block_copy() moves the block from the stack into the heap.
It would be more correct to save the block pointer returned from
f2b(fake_main)
Then after use call
Block_release()
On it.
Your type syntax is incorrect. Based on your usage, I'm guessing you are declaring f2b to be a pointer to a block, which takes a pointer to a function that takes an int and a char ** and returns an int, and the block returns another block that takes an int and a char ** and returns an int.
The proper syntax for that declaration would be:
int (^(^f2b)(int (*) (int, char **)))(int, char **)
The syntax for more complicated C types is often counter-intuitive, especially in cases of multiple levels of functions and arrays.
The ever-useful cdecl.org website supports blocks: declare f2b as block(pointer to function(int, pointer to pointer to char) returning int) returning block(int, pointer to pointer to char) returning int (they say "block" whereas I say "pointer to block")
Your block definition written out using full block literal syntax (including return types) would be something like this (remembering to copy the block in order to return it):
int (^(^f2b)(int (*) (int, char **)))(int, char **) =
^int (^(int (*func)(int, char **)))(int, char **) {
return Block_copy(^int (int argc, char **argv) {
return func(argc, argv);
});
};
Return types may be omitted in block literals, so it could be written like:
int (^(^f2b)(int (*) (int, char **)))(int, char **) =
^(int (*func)(int, char **)) {
return Block_copy(^(int argc, char **argv) {
return func(argc, argv);
});
};

C - Pass Array of Strings as Function Parameter

I need to pass a pre-allocated array of strings as a function parameter, and strcpy() to each of the strings within the string array, as in this example:
static void string_copy(char * pointer[]) {
strcpy(pointer[0], "Hello ");
strcpy(pointer[1], "world");
}
int main(int argc, const char * argv[]) {
char my_array[10][100];
string_copy(my_array);
printf("%s%s\n", my_array[0], my_array[1]);
}
And the resulting printed string would be 'Hello world'.
How do I pass a pre-allocated string array and fill out each string within a function as shown above?
When you are doing string_copy(my_array), you are passing a char (*)[100], i.e. pointer to char[100] array to your function. But your function is expecting a char *[], i.e. array of char pointers, because you have defined your function that way.
You can fix this by making changes so that your function (string_copy()) expects a char (*)[100], instead of a char *[].
For this, you can change your function definition as:
/* Your my_array gets converted to pointer to char[100]
so, you need to change your function parameter
from `char *pointer[]` to `char (*pointer)[100]`
*/
/* static void string_copy(char *pointer []) */
static void string_copy(char (*pointer) [100])
{
strcpy(pointer[0], "Hello ");
strcpy(pointer[1], "world");
}
* Alternative Solution *
A different design/solution would be to change in your main() function so that you are actually passing a char *[], which decays into a char ** - which is fine - to string_copy(). This way you would NOT have to change your string_copy() function.
int main(int argc, const char * argv[]) {
char my_array[10][100];
int tot_char_arrs, i;
char *char_arr_ptr[10];
/* Get total number of char arrays in my_array */
tot_char_arrs = sizeof(my_array) / sizeof(my_array[0]);
// Store all char *
for (i = 0; i < tot_char_arrs; i++)
char_arr_ptr[i] = my_array[i];
/* Actually passing a char *[].
it will decay into char **, which is fine
*/
string_copy(char_arr_ptr);
printf("%s%s\n", my_array[0], my_array[1]);
}
you need to use a pointer to the array. here is an example with 1 dimension array:
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
static void string_copy(char **pointer) {
strcpy(pointer[0], "Hello ");
}
int main(int argc, const char * argv[]) {
char my_array[10];
char * p_array = my_array;
string_copy(&p_array);
printf("%s\n", my_array);
}
Your function can simply accept matrix dimensions and pass a const char * that stores the array of literals (pre-allocated) strings:
#include <stdio.h>
#include <string.h>
#define STRINGS_LENGTH 100
static void string_copy(size_t n, size_t m, char pointer[n][m], const char *strings_to_copy[])
{
for (size_t i=0; i< n; i++)
{
strcpy(pointer[i], strings_to_copy[i]);
}
}
int main( void )
{
const char *strings[] = { "hello", "World" };
char my_array[sizeof(strings)/sizeof(strings[0])][STRINGS_LENGTH];
string_copy(sizeof(strings)/sizeof(strings[0]), STRINGS_LENGTH, my_array, strings);
printf("%s %s\n", my_array[0], my_array[1]);
}
You can also change the structure of your code using dynamic allocation for your output array like:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
static bool string_copy(char *pointer[], const char *strings_to_copy[], size_t strings)
{
for (size_t i=0; i< strings; i++)
{
pointer[i] = malloc(strlen(strings_to_copy[i])+1);
if (pointer[i] != NULL)
strcpy(pointer[i], strings_to_copy[i]);
else
return false;
}
return true;
}
int main(void)
{
const char *strings[] = { "hello", "World" };
char *my_array[sizeof(strings)/sizeof(strings[0])] = {0};
if (string_copy(my_array, strings, sizeof(strings)/sizeof(strings[0])) )
{
printf("%s %s\n", my_array[0], my_array[1]);
}
for (size_t i = 0; i<sizeof(strings)/sizeof(strings[0]); i++)
free (my_array[i]);
}

Reference to a pointer is lost [duplicate]

This question already has answers here:
Assignment of function parameter has no effect outside the function
(2 answers)
Closed 9 years ago.
I am trying to understand why this statement doesn't work.
char resp[] = "123456789";
void getValue(char *im)
{
im = resp;
printf("\n%s\n",im);
}
int main(int argc, char *argv[])
{
char imei[11] = {0};
getValue(imei);
printf("\nIMEI: %s\n",imei);
return 0;
}
Output:
123456789
IMEI:
You can not assign with =, use strcpy instead:
#include <stdio.h>
#include <string.h>
char resp[] = "123456789";
void getValue(char *im)
{
im = strcpy(im, resp);
printf("\n%s\n",im);
}
int main(int argc, char *argv[])
{
char imei[11] = {0};
getValue(imei);
printf("\nIMEI: %s\n",imei);
return 0;
}
That's because imei is an array[11] (not just a pointer to), if you want to assign via = you can:
#include <stdio.h>
char resp[] = "123456789";
void getValue(char **im)
{
*im = resp;
printf("\n%s\n",*im);
}
int main(int argc, char *argv[])
{
char *imei; /* Not an array but a pointer */
getValue(&imei);
printf("\nIMEI: %s\n",imei);
return 0;
}
C passes parameters by value. Whatever change you ale to the im will be lost when the function exits. If you want to preserve the change. Pass the address of the pointer. Then you can change the pointer at the address you pass.
Try this:
char resp[] = "123456789";
void getValue(char **im)
{
*im = resp;
printf("\n%s\n",*im);
}
You need to pass a pointer to a pointer as your program argument.

Modify struct from function?

I want to modify file in the items struct from parse_commandline().
I can without problems modify items->file from main() by using strncpy, but not from parse_commandline(). I need to modify parse_commandline() so it can recieve information about items from main(), by i don't know how?
typedef struct {
int pack_01;
int pack_02;
char file[100];
} items;
static items character_y = { 1, 1 }
parse_commandline(int argc, char *argv[])
{
/* PARSE COMMANDLINE ARGUMENTS */
}
int main(int argc, char* argv[])
{
items *ptr_items = &character_y;
parse_commandline(argc,argv);
return 0;
}
The way to do this is pass a pointer to items to the parse_commandline function and let the function update the structure based on the arguments.
parse_commandline(int argc, char *argv[], items* pItems) {
pItem->pack_01 = 42;
...
};
int main(int argc, char* argv[]) {
items items;
parse_commandline(argc, argv, &items);
...
}
Passing a structure to a function in C is no different from passing any other variable. In your case, you should do it by reference so that you can modify the caller's structure:
void parse_commandline(int argc, char *argv[], items *theItems)

Resources