1. 程式人生 > >C語言實現自己的動態陣列庫

C語言實現自己的動態陣列庫

動態陣列庫由兩部分構成:標頭檔案 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<