摘要:自己實(shí)現(xiàn)時(shí)返回值可根據(jù)實(shí)際情況而定源字符串必須以結(jié)束。語(yǔ)言中給了一些長(zhǎng)度受限的字符串函數(shù),而前面的函數(shù)是長(zhǎng)度不受限的字符串函數(shù)??截悅€(gè)字符從源字符串到目標(biāo)空間。
目錄
本章重點(diǎn)
?前言
C 語(yǔ)言中對(duì)字符和字符串的處理很是頻繁,但是 C 語(yǔ)言本身是沒有字符串類型的,字符串通常放在 常量字符串 中 或者 字符數(shù)組 中。 字符串常量 適用于那些對(duì)它不做修改的字符串?dāng)?shù)。
size_t strlen ( const char * str );
?注:size_t 即無符號(hào)整型(unsigned int)
strlen使用:
#include#includeint main(){ char arr1[] = "abcdef"; char arr2[] = { "a","b","c","d","e","f","/0"};//計(jì)算字符數(shù)組長(zhǎng)度時(shí)末尾必須加"/0", //否則計(jì)算出的長(zhǎng)度為隨機(jī)值. printf("%d/n", strlen(arr1)); printf("%d/n", strlen(arr2)); return 0;}
?strlen模擬實(shí)現(xiàn):
//方法一:使用計(jì)數(shù)器size_t my_strlen(char* str){ assert(str);//檢查指針有效性 int count = 0;//計(jì)數(shù)器 //while (*str != "/0") //{ //count++; //str++; //} //簡(jiǎn)化 while(*str++) { count++; } return count;}//方法二:遞歸size_t my_strlen2(char* str){ assert(str); if (!*str) { return 0; } else { return 1 + my_strlen(str + 1); }}//方法三:指針減指針size_t my_strlen3(char* str){ assert(str); char* cur = str; while (*cur) { cur++; } return cur - str;//兩指針相減,結(jié)果為他們之間的元素個(gè)數(shù)}
注:下面的代碼結(jié)果如何?
#include #include int main(){ const char*str1 = "abcdef"; const char*str2 = "bbb"; if(strlen(str2)-strlen(str1)>0)//由于strlen函數(shù)的返回值為無符號(hào)整型, //所以在計(jì)算時(shí),會(huì)恒為正數(shù)。自己實(shí)現(xiàn)時(shí)返回值可根據(jù)實(shí)際情況而定 { printf("str2>str1/n"); } else { printf("srt1>str2/n"); } return 0;}
char* strcpy(char * destination, const char * source );
?strcpy使用:
#include#includeint main(){ char arr1[10] = "xxxxxxxxx"; char arr2[] = "abcdef"; printf("%s/n", strcpy(arr1, arr2));//將arr2字符串中的內(nèi)容拷貝到arr1中(包括"/0) return 0; //需保證arr1的空間大于等于arr2的空間}
strcpy模擬實(shí)現(xiàn):
#include//用assert函數(shù)需包含此頭文件char* my_strcpy(char* dest, const char* src)//返回值為目標(biāo)空間的起始地址,src中的字符串 //不需要改變,為避免被修改所以再它前面加上const{ assert(dest && src);//檢查指針的有效性 char* ret = dest;//保存目標(biāo)空間的起始地址,dest后面會(huì)移動(dòng) //while (*src!="/0") //{ // *dest = *src; // dest++; // src++; //} //簡(jiǎn)化 while (*dest++ = *src++)//src先將值賦給dest,然后dest和src才++ { ; } return ret;}
char * strcat ( char * destination, const char * source );
?strcat使用:
#include#includeint main(){ char arr1[10] = "abcd"; char arr2[] = "efgh"; printf("%s", strcat(arr1, arr2));//將arr2中的字符串追加到arr1中的字符串后面 return 0; //需保證arr1的空間容納連接后的字符串}
strcat模擬實(shí)現(xiàn):
#includechar* my_strcat(char* dest, const char* src){ assert(dest && src); char* ret = dest; while (*dest)//因?yàn)槭菍rc中的字符串追加到dest的后面所以需先找到dest中"/0"的位置 { dest++; } while (*dest++ = *src++)//同strcpy { ; } return ret;}
其中大概步驟如圖:?
?
int strcmp ( const char * str1, const char * str2 );
strcmp使用 :
#include#includeint main(){ char arr1[] = "abcdef"; char arr2[] = "abcdxx"; int ret = strcmp(arr1, arr2); if (ret > 0) { printf("arr1 > arr2/n"); } else if (ret < 0) { printf("arr1 < arr2/n"); } else { printf("arr1 = arr2/n"); } return 0;}
strcmp模擬實(shí)現(xiàn)
#includeint my_strcmp(const char* str1, const char* str2)//str1和str2都不需要被改變{ assert(str1 && str2); while (*str1 == *str2)//如果找到不相等的字符直接返回他們的ascll碼值之差, //而不是將所有的字符全部比較完之后再返回. { if (*str1 == "/0") { return 0; } str1++; str2++; } return *str1 - *str2;}
前面學(xué)習(xí)了這些字符串函數(shù)之后,大家是否有些許收獲呢?
其實(shí)這些函數(shù)中有些是不安全的,比如:strcpy中如果目標(biāo)空間的大小不能夠容納原空間的字符串,就會(huì)造成數(shù)組越界訪問,strcat中也是同樣的道理。還有如果字符串自己給自己追加,是不能使用strcat函數(shù)的;如果我們只想比較字符串中的部分字符串的大小,而不是全部,也不能使用strcmp。C語(yǔ)言中給了一些長(zhǎng)度受限的字符串函數(shù),而前面的函數(shù)是長(zhǎng)度不受限的字符串函數(shù)。
char * strncpy ( char * destination, const char * source, size_t num );
?strncpy使用:
#include#includeint main(){ char arr1[] = "xxxxxxxxxx"; char arr2[] = "xx"; char arr3[] = "abcdef"; printf("%s/n", strncpy(arr1, arr3, 8));//拷貝了8個(gè)字符,所以字符串中的"/0"也會(huì)被拷貝 printf("%s/n", strncpy(arr2, arr3, 1));//拷貝了1個(gè)字符,"/0"不會(huì)被拷貝 return 0;}
strncpy模擬實(shí)現(xiàn):
#includechar* my_strncpy(char* dest, const char* src, int count)//參數(shù)count為需要拷貝的字節(jié)數(shù){ assert(dest && src); char* ret = dest; while(count--) { *dest++ = *src++; } return ret;}
char * strncat ( char * destination, const char * source, size_t num );
?strncat使用:
/* strncat example */#include #include int main (){ char str1[20]; char str2[20]; strcpy (str1,"To be "); strcpy (str2,"or not to be"); strncat (str1, str2, 6); puts (str1); return 0;}
?strncat模擬實(shí)現(xiàn):
char* my_strncat(char* dest, const char* src, int count){ assert(dest && src); char* ret = dest; while (*dest)//找到目標(biāo)字符串中"/0"的位置 { dest++; } while (count--) { *dest++ = *src++;//從"/0"處開始追加 } *dest = "/0";//末尾需"/0" return ret;}
int strncmp ( const char * str1, const char * str2, size_t num );
strncmp使用:?
/* strncmp example */#include #include int main (){ char str[][5] = { "R2D2" , "C3PO" , "R2A6" }; int n; puts ("Looking for R2 astromech droids..."); for (n=0 ; n<3 ; n++) if (strncmp (str[n],"R2xx",2) == 0)//比較兩個(gè)字符串的前兩個(gè)字符 { printf ("found %s/n",str[n]); } return 0;}
strncmp模擬實(shí)現(xiàn):
int my_strncmp(char* str1, char* str2, int count){ assert(str1 && str2); while (*str1 == *str2) { if (count <= 0) { return 0; } str1++; str2++; } return *str1 - *str2;}
char * strstr ( const char *str1, const char *str2 );?
strstr使用:
/* strstr example */#include #include int main (){ char str[] ="This is a simple string"; char * pch; pch = strstr (str,"simple"); strncpy (pch,"sample",6); puts (str); return 0;}
strstr模擬實(shí)現(xiàn):
char* my_strstr(const char* str1, const char* str2){ assert(str1 && str2); while (*str1) { char* cur1 = str1; char* cur2 = str2; while (*cur1 == *cur2) { cur1++; cur2++; if (*cur2 == "/0") { return str1; } } str1++; } return NULL;}
?
?此情況下可直接判斷str2是否是str1的子串,并且返回相應(yīng)的值。
?
當(dāng)比較到第三個(gè)字符時(shí),兩字符不相等,而str1并未結(jié)束,后續(xù)還需比較,所以cur2需回到起始地址,而cur1會(huì)回到第一個(gè)相等字符的下一個(gè)字符的地址處(即第二個(gè)b的地址)?。
?
char * strtok ( char * str, const char * sep );
strtok使用:
/* strtok example */#include #include int main (){ char str[] ="- This, a sample string."; char * pch; printf ("Splitting string /"%s/" into tokens:/n",str); pch = strtok (str," ,.-"); while (pch != NULL) { printf ("%s/n",pch); pch = strtok (NULL, " ,.-"); } return 0;}
char * strerror ( int errnum );
返回錯(cuò)誤碼,所對(duì)應(yīng)的錯(cuò)誤信息。
/* strerror example : error list */#include #include #include //必須包含的頭文件int main (){ FILE * pFile; pFile = fopen ("unexist.ent","r"); if (pFile == NULL) printf ("Error opening file unexist.ent: %s/n",strerror(errno)); //出現(xiàn)錯(cuò)誤時(shí),會(huì)將錯(cuò)誤碼(一種錯(cuò)誤對(duì)應(yīng)一個(gè)錯(cuò)誤碼)放進(jìn)errno中,strerror會(huì)將這個(gè)錯(cuò)誤碼對(duì)應(yīng)的內(nèi)容打印出來 //errno: Last error number return 0;}
例如:?
#include#include#includeint main(){ printf("%s/n", strerror(0)); printf("%s/n", strerror(1)); printf("%s/n", strerror(2)); printf("%s/n", strerror(3)); return 0;}
對(duì)應(yīng)錯(cuò)誤碼結(jié)果為:
void * memcpy ( void * destination, const void * source, size_t num );
memcpy使用:
#include#includeint main(){ int arr1[] = { 1,2,3,4,5,6,7,8,9 }; int arr2[10] = { 0 }; int* ret = memcpy(arr2, arr1, 16); int i = 0; for (i = 0; i < 10; i++) { printf("%d ", ret[i]); } return 0;}
memcpy模擬實(shí)現(xiàn):
#includevoid* my_memcpy(void* dest, const void* src, size_t count)//以字節(jié)為單位拷貝{ assert(dest && src); void* ret = dest; while (count--) { *(char*)dest = *(char*)src; dest = (char*)dest + 1; src = (char*)src + 1; } return ret;}
void * memmove ( void * destination, const void * source, size_t num );
memmove使用:
/* memmove example */#include #include int main (){ char str[] = "memmove can be very useful......"; memmove (str+20,str+15,11); puts (str); return 0;}
memmove模擬實(shí)現(xiàn):
情況一:不存在內(nèi)存重疊,可直接將內(nèi)容移動(dòng)。?
情況二:存在內(nèi)存重疊,且目標(biāo)空間地址大于源空間地址,?如圖將1移動(dòng)到3的位置之后,3就會(huì)被覆蓋,在移動(dòng)3時(shí)實(shí)際移動(dòng)的是1.
?解決方法:從后往前移動(dòng),先移動(dòng)4,再移動(dòng)3直到所有字節(jié)移動(dòng)完。
?
情況三:存在內(nèi)存重疊,且目標(biāo)空間地址小于源空間地址,如果再?gòu)暮笙蚯耙苿?dòng)也會(huì)導(dǎo)致前面的內(nèi)容被覆蓋。
解決方法:從前往后移動(dòng),先移動(dòng)3,再移動(dòng)4直到所有字節(jié)移動(dòng)完。
?實(shí)現(xiàn)代碼:
void* my_memmove(void* dest, const void* src, size_t count){ assert(dest && src); void* ret = dest; if (dest > src)//情況二 { void* cur1 = (char*)src + count - 1;//從后往前移動(dòng),需先找到兩個(gè)空間的末尾地址 void* cur2 = (char*)dest + count - 1;//減1是因?yàn)榧觕ount之后會(huì)直接跳到目標(biāo)空間和源空間的尾地址的下一個(gè)字節(jié)的地址 while (count--) { *(char*)cur2 = *(char*)cur1;//void*內(nèi)型指針不能直接加減或解引用操作,需強(qiáng)制類型轉(zhuǎn)換 cur2 = (char*)cur2 - 1;//指針移動(dòng) cur1 = (char*)cur1 - 1; } } else//情況1一,三 { void* cur1 = (char*)src; void* cur2 = (char*)dest; while (count--) { *(char*)cur2 = *(char*)cur1; cur2 = (char*)cur2 + 1; cur1 = (char*)cur1 + 1; } } return ret;}
int memcmp ( const void * ptr1,
? ? ? ? ? ? ? ? ? ? ? ?const void * ptr2,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ?size_t num );
?memcmp使用:
/* memcmp example */#include #include int main (){ char buffer1[] = "DWgaOtP12df0"; char buffer2[] = "DWGAOTP12DF0"; int n; n=memcmp ( buffer1, buffer2, sizeof(buffer1) ); if (n>0) printf (""%s" is greater than "%s"./n",buffer1,buffer2); else if (n<0) printf (""%s" is less than "%s"./n",buffer1,buffer2); else printf (""%s" is the same as "%s"./n",buffer1,buffer2); return 0;}
memcmp模擬實(shí)現(xiàn):
int my_memcmp(const void* str1, const void* str2, int count){ assert(str1 && str2); while (*(char*)str1 == *(char*)str2) { count--; if (count <= 0) { return 0; } str1 = (char*)str1 + 1; str2 = (char*)str2 + 1; } return (char*)str1 - (char*)str2;}
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/120819.html
摘要:在符號(hào)位中,表示正,表示負(fù)。我們知道對(duì)于整型來說,內(nèi)存中存放的是該數(shù)的補(bǔ)碼。在計(jì)算機(jī)系統(tǒng)中,數(shù)值一律用補(bǔ)碼來表示和存儲(chǔ)。表示有效數(shù)字,。規(guī)定對(duì)于位的浮點(diǎn)數(shù),最高的位是 ...
目錄 ? ?一、數(shù)據(jù)類型介紹 二、類型的意義 三、類型的基本歸類 整型家族 浮點(diǎn)數(shù)家族 構(gòu)造類型(自定義類型) 指針類型 空類型 四、整形在內(nèi)存中的存儲(chǔ) 原碼、反碼、補(bǔ)碼 大小端字節(jié)序 為什么有大端和小端? 一道經(jīng)典筆試題 ?一、數(shù)據(jù)類型介紹 數(shù)據(jù)從大的方向分為兩類: 內(nèi)置類型自定義類型內(nèi)置類型我們前面已經(jīng)學(xué)習(xí)過,如下: char? ? ? ? ? ? //字符數(shù)據(jù)類型 short? ? ? ...
摘要:的理解和區(qū)別代表有符號(hào),整數(shù)在內(nèi)存中存儲(chǔ)的二進(jìn)制位的最高位為符號(hào)位,表示負(fù)數(shù),表示正數(shù)。那接下來我們來學(xué)習(xí)數(shù)據(jù)在所開辟的內(nèi)存空間時(shí)如何存儲(chǔ)的。請(qǐng)看下面例子為什么內(nèi)存中存儲(chǔ)的是補(bǔ)碼對(duì)于整數(shù)來說數(shù)據(jù)存放內(nèi)存中其實(shí)存放的是補(bǔ)碼。 ...
摘要:目錄數(shù)據(jù)在計(jì)算機(jī)的存儲(chǔ)方式補(bǔ)碼,反碼,原碼數(shù)據(jù)在計(jì)算機(jī)的存儲(chǔ)方式補(bǔ)碼,反碼,原碼整形在內(nèi)存中的存儲(chǔ)整形在內(nèi)存中的存儲(chǔ)整形類型整形類型大端字節(jié)序和小端字節(jié)序大端字節(jié)序和小端字節(jié)序浮點(diǎn)數(shù)在內(nèi)存的儲(chǔ)存浮點(diǎn)數(shù)在內(nèi) 目錄 數(shù)據(jù)在計(jì)算機(jī)的存儲(chǔ)方式(補(bǔ)碼,反碼,原碼) 整形在內(nèi)存中的存儲(chǔ): ? ?整形...
摘要:函數(shù)的返回值為指針就按照字面意思,指針函數(shù)的定義顧名思義,指針函數(shù)即返回指針的函數(shù)。 目錄 前言指針與函數(shù)函數(shù)的返回值為指針作為函數(shù)參數(shù)的指針指針函數(shù)可以改變變量...
閱讀 1308·2021-11-04 16:09
閱讀 3509·2021-10-19 11:45
閱讀 2404·2021-10-11 10:59
閱讀 1019·2021-09-23 11:21
閱讀 2770·2021-09-22 10:54
閱讀 1146·2019-08-30 15:53
閱讀 2612·2019-08-30 15:53
閱讀 3484·2019-08-30 12:57