1. 程式人生 > >字串動態陣列的C實現方法

字串動態陣列的C實現方法

我們知道C++是支援容器的, 對於各種資料型別都能有很好的支援,但是C不一樣, C的資料型別支援真的很差,一旦換一種型別,又得重新編碼,比如從int型的動態陣列 轉到string型別的動態陣列,會發現這是件非常痛苦的事情。今天手賤,用C實現一下字串動態陣列的編寫。

主要目的是:
1. 回顧一下,C中的動態記憶體分配方法,(主要就是malloc, realloc, free的使用), 按照我們的理解C++中的 new 本質也就是 malloc + construct, 先分配一片記憶體, 然後在這片記憶體上placement new 一個物件。
2. 體會一下介面的封裝設計,指標的傳遞, 注意記憶體的分配和釋放。

編碼過程中遇到的兩個問題,記錄如下:

1.error C2275 將此型別用作表示式非法:
    主要原因, C中要求變數的宣告定義在區域的段首,若寫到中間會報錯, 而C++不存在這個問題
2. int StringInsertOneByPointer(StringArr * arr, const char * target, pStringNode pos) 
函式中由於realloc函式會對指標地址修改, 若此時沒有及時修正哨兵的值, 會存在錯誤。

下面放出原始碼:
程式碼寫的有些粗糙, 只是基本實現了功能, 還有很大的改進空間,比如搜尋的時候, 我們只是從頭到尾進行遍歷 是O(n)的演算法複雜度, 可以根據是否已經排序,設計出針對已經排序後序列的二分查詢演算法 O(logn)。
同樣的,排序那段,我們只是簡單的使用氣泡排序演算法, 複雜度為 O(n^2), 可以改用快速排序 O(nlogn), 當然這些在資料量小的時候,效果不明顯, 在大資料情況下,就可以看出差別了。

// =====================【字串的陣列】==================
// @ author         :           zhyh2010
// @ date           :           20150601
// @ version        :           1.0
// @ description    :       實現一個字串的陣列封裝,實現增加,刪除,插入,修改,排序
// =====================【字串的陣列】==================

#include <stdio.h>
#include <string.h>
#include <stdlib.h> #include <assert.h> #define SUCCESS 0 #define INPUT_ERROR -1 #define MALLOC_ERROR -2 #define NOT_FIND NULL typedef struct _StringNode { int length; char * pStr; }StringNode, *pStringNode; typedef struct _StringArr { StringNode * pHead; int length; int capacity; }StringArr, *pStringArr; // ====================== add ======================== int StringAddOne(StringArr * arr, const char * source); // ====================== delete ======================= int StringDeleteOne(StringArr * arr, const char * target); // ====================== search ======================= pStringNode StringSearchFirst(StringArr * arr, const char * target); // ====================== insert ======================= int StringInsertOneByPointer(StringArr * arr, const char * target, pStringNode pos); int StringInsertByStr(StringArr * arr, const char * target, const char * PosPointer); int StringInsertByID(StringArr * arr, const char * target, int id); // ======================= modify ======================== int StringModify(StringArr * arr, const char * target, const char * source); // ======================= sort ========================= int StringSort(StringArr * arr, int seq); // ====================== create ======================== pStringArr StringCreate(); // ===================== destroy ======================= void StringDestroy(pStringArr parr); // ==================== 測試用例 ====================== void main() { pStringArr pArr = StringCreate(); int ret = -1; pStringNode pres = NOT_FIND; // =========== insert ================ ret = StringInsertByID(pArr, "love", 10); ret = StringInsertByID(pArr, "new", 0); ret = StringInsertByStr(pArr, "hi", "love"); ret = StringInsertByStr(pArr, "ho", "new"); ret = StringInsertByStr(pArr, "hi", "zhyh201012"); ret = StringInsertByStr(pArr, "ho", "ll12"); // =========== add one =============== ret = StringAddOne(pArr, "hello world"); ret = StringAddOne(pArr, "zhyh2010"); ret = StringAddOne(pArr, "zh"); ret = StringAddOne(pArr, "hihocoder"); ret = StringAddOne(pArr, "ustc"); ret = StringAddOne(pArr, "china"); ret = StringAddOne(pArr, "jp"); // ========== search first =========== pres = StringSearchFirst(pArr, "zhyh2010"); pres = StringSearchFirst(pArr, "zhy"); // ========= deleteone =============== ret = StringDeleteOne(pArr, "hy"); ret = StringDeleteOne(pArr, "ustc"); ret = StringDeleteOne(pArr, "jp"); // ========== modify ================== ret = StringModify(pArr, "123", "asldf"); ret = StringModify(pArr, "zhyh2010", "[email protected]"); // =========== insert ================ ret = StringInsertByID(pArr, "love", 10); ret = StringInsertByStr(pArr, "ho", "china"); ret = StringInsertByStr(pArr, "hi12", "china"); ret = StringInsertByStr(pArr, "ho2", "china"); ret = StringInsertByStr(pArr, "h3i", "china"); ret = StringInsertByStr(pArr, "h2o", "china"); // =========== sort ======================= ret = StringSort(pArr, 0); // ========== destroy ================= StringDestroy(pArr); } // ====================== add ======================== int StringAddOne(StringArr * arr, const char * source) { if (arr == NULL || source == NULL) return INPUT_ERROR; // alloc memory if (arr->capacity <= arr->length) { if (arr->pHead == NULL) { // alloc space when phead == NULL pStringNode pNode = (pStringNode)malloc(sizeof(StringNode)); if (pNode == NULL) return MALLOC_ERROR; arr->pHead = pNode; arr->capacity += 1; } else { // realloc space pStringNode pNode = (pStringNode)realloc(arr->pHead, sizeof(StringNode)* 2 * arr->capacity); if (pNode == NULL) return MALLOC_ERROR; arr->pHead = pNode; arr->capacity = 2 * arr->capacity; } } int source_len = strlen(source); char * tmp = (char *)malloc(sizeof(char)* (source_len + 1)); if (tmp == NULL) return MALLOC_ERROR; //pStringNode pNode = arr->pHead + arr->length; // c2275 C不允許在中途宣告變數 //StringNode * pNode = &(arr->pHead)[arr->length]; arr->pHead[arr->length].length = source_len + 1; arr->pHead[arr->length].pStr = tmp; strcpy(arr->pHead[arr->length].pStr, source); arr->length += 1; return SUCCESS; } // ====================== delete ======================= int StringDeleteOne(StringArr * arr, const char * target) { pStringNode pres = (pStringNode)NOT_FIND; if (arr == NULL || target == NULL) return INPUT_ERROR; pres = StringSearchFirst(arr, target); if (pres == (pStringNode)NOT_FIND) return (int)NOT_FIND; free(pres->pStr); for (; pres != arr->pHead + arr->length - 1; pres++) *pres = *(pres + 1); pres->length = 0; pres->pStr = NULL; arr->length -= 1; return SUCCESS; } // ====================== search ======================= pStringNode StringSearchFirst(StringArr * arr, const char * target) { pStringNode pres = (pStringNode)NOT_FIND; if (arr == NULL || target == NULL) return (pStringNode)INPUT_ERROR; //pStringNode pres = NOT_FIND; for (int i = 0; i != arr->length; i++) { if (strcmp(target, arr->pHead[i].pStr) == 0) { pres = &arr->pHead[i]; break; } } return pres; } // ====================== insert ======================= int StringInsertOneByPointer(StringArr * arr, const char * target, pStringNode pos) { char * tmp = NULL; pStringNode pOld = NOT_FIND; if (arr == NULL || target == NULL || pos == NULL) return INPUT_ERROR; //assert(arr->capacity == 0); assert(arr->capacity > 0); if (arr->capacity <= arr->length) { pOld = arr->pHead; arr->pHead = (pStringNode)realloc(arr->pHead, sizeof(StringNode)* 2 * arr->capacity); arr->capacity = 2 * arr->capacity; // 修正邊界 pos += arr->pHead - pOld; } // 在指標指向的位置處插入 (前叉) tmp = (char *)malloc(sizeof(char)* (strlen(target) + 1)); if (tmp == NULL) return MALLOC_ERROR; for (pStringNode pres = arr->pHead + arr->length - 1; pres != pos - 1; pres--) *(pres + 1) = *pres; pos->pStr = tmp; strcpy(pos->pStr, target); pos->length = strlen(target) + 1; arr->length += 1; return SUCCESS; } int StringInsertByStr(StringArr * arr, const char * target, const char * PosPointer) { pStringNode pres = NOT_FIND; if (arr == NULL || target == NULL || PosPointer == NULL) return INPUT_ERROR; pres = StringSearchFirst(arr, PosPointer); return StringInsertOneByPointer(arr, target, pres); } // id 從 0 開始計算 int StringInsertByID(StringArr * arr, const char * target, int id) { pStringNode pres = NOT_FIND; if (arr == NULL || target == NULL) return INPUT_ERROR; if (id < 0) id = 0; if (id > arr->length) id = arr->length; if (arr->length == 0) return StringAddOne(arr, target); pres = arr->pHead + id; return StringInsertOneByPointer(arr, target, pres); } // ======================= modify ======================== int StringModify(StringArr * arr, const char * target, const char * source) { pStringNode pres = NOT_FIND; pStringNode tmp = NOT_FIND; if (arr == NULL || target == NULL || source == NULL) return INPUT_ERROR; pres = StringSearchFirst(arr, target); if (pres == NULL) return (int)NOT_FIND; tmp = (pStringNode)malloc(sizeof(char)* (strlen(source) + 1)); if (tmp == NULL) return MALLOC_ERROR; free(pres->pStr); pres->pStr = tmp; pres->length = strlen(source) + 1; strcpy(pres->pStr, source); return SUCCESS; } // ======================= sort ========================= int StringSort(StringArr * arr, int seq) { StringNode tmp; if (arr == NULL) return INPUT_ERROR; if (arr->pHead == NULL || arr->length == 1) return SUCCESS; #define MAX2MIN 1 #define MIN2MAX 0 seq = (seq > 0) ? MAX2MIN : MIN2MAX; if (seq == MIN2MAX) { // 使用冒泡法排序 for (int i = 0; i != arr->length - 1; i++) { for (int j = 0; j != arr->length - 1 - i; j++) { if (strcmp(arr->pHead[j].pStr, arr->pHead[j+1].pStr) > 0) { tmp = arr->pHead[j + 1]; arr->pHead[j + 1] = arr->pHead[j]; arr->pHead[j] = tmp; } } } } else { for (int i = 0; i != arr->length - 1; i++) { for (int j = 0; j != arr->length - 1 - i; j++) { if (strcmp(arr->pHead[j].pStr, arr->pHead[j + 1].pStr) < 0) { tmp = arr->pHead[j + 1]; arr->pHead[j + 1] = arr->pHead[j]; arr->pHead[j] = tmp; } } } } return SUCCESS; } // ====================== create ======================== pStringArr StringCreate() { pStringArr parr = (pStringArr)malloc(sizeof(StringArr)); if (parr == NULL) return parr; parr->capacity = 0; parr->length = 0; parr->pHead = NULL; return parr; } // ===================== destroy ======================= void StringDestroy(pStringArr parr) { if (parr == NULL) return; while (parr->length != 0) { if (parr->pHead[parr->length - 1].pStr != NULL) { free(parr->pHead[parr->length - 1].pStr); parr->pHead[parr->length - 1].length = 0; parr->length--; } } if (parr->pHead != NULL) free(parr->pHead); free(parr); }

相關推薦

字串動態陣列C實現方法

我們知道C++是支援容器的, 對於各種資料型別都能有很好的支援,但是C不一樣, C的資料型別支援真的很差,一旦換一種型別,又得重新編碼,比如從int型的動態陣列 轉到string型別的動態陣列,會發現這是件非常痛苦的事情。今天手賤,用C實現一下字串動態陣列的編寫

C#中事件的動態調用實現方法

ear too new std 實現 bject multicast using pad 本文實例講述了C#動態調用事件的方法。一般來說,傳統的思路是,通過Reflection.EventInfo獲得事件的信息,然後使用GetRaiseMethod方法獲得事件被觸發後調用

靜態陣列動態陣列 c形式與c++形式的字串

既然要學習陣列,那麼先來了解一下陣列是什麼,為什麼要有陣列的出現吧。 陣列:陣列是一系列具有相同型別元素的集合。 陣列的出現是為了當定義較多變數時,使操作更簡單化,直觀化。 靜態陣列與動態陣列 *靜態陣列:*在編譯階段,陣列包含的元素數以及佔用的記憶體量是不變的。 可分為:一維陣列與

C語言實現動態陣列 C語言函式指標和回撥函式

實現任意資料型別的動態陣列的初始化,插入,刪除(按值刪除;按位置刪除),銷燬功能。、 動態陣列結構體   實現動態陣列結構體的三個要素:(1)陣列首地址;(2)陣列的大小;(3)當前陣列元素的個數。 1 //動態陣列結構體 2 struct DynamicArray{ 3 void **a

一維動態陣列實現c語言)

程式設計輸入一個班的某課程的學生成績,計算其平均分,然後輸出。班級人數由鍵盤輸入。 #include <stdio.h> #include <stdlib.h> main() { int *p = NULL,i,n,s

基於私鑰加密公鑰解密的RSA算法C#實現方法

第一個 inter tro 十進制 函數 軟件 產生 ++ 原創 本文實例講述了基於私鑰加密公鑰解密的RSA算法C#實現方法,是一種應用十分廣泛的算法。分享給大家供大家參考之用。具體方法如下: 一、概述 RSA算法是第一個能同時用於加密和數字簽名的算法,也易於理解和操

動態陣列實現

#include <stdio.h> #include <malloc.h> #include <stdlib.h> /// 程 式 名: DyArray.c /// 程式功能: 動態陣列的實現 /// 功能描述: 動態陣列的建立與使用 int main()

一種使用編譯器編譯時確認字串佔用陣列大小的方法

@2018-10-19 【方法】 巧妙利用0大小陣列 char temp[0] = "This is test string!"; 編譯結果: error:  #144: a value of type "char [21]" cannot be used to initializ

資料結構筆記_動態陣列實現

public class Array<E> { private E[] data; private int size; public Array(int capacity){ data = (E[])new Object[capacity];

基於udp協議的字串計數【網路程式設計 - 基於udp協議的字串計數,C實現

udp_server.c #include <stdio.h> #include <winsock2.h> #pragma comment(lib, "ws2_32.lib") typedef struct sockaddr_in sockaddr_in ; typedef s

GPS定位,經緯度附近地點查詢–C 實現方法

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

lintcode --最大子陣列(c++實現)

class MaxSubArray { public: int maxSubArray(vector<int> &nums) { // write your code here // 判空 if (nums.s

1093 字串A+B——C++實現

題目 1093 字串A+B (20 分) 給定兩個字串 A 和 B,本題要求你輸出 A+B,即兩個字串的並集。要求先輸出 A,再輸出 B,但重複的字元必須被剔除。 輸入格式: 輸入在兩行中分別給出 A 和 B,均為長度不超過 10​6​​的、由可見 ASCII 字元

字串陣列的屬性方法

一、陣列的相關方法   1、陣列方法總覽:   concat()   連線兩個或更多的陣列,並返回結果。   join()   把陣列的所有元素放入一個字串。元素通過指定的分隔符進行分隔。   pop()   刪除並返回陣列的最後一個元素 。  push()   向陣列的末尾新增一個或更多元素,並返回新的

動態規劃C++實現--最長遞增子序列

題目: 給定陣列arr, 返回arr的最長遞增子序列。舉例:arr = [2, 1, 5, 3, 6, 4, 8, 9, 7], 返回的最長遞增子序列為 [1, 3, 4, 8, 9]要求:如果arr長度為N,請實現時間複雜度為O(NlogN)的方法。目錄: 一、 時間複雜度

Canvas三種動態畫圓實現方法說明

前言 canvas是HTML5出來的繪圖API容器,對於圖形的處理非常強大,下面使用canvas配合JavaScript來做一下動態畫圓效果。可以用它來做圓形進度條來使用。 這裡我個人總結了3種實現方法,大家可以參考一下。 方法一:arc(

經典演算法之歸併排序的C實現方法

以前寫過歸併排序的演算法,但是時間過了好久,忘記怎麼寫的了,(也是醉了)。正好複習演算法的時候遇到這個問題,就重新寫了一下,把遇到的一些問題順便記錄一下。 核心就是用兩個子陣列記錄分割後的兩個陣列中的變數, 然後依次比較大小即可。 這裡有個細節需要注意一下,

Java大用處——動態陣列實現

陣列大家平常都用,陣列雖然有優點但是最讓我不爽的就是它的定長。 有人會說,那就用連結串列啊,連結串列插入,刪除是方便,但是遍歷速度慢。 所以,我就想寫一個動態的陣列。 原理是這樣的,當你想增加陣列大小時,我們就另外開一個你想要的陣列,把以前的那個陣列放入其中即可。 具體程式

演算法設計與分析--求最大子段和問題(蠻力法、分治法、動態規劃法) C++實現

演算法設計與分析--求最大子段和問題 問題描述: 給定由n個整陣列成的序列(a1,a2, …,an),求該序列形如 的子段和的最大值,當所有整數均為負整數時,其最大子段和為0。 利用蠻力法求解: int maxSum(int a[],int n) { int ma

SDM(Supervised Descent Method)用於人臉對齊的C++實現方法

    為了除錯這個程式碼,花了我整整一天的時間,需要用到的東西太多了,所以比較費時費力,現在將實現過程總結如下: 需要的工具(建議都使用最新版的): 1、OpenCV 2.4.9或3.0版本即可,沒