摘要:參數(shù)指向的字符串必須要以結(jié)束。需要注意的是源字符串必須以結(jié)束。會將源字符串中的拷貝到目標空間。目標空間必須足夠大,以確保能存放源字符串。舉例最終字符串函數(shù)的模擬實現(xiàn)定義兩個數(shù)組,首先遍歷到,然后和函數(shù)相似開始拷貝即可。
前言:
C語言中對字符和字符串的處理很是頻繁,但是C語言本身是沒有字符串類型的,
字符串
通常放在常量字符串
中或者字符數(shù)組
中。
字符串常量
適用于那些對它不做修改的字符串函數(shù).
size_t strlen ( const char * str );
這里我們可以看到strlen函數(shù)的返回值是size_t
?:1.字符串已經(jīng) ‘/0’ 作為結(jié)束標志,strlen函數(shù)返回的是在字符串中 ‘/0’ 前面出現(xiàn)的字符個數(shù)(不包
含 ‘/0’ )。
?:2.參數(shù)指向的字符串必須要以 ‘/0’ 結(jié)束。
?:3.注意函數(shù)的返回值為size_t,是無符號的( 易錯 )
例子:?
#include #include int main(){ if (strlen("abc") - strlen("abcdef") > 0) { printf("hehe/n"); } else { printf("haha/n"); } return 0;}
這里輸出的結(jié)果是hehe,因為返回的是無符號整數(shù),這兩哥字符串無論怎么減都是正數(shù)。
這里直接計算個數(shù)即可,較為簡單,不做贅述。
#include #include size_t my_strlen(const char* str){ int count = 0; assert(str != NULL); while (*str) { count++; str++; } return count;}int main(){ char arr[] = "pwh"; int len = my_strlen(arr); printf("%d", len); return 0;}
?:strcpy把含有’/0’結(jié)束符的字符串復(fù)制到另一個地址空間,返回值的類型為char*。
char* strcpy(char * destination, const char * source );
需要注意的是:?
1.源字符串必須以 ‘/0’ 結(jié)束。
2.會將源字符串中的 ‘/0’ 拷貝到目標空間。
3.目標空間必須足夠大,以確保能存放源字符串。
4.目標空間必須可變。
為什么返回值為char*
返回strDest的原始值使函數(shù)能夠支持鏈式表達式,增加了函數(shù)的“附加值”。同樣功能的函數(shù),如果能合理地提高的可用性,也就就更加理想。
int iLength=strlen(strcpy(strA,strB));char * strA=strcpy(new char[10],strB);
舉例:?
char a[10],b[]={"PWH"};//定義字符數(shù)組a,bstrcpy(a,b);//將數(shù)組b中的PWH復(fù)制到數(shù)組a中
該代碼與strlen函數(shù)類似,只需要注意代碼的嚴謹,源地址的不可變性,拷貝至’/0’,數(shù)組空間夠大即可。且一定要是字符數(shù)組!
#include #include char* my_strcpy(char* dest, const char* src){ assert(dest != NULL); assert(src != NULL); char* ret = dest; while (*dest++ = *src++) { ; } return ret;}int main(){ char arr1[] = "abcdefghi"; char arr2[] = "bit"; my_strcpy(arr1, arr2); printf("%s", arr1); return 0;}
int strcmp(const char *s1,const char *s2);
?:1.第一個字符串大于第二個字符串,則返回大于0的數(shù)字
?:2.第一個字符串等于第二個字符串,則返回0
?:3.第一個字符串小于第二個字符串,則返回小于0的數(shù)字
?:注意:
比較的是字符串的ASCII碼值!
從第一個字符開始比較,第一個相等就從第二個字符比較,第一個大于返回正數(shù),小于返回負數(shù);然后從第二個開始比較。
#include #include int main(){ char* p1 = "abcdef";//6 char* p2 = "aqwer";//5 //if("abcdef"=="sqwer")//比較的是地址,所以肯定不相等 int ret = strcmp(p1, p2);//strcmp比較的是每個字符的ASCII碼值 //從第一個開始比較,第一個相等就從第二個字符比較,第一個大于返回1,小于返回-1;然后從第二個 printf("%d/n", ret); return 0;}
strcmp函數(shù)的實現(xiàn)思路為定義兩個數(shù)組,且都為不可變,使用while循環(huán)
從第一個字符開始比較,如果相等則返回0,如果不相等則繼續(xù)比較下個字符,字符地址+1,如果大于,返回正數(shù),小于返回負數(shù)。
#include #include int my_strcmp(const char* str1, const char* str2){ assert(str1 && str2); //比較 while (*str1 == *str2) { if (*str1 == "/0") { return 0;//相等 } str1++; str2++; } if (*str1 > *str2) { return 1;//大于 } else { return -1;//小于 }}int main(){ char* p1 = "abcdef"; char* p2 = "abqwe"; int ret = my_strcmp(p1, p2); printf("ret=%d/n", ret); return 0;}
char *strcat(char *dest, const char *src);
?:把src所指向的字符串(包括“/0”)復(fù)制到dest所指向的字符串后面(刪除dest原來末尾的“/0”)。要保證dest足夠長,以容納被復(fù)制進來的*src。*src中原有的字符不變。返回指向dest的指針。
舉例:?
#include #include int main (){ char src[50]="source"; char dest[50]="destination"; strcat(dest, src); printf("最終字符串:%s", dest); return 0;}
?:定義兩個數(shù)組,首先遍歷到’/0’,然后和strcpy函數(shù)相似開始拷貝即可。
#include #include char* my_strcat(char *dest, const char *src){ assert(dest && src); char *tmp = dest; while (*tmp != "/0") { tmp++; } while ((*tmp++ = *src++) != "/0"); return dest;}int main(){ char arr1[10] = "pwh"; char arr2[] = "hxs"; char* arr3 = my_strcat(arr1, arr2); printf("str1=%s/n", arr1); printf("str2=%s/n", arr2); printf("str3=%s/n", arr3); return 0;}
?:返回字符串中首次出現(xiàn)子串的地址
舉例:
int main(){ char* p1 = "abcdefghi"; char* p2 = "defq"; char* ret = strstr(p1, p2);//查找第一次出現(xiàn)的位置 if (ret == NULL) { printf("子串不存在/n"); } else { printf("%s/n", ret); } return 0;}
思路:
盡量不要讓p1,p2走,這樣無法記住它的位置
當相等時,cur作為一個大前提,先在cur的位置使用s1 s2進行查找,如果沒找到,cur++,從下一個字符查找。
這里定義了cur s1 s2,這樣可以互不干擾,然后s1重新等于cur,從此位置++。
char* my_strstr(const char* p1, const char* p2){ assert(p1 != NULL); assert(p2 != NULL); //這樣寫可以互不干擾,適用于比較復(fù)雜的場景 char* s1 = p1; char* s2 = p2; char* cur =(char*) p1; if (*p2 == "/0") { return p1; } while (*cur) { s1 = cur; s2 = (char*)p2; while (*s1 && *s2 && (*s1 == *s2)) { s1++; s2++; } if (*s2 == "/0") { return cur; } cur++; } return NULL;}int main(){ char* p1 = "abbbcdef"; char* p2 = "bbc"; char* ret = my_strstr(p1, p2);//查找第一次出現(xiàn)的位置 if (ret == NULL) { printf("子串不存在/n"); } else { printf("%s/n", ret); } return 0;}
char * strncpy ( char * destination, const char * source, size_t num );
?:拷貝num個字符從源字符串到目標空間。
?:如果源字符串的長度小于num,則拷貝完源字符串之后,在目標的后邊追加0,直到num個。
?:strncpy越界之后,拷貝完畢會把數(shù)組后面的內(nèi)容全部變?yōu)?。
只需要在strcpy基礎(chǔ)上加一個n的限制條件即可。
#include #include char*my_strncpy(char*dest, const char*src, size_t n){ assert(dest != NULL); assert(src != NULL); char*ret = dest; while (n) { *dest = *src; src++; dest++; n--; } return ret;} int main(){ char arr1[20] = "hxs"; char arr2[20]= "pwh"; int n = 0; printf("請輸入需要拷貝的字符個數(shù):/n"); scanf("%d", &n); char*ret = my_strncpy(arr1,arr2,n); printf("%s/n", ret); return 0;}
?:strncat越界之后,追加完畢后依舊會自動添加’/0’,但和strncpy區(qū)別在于,不會把數(shù)組后面的元素變?yōu)?
先遍歷到目標字符串/0處,加一個n的限制條件即可。
#include #include char* my_strncat(const char* dest, const char* src,unsigned n){ assert(dest && src); char* tmp = dest; while (*tmp != "/0") { tmp++; } while (n) { *tmp = *src; tmp++; src++; n--; }; return dest;}int main(){ char arr1[10] = "pwh"; char arr2[10] = "hxs"; int n = 0; printf("請輸入你要拷貝的字符個數(shù)"); scanf("%d", &n); my_strcat(arr1, arr2,n); printf("arr1=%s/n", arr1); return 0;}
?:比較的字符數(shù)可控。
沒什么好說的,就是很簡單!這里用for循環(huán)更加方便一些。
#include #include int my_strncmp(const char* str1, const char* str2,unsigned n){ assert(str1 && str2); //比較 unsigned i = 0; for (i = 0; i < n - 1 && *str1 && *str2; i++) { if (*str1 != *str2) { break; } str1++; str2++; } return (*str1 - *str2);}int main(){ char* p1 = "abcdef"; char* p2 = "abqwe"; int n = 0; printf("請輸入要檢驗的字符數(shù)"); scanf("%d", &n); int ret = my_strcmp(p1, p2,n); printf("ret=%d/n", ret); return 0;}
內(nèi)存函數(shù)可以對任意類型的值操作,而字符串函數(shù)只能對字符串操作!
void * memcpy ( void * destination, const void * source, size_t num );
?:1.函數(shù)memcpy從source的位置開始向后復(fù)制num個字節(jié)的數(shù)據(jù)到destination的內(nèi)存位置。
?:2.這個函數(shù)在遇到 ‘/0’ 的時候并不會停下來。
?:3.如果source和destination有任何的重疊,復(fù)制的結(jié)果都是未定義的。
將所傳入的指針強制類型轉(zhuǎn)換為char*類型,這樣可以對于各種類型的數(shù)據(jù)進行操作,其余過程和strncpy函數(shù)比較相似。
struct S{ char name[20]; int age;};void my_memcpy(void* dest, const void* src, size_t num)//void類型不可解引用也不能算術(shù)運算{ assert(dest); assert(src); void* ret = dest; while (num--) { *(char*)dest = *(char*)src; ++(char*)dest; ++(char*)src; } return dest;}int main(){ struct S arr3[] = { {"張三",20},{"李四",30} }; struct S arr4[3] = { 0 }; my_memcpy(arr4, arr3, sizeof(arr3)); //char *dest, const char*src //memcpy(arr2, arr1, sizeof(arr1)); printf("%d", arr4->age); return 0
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/120810.html
摘要:性能,大量運用在哈希的處理中,由于的不可變性,可以只計算一次哈希值,然后緩存在內(nèi)部,后續(xù)直接取就好了。這是目前的一個底層字節(jié)碼的實現(xiàn),那么是不是沒有使用或者的必要了呢。 凱倫說,公眾號ID: KailunTalk,努力寫出最優(yōu)質(zhì)的技術(shù)文章,歡迎關(guān)注探討。 1. 前言 最近看到幾個有趣的關(guān)于Java核心類String的問題。 String類是如何實現(xiàn)其不可變的特性的,設(shè)計成不可變的好處...
摘要:編寫工作首先介紹了一個稱為的內(nèi)部組件表示,并解釋了變更檢測過程在視圖上運行。本文主要由兩部分組成第一部分探討錯誤產(chǎn)生的原因,第二部分提出可能的修正。它對我意義重大,它能幫助其他人看到這篇文章。 在過去的8個月里,我大部分空閑時間都是reverse-engineering Angular。我最感興趣的話題是變化檢測。我認為它是框架中最重要的部分,因為它負責像DOM更新、輸入綁定和查詢列表...
摘要:本文僅用于學習和交流目的,不得用于商業(yè)目的。今年,我們依然會組織。隨著語言的發(fā)展,這種情況將不再適用。本系列主要討論如何獲得這些高度模塊化的應(yīng)用程序。這一系列內(nèi)的后續(xù)圖書會討論測試及部署等內(nèi)容。更多精彩,加入圖靈訪談微信 本文僅用于學習和交流目的,不得用于商業(yè)目的。非商業(yè)轉(zhuǎn)載請注明作譯者、出處,并保留本文的原始鏈接:http://www.ituring.com.cn/art... 訪談...
閱讀 3143·2021-11-23 10:02
閱讀 3118·2021-11-16 11:53
閱讀 3093·2021-09-23 11:21
閱讀 3369·2019-08-30 13:02
閱讀 1622·2019-08-29 16:18
閱讀 1557·2019-08-29 12:55
閱讀 1457·2019-08-26 12:24
閱讀 2085·2019-08-26 10:36