C和指针第13章第4题

题目:编写一个函数,它用于对一个任何类型的数组进行排序。

算法核心代码sort函数实现

/**
功能说明:sort函数可以对不同类型的数据进行排序
参数:
1、一个指向需要排序的数组的第一个值的指针。
2、数组中元素的个数。
3、每个数组元素的长度。
4、一个指向比较回调函数的指针
**/
void sort(void *array,int size,int element_size,int (*cmp)(void const *a,void const *b))
{
    char *pc = (char *)array;//默认void *大小未知,这里把它存入字符指针下
     //简单的冒泡排序 这里可以用更高级的算法实现,这里采用了简单的冒泡排序
     for(int i = 0; i < size; i++)
     for(int j = 1; j < size-i; j++)
     {
             if(cmp(pc+(j-1)*element_size,pc+j*element_size) < 0)
             {
                 void *p = malloc(element_size);//分配一个string大小的内存
                 //交换两个元素,借助于和中间变量p,由于具体类型未知,这里借助于内存cpy函数拷贝内存内的内容
                 memcpy(p,pc+j*element_size,element_size);
                 memcpy(pc+j*element_size,pc+(j-1)*element_size,element_size);
                 memcpy(pc+(j-1)*element_size,p,element_size);
                 free(p);//临时变量使用完毕后,记得释放,不然容易造成内存泄露
             }
     }
}

字符串比较函数,这里是第二个大于第一个返回值大于0,相等等于0,第二个数小于第一个返回值小于0

//string 比较
int string_cmp(void const *a,void const *b)
{
    char *num1 = (char *)a;
    char *num2 = (char *)b;
    assert(num1 != NULL && num2 != NULL);
    while(*num1 != ‘\0‘ && *num2 != ‘\0‘)
    {
        if(*num1 == *num2)
        {
            num1++;
            num2++;
            continue;
        }
        break;
    }
    return *num2-*num1;

}

测试代码,全部代码

/*************************************************************************
    > File Name: sort.c
    > Created Time: 2014年06月17日 星期二 23时22分34秒
 ************************************************************************/

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<string.h>

/**
功能说明:sort函数可以对不同类型的数据进行排序
参数:
1、一个指向需要排序的数组的第一个值的指针。
2、数组中元素的个数。
3、每个数组元素的长度。
4、一个指向比较回调函数的指针
**/
void sort(void *array,int size,int element_size,int (*cmp)(void const *a,void const *b))
{
    char *pc = (char *)array;//默认void *大小未知,这里把它存入字符指针下
     //简单的冒泡排序 这里可以用更高级的算法实现,这里采用了简单的冒泡排序
     for(int i = 0; i < size; i++)
     for(int j = 1; j < size-i; j++)
     {
             if(cmp(pc+(j-1)*element_size,pc+j*element_size) < 0)
             {
                 void *p = malloc(element_size);//分配一个string大小的内存
                 //交换两个元素,借助于和中间变量p,由于具体类型未知,这里借助于内存cpy函数拷贝内存内的内容
                 memcpy(p,pc+j*element_size,element_size);
                 memcpy(pc+j*element_size,pc+(j-1)*element_size,element_size);
                 memcpy(pc+(j-1)*element_size,p,element_size);
                 free(p);//临时变量使用完毕后,记得释放,不然容易造成内存泄露
             }
     }
}

//int比较
int int_cmp(void const *a,void const *b)
{
    int *num1 = (int *)a;
    int *num2 = (int *)b;
    if(*num1 == *num2)return 0;
    else return *num2-*num1;
}
//double比较
int double_cmp(void const *a,void const *b)
{
    double *num1 = (double *)a;
    double *num2 = (double *)b;
    if(*num1 == *num2)return 0;
    else return *num2-*num1;
}

//char 比较
int char_cmp(void const *a,void const *b)
{
    char *num1 = (char *)a;
    char *num2 = (char *)b;
    if(*num1 == *num2)return 0;
    else return *num2-*num1;
}

//string 比较
int string_cmp(void const *a,void const *b)
{
    char *num1 = (char *)a;
    char *num2 = (char *)b;
    assert(num1 != NULL && num2 != NULL);
    while(*num1 != ‘\0‘ && *num2 != ‘\0‘)
    {
        if(*num1 == *num2)
        {
            num1++;
            num2++;
            continue;
        }
        break;
    }
    return *num2-*num1;

}

int main()
{

    //int 数组
    int array[6] = {9,3,5,2,0,4};
    printf("int 数组排序前:\n");
    for(int i = 0; i < 6; i++)
    printf("%d ",array[i]);
    printf("\n");
    sort(array,6,sizeof(int),int_cmp);
    printf("int 数组排序后:\n");
    for(int i = 0; i < 6; i++)
    printf("%d ",array[i]);
    printf("\n");

    //double 数组
    double array_d[5] = {3.16,2.5,6.49,10.5,0.4};
    printf("double 数组排序前:\n");
    for(int i = 0; i < 5; i++)
        printf("%lf ",array_d[i]);
    printf("\n");
    sort(array_d,5,sizeof(double),double_cmp);
    printf("double 数组排序后:\n");
    for(int i = 0; i < 5; i++)
        printf("%lf ",array_d[i]);
    printf("\n");

    //char
    char array_c[5] = {‘E‘,‘C‘,‘A‘,‘D‘,‘B‘};
    printf("char 数组排序前:\n");
    for(int i = 0; i < 5; i++)
        printf("%c ",array_c[i]);
    printf("\n");
    sort(array_c,5,sizeof(char),char_cmp);
    printf("char 数组排序后:\n");
    for(int i = 0; i < 5; i++)
        printf("%c ",array_c[i]);
    printf("\n");
    //string 数组排序
    char array_s[5][10] = {"yello","world","herb","herd","sort"};
    printf("string 数组排序前:\n");
    for(int i = 0; i < 5; i++)
        printf("%s ",array_s[i]);
    printf("\n");
    sort(array_s,5,sizeof(char)*10,string_cmp);
    printf("string 数组排序后:\n");
    for(int i = 0; i < 5; i++)
        printf("%s ",array_s[i]);
    printf("\n");

    return 0;
}

运行结果:

C和指针第13章第4题,布布扣,bubuko.com

时间: 2024-10-12 23:09:30

C和指针第13章第4题的相关文章

C和指针第七章第五题

实现一个简化的printf函数,能够处理%d,%f,%s,%c等格式. /************************************************************************* > File Name: permutation.c > Created Time: 2014年06月17日 星期二 23时22分34秒 *********************************************************************

C++ primer plus读书笔记——第13章 类继承

第13章 类继承 1. 如果购买厂商的C库,除非厂商提供库函数的源代码,否则您将无法根据自己的需求,对函数进行扩展或修改.但如果是类库,只要其提供了类方法的头文件和编译后的代码,仍可以使用库中的类派生出新的类.而且可以在不公开实现的情况下将自己的类分发给其他人,同时允许他们在类中添加新特性. 2. 派生类构造函数首先创建基类对象,如果不调用基类构造函数,程序将使用默认的基类构造函数. 3. 创建派生类对象时,程序首先调用基类构造函数,然后再调用派生类构造函数.派生类对象过期时,程序将首先调用派生

第13章 GPIO-位带操作—零死角玩转STM32-F429系列

第13章 ????GPIO-位带操作 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.com/firege ? 本章参考资料:<STM32F4xx 中文参考手册>存储器和总线构架章节.GPIO章节,<Cortex?-M4内核编程手册>2.2.5 Bit-banding.学习本章时,配套这些参考资料学习效果会更佳. 13.1 位带简介 位操作就是可以单独的对一个比特位读和写,这个在51单

C++ Primer学习总结 第13章 拷贝控制

第13章 拷贝控制 1.    什么是拷贝构造函数? P440 如果一个类的构造函数的第一个参数是自己类类型的引用, 且所有其他参数都有默认值, 那么这就是一个拷贝构造函数. 2.    拷贝初始化和直接初始化.  P441 如果初始化的时候使用等号"="来初始化一个对象, 那么就是拷贝初始化. 相反, 如果初始化时, 没有用等号"=", 那么就是直接初始化. 如果是拷贝初始化, 那么用的一定是拷贝构造函数(也有可能用移动构造函数). 如果是直接初始化, 那么就用参

第13章 网络编程

1 /***************** 2 ***第13章 网络编程 3 *******知识点: 4 **************1.基本概念 5 ******************1.1 网络OSI模型 6 ******************1.2 IP地址 7 ******************1.3 端口地址 8 ******************1.4 通讯协议 9 **************2.Java网络相关类 10 ******************2.1 URLDe

第13章 GPIO—位带操作

第13章     GPIO-位带操作 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.com/firege 本章参考资料:<STM32F4xx 中文参考手册>存储器和总线构架章节.GPIO章节,<Cortex?-M4内核编程手册>2.2.5 Bit-banding.学习本章时,配套这些参考资料学习效果会更佳. 13.1 位带简介 位操作就是可以单独的对一个比特位读和写,这个在51单片机

《C++Primer》12、13章

第12章 动态内存 12.1 智能指针 shared_ptr<T> make_shared<T>(args) 直接初始化 new int(10); 默认初始化 new int; 值初始化 new int(); 由内置指针(而不是智能指针)管理的动态内存在被显示释放前一直都会存在. 最好坚持只使用智能指针: delete之后重置指针值为nullptr: unique_ptr u = nullptr 释放u指向的对象,将u置为空 u.release()  u放弃对指针的控制权,返回指针

第 13 章

13.1 [出题思路] 理解拷贝构造函数的基本概念. [解答] 如果构造函数的第一个参数是自身类类型的引用,且所有其他参数(如果有的话)都有默认值,则此构造函数是拷贝构造函数.拷贝构造函数在以下几种情况下会被使用: 拷贝初始化(用 = 定义变量). 将一个对象作为实参传递给非引用类型的形参. 一个返回类型为非引用类型的函数返回一个对象. 用花括号列表初始化一个数组中的元素或一个聚合类中的成员. 初始化标准库容器或调用其 insert/push 操作时,容器会对其元素进行拷贝初始化. 13.2 [

JavaScript权威指南第13章 web浏览器中的javascript

13.1 客户端javascript window对象是所有的客户端javascript特性和api的主要接入点.表示浏览器的一个窗口,可以通过window对象来引用它. window 的方法 alert() prompt() confirm() 13.2 在html里嵌入javascript 4种方法: 内联:放置在<script></script>标签之中 外部引入:<script src="   "></script> html程序