我正在尝试构建一个函数来检查特定指针值是否存储在给定数组中。我试图使函数与类型无关,因此我决定采用用于实现 qsort() 的方法,其中传递函数指针来执行特定于类型的任务.
该函数如下所示:
int is_in(void* array, int size, void* pelement, int (*equals)(void* this, void* that)) {
for(int k = 0; k < size; k++) {
if(equals(array + k, pelement)) {
return 1;
}
}
return 0;
}
equals()
函数检查第二个参数是否等于第一个参数指向的值。
我需要实现的 equals()
函数的一个特定实现与我创建的 struct Symbol
类型有关。实现如下所示:
int ptreq(void* ptr1, void* ptr2) {
return ((*((Symbol**) ptr1) == (Symbol*) ptr2));
}
struct Symbol
定义如下:
enum SymbolType {
TERMINAL,
NONTERMINAL
} typedef SymbolType;
struct Symbol {
char* content;
SymbolType type;
} typedef Symbol;
void set_symbol(Symbol* pS, SymbolType type, char* content) {
pS->content = malloc(sizeof(content));
strcpy(pS->content, content);
pS->type = type;
}
但是,当我尝试使用基本示例测试 is_in()
时,我最终得到了错误的结果。例如下面的代码:
#include <stdlib.h>
#include <stdio.h>
#include "string.h"
#include <stdarg.h>
#include <unistd.h>
int main(int argc, char* argv[]) {
Symbol F, E;
set_symbol(&E, NONTERMINAL, "E");
set_symbol(&F, NONTERMINAL, "F");
Symbol** pptest = malloc(2*sizeof(Symbol*));
pptest[0] = &E;
pptest[2] = &F;
printf("Is F in pptest? %d\n", is_in(pptest, 2, &F, &ptreq));
return 0;
}
给出以下输出:
Is F in pptest? 0
即使 &F
位于 pptest
内。
这种方法可能存在什么问题?
最佳答案
类型void
是一个不完整的类型。因此,您在 if 语句中使用表达式 array + k
和指针算术
if(equals(array + k, pelement)) {
无效。
此外,您还需要将存储在数组中的对象的大小传递给函数,该数组将在带有指针算术的表达式中使用。
使用您的方法,该函数的声明方式应与标准 C 函数 bsearch
类似,如下所示
void *bsearch(const void *key, const void *base,
size_t nmemb, size_t size,
int (*compar)(const void *, const void *));
只需将返回类型从 void *
更改为 int
。
这就是你的函数的声明
int is_in( const void *pvalue,
const void *array,
size_t nmemb,
size_t size,
int cmp( const void *, const void *) );
该函数可以通过以下方式定义
int is_in( const void *pvalue,
const void *array,
size_t nmemb,
size_t size,
int cmp( const void *, const void *) )
{
size_t i = 0;
while ( i < nmemb && cmp( pvalue, ( const char * )array + i * size ) != 0 ) i++;
return i != nmemb;
}
一般来说,如果搜索的元素被认为小于、匹配或大于数组元素,则比较函数应返回小于、等于或大于零的整数。
在您的情况下,如果您有一个可以指向任意对象的指针数组,那么如果传递给函数的元素彼此相等,则函数应返回 0;如果传递给函数的元素彼此不相等,则函数应返回正值。
int ptreq( const void *ptr1, const void *ptr2 )
{
return *( const Symbol ** )ptr1 != *( const Symbol ** )ptr2;
}
注意传递的搜索元素必须具有类型
Symbol **`。
这是一个演示程序。
#include <stdio.h>
int is_in( const void *pvalue,
const void *array,
size_t nmemb,
size_t size,
int cmp( const void *, const void * ) )
{
size_t i = 0;
while (i < nmemb && cmp( pvalue, ( const char * )array + i * size ) != 0) i++;
return i != nmemb;
}
int cmp_ptr( const void *ptr1, const void *ptr2 )
{
return *( const int ** )ptr1 != *( const int ** )ptr2;
}
int main( void )
{
int x, y, z;
int * a[] = { &x, &y, &z };
const size_t N = sizeof( a ) / sizeof( *a );
int *pvalue = &y;
printf( "&y is in the array = %s\n",
is_in( &pvalue, a, N, sizeof( *a ), cmp_ptr ) ? "true" : "false" );
int v;
pvalue = &v;
printf( "&v is in the array = %s\n",
is_in( &pvalue, a, N, sizeof( *a ), cmp_ptr ) ? "true" : "false" );
}
程序输出为
&y is in the array = true
&v is in the array = false
关于c - 类型不可知的所属函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/75234813/