首頁 > 軟體

基於C語言實現泛型程式設計詳解

2022-07-06 10:01:51

心理歷程

寫了一段時間C++後,真心感覺STL裡的容器是個好東西。一個容器可以容納任意型別,容器對外的介面可以操作任意型別的資料,甚至包括自定義型別的資料。這種泛型程式設計的思想,對於大型專案而言是非常有好處的。

對於C而言,想實現泛型程式設計並非易事,甚至可以說非常繁瑣,一大堆坑。最主要也沒有現成的輪子可用。當然也有一些通過宏實現了泛型的基礎功能,但是可讀性,可偵錯性太差了。

於是就想自己造一個輪子,實現基於C對視窗(順序表)的泛化,目標就是實現不同型別下,規範介面的一致性。拋磚引玉。

輪子用法

int main( void )
{
	// 1、建立一個視窗,並初始化它,大小為10,型別為double
    ValueWindowSquential tmp;
    InitValueWindow( &tmp, kValueTypeList[ DOUBLE ], 10 );

    double insert_data = 0;
    for ( int i = 0; i < tmp.max_size; i++ )
    {
    	// 2、填充這個視窗,直到視窗填滿
        insert_data = i * 10;
        if ( kWindowAlreadyFull == ValueWindowFixedInsert( &tmp, &insert_data ) )
        {
        	// 3、列印整個視窗
            printf( "start sort rn" );
            ShowTheWindow( &tmp );
	
			// 4、整個視窗排序
            ValueWindowSelectSort( &tmp );
	
			// 5、列印排序後的視窗
            printf( "end sort rn" );
            ShowTheWindow( &tmp );

            break;
        }
    }

    printf( "test generics rn" );
    return 0;
}

列印log如下:

這時想換成建立一個uint8_t型別的串列埠,只需要改兩個地方,這兩個地方在C++裡也避免不了。

int main( void )
{
    ValueWindowSquential tmp;
    InitValueWindow( &tmp, kValueTypeList[ UINT8 ], 10 );

    uint8_t insert_data = 0;
    for ( int i = 0; i < tmp.max_size; i++ )
    {
        insert_data = ( tmp.max_size - i ) * 1;
        if ( kWindowAlreadyFull == ValueWindowFixedInsert( &tmp, &insert_data ) )
        {
            printf( "start sort rn" );
            ShowTheWindow( &tmp );

            ValueWindowSelectSort( &tmp );

            printf( "end sort rn" );
            ShowTheWindow( &tmp );

            break;
        }
    }

    printf( "test generics rn" );
    return 0;
}

大體流程

1.首先初始化一個空視窗物件,然後呼叫 InitValueWindow 傳入視窗型別,大小,然後初始化它。

2.呼叫 ValueWindowFixedInsert 往視窗中插入值,直到視窗滿後反饋狀態。

3.列印整個視窗

4.對視窗排序

5.列印整個視窗

這裡的泛型主要通過查表實現了,將希望包含的型別加入表中,然後初始化時傳入其型別和大小。

插入資料的時候,需要保證資料型別和視窗型別統一,這算是個侷限性了。

視窗被填充完畢後,會有反饋視窗狀態,這時可以呼叫 ShowTheWindow 將原始視窗列印。

在呼叫 ValueWindowSelectSort 將視窗排序。排序完後再次列印。

可以看到除了初始化的時候,需要設定視窗的型別,這和 std::vector< double > 沒什麼兩樣,插入資料時需要呼叫者確保資料型別與視窗統一。

部分原始碼

#ifndef __TEST_GENERICS_h
#define __TEST_GENERICS_h

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

#include <assert.h>

typedef signed char   int8_t;
typedef unsigned char uint8_t;

typedef signed short   int16_t;
typedef unsigned short uint16_t;

typedef signed int   int32_t;
typedef unsigned int uint32_t;

typedef enum
{
    UINT8 = 0,
    INT,
    FLOAT,
    DOUBLE,

    ERROR

} TypeName;

const char* kValueTypeList[ ERROR + 1 ] = {

    "uint8_t",

    "int",
    "float",
    "double",

    "error",
};

TypeName ChangeStringToEnum( const char* tmp );

/**
 * @brief 該結構體用於構建基礎視窗順序表
 *        this structure is used to build the basic window sequence table
 */
typedef struct ValueWindowSquential
{
    char* type;
    void* data;

    uint32_t max_size;

    uint32_t sequence;

} ValueWindowSquential;

/**
 * @brief 初始化視窗,根據視窗型別,大小,動態分配記憶體給到內部緩衝區
 *        initialize the window, and dynamically allocate memory to the internal buffer according to the window type and size
 *
 * @param tmp base structure for Window
 * @param type Window type
 * @param max_size Window size
 *
 * @throw assert
 */
void InitValueWindow( ValueWindowSquential* tmp, const char* type, uint32_t max_size );

/**
 * @brief 重置或銷燬視窗
 *        reset or destroy window
 *
 * @param tmp base structure for Window
 */
void ResetValueWindow( ValueWindowSquential* tmp );

typedef enum
{
    kWindowIsNotFull = ( 0 ),
    kWindowIsSliding,

    kWindowCanNotInsert,
    kWindowInputFail,

} SlideWindowState;
/**
 * @brief 滑動插入資料進入視窗,先入先出(FIFO模型)
 *        slide insert data into the window, first in first out (FIFO model)
 *
 * @param tmp base structure for Window
 * @param data insert data
 *
 * @return SlideWindowState
 *              kWindowIsNotFull    視窗未填充滿
 *              kWindowIsSliding    視窗已填充滿並開始滑動
 *
 *              kWindowCanNotInsert 視窗不允許插入
 *              kWindowInputFail    視窗插入資料失敗
 */
SlideWindowState ValueWindowSlideInsert( ValueWindowSquential* tmp, void* data );

typedef enum
{
    kWindowNotFull = ( 0 ),
    kWindowAlreadyFull,

    kFixWindowCanNotInsert,
    kFixWindowInputFail,

} FixedWindowState;
/**
 * @brief 固定窗,往視窗裡插入資料,直到視窗滿了反饋 kWindowAlreadyFull ,否在反饋 kWindowNotFull
 *        與滑動窗區別是,固定窗會採集多組資料,採集完成才能使用視窗,使用完後從頭重新採集
 *        也就是降頻處理資料,視窗大小20,10ms插入一次,那麼降頻到200ms處理一次視窗(資料)
 *
 * @param tmp base structure for Window
 * @param data insert data
 *
 * @return FixedWindowState
 *              kWindowNotFull 視窗未滿
 *              kWindowAlreadyFull 視窗已滿,可以開始操作
 *
 *              kFixWindowCanNotInsert 視窗不允許插入
 *              kFixWindowInputFail 視窗插入資料失敗
 */
FixedWindowState ValueWindowFixedInsert( ValueWindowSquential* tmp, void* data );

/**
 * @brief 遍歷並列印視窗
 *
 * @param tmp base structure for Window
 */
void ShowTheWindow( ValueWindowSquential* tmp );

#endif // __TEST_GENERICS_h
/**
 * @file test_generics.cpp
 * @author benzs_war_pig (benzwarpig@outlook.com)
 * @brief   構建一種基於C的泛型順序表,針對不同型別的順序表,實現介面一致化。
 *        同時針對順序表實現一些常用操作(排序,濾波,統計等)
 *
 *          build a generic sequence table based on C, and realize interface consistency
 *          for different types of sequence tables. At the same time, some common operations (sorting, filtering, statistics, etc.)
 *          are implemented for the sequence table
 *
 * @version 1.0
 * @date 2022-06-30
 *
 * @copyright Copyright (c) 2022
 *
 */
#include "test_generics.h"

#include "generics_impl.h"

/**
 * @brief 將字串轉換成TypeName
 *          private interface
 *
 * @param tmp
 * @return TypeName
 */
TypeName ChangeStringToEnum( const char* tmp )
{
    assert( tmp != NULL );

    TypeName return_tmp = ERROR;

    if ( strcmp( tmp, kValueTypeList[ UINT8 ] ) == 0 )
    {
        return_tmp = UINT8;
    }
    else if ( strcmp( tmp, kValueTypeList[ FLOAT ] ) == 0 )
    {
        return_tmp = FLOAT;
    }
    else if ( strcmp( tmp, kValueTypeList[ DOUBLE ] ) == 0 )
    {
        return_tmp = DOUBLE;
    }
    else if ( strcmp( tmp, kValueTypeList[ INT ] ) == 0 )
    {
        return_tmp = INT;
    }
    else
    {
        printf( "error char* input !!!" );
        assert( 0 );
    }
    return return_tmp;
}

// 初始化視窗
// Initialize window
void InitValueWindow( ValueWindowSquential* tmp, const char* type, uint32_t max_size )
{
    assert( tmp != NULL );

    tmp->type = ( char* ) malloc( strlen( type ) * sizeof( char ) );
    strncpy( tmp->type, type, strlen( type ) );

    tmp->max_size = max_size;
    tmp->sequence = 0;

    switch ( ChangeStringToEnum( tmp->type ) )
    {
        case UINT8: {
            tmp->data = ( uint8_t* ) malloc( max_size * sizeof( uint8_t ) );
            memset( tmp->data, 0, tmp->max_size );
        }
        break;

        case INT: {
            tmp->data = ( int* ) malloc( max_size * sizeof( int ) );
            memset( tmp->data, 0, tmp->max_size );
        }
        break;

        case FLOAT: {
            tmp->data = ( float* ) malloc( max_size * sizeof( float ) );
            memset( tmp->data, 0, tmp->max_size );
        }
        break;

        case DOUBLE: {
            tmp->data = ( double* ) malloc( max_size * sizeof( double ) );
            memset( tmp->data, 0, tmp->max_size );
        }
        break;

        default: {
            printf( "error tmp->type input !!!" );
            assert( 0 );
        }
        break;
    }

    printf( "type is : %s , number is : %d  rn", tmp->type, max_size );
}

// 重置/銷燬視窗
void ResetValueWindow( ValueWindowSquential* tmp )
{
    tmp->sequence = 0;
    tmp->max_size = 0;

    if ( tmp->data != NULL )
    {
        free( tmp->data );
        tmp->data = NULL;
    }

    if ( tmp->type != NULL )
    {
        free( tmp->type );
        tmp->type = NULL;
    }
}

// 滑動往視窗插入資料
SlideWindowState ValueWindowSlideInsert( ValueWindowSquential* tmp, void* data )
{
    SlideWindowState return_tmp = kWindowIsNotFull;

    switch ( ChangeStringToEnum( tmp->type ) )
    {
        case UINT8: {
            uint8_t* tmp_buffer = ( uint8_t* ) tmp->data;
            for ( int i = 1; i < tmp->max_size; i++ )
            {
                tmp_buffer[ i - 1 ] = tmp_buffer[ i ];
            }
            uint8_t* res                    = ( uint8_t* ) data;
            tmp_buffer[ tmp->max_size - 1 ] = *res;
        }
        break;

        case INT: {
            int* tmp_buffer = ( int* ) tmp->data;
            for ( int i = 1; i < tmp->max_size; i++ )
            {
                tmp_buffer[ i - 1 ] = tmp_buffer[ i ];
            }
            int* res                        = ( int* ) data;
            tmp_buffer[ tmp->max_size - 1 ] = *res;
        }
        break;

        case FLOAT: {
            float* tmp_buffer = ( float* ) tmp->data;
            for ( int i = 1; i < tmp->max_size; i++ )
            {
                tmp_buffer[ i - 1 ] = tmp_buffer[ i ];
            }
            float* res                      = ( float* ) data;
            tmp_buffer[ tmp->max_size - 1 ] = *res;
        }
        break;

        case DOUBLE: {
            double* tmp_buffer = ( double* ) tmp->data;
            for ( int i = 1; i < tmp->max_size; i++ )
            {
                tmp_buffer[ i - 1 ] = tmp_buffer[ i ];
            }
            double* res                     = ( double* ) data;
            tmp_buffer[ tmp->max_size - 1 ] = *res;
        }
        break;

        default: {
            printf( "error tmp->type input !!!" );
            assert( 0 );
        }
        break;
    }
    if ( ++tmp->sequence > tmp->max_size )
    {
        return_tmp    = kWindowIsSliding;
        tmp->sequence = tmp->max_size;
    }

    return return_tmp;
}

// 插入資料直到填滿整個視窗
FixedWindowState ValueWindowFixedInsert( ValueWindowSquential* tmp, void* data )
{
    FixedWindowState return_tmp = kWindowNotFull;

    switch ( ChangeStringToEnum( tmp->type ) )
    {
        case UINT8: {
            uint8_t* tmp_buffer = ( uint8_t* ) tmp->data;
            uint8_t* res        = ( uint8_t* ) data;

            tmp_buffer[ tmp->sequence ] = *res;
        }
        break;

        case INT: {
            int* tmp_buffer = ( int* ) tmp->data;
            int* res        = ( int* ) data;

            tmp_buffer[ tmp->sequence ] = *res;
        }
        break;

        case FLOAT: {
            float* tmp_buffer = ( float* ) tmp->data;
            float* res        = ( float* ) data;

            tmp_buffer[ tmp->sequence ] = *res;
        }
        break;

        case DOUBLE: {
            double* tmp_buffer = ( double* ) tmp->data;
            double* res        = ( double* ) data;

            tmp_buffer[ tmp->sequence ] = *res;
        }
        break;

        default: {
            printf( "error tmp->type input !!!" );
            assert( 0 );
        }
        break;
    }

    if ( ++tmp->sequence >= tmp->max_size )
    {
        tmp->sequence = 0;
        return_tmp    = kWindowAlreadyFull;
    }
    return return_tmp;
}

// 列印視窗內全部值
void ShowTheWindow( ValueWindowSquential* tmp )
{
    // printf("current_type:{%d}", ChangeStringToEnum(tmp->type));
    switch ( ChangeStringToEnum( tmp->type ) )
    {
        case UINT8: {
            uint8_t* msg = ( uint8_t* ) tmp->data;
            for ( int i = 0; i < tmp->max_size; ++i )
            {
                printf( "i : {%d} , %d rn", i, msg[ i ] );
            }
        }
        break;

        case INT: {
            int* msg = ( int* ) tmp->data;
            for ( int i = 0; i < tmp->max_size; ++i )
            {
                printf( "i : {%d} , %d rn", i, msg[ i ] );
            }
        }
        break;

        case FLOAT: {
            float* msg = ( float* ) tmp->data;
            for ( int i = 0; i < tmp->max_size; ++i )
            {
                printf( "i : {%d} , %f rn", i, msg[ i ] );
            }
        }
        break;

        case DOUBLE: {
            double* msg = ( double* ) tmp->data;
            for ( int i = 0; i < tmp->max_size; ++i )
            {
                printf( "i : {%d} , %f rn", i, msg[ i ] );
            }
        }
        break;

        default: {
            printf( "error tmp->type input !!!" );
            assert( 0 );
        }
        break;
    }
}

int main( void )
{
    ValueWindowSquential tmp;
    InitValueWindow( &tmp, kValueTypeList[ DOUBLE ], 10 );

    double insert_data = 0;
    for ( int i = 0; i < tmp.max_size; i++ )
    {
        insert_data = ( tmp.max_size - i ) * 10;
        if ( kWindowAlreadyFull == ValueWindowFixedInsert( &tmp, &insert_data ) )
        {
            printf( "start sort rn" );
            ShowTheWindow( &tmp );

            ValueWindowSelectSort( &tmp );

            printf( "end sort rn" );
            ShowTheWindow( &tmp );

            break;
        }
    }
    ResetValueWindow(&tmp);

    printf( "test generics rn" );
    return 0;
}

這是最開始的一版原始碼,基本的思路是基於 void* 實現對視窗的泛化,把視窗的地址,大小,型別 在初始化時設定好,以後所有的結構便基於這些資訊,實現介面一致性。

目前實現了兩種視窗型別, ValueWindowSlideInsert (滑動窗) 和 ValueWindowFixedInsert(固定窗) 。 兩者不同之處只是插入資料時的處理不同。滑動窗遵循FIFO模型,即先入先出,視窗狀態有未滿和開始滑動,一般開始滑動後再對視窗進行操作。

固定窗有未滿和已滿兩種狀態,已滿後會清空視窗,重新開始填充,這也是兩種常見的視窗模型。

在STL裡,當有一些底層資料結構去儲存資料時,要有一些容器的方法(演演算法),比如排序等,這裡先實現了一些基礎的泛型演演算法介面:

#ifndef GENERICS_IMPL_H
#define GENERICS_IMPL_H

#include <stdbool.h>

#include "test_generics.h"

/**
 * @file generics_impl.h
 * @author benzs_war_pig (benzwarpig@outlook.com)
 * @brief 該檔案實現了一些操作泛型順序表的演演算法,如排序,查詢,遍歷,判斷變化率等等
 *
 *        this file implements some algorithms for operating generic sequential tables, such as sorting, searching, traversing,
 *          judging the rate of change, and so on
 *
 * @version 1.0
 * @date 2022-06-30
 *
 * @copyright Copyright (c) 2022
 *
 */

/**
 * @brief 交換順序表中兩個成員的值
 *
 * @param tmp base structure for Window
 * @param i
 * @param j
 */
static void swap( ValueWindowSquential* tmp, uint32_t i, uint32_t j )
{
    assert( tmp != NULL );
    // assert( i > tmp->max_size || j > tmp->max_size );
    // assert( i >= tmp->max_size || j >= tmp->max_size );

    switch ( ChangeStringToEnum( tmp->type ) )
    {
        case UINT8: {
            uint8_t* tmp_buffer = ( uint8_t* ) tmp->data;
            uint8_t  res        = tmp_buffer[ i ];

            tmp_buffer[ i ] = tmp_buffer[ j ];
            tmp_buffer[ j ] = res;
        }
        break;

        case INT: {
            int* tmp_buffer = ( int* ) tmp->data;
            int  res        = tmp_buffer[ i ];

            tmp_buffer[ i ] = tmp_buffer[ j ];
            tmp_buffer[ j ] = res;
        }
        break;

        case FLOAT: {
            float* tmp_buffer = ( float* ) tmp->data;
            float  res        = tmp_buffer[ i ];

            tmp_buffer[ i ] = tmp_buffer[ j ];
            tmp_buffer[ j ] = res;
        }
        break;

        case DOUBLE: {
            double* tmp_buffer = ( double* ) tmp->data;
            double  res        = tmp_buffer[ i ];

            tmp_buffer[ i ] = tmp_buffer[ j ];
            tmp_buffer[ j ] = res;
        }
        break;

        default: {
            printf( "error tmp->type input !!!" );
            assert( 0 );
        }
        break;
    }
}

static inline void ValueWindowBubbleSort( ValueWindowSquential* tmp )
{
    switch ( ChangeStringToEnum( tmp->type ) )
    {
        case UINT8: {
            uint8_t* tmp_buffer = ( uint8_t* ) tmp->data;

            bool is_end_loop = true;
            for ( int i = 0; i < tmp->max_size && is_end_loop; i++ )
            {
                is_end_loop = false;

                for ( int j = tmp->max_size - 1; j >= i; j-- )
                {
                    if ( tmp_buffer[ j - 1 ] > tmp_buffer[ j ] )
                    {
                        swap( tmp, j - 1, j );
                        is_end_loop = true;
                    }
                }
            }
        }
        break;

        case INT: {
            int* tmp_buffer = ( int* ) tmp->data;

            bool is_end_loop = true;
            for ( int i = 0; i < tmp->max_size && is_end_loop; i++ )
            {
                is_end_loop = false;

                for ( int j = tmp->max_size - 1; j >= i; j-- )
                {
                    if ( tmp_buffer[ j - 1 ] > tmp_buffer[ j ] )
                    {
                        swap( tmp, j - 1, j );
                        is_end_loop = true;
                    }
                }
            }
        }
        break;

        case FLOAT: {
            float* tmp_buffer = ( float* ) tmp->data;

            bool is_end_loop = true;
            for ( int i = 0; i < tmp->max_size && is_end_loop; i++ )
            {
                is_end_loop = false;

                for ( int j = tmp->max_size - 1; j >= i; j-- )
                {
                    if ( tmp_buffer[ j - 1 ] > tmp_buffer[ j ] )
                    {
                        swap( tmp, j - 1, j );
                        is_end_loop = true;
                    }
                }
            }
        }
        break;

        case DOUBLE: {
            double* tmp_buffer = ( double* ) tmp->data;

            bool is_end_loop = true;
            for ( int i = 0; i < tmp->max_size && is_end_loop; i++ )
            {
                is_end_loop = false;

                for ( int j = tmp->max_size - 1; j >= i; j-- )
                {
                    if ( tmp_buffer[ j - 1 ] > tmp_buffer[ j ] )
                    {
                        swap( tmp, j - 1, j );
                        is_end_loop = true;
                    }
                }
            }
        }
        break;

        default: {
            printf( "error tmp->type input !!!" );
            assert( 0 );
        }
        break;
    }
}

static inline void ValueWindowSelectSort( ValueWindowSquential* tmp )
{
    switch ( ChangeStringToEnum( tmp->type ) )
    {
        case UINT8: {
            uint8_t* tmp_buffer = ( uint8_t* ) tmp->data;

            int tmp_data = 0;
            for ( int i = 0; i < tmp->max_size; i++ )
            {
                tmp_data = i;
                for ( int j = i; j < tmp->max_size; j++ )
                {
                    if ( tmp_buffer[ tmp_data ] > tmp_buffer[ j ] )
                    {
                        tmp_data = j;
                    }
                }
                if ( tmp_data != i )
                {
                    swap( tmp, i, tmp_data );
                }
            }
        }
        break;

        case INT: {
            int* tmp_buffer = ( int* ) tmp->data;

            int tmp_data = 0;
            for ( int i = 0; i < tmp->max_size; i++ )
            {
                tmp_data = i;
                for ( int j = i; j < tmp->max_size; j++ )
                {
                    if ( tmp_buffer[ tmp_data ] > tmp_buffer[ j ] )
                    {
                        tmp_data = j;
                    }
                }
                if ( tmp_data != i )
                {
                    swap( tmp, i, tmp_data );
                }
            }
        }
        break;

        case FLOAT: {
            float* tmp_buffer = ( float* ) tmp->data;

            int tmp_data = 0;
            for ( int i = 0; i < tmp->max_size; i++ )
            {
                tmp_data = i;
                for ( int j = i; j < tmp->max_size; j++ )
                {
                    if ( tmp_buffer[ tmp_data ] > tmp_buffer[ j ] )
                    {
                        tmp_data = j;
                    }
                }
                if ( tmp_data != i )
                {
                    swap( tmp, i, tmp_data );
                }
            }
        }
        break;

        case DOUBLE: {
            double* tmp_buffer = ( double* ) tmp->data;

            int tmp_data = 0;
            for ( int i = 0; i < tmp->max_size; i++ )
            {
                tmp_data = i;
                for ( int j = i; j < tmp->max_size; j++ )
                {
                    if ( tmp_buffer[ tmp_data ] > tmp_buffer[ j ] )
                    {
                        tmp_data = j;
                    }
                }
                if ( tmp_data != i )
                {
                    swap( tmp, i, tmp_data );
                }
            }
        }
        break;

        default: {
            printf( "error tmp->type input !!!" );
            assert( 0 );
        }
        break;
    }
}

static inline void ValueWindowInsertSort( ValueWindowSquential* tmp )
{
    switch ( ChangeStringToEnum( tmp->type ) )
    {
        case UINT8: {
            uint8_t* tmp_buffer = ( uint8_t* ) tmp->data;

            uint8_t tmp_data = 0;
            int     j        = 0;
            for ( int i = 1; i < tmp->max_size; i++ )
            {
                if ( tmp_buffer[ i ] < tmp_buffer[ i - 1 ] )
                {
                    tmp_data = tmp_buffer[ i ];
                    // TAG : 資料整體向後遷移,尋找數值更大的成員
                    for ( j = i - 1; tmp_buffer[ j ] > tmp_data && j >= 0; j-- )
                    {
                        tmp_buffer[ j + 1 ] = tmp_buffer[ j ];
                    }
                    tmp_buffer[ j + 1 ] = tmp_data;
                }
            }
        }
        break;

        case INT: {
            int* tmp_buffer = ( int* ) tmp->data;

            int tmp_data = 0;
            int j        = 0;
            for ( int i = 1; i < tmp->max_size; i++ )
            {
                if ( tmp_buffer[ i ] < tmp_buffer[ i - 1 ] )
                {
                    tmp_data = tmp_buffer[ i ];
                    // TAG : 資料整體向後遷移,尋找數值更大的成員
                    for ( j = i - 1; tmp_buffer[ j ] > tmp_data && j >= 0; j-- )
                    {
                        tmp_buffer[ j + 1 ] = tmp_buffer[ j ];
                    }
                    tmp_buffer[ j + 1 ] = tmp_data;
                }
            }
        }
        break;

        case FLOAT: {
            float* tmp_buffer = ( float* ) tmp->data;

            float tmp_data = 0;
            int   j        = 0;
            for ( int i = 1; i < tmp->max_size; i++ )
            {
                if ( tmp_buffer[ i ] < tmp_buffer[ i - 1 ] )
                {
                    tmp_data = tmp_buffer[ i ];
                    // TAG : 資料整體向後遷移,尋找數值更大的成員
                    for ( j = i - 1; tmp_buffer[ j ] > tmp_data && j >= 0; j-- )
                    {
                        tmp_buffer[ j + 1 ] = tmp_buffer[ j ];
                    }
                    tmp_buffer[ j + 1 ] = tmp_data;
                }
            }
        }
        break;

        case DOUBLE: {
            double* tmp_buffer = ( double* ) tmp->data;

            double tmp_data = 0;
            int    j        = 0;
            for ( int i = 1; i < tmp->max_size; i++ )
            {
                if ( tmp_buffer[ i ] < tmp_buffer[ i - 1 ] )
                {
                    tmp_data = tmp_buffer[ i ];
                    // TAG : 資料整體向後遷移,尋找數值更大的成員
                    for ( j = i - 1; tmp_buffer[ j ] > tmp_data && j >= 0; j-- )
                    {
                        tmp_buffer[ j + 1 ] = tmp_buffer[ j ];
                    }
                    tmp_buffer[ j + 1 ] = tmp_data;
                }
            }
        }
        break;

        default: {
            printf( "error tmp->type input !!!" );
            assert( 0 );
        }
        break;
    }
}
#endif // GENERICS_IMPL_H

以上就是基於C語言實現泛型程式設計詳解的詳細內容,更多關於C語言 泛型程式設計的資料請關注it145.com其它相關文章!


IT145.com E-mail:sddin#qq.com