I want to pass a function with arguments as argument into some other function, but I don't know how (or if) I can do that.
What I want to do is:
#include <stdio.h>
void getInput(char* request, int (*func)());
int main()
{
double input;
getInput("Input: ", scanf("%lf", &input));
}
void getInput(char* request, int (*func)())
{
// do stuff
func()
// do more stuff
}
Unfortunately this doesn't work. I think the scanf is getting executed when I'm trying to pass it as an argument.
How do I get this to run in getInput?
You can't do that in C, the language doesn't support such a construct.
You can often solve this exact type of problem using variable-arguments functions again:
void getInput(const char *request, const char *fmt, ...)
{
va_list args;
printf("%s: ", request);
fflush(stdout);
va_start(fmt, args);
vscanf(fmt, args);
va_end(args);
}
Usage is like this:
int main(void)
{
double input;
getInput("Input", "%lf", &input);
return 0;
}
Of course you might want to add proper return-value handling, otherwise it's impossible to know if the embedded vscanf() succeeded so the variable is OK to use.
Related
I'm working on a STM32 Cortex M4 with a FreeRTOS running.
I try to redirect my printf to the USB CDC output but it seems like my implementation isn't thread safe. A loop of printf('test') prints
ettttt
tttetttttttst
ttetettttttettttttettttttt
ttttttttttttt
t
tttttttttetttttttstttt
tettttttttttttt
t
tttttttetttetttttttett
ttttettttttetettetttt
ttttttttt
ttetetttt
t
ttt
I use the following putchar prototype
PUTCHAR_PROTOTYPE {
CDC_Transmit_FS((uint8_t*)&ch, 1);
return ch;
}
Additionally I use the printf-stdarg.c, at least I thought I do. But when I change
int printf(const char *format, ...)
{
va_list args;
va_start( args, format );
return print( 0, format, args );
}
to an empty implementation
int printf(const char *format, ...)
{
return 0;
}
it still prints to the console as before. So it seems like it's not actually using the implementation from printf-stdarg.c.
My idea was to surround the print call with a mutex.
I am looking to make a small logger to be used like this:
logger log;
const char* text = "World";
log.write("Hello %s", text);
log.write("Step %d", 1);
This is my code, which doesn't work correctly:
class logger
{
public:
void write(const char* msg, ...)
{
FILE* file = fopen("c:/test.txt", "a");
if(file != NULL)
{
va_list args;
va_start(args, msg);
fprintf(file, "%s\n", msg, args);
va_end(args);
fclose(file);
}
}
};
This is what I get:
Hello %s
Step %d
I never used varargs before so I am not sure if I am using it correctly.
You're thinking that C behaves in a manner similar to Java or Python or other languages that can "splat" an array argument to a function that accepts varargs, but C isn't that sophisticated. When you pass args to fprintf, C literally pushes the value of args (a variable of type va_list) onto the stack. What you need instead is to push the contents of args onto the stack.
Or, instead, you could use a function that accepts a va_list as a parameter. That function is vprintf (and friends vsprintf, vfprintf, etc.).
You have another issue, which is that you're fprintf-ing the caller's "msg" parameter using "%s" but then apparently expecting fprintf to recursively use the result as a format string and fprintf the args too. That's not going to work. Instead just use the caller's msg as the format string.
va_list args;
va_start(args, msg);
vfprintf(file, msg, args);
fputc('\n', file);
va_end(args);
I've developed the producer / consumer problem in C and for some reason it doesn't compile. I'm getting the error message:
try1.c: In function ‘main’:
try1.c:19:21: warning: incompatible implicit declaration of built-in function ‘malloc’ [enabled by default]
BUFFER=(char *) malloc(sizeof(char) * BufferSize);
Please could someone identify the issue? Have tried for a while to fix this now however haven't had any luck.
#include <stdio.h>
#include <pthread.h>
#define BufferSize 10
void *Producer();
void *Consumer();
int BufferIndex=0;
char *BUFFER;
pthread_cond_t Buffer_Not_Full=PTHREAD_COND_INITIALIZER;
pthread_cond_t Buffer_Not_Empty=PTHREAD_COND_INITIALIZER;
pthread_mutex_t mVar=PTHREAD_MUTEX_INITIALIZER;
int main()
{
pthread_t ptid,ctid;
BUFFER=(char *) malloc(sizeof(char) * BufferSize);
pthread_create(&ptid,NULL,Producer,NULL);
pthread_create(&ctid,NULL,Consumer,NULL);
pthread_join(ptid,NULL);
pthread_join(ctid,NULL);
return 0;
}
void *Producer()
{
for(;;)
{
pthread_mutex_lock(&mVar);
if(BufferIndex==BufferSize)
{
pthread_cond_wait(&Buffer_Not_Full,&mVar);
}
BUFFER[BufferIndex++]='#';
printf("Produce : %d \n",BufferIndex);
pthread_mutex_unlock(&mVar);
pthread_cond_signal(&Buffer_Not_Empty);
}
}
void *Consumer()
{
for(;;)
{
pthread_mutex_lock(&mVar);
if(BufferIndex==-1)
{
pthread_cond_wait(&Buffer_Not_Empty,&mVar);
}
printf("Consume : %d \n",BufferIndex--);
pthread_mutex_unlock(&mVar);
pthread_cond_signal(&Buffer_Not_Full);
}
}
Thanks a lot for your help.
First of all, this question has nothing to do with producer/consumer. It has to do with the use of a function you didn't declare.
Historically, C allowed calling a function which was never declared. Since technically function declaration is not needed to call it, compiler gladly added instructions to call the unknown function. Allegedly, it allowed developers to save precious keystrokes. However, you need a function declaration to know it's return value, and compiler assumed that return value of such a function is int. And you are having just that - an implicitly declared malloc() with assumed return type of int.
Now, compiler knows what malloc() is. It is often built-in intrinstic function. However, compiler also knows that return value of said malloc() is void*, not int - and thus it complains.
Solution - get rid of implicit declaration, and make a habit of always including apropriate header files for every function you are using.
You also have issues with the way you are using conditional variables, but I would leave it for another question.
The producer should go to sleep when the buffer is full. Next time when the consumer removes data it notifies the producer and producer start producing data again. The consumer should go to sleep when a buffer is empty. Next time when producer adds data it notifies the consumer and consumer starts consuming data. This solution can be achieved using semaphores.
#include<stdio.h>
#include<stdlib.h>
#include <pthread.h>
#include <semaphore.h>
int mutex=1,full=0,empty=3,x=0;
int main()
{
int n;
void producer(void);
void consumer(void);
int waiting(int);
int signaling(int);
printf("\n1.Producer\n2.Consumer\n3.Exit");
while(1)
{
printf("\nEnter your choice:");
scanf("%d",&n);
switch(n)
{
case 1: if((mutex==1)&&(empty!=0))
producer();
else
printf("Buffer is full!!");
break;
case 2: if((mutex==1)&&(full!=0))
consumer();
else
printf("Buffer is empty!!");
break;
case 3:
exit(0);
break;
}
}
return 0;
}
int waiting(int s)
{
return (--s);
}
int signaling(int s)
{
return(++s);
}
void producer()
{
mutex=wait(&mutex);
full=signaling(full);
empty=wait(&empty);
x++;
printf("\nProducer produces the item %d",x);
mutex=signaling(mutex);
}
void consumer()
{
mutex=wait(&mutex);
full=wait(&full);
empty=signaling(empty);
printf("\nConsumer consumes item %d",x);
x--;
mutex=signaling(mutex);
}
Just include the stdlib.h library. This library will include the malloc() function.
You are using malloc without including the header file that declares it (stdlib.h).
Your usage (without that explicit declaration from stdlib.h) creates an "implicit declaration" which doesn't match the one the compiler knows about because yours returns char* and the proper malloc returns void*.
So add include <stdlib.h> and also note that you shouldn't cast the result of a malloc. See Do I cast the result of malloc?
Let's say I have a function to perform a small and particular task that has a fairly good possibility of failure. What is the best way to handle something going wrong? (Assuming I know what the problem is).
For example lets say I have a function that reads a two byte string and returns it:
#include <stdio.h>
#include <stdlib.h>
char *bar(void)
{
char *foo = malloc(3);
scanf("%2s", foo);
return foo;
}
int main(void)
{
char *foo = bar();
puts(foo);
free(foo);
return 0;
}
The above example has absolutely no error handling whatsoever. There are two ways that I would implement some sort of error handling, but I'm not sure which would be more preferred or considered best practice.
Method 1 (print error message To stderr from within the function):
#include <stdio.h>
#include <stdlib.h>
char *bar(void)
{
char *foo;
if(!(foo = malloc(3)))
{
fputs("\nError! Memory allocation failed.", stderr);
return 0x00;
}
scanf("%2s", foo);
return foo;
}
int main(void)
{
char *foo;
if(!(foo = bar())) return 1;
puts(foo);
free(foo);
return 0;
}
Method 2 (print error message to stderr from the calling function):
#include <stdio.h>
#include <stdlib.h>
char *bar(void)
{
char *foo;
if(!(foo = malloc(3))) return 0x00;
scanf("%2s", foo);
return foo;
}
int main(void)
{
char *foo;
if(!(foo = bar()))
{
fputs("\nError! Memory allocation failed.", stderr);
return 1;
}
puts(foo);
free(foo);
return 0;
}
I'm almost thinking that method two would be the best way to go because that way I could get more specific with my error messages depending on what I'm calling that function for at the time.
What I worry about with method two is the fact that I lose the ability to print what specifically went wrong in the function if it has more than one potential point of failure.
Pseudo Code:
IF FAILUREA
PRINT "FAILUREA OCCURED"
RETURN
IF FAILUREB
PRINT "FAILUREB OCCURED"
RETURN
This wouldn't be much of a problem if the function I was calling was an int because then I could just return a different integer value based on what went wrong. But in the case of a char* I typically try to return NULL on failure (so both FAILUREA and FAILUREB would be returning NULL); there would be no way to know what caused the function to fail.
So my question is what is best practice when it comes to handling error messages?
Allowing the caller to handle error reporting is better because:
if the function is forming part of a library stderr may not be available and an alternative reporting mechanism is required.
the calling code may have an alternative action that can be taken and may not deem the failure of function bar() as an actual failure and have no need to report it.
If a function has multiple possible failure reasons then a possibility is to pass an argument to the function that is updated in the event of failure. The calling function can then choose an appropriate action depending on the actual failure reason. For example:
enum Status
{
STATUS_OK,
STATUS_MEMORY_ALLOCATION_FAILURE,
STATUS_ACCESS_DENIED
};
enum Status status;
char* foo = bar(&status);
if (!foo)
{
if (STATUS_MEMORY_ALLOCATION_FAILURE == status)
{
/* report failure. */
}
else if (STATUS_ACCESS_DENIED == status)
{
/* try somewhere else */
}
}
If you can do anything about a failure and if you are going to, then you do it.
Otherwise, you may implement a generic failure function, call it in case of an error and call it a day:
void error(const char* format, ...)
{
va_list vl;
va_start(vl, format);
vfprintf(stderr, format, vl);
va_end(vl);
exit(-1);
}
You can optionally wrap it in a macro supplying it with the line# and file name:
#define ERROR(fmt, ...) \
error("file:'%s',line:%d " fmt, __FILE__, __LINE__, __VA_ARGS__)
This will make errors in the console very easy to figure out because the error messages tell precisely the file and the line in it where the error has occurred.
Typical usage, nothing fancy:
char *bar(void)
{
char *foo;
if ((foo=malloc(3)) == NULL)
ERROR("malloc() failed!\n");
if (scanf("%2s", foo) != 1)
ERROR("scanf() failed!\n");
return foo;
}
You may use longjmp() in place of exit(-1) to immediately return to the caller (=the one that did the respective setjmp()) if you want to actually do something upon the error, maybe close all files open for writing, so the buffered data isn't lost.
If you're writing a simple compiler, for example, this kind of error() is more than enough for most errors internal to the compiler and for problems in the source code being compiled (e.g. a missing colon/paren or something else that makes the code not compilable).
If you cannot or do not want to do any of that, you need to carefully write the code, do proper clean ups and return different error codes to communicate actionable errors to the caller.
You can do in this way if your function return more than 1 error case
#include <stdio.h>
#include <stdlib.h>
int bar(char **foo)
{
if(!(malloc(3))) return 1; /* return error case 1*/
scanf("%2s", *foo);
if(!(malloc(4))) return 2; /* return error case 2*/
return 0; /* no error*/
}
int catcherror(int error)
{
switch (error) {
case 1:
/*do something 1*/
case 2:
/*do something 1*/
case 3:
/*do something 1*/
case 4:
/*do something 1*/
case 5:
/*do something 1*/
default:
/*do something 1*/
}
}
int main(void)
{
char *foo;
int error
error = bar(&foo);
catcherror(error);
puts(foo);
free(foo);
return 0;
}
The catcherror() function could be very useful if your project contains many functions which return a common error cases
I have one problem with variable length argument debug log print function. I will just simulate the code here.
void SecondPrint(int level, const char* format,...)
{
//Printing the log here
va_list arg;
va_start(arg, format);
vprintf(format, arg);
va_end(arg);
}
void FirstPrint(int level, const char* format,...)
{
SecondPrint(level,format);
}
void main()
{
int level = 100;
FirstPrintf("Log level = %d message = %s \n",level,"Error message");
}
"SecondPrint" is supposed to print "100 Error message" as expected, But its not printing like that its printing " Error message".
I am not getting whats wrong with this one. I am suspecting the way of calling "SecondPrint" from "FirstPrint" function. FirstPrint is receiving remaining arguments through ... but its invoking SecondPrint with level and format arguments.
I can't use SecondPrint from main directly. I have to use FirstPrint and FirstPrint has to call SecondPrint to print the log. So how can I achieve this one.. I thought to use VA_ARGS but it is for only macro definitions not in function definition.
And one more thing I can't do like *#define FirstPrint(a,b,...) SecondPrint(a,b,...)*
any help is highly appreciated thanks in advance.
C varargs are not designed to be passed more than one level; the kind of necessary stack manipulation required is too deep for the language. Typically, in a case like this, you would have a version of SecondPrint analagous to vprintf -- SecondPrintV or similar, and you would have FirstPrint invoke SecondPrintV after extracting the varargs, rather than invoking SecondPrint directly (and, for consistency, usually have SecondPrint invoke SecondPrintV internally).
You need to pass a va_list to SecondPrint, so it can access the arguments to FirstPrint
void SecondPrint(int level, const char* format, va_list args)
{
//Printing the log here
vprintf(format, arg);
}
void FirstPrint(int level, const char* format,...)
{
va_list args;
va_start(args, format);
SecondPrint(level, format, args);
va_end(args);
}
void main()
{
int level = 100;
FirstPrintf("Log level = %d message = %s \n",level,"Error message");
}
It may be possible to do it in specific platform-specific ways, or (since the arguments are exactly the same in the same order) use assembly to "replace" the current function frame with the function to call. GCC also has an extension to do it with the __builtin_apply_args() and __builtin_apply() functions (although you must somehow figure out how to compute the size of the stack argument data).