ArrayLib.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546
  1. /********************************************
  2. * 文件名:arrayLib.c
  3. * 文件描述:动态数组库函数所有功能函数的定义
  4. * 编辑人:王廷云
  5. * 编辑日期:2017-10-1
  6. * 修改日期:2018-1-10
  7. *********************************************/
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #include "arrayLib.h"
  12. /*
  13. * 函数名: initArray
  14. * 函数功能: 初始化动态数组
  15. * 参数: 数组元素的空间大小
  16. * 返回值: 成功则返回初始化后的动态数组指针
  17. * 失败返回NULL
  18. */
  19. Array_t *initArray(int size)
  20. {
  21. Array_t *ar;
  22. ar = malloc(sizeof(Array_t));
  23. if (ar == NULL) return NULL;
  24. ar->size = size;
  25. ar->n = 0;
  26. ar->addr = NULL;
  27. return ar;
  28. }
  29. /*
  30. * 函数名: appendArrayTail
  31. * 函数功能: 尾部追加数组元素
  32. * 参数: 1.需要追加的数组指针 2.需要追加的元素指针
  33. * 返回值: 成功追加返回0 失败返回-1
  34. */
  35. int appendArrayTail(Array_t *ar, const void *data)
  36. {
  37. void *temp;
  38. #if 0
  39. /* 分配比原来多一个数据的空间 */
  40. temp = realloc(ar->addr, (ar->n+1)*ar->size);
  41. if (temp == NULL)
  42. {
  43. return -1;
  44. }
  45. #else
  46. /* 分配比原来多一个数据的空间 */
  47. temp = malloc((ar->n+1) * ar->size);
  48. if (temp == NULL)
  49. {
  50. return -1;
  51. }
  52. /* 把原来数据移动到新空间 */
  53. memmove(temp, ar->addr, ar->n * ar->size);
  54. /* 释放原来数据空间 */
  55. free(ar->addr);
  56. #endif
  57. /* 把新数据复制到新空间的尾部 */
  58. memmove(temp+(ar->n*ar->size), data, ar->size);
  59. /* 数据个数加1 */
  60. ar->n += 1;
  61. /* 更新数据地址指针 */
  62. ar->addr = temp;
  63. return 0;
  64. }
  65. /*
  66. * 函数名: appendArrayTop
  67. * 函数功能: 头部追加数组元素
  68. * 参数: 1.需要追加的数组指针 2.需要追加的元素指针
  69. * 返回值: 成功追加返回0 失败返回-1
  70. */
  71. int appendArrayTop(Array_t *ar, const void *data)
  72. {
  73. void *temp;
  74. #if 0
  75. /* 分配比原来多一个数据的空间 */
  76. temp = realloc(ar->addr, (ar->n+1)*ar->size);
  77. if (temp == NULL)
  78. {
  79. return -1;
  80. }
  81. #else
  82. /* 分配比原来多一个数据的空间 */
  83. temp = malloc((ar->n+1) * ar->size);
  84. if (temp == NULL)
  85. {
  86. return -1;
  87. }
  88. /* 把原来数据移动到新空间 */
  89. memmove(temp+ar->size, ar->addr, ar->n * ar->size);
  90. /* 释放原来数据空间 */
  91. free(ar->addr);
  92. #endif
  93. /* 把新数据复制到新空间的头部 */
  94. memmove(temp, data, ar->size);
  95. /* 数据个数加1 */
  96. ar->n += 1;
  97. /* 更新数据地址指针 */
  98. ar->addr = temp;
  99. return 0;
  100. }
  101. /*
  102. * 函数名: insertArrayByIndex
  103. * 函数功能: 指定数组下标插入数组元素
  104. * <函数会检查下标的合法性>
  105. * 参数: 1.需要插入数据的数组指针 2.需要插入的数据指针
  106. * 2.数组下标值
  107. * 返回值: 成功插入返回0 失败返回-1
  108. */
  109. int insertArrayByIndex(Array_t *ar, const void *data, int idx)
  110. {
  111. /* 检查下标合法性 */
  112. if (idx < 0 || idx > ar->n)
  113. {
  114. printf("Error! index is illegal!\n");
  115. return -1;
  116. }
  117. void *temp;
  118. #if 0
  119. /* 分配比原来多一个数据的空间 */
  120. temp = realloc(ar->addr, (ar->n+1)*ar->size);
  121. if (temp == NULL)
  122. {
  123. return -1;
  124. }
  125. /* 把原来空间idx以及后面的数据移动到新空间的idx之后 */
  126. memmove(temp+(idx+1)*ar->size, temp+idx*ar->size, \
  127. (ar->n-idx)*ar->size);
  128. /* 把新数据插入到新空间的idx处 */
  129. memmove(temp+idx*ar->size, data, ar->size);
  130. #else
  131. /* 分配比原来多一个数据的空间 */
  132. temp = malloc((ar->n+1)*ar->size);
  133. if (temp == NULL)
  134. {
  135. return -1;
  136. }
  137. /* 把原来空间idx以前的数据移动到新空间前面 */
  138. memmove(temp, ar->addr, idx*ar->size);
  139. /* 把新数据插入到新空间的idx处 */
  140. memmove(temp+idx*ar->size, data, ar->size);
  141. /* 把原来空间idx以及后面的数据移动到新空间的idx之后 */
  142. memmove(temp+(idx+1)*ar->size, ar->addr+(idx*ar->size), \
  143. (ar->n-idx)*ar->size);
  144. #endif
  145. /* 数据元素个数加1 */
  146. ar->n += 1;
  147. /* 更新数据地址 */
  148. ar->addr = temp;
  149. return 0;
  150. }
  151. /*
  152. * 函数名: travelArray
  153. * 函数功能: 遍历动态数组元素
  154. * 参数: 1.需要遍历的数组指针 2.回调函数
  155. * 返回值: 无
  156. */
  157. void travelArray(Array_t *ar, void (*func)(void *data))
  158. {
  159. int i;
  160. for (i = 0; i < ar->n; i++)
  161. {
  162. /* ar->addr + i*ar->size: 每个数据的起始地址 */
  163. func(ar->addr + i*ar->size);
  164. }
  165. }
  166. /*
  167. * 函数名: searchArrayByIndex
  168. * 函数功能: 根据下标查找数组元素<会检查下标的合法性>
  169. * 参数: 1.需要查找的数组指针 2.查找的下标
  170. * 返回值: 数据存在返回数据地址 不存在则返回NULL
  171. */
  172. void *searchArrayByIndex(Array_t *ar, const int idx)
  173. {
  174. /* 下标合法性检查 */
  175. if (idx < 0 || idx >= ar->n)
  176. {
  177. fprintf(stderr,"Error! index is illegal!\n");
  178. return NULL;
  179. }
  180. return ar->addr + idx*ar->size;
  181. }
  182. /*
  183. * 函数名: searchArrayOneByCond
  184. * 函数功能: 根据条件查找元素,如果有多个则找第一个
  185. * 参数: 1.需要查找的数组指针 2.比较回调函数指针 3.条件指针
  186. * 返回值: 数据存在返回数据地址 不存在则返回NULL
  187. */
  188. void *searchArrayOneByCond(Array_t *ar, compare_t *func, \
  189. const void *key)
  190. {
  191. int i;
  192. for (i = 0; i < ar->n; i++)
  193. {
  194. /* 比较函数条件匹配func返回1 */
  195. if (func(ar->addr+i*ar->size, key) == 1)
  196. {
  197. return ar->addr + i*ar->size;
  198. }
  199. }
  200. return NULL;
  201. }
  202. /*
  203. * 函数名: searchArrayByCond
  204. * 函数功能: 根据条件查找元素
  205. * 参数: 1.需要查找的数组指针 2.比较回调函数指针 3.条件指针
  206. * 返回值: 数据存在返回数据数组 不存在则返回NULL
  207. */
  208. Array_t *searchArrayByCond(Array_t *ar, compare_t *func, \
  209. const void *key)
  210. {
  211. int i, ret;
  212. Array_t *result;
  213. /* 创建用于保存结果的数组 */
  214. result = initArray(ar->size);
  215. if (result == NULL)
  216. {
  217. return NULL;
  218. }
  219. /* 遍历查找 */
  220. for (i = 0; i < ar->n; i++)
  221. {
  222. /* 比较函数条件匹配func返回1 */
  223. if (func(ar->addr+i*ar->size, key) == 1)
  224. {
  225. /* 把匹配的数据尾部追加到数组里 */
  226. ret = appendArrayTail(result, ar->addr+i*ar->size);
  227. if (ret != 0)
  228. {
  229. destoryArray(result);
  230. return NULL;
  231. }
  232. }
  233. }
  234. return result;
  235. }
  236. /*
  237. * 函数名: deleteArrayByIndex
  238. * 函数功能: 根据下标删除数组元素
  239. * 参数: 1.数组指针 2.下标
  240. * 返回值: 成功删除返回0 失败返回-1
  241. */
  242. int deleteArrayByIndex(Array_t *ar, const int idx)
  243. {
  244. /* 检查下标合法性 */
  245. if (idx < 0 || idx >= ar->n)
  246. {
  247. fprintf(stderr, "Error! index is illegal!\n");
  248. return -1;
  249. }
  250. /* 通过数据搬运达到删除目的 */
  251. void *temp;
  252. temp = malloc((ar->n-1)*ar->size);
  253. if (temp == NULL)
  254. {
  255. return -1;
  256. }
  257. /* 把idx之前的数据移到新空间 */
  258. memmove(temp, ar->addr, idx*ar->size);
  259. /* 把idx之后的数据移到新空间 */
  260. memmove(temp+idx*ar->size, ar->addr+(idx+1)*ar->size, \
  261. (ar->n-idx-1)*ar->size);
  262. /* 释放原来数据空间 */
  263. free(ar->addr);
  264. /* 更新元素个数 */
  265. ar->n -= 1;
  266. /* 更新数组元素地址 */
  267. ar->addr = temp;
  268. return 0;
  269. }
  270. /*
  271. * 函数名: deleteArrayOneByCond
  272. * 函数功能: 根据条件删除数组元素,如果多个匹配则只删除第一个
  273. * 参数: 1.数组指针 2.比较回调函数指针 3.条件
  274. * 返回值: 成功删除返回0 失败返回-1
  275. */
  276. int deleteArrayOneByCond(Array_t *ar, compare_t *func, \
  277. const void *key)
  278. {
  279. int i;
  280. for (i = 0; i < ar->n; i++)
  281. {
  282. /* 比较函数条件匹配返回1 */
  283. if (func(ar->addr+i*ar->size, key) == 1)
  284. {
  285. return deleteArrayByIndex(ar,i);
  286. }
  287. }
  288. return -1;
  289. }
  290. /*
  291. * 函数名: deleteArrayByCond
  292. * 函数功能: 根据条件删除所有匹配的数组元素
  293. * 参数: 1.数组指针 2.比较回调函数指针 3.条件
  294. * 返回值: 返回成功删除的元素个数
  295. */
  296. int deleteArrayByCond(Array_t *ar, compare_t *func, \
  297. const void *key)
  298. {
  299. int i;
  300. int count = 0;
  301. for (i = 0; i < ar->n; i++)
  302. {
  303. /* 比较函数条件匹配返回1 */
  304. if (func(ar->addr+i*ar->size, key) == 1)
  305. {
  306. if (deleteArrayByIndex(ar,i) == 0)
  307. {
  308. count++;
  309. i--; /* 弥补按下标删除元素后的下标变化 */
  310. }
  311. }
  312. }
  313. return count;
  314. }
  315. /*
  316. * 函数名: sortArray
  317. * 函数功能: 对数组元素进行排序
  318. * <至于按什么顺序排列则由用户的回调函数具体来实现>
  319. * 参数: 1.数组指针 2.比较回调函数指针
  320. * 返回值: 排序成功返回0 失败返回-1
  321. */
  322. int sortArray(Array_t *ar, compare_t *func)
  323. {
  324. int i, j;
  325. void *temp;
  326. temp = malloc(ar->size);
  327. if (temp == NULL) return -1;
  328. for (i = 0; i < ar->n; i++)
  329. {
  330. for (j = 1; j < ar->n-i; j++)
  331. {
  332. /* 比较函数条件匹配返回1 */
  333. if (func(ar->addr+i*ar->size, \
  334. ar->addr+j*ar->size) == 1)
  335. {
  336. memmove(temp, ar->addr+i*ar->size, ar->size);
  337. memmove(ar->addr+i*ar->size, \
  338. ar->addr+j*ar->size, ar->size);
  339. memmove(ar->addr+j*ar->size, temp, ar->size);
  340. }
  341. }
  342. }
  343. free(temp);
  344. return 0;
  345. }
  346. /*
  347. * 函数名: saveArrayToFile
  348. * 函数功能: 把数组元素数据保存到文件中
  349. * 参数: 1.数组指针 2.需要保存的文件
  350. * 返回值: 保存成功返回0 失败返回-1
  351. */
  352. int saveArrayToFile(Array_t *ar, const char *file)
  353. {
  354. FILE *fout;
  355. int ret;
  356. /* 打开文件流 */
  357. fout = fopen(file, "w");
  358. if (fout == NULL)
  359. {
  360. perror(file);
  361. return -1;
  362. }
  363. /* 写入数组元素个数 */
  364. ret = fwrite(&ar->n, sizeof(ar->n), 1, fout);
  365. if (ret != 1)
  366. {
  367. /* 写入失败:关闭文件流,关闭文件 */
  368. fclose(fout);
  369. remove(file);
  370. return -1;
  371. }
  372. /* 写入数组元素空间大小 */
  373. ret = fwrite(&ar->size, sizeof(ar->size), 1, fout);
  374. if (ret != 1)
  375. {
  376. /* 写入失败:关闭文件流,关闭文件 */
  377. fclose(fout);
  378. remove(file);
  379. return -1;
  380. }
  381. /* 写入数据 */
  382. ret = 0;
  383. while (ret != ar->n) /* 保证写完 */
  384. {
  385. ret += fwrite(ar->addr+ret*ar->size, \
  386. ar->size, ar->n-ret, fout);
  387. /* 如果遇到写文件错误 */
  388. if (ferror(fout))
  389. {
  390. fclose(fout);
  391. remove(file);
  392. return -1;
  393. }
  394. }
  395. fclose(fout);
  396. return 0;
  397. }
  398. /*
  399. * 函数名: loadArrayFromFile
  400. * 函数功能: 从文件中加载数组数据
  401. * 参数: 需要加载的文件
  402. * 返回值: 成功加载返回数组指针 失败返回NULL
  403. */
  404. Array_t *loadArrayFromFile(const char *file)
  405. {
  406. int ret;
  407. FILE *fin;
  408. Array_t *ar;
  409. /* 打开文件 */
  410. fin = fopen(file, "r");
  411. if (fin == NULL)
  412. {
  413. return NULL;
  414. }
  415. /* 成功打开文件 */
  416. ar = initArray(0);
  417. if (ar == NULL)
  418. {
  419. fclose(fin);
  420. return NULL;
  421. }
  422. /* 成功初始化数组 */
  423. /* 读取数组元素个数 */
  424. ret = fread(&ar->n, sizeof(ar->n), 1, fin);
  425. if (ret != 1)
  426. {
  427. fclose(fin);
  428. destoryArray(ar);
  429. return NULL;
  430. }
  431. /* 读取数组元素空间大小 */
  432. ret = fread(&ar->size, sizeof(ar->size), 1, fin);
  433. if (ret != 1)
  434. {
  435. fclose(fin);
  436. destoryArray(ar);
  437. return NULL;
  438. }
  439. /* 读取数组元素数据 */
  440. ar->addr = malloc(ar->n * ar->size);
  441. if (ar->addr == NULL)
  442. {
  443. fclose(fin);
  444. destoryArray(ar);
  445. return NULL;
  446. }
  447. ret = 0;
  448. while (ret != ar->n) /* 保证读完 */
  449. {
  450. ret += fread(ar->addr + ret*ar->size, \
  451. ar->size, ar->n-ret, fin);
  452. if (ferror(fin))
  453. {
  454. if (ret > 0) /* 已经读取到了一部分 */
  455. {
  456. break;
  457. }
  458. else
  459. {
  460. fclose(fin);
  461. destoryArray(ar);
  462. return NULL;
  463. }
  464. }
  465. /* 有可能文件记录的个数与实际的不一样 */
  466. else if (feof(fin))
  467. {
  468. break;
  469. }
  470. }
  471. /* 文件数据丢失,没有之前存储的那么多 */
  472. if (ar->n != ret)
  473. {
  474. void *temp;
  475. ar->n = ret;
  476. temp = realloc(ar->addr, ar->n*ar->size);
  477. }
  478. fclose(fin); // 关闭打开的文件
  479. return ar;
  480. }
  481. /*
  482. * 函数名: destoryArray
  483. * 函数功能: 销毁动态数组线性表
  484. * 参数: 数组指针
  485. * 返回值: 无
  486. */
  487. void destoryArray(Array_t *ar)
  488. {
  489. /* 释放数组元素空间 */
  490. free(ar->addr);
  491. /* 释放数组本身空间 */
  492. free(ar);
  493. /* 避免再次使用释放的空间 */
  494. ar = NULL;
  495. }
  496. /*
  497. * 函数名: isEmptyArray
  498. * 函数功能: 判断是否是空数组
  499. * 参数: 数组指针
  500. * 返回值: 为空返回1 不为空返回0
  501. */
  502. int isEmptyArray(Array_t *ar)
  503. {
  504. /* 元素个数为零同时元素地址为NULL */
  505. return ar->n==0 && ar->addr==NULL;
  506. }
  507. /*
  508. * 函数名: arrayLenth
  509. * 函数功能: 求数组的长度(元素个数)
  510. * 参数: 数组指针
  511. * 返回值: 返回数组的元素个数
  512. */
  513. int arrayLenth(Array_t *ar)
  514. {
  515. return ar->n;
  516. }