真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

C語言字符串庫函數(shù)模擬實現(xiàn)-創(chuàng)新互聯(lián)

字符串檢驗 strlen 函數(shù)原型
/// @brief 返回給定空終止字符串的長度,即首元素為 str 所指,且不包含首個空字符的字符數(shù)組中的字符數(shù)
/// @param str 指向要檢測的字符串的指針
/// @return 字符串 str 的長度
size_t strlen( const char *str );

空終止字符串即 C 語言中以 ‘\0’ 作為終止符的字符串,strlen 計算字符串的長度并返回,返回的長度不包含 ‘\0’。

在淮上等地區(qū),都構(gòu)建了全面的區(qū)域性戰(zhàn)略布局,加強發(fā)展的系統(tǒng)性、市場前瞻性、產(chǎn)品創(chuàng)新能力,以專注、極致的服務(wù)理念,為客戶提供成都做網(wǎng)站、成都網(wǎng)站設(shè)計、成都外貿(mào)網(wǎng)站建設(shè) 網(wǎng)站設(shè)計制作按需求定制設(shè)計,公司網(wǎng)站建設(shè),企業(yè)網(wǎng)站建設(shè),成都品牌網(wǎng)站建設(shè),營銷型網(wǎng)站,外貿(mào)營銷網(wǎng)站建設(shè),淮上網(wǎng)站建設(shè)費用合理。
char arr[] = "qgw";
// num 的值是 3
int num = strlen(arr);
模擬實現(xiàn)

下面的實現(xiàn)方式比較簡單,采用遍歷字符串的方式,遇到 ‘\0’ 就退出循環(huán),返回結(jié)果。

size_t my_strlen(const char* str) {size_t cnt = 0;
	while (*str != '\0') {++str;
		++cnt;
	}
	return cnt;
}
strcmp 函數(shù)原型
/// @brief 以字典序比較二個字符串
/// @param str rhs 要比較的兩字符串
/// @return 相等返回 0
int strcmp(const char* lhs, const char* rhs);

返回值:

  • 兩字符串字典序相同,返回 0
  • lhs 字典序大于 rhs,返回一個正數(shù)
  • lhs 字典序小于 rhs,返回一個負數(shù)
模擬實現(xiàn)

實現(xiàn)的思路是:遍歷兩個字符串,直到出現(xiàn)不同或有字符串結(jié)束。

res 存儲兩字符串比較的結(jié)果,如果等于 0 循環(huán)繼續(xù),不等于 0 直接退出,lhs 指向的字符大于 rhs 指向的字符就為正數(shù),否則反之。

若 lhs 先結(jié)束,rhs 還沒結(jié)束,此時 res 為負數(shù),\0 的 ASCII 碼為 0,是最小的。若 rhs 先結(jié)束,lhs 還沒結(jié)束,此時 res 為正數(shù)。若同時結(jié)束,res 剛好為 0 返回。

int my_strcmp(const char* lhs, const char* rhs) {int res = 0;
	while ((res = *lhs - *rhs) == 0 && *lhs != '\0' && *rhs != '\0') {++lhs;
		++rhs;
	}
	return res;
}
strstr 函數(shù)原型
/// @brief 在 str 中查找 substr 子串
/// @param str 指向要檢驗的空終止字符串的指針
/// @param substr 指向要查找的空終止字節(jié)字符串的指針
/// @return 指向于 str 中找到的子串首字符的指針,或若找不到該子串則為空指針
char *strstr( const char* str, const char* substr );

若 substr 指向空,則會返回 str。

模擬實現(xiàn)

下面實現(xiàn)的方法為暴力匹配子串,實際中可以使用 KMP 或 BM 等字符串搜索函數(shù)優(yōu)化這一過程。

char* my_strstr(const char* str, const char* substr) {if (substr == NULL) {return str;
	}

	// 遍歷 str 所有字符,看以其起始字符是否匹配
	while (*str != '\0') {const char* backStr = str;
		const char* backSub = substr;
		while (*backStr != '\0' && *backSub != '\0' && *backStr == *backSub) {	++backStr;
			++backSub;
		}
		// 如果 substr 走完了,說明匹配成功了,返回此時的 str
		if (*backSub == '\0') {	return str;
		}
		++str;
	}
}
字符串操作 strcpy 函數(shù)原型
/// @brief 復(fù)制 src 所指向的空終止字符串,包含空終止符,到首元素為 dest 所指的字符數(shù)組
/// @param dest 指向要寫入的字符數(shù)組的指針
/// @param src 指向要復(fù)制的空終止字符串的指針
/// @return 返回 dest 的副本
char *strcpy( char *dest, const char *src );

需要注意的是:

  • 若 dest 數(shù)組長度不足則行為未定義
    • 即 dest 數(shù)組不足以包含 src 中所有元素,此時大概率會因越屆訪問崩潰
  • 若字符串覆蓋則行為未定義
    • 現(xiàn)在主流編譯器都可以處理有覆蓋的情況,比如:MSVC、GCC
  • 若 dest 不是指向字符數(shù)組的指針或 src 不是指向空終止字符串的指針則行為未定義
模擬實現(xiàn)

下面的方法先記錄要返回的地址,最后遍歷 src 遇到 \0,此時退出循環(huán)。

注意:該實現(xiàn)方法并不能解決字符串有覆蓋的情況。

char* my_strcpy(char* dest, const char* src) {char* res = dest;
	while (*dest = *src) {++dest;
		++src;
	}
	return res;
}
strcat 函數(shù)原型
/// @brief 后附 src 所指向的空終止字符串的副本到 dest 所指向的空終止字符串的結(jié)尾
/// @param dest 指向要后附到的空終止字符串的指針
/// @param src 指向作為復(fù)制來源的空終止字符串的指針
/// @return 返回 dest 的副本
char *strcat( char *dest, const char *src );

需要注意的是:

  • 會用字符 src[0] 替換 dest 末尾的 \0
  • 若目標數(shù)組對于 src 和 dest 的內(nèi)容以及空終止符不夠大,則行為未定義
  • 若字符串重疊,則行為未定義
  • 若 dest 或 src 不是指向空終止字符串的指針,則行為未定義
模擬實現(xiàn)

因為會先用 src 第一個字符替換 dest 結(jié)尾的 \0,所以要先找到 dest 結(jié)尾 \0。然后再遍歷 src,將其添加到 dest 結(jié)尾。

char* my_strcat(char* dest, const char* src) {char res = dest;
	// 先找 \0 的位置
	while (*dest != '\0') {++dest;
	}
	// 追加到 dest 后面
	while (*dest = *src) {++dest;
		++src;
	}
	return res;
}
內(nèi)存操作 memcpy 函數(shù)原型
/// @brief 從 src 所指向的對象復(fù)制 count 個字符到 dest 所指向的對象
/// @param dest 指向要復(fù)制的對象的指針
/// @param src 指向復(fù)制來源對象的指針
/// @param count 復(fù)制的字節(jié)數(shù)
/// @return 返回 dest 的副本
void* memcpy(void* dest, const void* src, size_t count);

要注意的是:

  • 若訪問發(fā)生在 dest 數(shù)組結(jié)尾后則行為未定義
  • 若對象重疊,則行為未定義
    • 也就是說在標準中 memcpy 也不能處理對象重疊的情況
  • 若 dest 或 src 為非法或空指針則行為未定義
模擬實現(xiàn)

下面給出的實現(xiàn)方式與 strcpy 相似,不過是改用 count 變量來控制循環(huán)次數(shù)。

memcpy 是最快的內(nèi)存到內(nèi)存復(fù)制子程序。它通常比必須掃描其所復(fù)制數(shù)據(jù)的 strcpy,或必須預(yù)防以處理重疊輸入的 memmove更高效。

void* my_memcpy(void* dest, const void* src, size_t count) {void* res = dest;
	while (count--) {*(char*)dest = *(char*)src;
		++(char*)dest;
		++(char*)src;
	}
	return res;
}
memmove 函數(shù)原型
/// @brief 從 src 所指向的對象復(fù)制 count 個字節(jié)到 dest 所指向的對象
/// @param dest 指向要復(fù)制的對象的指針
/// @param src 指向復(fù)制來源對象的指針
/// @param count 復(fù)制的字節(jié)數(shù)
/// @return 返回 dest 的副本
void* memmove(void* dest, const void* src, size_t count);

memmove 是不是看起來和 memcpy 一模一樣,但 memmove 可以處理內(nèi)存重疊的情況,這也就說明它要做一些檢查,來保證能夠處理內(nèi)存重疊的情況。

  1. 無重疊
    • 直接調(diào)用更高校的 memcpy
  2. 有重疊,dest 在 src 之前,正常正向復(fù)制

Forward replication

  1. 有重疊,dest 在 src 之后,需要反向復(fù)制

foreard copy

reverse copy

模擬實現(xiàn)

通過對上圖的觀察,我們可以發(fā)現(xiàn):若 dest 在 src 的后面并且存在內(nèi)存重疊,就需要反向復(fù)制。

我們可以簡化這一函數(shù),對無重疊的情況不去調(diào)用 memcpy 而是包含在下面兩種情況中。

  1. dest 在 src 之前,采用正向復(fù)制
  2. dest 在 src 之后,采用反向復(fù)制
void* my_memmove(void* dest, const void* src, size_t count) {void* res = dest;
	if (dest< src) {while (count--) {	*(char*)dest = *(char*)src;
			++(char*)dest;
			++(char*)src;
		}
	} else {while (count--) {	*((char*)dest + count) = *((char*)src + count);
		}
	}
}

你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機房具備T級流量清洗系統(tǒng)配攻擊溯源,準確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級服務(wù)器適合批量采購,新人活動首月15元起,快前往官網(wǎng)查看詳情吧


本文題目:C語言字符串庫函數(shù)模擬實現(xiàn)-創(chuàng)新互聯(lián)
文章路徑:http://weahome.cn/article/dhdepo.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部