提问人:Drox 提问时间:10/9/2023 更新时间:10/9/2023 访问量:53
函数中生成的指针变量不能在函数指针的参数中传递
Pointer variables generated in functions cannot be passed in parameters of function pointers
问:
主题: 给定一个不超过 5 位数字的正整数,需要:
- 找出它有多少位数字;
- 分别输出每个数字;
- 以相反的顺序输出每个数字。例如,如果原始数字为 321,则应输出 123。
当我使用函数指针调用以下程序时,我发现参数“number”和“digit”无法传递给每个函数。
#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;
}
我希望函数指针中的参数由其他函数生成的指针变量传递。
答:
当您用零覆盖每个函数时,下一个调用将使用该修改后的值。你已经陷入了副作用的陷阱。number
您需要在每次调用之前恢复它:
void function(int *number, int *digit, void (*fun[])(int*, int*))
{
int savedNumber = *number;
for(int i = 0; i < 3; i++)
{
fun[i](number, digit);
*number = savedNumber;
}
}
https://godbolt.org/z/6GWKqbfMq
参数传递没有问题。问题在于,您一直在内部除以数字,从而确保在离开函数时原始数字为零。这可以通过改用临时变量来解决:outputDigit
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);
}
另一个错误是检查数字是否大于四位数,而不是五位数。应该是 。*number > 9999
99999
一般代码审查:
避免,因为它的标准化程度很差。如果您检查结果,原始实际上支持读取固定数量的字符。但是,在这种特定情况下,将输入读取为字符串会方便得多,因为以 10 为基数的十进制数字是一种繁琐的格式,迫使您一遍又一遍地使用除法。
scanf_s
scanf
fgets
在这里使用函数指针完全没有意义。数组中的各种函数执行不相关的任务,因此使用抽象层进行泛型编程只会使程序难以阅读,而不会获得任何好处。我认为您只是将它们用于学习目的。
如果您使用 const 正确性,则可以避免此处的大错误,这意味着不应修改的指针参数应标记为只读。那是:
void outputDigit(const int *number, int *digit); void outputNumber(const int *number, const int *digit); void outputReverseNumber(const int *number, const int *digit)
尽管现在函数具有不同的类型,因此也无法再使用函数指针数组。
通常,不要将算法(计算位数)与用户 I/O(打印或输入)混淆。程序员不期望一个名为的函数来计算一个数字,他们希望它打印一个数字。
outputDigit
对单个使用动态分配是没有意义的。同样,投射的结果是没有意义的。
int
malloc
在处理函数指针时,请始终使用 typedef,以提高可读性。在这种情况下,您可以执行以下操作:
typedef void func_t (int*, int*); ... func_t* fun[3] = {outputDigit, outputNumber, outputReverseNumber}; ... void function(int *number, int *digit, func_t* fun[3])
评论
malloc
的结果;其次,不要动态分配单个整数值。改用指针运算符获取指向变量的指针。喜欢&
int number = 0; inputNumber(&number);
number
digt
outputDigit