问题描述
在此void* ic = b + j * sz;
和此void* jc = ic - sz;
行中,写表达式必须是指向完整类型的指针。我需要wright函数,它可以对所有内容进行排序,因此我使用void *。我现在不怎么用void *进行迭代。如何访问元素void* base
之类的数组。
UPD
pcharToInt是错误的。我首先将void*
投射到char*
上,
原来是心脏符号。比我尝试与void*
合作。
#include <iostream>
using namespace std;
typedef int (*CFT) (const void*,const void*);
int pcharToInt(char* a);
int cmp1(const void* a,const void* b);
void insort(void* base,size_t n,size_t sz,CFT cmp);
int main() {
int arr[] = { 9,3,5,7,9,4 };
void* a = arr;
char* b = static_cast<char*>(a);
return 0;
}
int pcharToInt(char* a) {
int b = 0;
char* tmp = a;
while (*a) {
b *= 10;
b += (*a++ - '0');
}
a = tmp;
return b;
}
int cmp1(const void* a,const void* b) {
int n1 = 0;
int n2 = 0;
n1 = pcharToInt((char*)a);
n2 = pcharToInt((char*)b);
if (n1 > n2) return 1;
else return 0;
}
void insort(void* base,CFT cmp) {
void* b = base;
for (int i = 1; i < n; i++)
{
for (int j = i; j > 0; j--)
{
void* ic = b + j * sz;
void* jc = ic - sz;
if (cmp1(jc,ic)) {
for (int k = 0; k < sz; k++) {
char tmp = jc[k];
jc[k] = ic[k];
ic[k] = tmp;
}
}
break;
}
}
}
UPD2其旧代码为char
char* b = static_cast<char*> (base);
for (int i = 1; i < n; i++)
{
for (int j = i; j > 0; j--)
{
char* ic = b + j * sz;
char* jc = ic - sz;
if (cmp1(jc,ic)) {
for (int k = 0; k < sz; k++) {
char tmp = jc[k];
jc[k] = ic[k];
ic[k] = tmp;
}
}
break;
}
}
UPD3
我在将void*
投射到char*
时遇到了麻烦。结果是哪里没有正确的符号。示例代码中必须是数字。
解决方法
如果您试图模仿C标准库中qsort()
的操作,则需要根据要排序的元素的类型和排序顺序(升序或降序)来定制比较功能。比较比较时使用类型为const void *
的指针参数进行调用,因为qsort()
设计为可与任何类型的数组一起使用,并且void *
是最通用的对象指针类型。
对于比较int
元素的特定情况,应将const void *
参数转换为const int *
并取消引用以获取要比较的int
元素的值。比较函数应返回负值,零值或正值,以指示要比较的两个元素的相对顺序。为了按升序对int
类型的元素进行排序,下面是一个合适的比较函数:
int cmp1(const void *a,const void *b)
{
int aa = *(const int *)a; // convert pointer a and dereference
int bb = *(const int *)b; // convert pointer b and defererence
if (aa < bb)
return -1;
if (aa > bb)
return 1;
return 0;
}
用于按降序对int
元素进行排序的比较函数与上面的类似,但是交换了-1
和1
返回值。
您的insort()
函数需要与比较函数不同的返回值,返回0而不是负值。为了与您的insort()
函数兼容,需要对该函数进行如下修改:
int cmp1(const void *a,const void *b)
{
int aa = *(const int *)a; // convert pointer a and dereference
int bb = *(const int *)b; // convert pointer b and defererence
return (aa > bb);
}
对于标准C(和C ++?),不允许在void *
上使用指针算法,因为仅在指向 complete 对象类型的指针上使用指针算法,而void
是根据定义为不完整对象类型。某些编译器(例如GCC)允许将指针void *
作为C标准的扩展,就指针算法而言,它与char *
相同。可移植代码应避免对void *
使用指针算术。您的insort()
函数可以进行以下修改以实现可移植性:
void insort(void* base,size_t n,size_t sz,CFT cmp) {
char* b = (char*)base;
for (int i = 1; i < n; i++)
{
for (int j = i; j > 0; j--)
{
char* ic = b + j * sz;
char* jc = ic - sz;
if (cmp1((void*)jc,(void*)ic)) {
for (int k = 0; k < sz; k++) {
char tmp = jc[k];
jc[k] = ic[k];
ic[k] = tmp;
}
}
break;
}
}
}
,
在C ++中,您不会丢弃类型信息。
代替
{
"errors": [
{
"debugMessage": "Call to a member function articles() on null","message": "Internal server error","extensions": {
"category": "internal"
},"locations": [
{
"line": 6,"column": 3
}
],"path": [
"createArticle"
],
你应该在写
typedef int (*CFT) (const void*,const void*);
void insort(void* base,CFT cmp);
int cmp1(const void* a,const void* b);
请注意,您忽略了第一个元素,而template<typename T>
using CFT = bool(*)(const T *,const T *);
template<typename T>
void insort(T* base,CFT<T> cmp) {
for (T* i = base + 1; i < base + n; i++)
{
for (T* j = i; j > base; j--)
{
if (cmp(j,i)) {
std::swap(*j,*i)
}
break;
}
}
}
int cmp1(const int * a,const int * b)
{
return *a > *b;
}
似乎可疑。当发现不规则的东西时,通常需要移动多个元素。
正确的插入排序(adapted from here)
break