I am trying to pass multiple parameters when running a compiled C code
code would be like this
void main(char argc,char *argv[]){
printf("%s",argv[1]) //filename
FILE *file = fopen(argv[1], "r")
printf("%s",argv[2]) //function to be called
char* func_name = argv[2];
printf("%s",argv[3]) //how many times the function is called
int repeat = argv[3];
for(int i=0;i<repeat;i++){
func_name(file) //calls some function and passes the file to it
}
}
i would compile like this
gcc cprog.c -o cprog
run like -
./cprog textfile.txt function1 4
how do i do this ? any help would be appreciated !
First off:
You are missing some semicolons, so your code won't even compile.
argv[] are strings, so you'll have to convert them to integers if you want to use them as such.
C does not store function names in the binary, so you have to create some kind of calling table.
Below find a working example. I creates a struct that maps a name to a function, implement that function and go look for it. It's quite buggy (no input validation is done), but gives you a proof of concept on how to possibly implement this.
#include <stdlib.h>
#include <stdio.h>
struct fcn_entry {
char *name;
void (*fcn)(char *);
};
void fcn1(char *fn) {
printf("fcn1: %s\n", fn);
}
void fcn2(char *fn) {
printf("fcn2: %s\n", fn);
}
void main(char argc,char *argv[]){
// name-to-function table
struct fcn_entry entries[] = {
{ "fcn1", fcn1 },
{ "fcn2", fcn2 },
{ NULL, NULL }
};
void (*fcn_to_call)(char *);
int i = 0;
printf("%s",argv[1]); //filename
printf("%s",argv[2]); //function to be called
char* func_name = argv[2];
i = 0;
while(entries[i].name != NULL) {
if (strcmp(entries[i].name, func_name) == 0) {
fcn_to_call = entries[i].fcn;
break;
} else {
fcn_to_call = NULL;
}
i++;
}
printf("%s",argv[3]); //how many times the function is called
int repeat = atoi(argv[3]);
for(i=0;i<repeat;i++){
fcn_to_call(argv[1]);
}
}
There are a lots of error here.
int repeat = argv[3]; //You must convert char* to int before assignment.
func_name(file) //func_name is a char* not a function. C does not support reflection so there is no way to call function like this.
To be able to call a function that you have as a string, you have know which name is paired to which function.
If all functions take the same arguments, you can have an array of structures with name and function pointer, and then match the name with the correct entry in the table.
Otherwise, if the arguments are different you have to have a chain of strcmp calls to call the correct function.
Related
I have a simple C function which I would like to pass an array of pointers to various strings. I am having trouble with the compiler barking at my function call parameters. Here is simple representation of what I am doing,
myfunction.h
int myServices(int, char *[]);
myfunction.c
#include <myfunction.h>
int myService(int value, char *strpointer[]) {
***
}
mainroutine.c
#include <myfuntion.h>
void main () {
// Initialize Parameters
int result;
int stringcnt;
char string1[8] = "-st";
char string2[8] = "-ir";
char * stringptr[10];
// Initialize stringptr
stringptr[0] = string1;
stringptr[1] = string2;
stringcnt = 2;
// Call Service
result = myService(stringcnt, stringptr); <== gcc issue with stringptr
}
The C compiler keeps giving me a "invalid use of member (did you forget the '&'?" with the stringptr in the myService call. I tried '&' and '*' with stringptr in the myService call in the main routine with no luck. Any ideas.
I ran your code and notices a few things: first of all in your header file you didn't define the arguments properly (case of the missing coma), and likewise your main entry point did not have the proper return type (needs to be int) nor arguments (int argc, char *argv[]). I've made the changes and attached them below:
// func.h
int myService(int, char*[]);
Then the function code:
// func.c
#include "func.h"
int myService(int value, char *strpointer[]) {
// your code here
return 0;
}
// prog.c
-
#include "func.h"
int main (int argc, char *argv[]) {
// Initialize Parameters
int result;
int stringcnt;
char string1[8] = "-st";
char string2[8] = "-ir";
char * stringptr[10];
// Initialize stringptr
stringptr[0] = string1;
stringptr[1] = string2;
stringcnt = 2;
// Call Service
result = myService(stringcnt, stringptr);
return 0;
}
I compiled this using the command gcc -o prog.o prog.c func.c with no errors and smooth execution. Hope this works for you
I want myprogram to take user-entered arguments and see if each argument matches a hard-coded list. I am looking for a better alternative to a long switch statement or a series of if else.
Here is a minimal example of what I'm attempting using enum:
$ ./myprogram blue square
//myprogram.c
#include<stdio.h>
int main(int argc, char ** argv){
//many allowable colors and shapes
enum colors_t {blue, red, /*...*/ green};
enum shape_t {square, circle, /*...*/ triangle};
//how do I check if argv[1] is on the list of colors?
if(COMPARE(argv[1], colors_t)
colors_t user_color = argv[1];
else
printf("%s is not a usable color\n",argv[1]);
//same question with shapes
if(COMPARE(argv[2], shape_t)
shape_t user_shape = argv[2];
else
printf("%s is not a usable shape\n",argv[2]);
return 0;
}
I need help with the COMPARE() function to see if argv[i] matches a member of its corresponding enum list.
One way to do this would be to use qsort and bsearch (well, if you don't mind making sure the array is sorted yourself, you don't need qsort). Something like (using your enum color_t):
struct color_picker {
char const *name;
enum colors_t id;
} acolor[] = { {"blue", blue}, {"red", red}, {"green", green} };
const unsigned acolor_count = sizeof acolor / sizeof acolor[0];
int cmp_color(struct color_picker const *l, struct color_picker const *r)
{
return strcmp(l->name, r->name);
}
int main(int argc, char *argv[])
{
struct color_picker *ptr;
qsort(acolor, acolor_count, sizeof acolor[0], cmp_color);
ptr = bsearch(name, acolor, acolor_count, sizeof acolor[0], cmp_color);
if (NULL == ptr) {
printf("%s is not a usable color\n",argv[1]); }
}
/* the value for `enum color_t` is in `ptr->id` */
return 0;
}
You could also use hash tables here, but there is not support for those in the C standard library, so you'd have to code it yourself, or use some third-party library.
I am having a problem with passing a pointer to a function. When the function returns the pointer seems to be different than what it is in the function.
So I pass a pointer to the function which gets raw image data which should then be stored in the memory referenced by the pointer.
If I then pass the pointer from inside the raw image function to a function to create a JPEG file from the raw data then it works correctly.
If I first wait for the raw image function to finish and then call the JPEG function using the pointer I passed to the raw image function then it fails to create the image.
A simplified version of the code is below:
int getRawImage(unsigned char *pBuffer);
int writeJPEGBFile(unsigned char *idata, char *ofile);
int main(int argc, char** argv) {
unsigned char *rawData = NULL;
char filename[MAXPATHLEN] = "/home/user/tst/img.jpg";
getRawImage(rawData);
// This does not work
writeJPEGBFile(rawData, filename);
free(rawData);
return 0;
}
int getRawImage(unsigned char *pBuffer) {
void *hDevice;
hDevice = scanOpenDevice();
// Removed code for simplification
scanGetFrame(hDevice, pBuffer, NULL)
scanCloseDevice(hDevice);
// This Works!!
//char filename[MAXPATHLEN] = "/home/user/tst/img.jpg";
//writeJPEGBFile(pBuffer, filename);
return 0;
}
int writeJPEGBFile(unsigned char *idata, char *ofile) {
// JPEG code goes here
return 0;
}
My question is what am I doing wrong and how can I pass the rawData pointer to the writeJPEGBFile() function successfully in the main() function?
The definition for scanGetFrame() is as follows:
typedef void *FTR_PVOID;
FTR_API_PREFIX FTR_BOOL FTR_API ftrScanGetFrame( FTRHANDLE ftrHandle, FTR_PVOID pBuffer, PFTRSCAN_FRAME_PARAMETERS pFrameParameters );
The scanGetFrame() function comes from a 3rd party library that I am linking with so I will not be able to change the definition.
Given that rawData is a null pointer in main(), you almost certainly need to revise the interface to getRawImage() so that it takes a char ** and you pass &rawData to it. You also need to think about how the calling code will know how big the data is.
I managed to work it out. Thanks to all for the pointers which led me to the solution:
int getRawImage(unsigned char *pBuffer);
int writeJPEGBFile(unsigned char *idata, char *ofile);
int main(int argc, char** argv) {
unsigned char *rawData; // Removed the NULL assignment
char filename[MAXPATHLEN] = "/home/user/tst/img.jpg";
// Set the size of rawData - loadImageSize() sets the value of the ImageSize class variable.
loadImageSize();
rawData = (unsigned char *) malloc(ImageSize.nImageSize);
getRawImage(rawData);
// This works now
writeJPEGBFile(rawData, filename);
free(rawData);
return 0;
}
int getRawImage(unsigned char *pBuffer) {
void *hDevice;
hDevice = scanOpenDevice();
// Removed code for simplification
scanGetFrame(hDevice, pBuffer, NULL)
scanCloseDevice(hDevice);
return 0;
}
int writeJPEGBFile(unsigned char *idata, char *ofile) {
// JPEG code goes here
return 0;
}
This is the part of the code I need help with -
include <stdlib.h>
include <time.h>
include <stdio.h>
include "aes.h"
void encrypt(const char *fileIn, const char *fileOut,
const unsigned char *key);
void decrypt(const char *fileIn, const char *fileOut,
const unsigned char *key);
int main()
{
const unsigned char key[] = "my key";
srand(time(NULL));
aes_init();
encrypt( "main.c", "main.c.encrypted", key);
decrypt("main.c.encrypted", "main.c.decrypted", key);
return 0;
}
Right now, what I do is, every time before running the program is... I go to the code and change the name of the file like..
encrypt("main.c", "main.c.encrypted", key);
decrypt("main.c.encrypted", "main.c.decrypted", key);
or
encrypt("trial.doc", "trial.doc.encrypted", key);
decrypt("trial.doc.encrypted", "trial.doc.decrypted", key);
However, I would like for the user to be able to enter these file names when the program is run.
HOW CAN I DO THAT?
For passing arguments to the program,
int main (int argc, char *argv[]) { ...
is the main prototype you want to use, and then you can get at the argument count and arguments themselves.
For example, the following C program prints out all its arguments, including the one representing the executable:
#include <stdio.h>
int main (int argc, char *argv[]) {
for (int i = 0; i < argc; i++)
printf ("argv[%d] = '%s'\n", i, argv[i]);
return 0;
}
If you run it with:
./myprog three point one four one five nine
you'll see the output:
argv[0] = './myprog'
argv[1] = 'three'
argv[2] = 'point'
argv[3] = 'one'
argv[4] = 'four'
argv[5] = 'one'
argv[6] = 'five'
argv[7] = 'nine'
The other alternative is to enter them from within the program and, for that, you can use a safe input function such as the one shown here.
A safe input function will generally use fgets() to ensure there's no chance of buffer overflow. The function linked to above has all sorts of other handy features like end-of-file detection, handling of lines that are too long (detecting and correcting) and prompting.
How about using scanf(), so the user can run the program and enter desired file names?
printf("Please enter file name to encrypt: ");
char name[80];
scanf("%s", name);
then you can copy the string and concat with ".encrypted" or ".decrypted" string like described here: C String Concatenation
This question already has answers here:
Call a function named in a string variable in C
(12 answers)
Closed 9 years ago.
How can I call a function on the runtime? I'm wondering if I can do that without using an if or a switch to call it,
if(arg[1] == something) //Now what I'm looking for
call_function;
Below is what I'm looking for, which is calling the function print using arg?
#include <stdio.h>
void print()
{
printf("print function called\n");
}
int main(int argc, char *argv[])
{
argv[1] to call the print function
}
So then I can call it like this,
./a.out print
This isn't trivial or automatic. Function names only exist in the language, not in the executing program. You have to supply a mapping from a suitable string constant to the function yourself (or use some existing mechanism like dlsym on Posix). You can refer to the function via a function pointer:
typedef void (void_function)(void);
extern void print(void);
extern void foo(void);
extern void bar(void);
void_function my_little_functions[] = { print, foo, bar };
int main(int argc, char * argv[])
{
if (strcmp(argv[1], "print") == 0) { my_little_functions[0](); }
// ...
}
This is for illustration only; instead of a sequence of conditional statements, you should implement some suitable, function-pointer-valued associative lookup structure.
(In C++, this would be a std::unordered_map<std::string, void_function *>. In C, you have to find your own.)
If you are not looking for a "pure C" solution, then chances are you can use APIs of your OS to do the mapping for you. Under POSIX (this compiles and runs):
#include <stdio.h>
#include <dlfcn.h>
void foo(void)
{
printf("foo\n");
}
void bar(void)
{
printf("bar\n");
}
void baz(void)
{
printf("baz\n");
}
int main(int argc, char *argv[])
{
void *hndl = dlopen(NULL, RTLD_LAZY);
void (*fn)(void) = dlsym(hndl, argv[1]);
if (fn) {
fn();
} else {
printf("Function %s() not found\n", argv[1]);
}
return 0;
}
Well, actually there is a way...
At runtime you could write a .c file containing the functions definitions and in main you would write the call to the function named in argv[1]. Then you could invoke a compiler (gcc-linux or cl-windows or whatever) (via system(command)) to generate an executable. Then you invoke that executable (via system(command)) and voilĂ job done.
What? I didn't say it's a practical way, I just said it's a way.
Proof that this actually works:
#include <stdio.h>
#include <stdlib.h>
const char file_includes[] = "#include <stdio.h>\n";
const char file_functions[] =
"void print() {\n"
" printf(\"print function called\\n\");\n"
"}\n"
"void print2() {\n"
" printf(\"second print function called\\n\");\n"
"}\n";
const char file_main_prolog[] = "int main() {\n";
const char file_main_epilog[] = " return 0;\n}\n";
int main(int argc, char *argv[]) {
if (argc < 2) {
printf("invalid program arguments\n");
return 1;
}
FILE *fout = fopen("function_call.c", "w");
fprintf(fout, "%s", file_includes);
fprintf(fout, "%s", file_functions);
fprintf(fout, "%s", file_main_prolog);
fprintf(fout, " %s();\n", argv[1]);
fprintf(fout, "%s", file_main_epilog);
fclose(fout);
system("gcc -o function_call function_call.c");
system("./function_call");
return 0;
}
This works under linux with gcc installed. You can run this program with the argument print or print2 and you will get print function called or second print function called respectively.