C語言實現自己的動態陣列庫
阿新 • • 發佈:2019-01-26
動態陣列庫由兩部分構成:標頭檔案 ArrayLib.h 和所有函式方法實現檔案 ArrayLib.c 根據標頭檔案所需要的功能直接呼叫就可以了!
ArrayLib.h
/***********************************************
* 檔名:arrayLib.h
* 檔案描述:動態陣列庫函式標頭檔案,包含了動態陣列
* 所有功能的函式的宣告以及型別定義等
* 編輯人:王廷雲
* 編輯日期:2017-10-1
* 修改日期:2018-1-10
************************************************/
#ifndef _ARRAY_LIB_H_
#define _ARRAY_LIB_H_
/* 動態陣列結構體封裝 */
typedef struct {
int n; // 動態陣列的元素個數
int size; // 動態陣列的元素空間大小
void *addr; // 動態陣列的資料起始地址
} Array_t;
/* 比較函式型別定義 */
typedef int compare_t(const void *data1, const void *data2);
/******************************
* 以下為所有動態陣列庫函式宣告
*******************************/
/*
* 函式名: initArray
* 函式功能: 初始化動態陣列
* 引數: 陣列元素的空間大小
* 返回值: 成功則返回初始化後的動態陣列指標
* 失敗返回NULL
*/
Array_t *initArray(int size);
/*
* 函式名: appendArrayTail
* 函式功能: 尾部追加陣列元素
* 引數: 1.需要追加的陣列指標 2.需要追加的元素指標
* 返回值: 成功追加返回0 失敗返回-1
*/
int appendArrayTail(Array_t *ar, const void *data);
/*
* 函式名: appendArrayTop
* 函式功能: 頭部追加陣列元素
* 引數: 1.需要追加的陣列指標 2.需要追加的元素指標
* 返回值: 成功追加返回0 失敗返回-1
*/
int appendArrayTop(Array_t *ar, const void *data);
/*
* 函式名: insertArrayByIndex
* 函式功能: 指定陣列下標插入陣列元素
* <函式會檢查下標的合法性>
* 引數: 1.需要插入資料的陣列指標 2.需要插入的資料指標
* 2.陣列下標值
* 返回值: 成功插入返回0 失敗返回-1
*/
int insertArrayByIndex(Array_t *ar, const void *data, int idx);
/*
* 函式名: travelArray
* 函式功能: 遍歷動態陣列元素
* 引數: 1.需要遍歷的陣列指標 2.回撥函式
* 返回值: 無
*/
void travelArray(Array_t *ar, void (*func)(void *data));
/*
* 函式名: searchArrayByIndex
* 函式功能: 根據下標查詢陣列元素<會檢查下標的合法性>
* 引數: 1.需要查詢的陣列指標 2.查詢的下標
* 返回值: 資料存在返回資料地址 不存在則返回NULL
*/
void *searchArrayByIndex(Array_t *ar, const int idx);
/*
* 函式名: searchArrayOneByCond
* 函式功能: 根據條件查詢元素,如果有多個則找第一個
* 引數: 1.需要查詢的陣列指標 2.比較回撥函式指標 3.條件指標
* 返回值: 資料存在返回資料地址 不存在則返回NULL
*/
void *searchArrayOneByCond(Array_t *ar, compare_t *func, \
const void *key);
/*
* 函式名: searchArrayByCond
* 函式功能: 根據條件查詢元素
* 引數: 1.需要查詢的陣列指標 2.比較回撥函式指標 3.條件指標
* 返回值: 資料存在返回資料陣列 不存在則返回NULL
*/
Array_t *searchArrayByCond(Array_t *ar, compare_t *func, \
const void *key);
/*
* 函式名: deleteArrayByIndex
* 函式功能: 根據下標刪除陣列元素
* 引數: 1.陣列指標 2.下標
* 返回值: 成功刪除返回0 失敗返回-1
*/
int deleteArrayByIndex(Array_t *ar, const int idx);
/*
* 函式名: deleteArrayOneByCond
* 函式功能: 根據條件刪除陣列元素,如果多個匹配則只刪除第一個
* 引數: 1.陣列指標 2.比較回撥函式指標 3.條件
* 返回值: 成功刪除返回0 失敗返回-1
*/
int deleteArrayOneByCond(Array_t *ar, compare_t *func, \
const void *key);
/*
* 函式名: deleteArrayByCond
* 函式功能: 根據條件刪除所有匹配的陣列元素
* 引數: 1.陣列指標 2.比較回撥函式指標 3.條件
* 返回值: 返回成功刪除的元素個數
*/
int deleteArrayByCond(Array_t *ar, compare_t *func, \
const void *key);
/*
* 函式名: sortArray
* 函式功能: 對陣列元素進行排序
* <至於按什麼順序排列則由使用者的回撥函式具體來實現>
* 引數: 1.陣列指標 2.比較回撥函式指標
* 返回值: 排序成功返回0 失敗返回-1
*/
int sortArray(Array_t *ar, compare_t *func);
/*
* 函式名: saveArrayToFile
* 函式功能: 把陣列元素資料儲存到檔案中
* 引數: 1.陣列指標 2.需要儲存的檔案
* 返回值: 儲存成功返回0 失敗返回-1
*/
int saveArrayToFile(Array_t *ar, const char *file);
/*
* 函式名: loadArrayFromFile
* 函式功能: 從檔案中載入陣列資料
* 引數: 需要載入的檔案
* 返回值: 成功載入返回陣列指標 失敗返回NULL
*/
Array_t *loadArrayFromFile(const char *file);
/*
* 函式名: destoryArray
* 函式功能: 銷燬動態陣列線性表
* 引數: 陣列指標
* 返回值: 無
*/
void destoryArray(Array_t *ar);
/*
* 函式名: isEmptyArray
* 函式功能: 判斷是否是空陣列
* 引數: 陣列指標
* 返回值: 為空返回1 不為空返回0
*/
int isEmptyArray(Array_t *ar);
/*
* 函式名: arrayLenth
* 函式功能: 求陣列的長度(元素個數)
* 引數: 陣列指標
* 返回值: 返回陣列的元素個數
*/
int arrayLenth(Array_t *ar);
#endif /* _ARRAY_LIB_H_ */
ArrayLib.c
/********************************************
* 檔名:arrayLib.c
* 檔案描述:動態陣列庫函式所有功能函式的定義
* 編輯人:王廷雲
* 編輯日期:2017-10-1
* 修改日期:2018-1-10
*********************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "arrayLib.h"
/*
* 函式名: initArray
* 函式功能: 初始化動態陣列
* 引數: 陣列元素的空間大小
* 返回值: 成功則返回初始化後的動態陣列指標
* 失敗返回NULL
*/
Array_t *initArray(int size)
{
Array_t *ar;
ar = malloc(sizeof(Array_t));
if (ar == NULL) return NULL;
ar->size = size;
ar->n = 0;
ar->addr = NULL;
return ar;
}
/*
* 函式名: appendArrayTail
* 函式功能: 尾部追加陣列元素
* 引數: 1.需要追加的陣列指標 2.需要追加的元素指標
* 返回值: 成功追加返回0 失敗返回-1
*/
int appendArrayTail(Array_t *ar, const void *data)
{
void *temp;
#if 0
/* 分配比原來多一個數據的空間 */
temp = realloc(ar->addr, (ar->n+1)*ar->size);
if (temp == NULL)
{
return -1;
}
#else
/* 分配比原來多一個數據的空間 */
temp = malloc((ar->n+1) * ar->size);
if (temp == NULL)
{
return -1;
}
/* 把原來資料移動到新空間 */
memmove(temp, ar->addr, ar->n * ar->size);
/* 釋放原來資料空間 */
free(ar->addr);
#endif
/* 把新資料複製到新空間的尾部 */
memmove(temp+(ar->n*ar->size), data, ar->size);
/* 資料個數加1 */
ar->n += 1;
/* 更新資料地址指標 */
ar->addr = temp;
return 0;
}
/*
* 函式名: appendArrayTop
* 函式功能: 頭部追加陣列元素
* 引數: 1.需要追加的陣列指標 2.需要追加的元素指標
* 返回值: 成功追加返回0 失敗返回-1
*/
int appendArrayTop(Array_t *ar, const void *data)
{
void *temp;
#if 0
/* 分配比原來多一個數據的空間 */
temp = realloc(ar->addr, (ar->n+1)*ar->size);
if (temp == NULL)
{
return -1;
}
#else
/* 分配比原來多一個數據的空間 */
temp = malloc((ar->n+1) * ar->size);
if (temp == NULL)
{
return -1;
}
/* 把原來資料移動到新空間 */
memmove(temp+ar->size, ar->addr, ar->n * ar->size);
/* 釋放原來資料空間 */
free(ar->addr);
#endif
/* 把新資料複製到新空間的頭部 */
memmove(temp, data, ar->size);
/* 資料個數加1 */
ar->n += 1;
/* 更新資料地址指標 */
ar->addr = temp;
return 0;
}
/*
* 函式名: insertArrayByIndex
* 函式功能: 指定陣列下標插入陣列元素
* <函式會檢查下標的合法性>
* 引數: 1.需要插入資料的陣列指標 2.需要插入的資料指標
* 2.陣列下標值
* 返回值: 成功插入返回0 失敗返回-1
*/
int insertArrayByIndex(Array_t *ar, const void *data, int idx)
{
/* 檢查下標合法性 */
if (idx < 0 || idx > ar->n)
{
printf("Error! index is illegal!\n");
return -1;
}
void *temp;
#if 0
/* 分配比原來多一個數據的空間 */
temp = realloc(ar->addr, (ar->n+1)*ar->size);
if (temp == NULL)
{
return -1;
}
/* 把原來空間idx以及後面的資料移動到新空間的idx之後 */
memmove(temp+(idx+1)*ar->size, temp+idx*ar->size, \
(ar->n-idx)*ar->size);
/* 把新資料插入到新空間的idx處 */
memmove(temp+idx*ar->size, data, ar->size);
#else
/* 分配比原來多一個數據的空間 */
temp = malloc((ar->n+1)*ar->size);
if (temp == NULL)
{
return -1;
}
/* 把原來空間idx以前的資料移動到新空間前面 */
memmove(temp, ar->addr, idx*ar->size);
/* 把新資料插入到新空間的idx處 */
memmove(temp+idx*ar->size, data, ar->size);
/* 把原來空間idx以及後面的資料移動到新空間的idx之後 */
memmove(temp+(idx+1)*ar->size, ar->addr+(idx*ar->size), \
(ar->n-idx)*ar->size);
#endif
/* 資料元素個數加1 */
ar->n += 1;
/* 更新資料地址 */
ar->addr = temp;
return 0;
}
/*
* 函式名: travelArray
* 函式功能: 遍歷動態陣列元素
* 引數: 1.需要遍歷的陣列指標 2.回撥函式
* 返回值: 無
*/
void travelArray(Array_t *ar, void (*func)(void *data))
{
int i;
for (i = 0; i < ar->n; i++)
{
/* ar->addr + i*ar->size: 每個資料的起始地址 */
func(ar->addr + i*ar->size);
}
}
/*
* 函式名: searchArrayByIndex
* 函式功能: 根據下標查詢陣列元素<會檢查下標的合法性>
* 引數: 1.需要查詢的陣列指標 2.查詢的下標
* 返回值: 資料存在返回資料地址 不存在則返回NULL
*/
void *searchArrayByIndex(Array_t *ar, const int idx)
{
/* 下標合法性檢查 */
if (idx < 0 || idx >= ar->n)
{
fprintf(stderr,"Error! index is illegal!\n");
return NULL;
}
return ar->addr + idx*ar->size;
}
/*
* 函式名: searchArrayOneByCond
* 函式功能: 根據條件查詢元素,如果有多個則找第一個
* 引數: 1.需要查詢的陣列指標 2.比較回撥函式指標 3.條件指標
* 返回值: 資料存在返回資料地址 不存在則返回NULL
*/
void *searchArrayOneByCond(Array_t *ar, compare_t *func, \
const void *key)
{
int i;
for (i = 0; i < ar->n; i++)
{
/* 比較函式條件匹配func返回1 */
if (func(ar->addr+i*ar->size, key) == 1)
{
return ar->addr + i*ar->size;
}
}
return NULL;
}
/*
* 函式名: searchArrayByCond
* 函式功能: 根據條件查詢元素
* 引數: 1.需要查詢的陣列指標 2.比較回撥函式指標 3.條件指標
* 返回值: 資料存在返回資料陣列 不存在則返回NULL
*/
Array_t *searchArrayByCond(Array_t *ar, compare_t *func, \
const void *key)
{
int i, ret;
Array_t *result;
/* 建立用於儲存結果的陣列 */
result = initArray(ar->size);
if (result == NULL)
{
return NULL;
}
/* 遍歷查詢 */
for (i = 0; i < ar->n; i++)
{
/* 比較函式條件匹配func返回1 */
if (func(ar->addr+i*ar->size, key) == 1)
{
/* 把匹配的資料尾部追加到數組裡 */
ret = appendArrayTail(result, ar->addr+i*ar->size);
if (ret != 0)
{
destoryArray(result);
return NULL;
}
}
}
return result;
}
/*
* 函式名: deleteArrayByIndex
* 函式功能: 根據下標刪除陣列元素
* 引數: 1.陣列指標 2.下標
* 返回值: 成功刪除返回0 失敗返回-1
*/
int deleteArrayByIndex(Array_t *ar, const int idx)
{
/* 檢查下標合法性 */
if (idx < 0 || idx >= ar->n)
{
fprintf(stderr, "Error! index is illegal!\n");
return -1;
}
/* 通過資料搬運達到刪除目的 */
void *temp;
temp = malloc((ar->n-1)*ar->size);
if (temp == NULL)
{
return -1;
}
/* 把idx之前的資料移到新空間 */
memmove(temp, ar->addr, idx*ar->size);
/* 把idx之後的資料移到新空間 */
memmove(temp+idx*ar->size, ar->addr+(idx+1)*ar->size, \
(ar->n-idx-1)*ar->size);
/* 釋放原來資料空間 */
free(ar->addr);
/* 更新元素個數 */
ar->n -= 1;
/* 更新陣列元素地址 */
ar->addr = temp;
return 0;
}
/*
* 函式名: deleteArrayOneByCond
* 函式功能: 根據條件刪除陣列元素,如果多個匹配則只刪除第一個
* 引數: 1.陣列指標 2.比較回撥函式指標 3.條件
* 返回值: 成功刪除返回0 失敗返回-1
*/
int deleteArrayOneByCond(Array_t *ar, compare_t *func, \
const void *key)
{
int i;
for (i = 0; i < ar->n; i++)
{
/* 比較函式條件匹配返回1 */
if (func(ar->addr+i*ar->size, key) == 1)
{
return deleteArrayByIndex(ar,i);
}
}
return -1;
}
/*
* 函式名: deleteArrayByCond
* 函式功能: 根據條件刪除所有匹配的陣列元素
* 引數: 1.陣列指標 2.比較回撥函式指標 3.條件
* 返回值: 返回成功刪除的元素個數
*/
int deleteArrayByCond(Array_t *ar, compare_t *func, \
const void *key)
{
int i;
int count = 0;
for (i = 0; i < ar->n; i++)
{
/* 比較函式條件匹配返回1 */
if (func(ar->addr+i*ar->size, key) == 1)
{
if (deleteArrayByIndex(ar,i) == 0)
{
count++;
i--; /* 彌補按下標刪除元素後的下標變化 */
}
}
}
return count;
}
/*
* 函式名: sortArray
* 函式功能: 對陣列元素進行排序
* <至於按什麼順序排列則由使用者的回撥函式具體來實現>
* 引數: 1.陣列指標 2.比較回撥函式指標
* 返回值: 排序成功返回0 失敗返回-1
*/
int sortArray(Array_t *ar, compare_t *func)
{
int i, j;
void *temp;
temp = malloc(ar->size);
if (temp == NULL) return -1;
for (i = 0; i < ar->n; i++)
{
for (j = 1; j < ar->n-i; j++)
{
/* 比較函式條件匹配返回1 */
if (func(ar->addr+i*ar->size, \
ar->addr+j*ar->size) == 1)
{
memmove(temp, ar->addr+i*ar->size, ar->size);
memmove(ar->addr+i*ar->size, \
ar->addr+j*ar->size, ar->size);
memmove(ar->addr+j*ar->size, temp, ar->size);
}
}
}
free(temp);
return 0;
}
/*
* 函式名: saveArrayToFile
* 函式功能: 把陣列元素資料儲存到檔案中
* 引數: 1.陣列指標 2.需要儲存的檔案
* 返回值: 儲存成功返回0 失敗返回-1
*/
int saveArrayToFile(Array_t *ar, const char *file)
{
FILE *fout;
int ret;
/* 開啟檔案流 */
fout = fopen(file, "w");
if (fout == NULL)
{
perror(file);
return -1;
}
/* 寫入陣列元素個數 */
ret = fwrite(&ar->n, sizeof(ar->n), 1, fout);
if (ret != 1)
{
/* 寫入失敗:關閉檔案流,關閉檔案 */
fclose(fout);
remove(file);
return -1;
}
/* 寫入陣列元素空間大小 */
ret = fwrite<