Why use this method of function pointers [duplicate] - c

This question already has answers here:
What are function pointers used for, and how would I use them?
(9 answers)
Closed 8 years ago.
Yesterday I learned of this really cool way to use function pointers.
Although I think its a really cool thing to be able to do I cant see WHY and WHERE this sort of method will be used?
Could someone shed some light on this?
int Mul(int x , int y)
{
return x*y;
}
int Div(int x , int y)
{ return x/y;
}
typedef int (*FuncP)(int,int);
int compu(FuncP functionP, int x , int y)
{return functionP(x , y)}
//Calling it will look like
compu(Mul,5,10);
Thanks
Cart

If you need something to be dynamic based on a situation like so:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <stdbool.h>
typedef int (*worker_operation)(int);
int check_for_new_woot(int inVal) {
int ret = arc4random() % 10;
if (ret < 5) {
puts("Found new woot!");
sleep(1);
return 1;
} else {
puts("No new woot :(");
sleep(1);
return 0;
}
}
int buy_current_woot(int inVal) {
if (inVal != 0) {
fprintf(stderr, "Insufficient funds!!!\n");
}
return 0;
}
int check_if_should_buy_woot(int inVal) {
printf("Should we buy the latest woot? ");
char input[10];
read(STDIN_FILENO, input, 10);
if (input[0] == 'y') {
return 1;
} else {
return 0;
}
}
void *worker_thread(void *inVal) {
worker_operation *ops = (worker_operation *)inVal;
int i = 0;
worker_operation op = ops[i];
int arg = 0;
while (op) {
arg = op(arg);
op = ops[++i];
}
free(ops);
return NULL;
}
pthread_t start_worker(worker_operation *ops) {
pthread_t pt;
pthread_create(&pt, NULL, worker_thread, ops);
return pt;
}
int main(int argc, const char *argv[]) {
bool autoBuy = true; // fetch whether we should automatically buy from woot.com from argv or stdin
int numberLoops = 10; // fetch number of times to loop through the process
int i;
worker_operation *operations;
if (autoBuy) {
operations = (worker_operation *)malloc(sizeof(worker_operation) * (numberLoops * 2 + 1));
for (i = 0; i < numberLoops; i++) {
operations[2 * i] = check_for_new_woot;
operations[2 * i + 1] = buy_current_woot;
}
operations[2 * i] = (worker_operation)NULL;
} else {
operations = (worker_operation *)malloc(sizeof(worker_operation) * (numberLoops * 3 + 1));
for (i = 0; i < numberLoops; i++) {
operations[3 * i] = check_for_new_woot;
operations[3 * i + 1] = check_if_should_buy_woot;
operations[3 * i + 2] = buy_current_woot;
}
operations[3 * i] = (worker_operation)NULL;
}
pthread_join(start_worker(operations), NULL);
return 0;
}
Note that in this code snippet uses function pointers in two places. We have a function which is agnostic of how the user wants the program to perform, that is start_worker simply creates a worker thread that will work with a list of operations. This can be easily used to create a program which has multiple threads going all with different operation queues. The second place function pointers are used are with threads. The ptrhead_create call uses a function pointer in order to create a new thread (the function specified is the function to be ran on the new thread).
Generally this is called a command programming paradigm. One can easily create an operation that another part of code can call, agnostic of what the function does. For instance this could be useful for games in the following situation:
We have a game controller that gives input. The user clicks 'up'. In code call the operation that is hooked to the 'up' action.
This modular approach allows one to enable settings for the controls so someone can hook a 'jump' operation to 'up' or a 'move forward' operation, or anything really.
Hope this helps!

Pointers to functions has multiple uses but, sticking to your example, pointer to funcions can help you to avoid hurge and ugly conditional branches like if's and switches:
If you create an associative array of operations characters as index and pointer to functions as value:
//implementacion in C doesn't matter for the example
operations["*"] = Mul;
operations["/"] = Div;
operations["*"] = Add;
operations["-"] = Sub;
You can do something like this:
int op1;
int op2;
char operation;
cout << "Insert first number /n";
cin >> op1;
cout << "Insert second number /n";
cin >> op2;
cout << "Insert operator /n";
cin >> operation;
cout >> compu(operations[operation],op1,op2);

Related

how to devide code into functions in c programming

I have a perfect running code, BUT one criteria for this homework is that it has atleast two different functions. How can i devide this code into one more functions?
I want to sort the alarmClock() function into more functions. There's alot going on in there. Maybe a updateTime() function. I tried something like this but this doesn't work:
#include <stdio.h>
void alarmClock(int, int);
void updateTime(int, int, int);
int main() {
int present_time;
int time_for_alarm;
printf("Time indicates in HHMMSS! \nPresent time: ");
scanf("%d", &present_time);
printf("Time for alarm: ");
scanf("%d", &time_for_alarm);
if (present_time == time_for_alarm)
printf("ALARM!");
else
alarmClock(present_time, time_for_alarm);
return 0;
}
void alarmClock(int presT, int alarmT) {
int presentHH = presT / 10000;
int presentMM = (presT / 100) % 100;
int presentSS = presT % 100;
int combineTime;
while (presT != alarmT) {
printf("%02d:%02d:%02d \n", presentHH, presentMM, presentSS);
presentSS++;
updateTime(presentHH, presentMM, presentSS);
combineTime = presentHH * 100 + presentMM;
presT = combineTime * 100 + presentSS;
}
printf("ALARM!");
}
void updateTime(int presentHH, int presentMM, int presentSS) {
if (presentSS > 59) {
presentSS = 0;
presentMM++;
if (presentMM > 59) {
presentMM = 0;
presentHH++;
if (presentHH > 24) {
presentHH = 1;
}
}
}
}
My teacher hinted me saying "you could make on printTime() function and one updateTime() function sending present_time as arguments". But i dont know how...
This is my working code that needs atleast one more function.
#include <stdio.h>
void alarmClock(int, int);
int main() {
int present_time;
int time_for_alarm;
printf("Time indicates in HHMMSS! \nPresent time: ");
/ scanf("%d", &present_time);
/
printf("Time for alarm: ");
scanf("%d", &time_for_alarm);
if (present_time == time_for_alarm)
printf("ALARM!");
else
alarmClock(present_time, time_for_alarm);
return 0;
}
void alarmClock(int presT, int alarmT) {
int presentHH = presT / 10000;
int presentMM = (presT / 100) % 100;
int presentSS = presT % 100;
int combineTime;
while (presT != alarmT) {
printf("%02d:%02d:%02d \n", presentHH, presentMM, presentSS);
presentSS++;
if (presentSS > 59) {
presentSS = 0;
presentMM++;
if (presentMM > 59) {
presentMM = 0;
presentHH++;
if (presentHH > 24) {
presentHH = 1;
}
}
}
combineTime = presentHH * 100 + presentMM;
presT = combineTime * 100 + presentSS;
}
printf("ALARM!");
}
The working code gives this output (correct output);
if present_time = 115957
and time_for_alarm = 120001
output is
11:59:57
11:59:58
11:59:59
12:00:00
ALARM
but when i created the updateTime() function the code keeps running forever if i have these values:
if present_time = 115957
and time_for_alarm = 120001
output is
11:59:57
11:59:58
11:59:59
11:59:60
11:59:61
11:59:62
11:59:63
... and so on and on (presentSS keeps going +=1 forever)
The variables presentHH, presentMM, and presentSS in the function updateTime are distinct from the ones in alarmClock, so changes to those variables in updateTime are not visible in the calling function.
You need to pass the address of each of these variables and dereference those pointers in updateTime. Then you're actually changing the variables defined in alarmClock.
So change the definition of updateTime to:
void updateTime(int *presentHH, int *presentMM, int *presentSS);
And call it like this:
updateTime(&presentHH, &presentMM, &presentSS);
You'll also need to change the body of updateTime to reflect that the parameters are now pointers and to dereference them. I'll leave that as an exercise to the reader.
dbush shows a good way to solve the problem with not many changes to the general structure. I would suggest a different approach to the task. Instead of passing the addresses of these values, you could restructure your code to pass the composite time and return the updated time. Similiar to this
int updateTime(int presT){
//seperate, update and combine the time value
return updatedTime;
}
this would reduce the interface and would also enable you to write even more functions that can be reused. As you now will have to seperate and combine the time in updateTimeand alarmClock you can write functions that do this instead of writing the same code twice.
example:
int getHours(int time){
return time / 10000;
}
and:
int combineTime(int hours, int minutes, int seconds){
combinedTime = (presentHH * 100 + presentMM)* 100 + presentSS;
return combinedTime;
}
This will help you get more expierience with functions and also helps to let you see one big benefit of functions (having reusable code).

Customized sort in the order mentioned {2,3....9,A,B,C,D,1,E,F,0}

I am currently implementing a logic to sort the alphanumerical numbers in the order as mentioned {2,3....9,A,B,C,D,1,E,F,0}. Is there a easy and a possible way to do this? I prefer only C programming.
The request is regarding the sort of the 1st nibble in the PI code of FM RDS stations. As Germany is the only country which supports 2 PI codes(D & 1), the order is maintained in this manner.
Thanks in advance guys.
You should write a function (e.g., int custom_compare(const void *p1, const void *p2); that defines this sorting order. That method will return 1 if p1 comes after p2, 0 if they are 'equal', and -1 if p1 comes before p2.
Then, write your sorting method and call your ordering function instead of comparing using operators. That is, instead of if (a < b), use if (custom_compare(&b, &a)).
Also, I created that function prototype above (specifically using pointers as the parameters) because it would work with the qsort library, which is a quicksort implementation that accepts a custom comparison function.
An Implementation
I decided to quickly do a implementation of what I suggested and a small test example.
#include <stdlib.h>
#include <stdio.h>
int custom_compare(const void *p1, const void *p2) {
char *param1 = (char*)p1;
char *param2 = (char*)p2;
int loc1 = 0;
int loc2 = 0;
char order[17] = "23456789ABCD1EF0";
int i;
for (i=0; i<17; i++) {
if (*param1 == order[i]) { loc1 = i; }
if (*param2 == order[i]) { loc2 = i; }
}
if (loc2 < loc1) {
return 1;
} else if (loc1 < loc2) {
return -1;
} else {
return 0;
}
}
void bubble_sort_string(char *string) {
if (!string || !string[0] || !string[1]) { return; }
int i;
int tail = 0;
char tmp;
while (string[tail]) { tail++; }
while (tail) {
i = 1;
while (i <= tail) {
if (custom_compare(&string[i-1], &string[i]) > 0) {
// swap
tmp = string[i];
string[i] = string[i-1];
string[i-1] = tmp;
}
i++;
}
tail--;
}
}
int main() {
char string[33] = "00FFEE11DDCCBBAA9988776655443322";
printf("old string: %s\n", string);
bubble_sort_string(string);
printf("new_string: %s\n", string);
return 0;
}
Output:
$ ./csort
old string: 00FFEE11DDCCBBAA9988776655443322
new_string: 2233445566778899AABBCCDD11EEFF00
$

C Program hangs after trying to call function from main

This is the code:
#include <stdlib.h>
#include <stdio.h>
#include "descartes.h"
/*
* Eulidean travelling salesman
*/
#define MAXCITIES 100
#define FALSE 0
#define TRUE 1
point_t city [MAXCITIES];
int numCities = 0;
int ReadCities(void);
double TourLength(lineSeg_t cityLines[]);
void DrawTour(void);
int main(void) {
printf ("main1\n");
OpenGraphics();
printf ("main2\n");
ReadCities();
DrawTour();
double TourLength(lineSeg_t cityLines[]);
CloseGraphics();
return EXIT_SUCCESS;
}
int ReadCities(void) {
printf ("ReadCities1");
int i = 1;
printf ("ReadCities2");
city[0] = GetPoint();
while ((XCoord(city[i])) >= 0) {
city[i] = GetPoint();
printf ("(%d, %d)", XCoord(city[i]), YCoord(city[i]));
numCities++;
i++;
}
if (numCities <= MAXCITIES) {
return TRUE;
}
else {
return FALSE;
}
}
double TourLength(lineSeg_t cityLines[]) {
double totLen = 0;
int i;
for (i = 0; i < (numCities - 1); i++) {
totLen += Length(cityLines[i]);
}
return totLen;
}
void DrawTour(void) {
lineSeg_t cityLines[MAXCITIES];
int i;
for (i = 0; i < (numCities - 1); i++) {
cityLines[i] = LineSeg(city[i], city[i + 1]);
DrawLineSeg(cityLines[i]);
}
}
When I run the program it prints:
main1
main2
Then the program hangs. I would at least expect it to call ReadCities() and at get as far as printing
ReadCities1
ReadCities2
but no matter what I try it just hangs with a flashing cursor in the terminal after printing main2. There might also be other mistakes in the code but I can't even get far enough to test it out!
Sorry if it's something obvious, i'm new to programming!
Cheers!
Not really sure what this line:
while ((XCoord(city[i])) >= 0)
Is returning, seems this loop might not be breaking. In a situation like this I'd printf() the value ofo XCoord(city[i]) within my loop to see what value is actually in there...
Using printf()'s can be quite useful for things like this.
Also, as someone said there's a function prototype declaration in main:
double TourLength(lineSeg_t cityLines[]);

how can we return an array from a function in c? [duplicate]

This question already has answers here:
Returning an array using C
(8 answers)
Closed 7 years ago.
How can we return an array from a function i have no idea how to do this???
the are three cars and each is parked in a parking area for maximum 24 hours we have to find the cost for each car by making a function which wil evaluate the cost..??
#include <stdio.h>
#include <math.h>
#include <conio.h>
int calculateCharges(float hours[]);
int main() {
float hours[3];
int i;
for (i = 0; i <= 2; i++) {
printf("Enter the hours you parked for car : %d\n", i + 1);
scanf_s("%f", &hours[i]);
}
hours[i] = calculateCharges(hours[]);
printf("%-10s%-10s%-10s\n", "Cars", "Hours", "Charge");
for (i = 0;i <= 2;i++) {
printf("%-10d%-10.2f%-10.2f\n", i + 1, hours[i], calculateCharges(hours));
}
_getch();
return 0;
}
int calculateCharges(float hours[]) {
float cost[3];
int i;
for (i = 0; i <= 2; i++) {
if (hours[i] <= 3) { //if car parked for 3 or less hours it cost 2$
cost[i] = 2;
}
else if (hours[i] > 3 && hours[i] < 24) { //if car parked for more than 3 or less then 24 hours it cost 0.5$for each extra hour$
cost[i] = 2 + ((hours[i] - 3) / 2);
}
else if (hours[i] == 24) { //if hours = 24 hours 10$
cost[i] = 10;
}
else {
cost[i] = 0; //else its an error value zero cost
}
return cost[i];
}
}
You could pass in another array in which you return the cost, instead of making it a local array. Your method would look something like this:
int calculateCharges(float hours[], float costs[], int num) {
...
for(i=0;i<num;i++) {
...
costs[i] = 2;
Functions cannot return arrays, but they can return pointers, and they can modify caller-visible variables via pointer arguments. If you want a function to create an array and provide it to the caller, then that function would need to allocate the array dynamically (via malloc() or calloc()) and then use one of the methods I named to return a pointer to the first element of that array.
But as commenters also remarked, none of that appears to be needed for the problem you presented. As far as I can tell, you just need a function that computes one cost for one car. You can call such a function from inside a loop (even the same loop in which you read the input) to calculate the cost for each car, which the caller can then handle however is appropriate.

Decimal to Binary conversion not working

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int myatoi(const char* string) {
int i = 0;
while (*string) {
i = (i << 3) + (i<<1) + (*string -'0');
string++;
}
return i;
}
void decimal2binary(char *decimal, int *binary) {
decimal = malloc(sizeof(char) * 32);
long int dec = myatoi(decimal);
long int fraction;
long int remainder;
long int factor = 1;
long int fractionfactor = .1;
long int wholenum;
long int bin;
long int onechecker;
wholenum = (int) dec;
fraction = dec - wholenum;
while (wholenum != 0 ) {
remainder = wholenum % 2; // get remainder
bin = bin + remainder * factor; // store the binary as you get remainder
wholenum /= 2; // divide by 2
factor *= 10; // times by 10 so it goes to the next digit
}
long int binaryfrac = 0;
int i;
for (i = 0; i < 10; i++) {
fraction *= 2; // times by two first
onechecker = fraction; // onechecker is for checking if greater than one
binaryfrac += fractionfactor * onechecker; // store into binary as you go
if (onechecker == 1) {
fraction -= onechecker; // if greater than 1 subtract the 1
}
fractionfactor /= 10;
}
bin += binaryfrac;
*binary = bin;
free(decimal);
}
int main(int argc, char **argv) {
char *data;
data = malloc(sizeof(char) * 32);
int datai = 1;
if (argc != 4) {
printf("invalid number of arguments\n");
return 1;
}
if (strcmp(argv[1], "-d")) {
if (strcmp(argv[3], "-b")) {
decimal2binary(argv[2], &datai);
printf("output is : %d" , datai);
} else {
printf("invalid parameter");
}
} else {
printf("invalid parameter");
}
free(data);
return 0;
}
In this problem, myatoi works fine and the decimal2binary algorithm is correct, but every time I run the code it gives my output as 0. I do not know why. Is it a problem with pointers? I already set the address of variable data but the output still doesn't change.
./dec2bin "-d" "23" "-b"
The line:
long int fractionfactor = .1;
will set fractionfactor to 0 because the variable is defined as an integer. Try using a float or double instead.
Similarly,
long int dec = myatoi(decimal);
stores an integer value, so wholenum is unnecessary.
Instead of
i = (i << 3) + (i<<1) + (*string -'0');
the code will be much more readable as
i = i * 10 + (*string - '0');
and, with today's optimizing compilers, both versions will likely generate the same object code. In general, especially when your code isn't working, favor readability over optimization.
fraction *= 2; // times by two first
Comments like this, that simply translate code to English, are unnecessary unless you're using the language in an unusual way. You can assume the reader is familiar with the language; it's far more helpful to explain your reasoning instead.
Another coding tip: instead of writing
if (strcmp(argv[1], "-d")) {
if (strcmp(argv[3], "-b")) {
decimal2binary(argv[2], &datai);
printf("output is : %d" , datai);
} else {
printf("invalid parameter");
}
} else {
printf("invalid parameter");
}
you can refactor the nested if blocks to make them simpler and easier to understand. In general it's a good idea to check for error conditions early, to separate the error-checking from the core processing, and to explain errors as specifically as possible so the user will know how to correct them.
If you do this, it may also be easier to realize that both of the original conditions should be negated:
if (strcmp(argv[1], "-d") != 0) {
printf("Error: first parameter must be -d\n");
else if (strcmp(argv[3], "-b") != 0) {
printf("Error: third parameter must be -b\n");
} else {
decimal2binary(argv[2], &datai);
printf("Output is: %d\n" , datai);
}
void decimal2binary(char *decimal, int *binary) {
decimal = malloc(sizeof(char) * 32);
...
}
The above lines of code allocate a new block of memory to decimal, which will then no longer point to the input data. Then the line
long int dec = myatoi(decimal);
assigns the (random values in the) newly-allocated memory to dec.
So remove the line
decimal = malloc(sizeof(char) * 32);
and you will get the correct answer.
if(!strcmp(argv[3] , "-b"))
if(!strcmp(argv[3] , "-d"))
The result of the string compare function should be negated so that you can proceed. Else it will print invalid parameter. Because the strcmp returns '0' when the string is equal.
In the 'decimal2binary' function you are allocating a new memory block inside the function for the input parameter 'decimal',
decimal = malloc(sizeof(char) * 32);
This would actually overwrite your input parameter data.

Resources