Topic: Given a positive integer with no more than 5 digits, require:
When I called the following program using a function pointer, I found that the parameters "number" and "digit" could not be passed to each function.
#include <stdio.h>
#include <stdlib.h>
void inputNumber(int *number){
printf("Enter number: ");
scanf_s("%d", number);
while(*number <= 0 || *number > 9999){
if(*number <= 0){
printf("The number is not positive integer! Retry!\nEnter number: ");
}
if(*number > 9999){
printf("The number is more than 5 digits! Retry!\nEnter number: ");
}
scanf_s("%d", number);
}
}
void outputDigit(int *number, int *digit){
int i;
for(i = 0; *number != 0; i++){
*number /= 10;
}
*digit = i;
//printf("%d\n", *number); Test Output
printf("The number is %d digits!\n", i);
}
void outputNumber(int *number, int *digit){
int base = 10;
int temp = *number;
for(int i = 1; i < *digit - 1; i++){
base *= 10;
}
//printf("%d %d\n", *number, temp); Test Output
for(int i = 0; i < *digit; i++){
printf("%d ", temp / base);
temp -= temp / base * base;
base /= 10;
}
printf("\n");
}
void outputReverseNumber(int *number, int *digit){
int temp = *number;
for(int i = 0; i < *digit; i++){
printf("%d ", temp % 10);
temp = (temp - temp % 10) / 10;
}
printf("\n");
}
void function(int *number, int *digit, void (*fun[])(int*, int*)){
for(int i = 0; i < 3; i++){
fun[i](number, digit);
}
}
int main(){
int *number = (int*)malloc(sizeof(int));
int *digit = (int*)malloc(sizeof(int));
void (*fun[3])(int*, int*) = {outputDigit, outputNumber, outputReverseNumber};
inputNumber(number);
function(number, digit, fun);
free(number);
free(digit);
system("pause");
return 0;
}
I want parameters in function pointers to be passed by pointer variables generated by other functions.
There is no problem with parameter passing. The problem is that you keep dividing numbers inside outputDigit
and thereby ensuring that the original number is zero upon leaving the function. That can be fixed by using a temporary variable instead:
void outputDigit(int *number, int *digit){
int i;
int tmp = *number;
for(i = 0; tmp != 0; i++){
tmp /= 10;
}
*digit = i;
printf("The number is %d digits!\n", i);
}
Another bug is that *number > 9999
checks that a number isn't larger than four digits, not five. Should be 99999
.
General code review:
Avoid scanf_s
since it is poorly standardized. Original scanf
actually supports reading a fixed amount of characters if you check the result. However, in this specific case it would have been much more convenient to read the input as a string with fgets
, since base-10 decimal digits is a cumbersome format forcing you to use division over and over.
It makes no sense at all to use function pointers here. The various functions in your array do unrelated tasks, so generic programming with an abstraction layer only makes the program hard to read for nothing gained. I take it you are just using them for learning purposes.
The big bug here could have been avoided if you use const correctness, meaning that pointer parameters that aren't supposed to be modified should be marked read-only. That is:
void outputDigit(const int *number, int *digit);
void outputNumber(const int *number, const int *digit);
void outputReverseNumber(const int *number, const int *digit)
Although now the functions have different types so the function pointer array can no longer be used either.
In general don't mix up algorithms (calculating number of digits) with user I/O (printing or taking input). Programmers don't expect a function named outputDigit
to calculate a digit, they expect it to print one.
Using dynamic allocation for a single int
is senseless. Similarly, casting the result of malloc
is pointless.
Always use typedef when dealing with function pointers, for readability. In this case you could have done:
typedef void func_t (int*, int*);
...
func_t* fun[3] = {outputDigit, outputNumber, outputReverseNumber};
...
void function(int *number, int *digit, func_t* fun[3])