那么博主寫這一片博客的目的就是為下一篇c++的string類做鋪墊,那么下面就請期待博主的下一篇文章吧。?
目錄
1.字符函數
2.字符串函數(均在string.h頭文件中)
strlen的使用和模擬實現
strcpy 的使用和模擬實現?
?strcat 的使用和模擬實現
?strcmp的使用和模擬實現
?strncpy 函數的使用
strncat 函數的使用
strncmp函數的使用
?strstr 的使用和模擬實現
strtok函數的使用
?strerror 函數的使用
3.C語言內存函數
memcpy使用和模擬實現
?memmove使用和模擬實現(可以實現自己給自己追加)
?memset函數的使用
?memcmp函數的使用
1.字符函數
? ? ? ??C語言標準庫中的字符處理函數主要是在ctype.h頭文件中定義的。先來看字符函數的速查表。
感覺很生澀?沒關系,咱們來看幾個例子:
寫 ?個代碼,將字符串中的?寫字?轉?寫,其他字符不變。
int main ()
{
int i = 0;
char str[] = "Test String.\n";
char c;
while (str[i])
{
????????c = str[i];
????????if (islower(c))
????????c -= 32;//小寫字母與大寫字母之間的ASCII值相差32。
????????putchar(c);
???????? i++;
}
????????return 0;
}
那么字符函數咱們就不過多的闡述了。下面看字符串函數。
2.字符串函數(均在string.h頭文件中)
strlen的使用和模擬實現
size_t? strlen (const char*str)?
? ? ? ?1.??字符串以 ?'\0' 作為結束標志,strlen函數返回的是在字符串中 '\0' 前面出現的字符個數(不包含'\0')
? ? ? ?2. 參數指向的字符串必須要以 '\0' 結束。
? ? ? ?3. 注意函數的返回值為size_t,是無符號的
? ? ? ? ?4.strlen的使用需要包含頭文件
那么下面咱們來看strlen的模擬實現,下面我提供了三種實現方式:
int my_strlen(const char * str)
{
????????int count = 0;
????????assert(str);
????????while(*str)
{
????????count++;
????????str++;
}
????????return count;
}//這個得引入一個新變量
int my_strlen(const char * str)
{
????????assert(str);
????????if(*str == '\0')
????????return 0;
????????else
????????return 1+my_strlen(str+1);?
}//采用遞歸的方式
int my_strlen(char *s)
{
????????assert(str);
????????char *p = s;
????????while(*p != '\0' )
{
????????p++;
}
????????return p-s;?
}//采用指針減指針的方式,這個方法在C語言指針這一篇博客有講解
OK,下面進入六個函數的講解
strcpy 的使用和模擬實現?
char *strcpy? (char*destination,const char*source)
1.源字符串必須以?'\0' 結束。
2.會將源字符串中的 '\0' 拷貝到目標空間。
?3.目標空間必須足夠大,以確保能存放源字符串。
4. 目標空間必須可修改?
5.從源頭開始拷貝。
但是這樣你打印的話,只能打印出來“xxx”,因為,打印自動到'\0'停止,所以你打印不出完整的拷貝后的字符串,不過可以通過調試觀察。
以上也是strcpy函數的模擬實現。
思路:
1.由于返回起始空間的地址,所以要先保存起始空間的地址,防止后面++后,找不到起始空間的地址了。
2.接著斷言,防止p與p1指針傳的是無效地址。
3.然后把p1指向的字符串中的字符挨個拷貝到p指向的字符串中,之后p1指向的字符串中的字符位置與p指向的字符串中的位置都往后挪動一位。依次重復。
?strcat 的使用和模擬實現
char*strcat? (char*destination,const char*source)
1.源字符串必須以 '\0' 結束。
?2.目標字符串中也得有 \0 ,否則沒辦法知道追加從哪里開始。
3. 目標空間必須有足夠的大,能容納下源字符串的內容。
4. 目標空間必須可修改。?
5.destination中的'\0'也會被覆蓋。
以上是strcat的模擬實現,需要注意的是這里不可以自己給自己追加,否則會導致未定義。
思路:
1.首先先斷言一下,由于這里傳的是起始空間的地址,所以還要創建一個變量,用來存儲起始地址。
2.之后先去找destination中的'\0',找到之后,就從這開始拷貝即可,需要注意的是,source中的'\0'也會別拷貝到目標字符串中。
?strcmp的使用和模擬實現
int? ?strcmp? (const char*str1,const char*str2)
其實這個函數就是一個用于比較字符串大小的工具。?
1.第?個字符串大于第二個字符串,則返回大于0的數字 ?
2.第?個字符串等于第二個字符串,則返回0 ?
3.第?個字符串小于第二個字符串,則返回小于0的數字 ?
4.那么如何判斷兩個字符串?比較兩個字符串中對應位置上字符ASCII碼值的大小。
下面看strcmp函數的模擬實現:
不過要注意的是這里博主用的編譯器是vs,并且返不返回1,-1,0,純看編譯器,有的編譯器就是不返回這幾個數字。
模擬實現代碼思路:
1.還是老樣子先斷言,之后從第一個字符的ASCII值開始比較。
2.如果第一個字符相等,那么++,繼續往后比較,如果比較完了,直到最后一個標識字符'\0'都相等,那么就返回0.
3.如果第一個字符串的第一個字符比第二個字符串的第一個字符大,那么就返回1(vs下),否則返回-1.
以上三個函數都是長度不受限制的,那么下面看3個長度受限制的。
?strncpy 函數的使用
?char * strncpy? ?( char * destination, const char * source, size_t num );
1.拷貝num個字符(不是字節)從源字符串到目標空間。
2.如果源字符串的長度小于num,則拷貝完源字符串之后,在目標的后邊追加'\0'(可通過調試觀察),直到num個?。
該函數就是strcpy函數的減縮版,模擬實現方式差不多,這里就不做演示了。
strncat 函數的使用
char * strncat? ?( char * destination, const char * source, size_t num );
1.將source指向字符串的前num個字符追加到destination指向的字符串末尾,再追加?個'\0'字符。
很細節,方便打印?
2.如果source 指向的字符串的長度小于num的時候,它不會像strncpy一樣,在后面追加'\0',而是直接不管,直接在destination的字符串末尾加一個'\0'即可。
strncmp函數的使用
int? strncmp? ( const char * str1, const char * str2, size_t num );
比較str1和str2的前num個字符,如果相等就繼續往后比較,最多比較num個字母,如果提前發現不? 樣,就提前結束,大的字符所在的字符串大于另外?個。如果num個字符都相等,就是相等返回0。?(就是比strcmp函數多了個限制條件)
?strstr 的使用和模擬實現
strstr的作用是用來查找子串的。
char * strstr? ?( const char * str1, const char * str2);
1.函數返回字符串str2在字符串str1中第一次出現的位置。
2.字符串的比較匹配不包含 '\0' 字符,以 '\0 '作為結束標志。
來看它的模擬實現吧。
思路:
1.首先先斷言一下,因為要返回起始空間的地址,所以說要創建一個變量存放起始地址。
2.先來一個循環,條件是找的時候第一個字符串!='\0',之后,將指向第一個字符串的指針再賦值給s1,指向第二個字符串的指針再賦值給s2,之后便可以開始比較了。
3.如果說找到了s1跟s2相等的字符,那么各自++,繼續往后比較,但凡有一個字符不相等了,直接退出循環,cur++,(即返回第一個字符串的起始地址,并且加一,讓它從第一個字符串的第二個字符開始比較)。
4.如果說,比較完了,而且正好發現了第一個字符串中藏了第二個字符串,就是到了if階段,那么這時候,s2就到了'\0'的位置,這時候直接返回當時找的第一個字符串的起始地址即可。
5.不過這里需要注意的是,你打印的時候,是會遇到'\0'才會停止的,所以說,比如,第一個字符串“abcdef”,第二個字符串“cde”,那么可以打印出cdef。
strtok函數的使用
1.sep參數指向?個字符串,定義了用作分隔符的字符集合?
2.第?個參數指定?個字符串,它包含了0個或者多個由sep字符串中?個或者多個分隔符分割的標 記。
?3.strtok函數找到str中的下?個標記,并將其用?\0 結尾,返回?個指向這個標記的指針。
(注: strtok函數會改變被操作的字符串,所以被strtok函數切分的字符串?般都是臨時拷貝的內容并且可修改。)
?4.strtok函數的第?個參數不為 中的位置。 NULL ,函數將找到str中第一個標記,strtok函數將保存它在字符串
?5.strtok函數的第?個參數為 NULL ,函數將在同?個字符串中被保存的位置開始,查找下?個標 記。
?6.如果字符串中不存在更多的標記,則返回 NULL 指針
?strerror 函數的使用
char* strerror ( int errnum );
strerror 函數可以把參數部分錯誤碼對應的錯誤信息的字符串地址返回來。 在不同的系統和C語言標準庫的實現中都規定了?些錯誤碼,?般是放在 errno.h 這個頭文件中說明 的,C語言程序啟動的時候就會使用?個全局的變量errno來記錄程序的當前錯誤碼,只不過程序啟動 的時候errno是0,表示沒有錯誤,當我們在使用標準庫中的函數的時候發?了某種錯誤,就會將對應 的錯誤碼,存放在errno中,而?個錯誤碼的數字是整數很難理解是什么意思,所以每?個錯誤碼都 是有對應的錯誤信息的。strerror函數就可以將錯誤對應的錯誤信息字符串的地址返回?。
3.C語言內存函數(也在string.h頭文件中)
memcpy使用和模擬實現(覆蓋原理)
void * memcpy ( void * destination, const void * source, size_t num );
1.函數memcpy從source的位置開始向后復制num個字節的數據到destination指向的內存位置。
2. 這個函數在遇到 '\0' 的時候并不會停下來。
3.如果source和destination有任何的重疊,復制的結果都是未定義的?。
4.對于重疊的內存,交給memmove來處理。
來看它的模擬實現
思路:
1.由于也是返回起始空間的地址,所以說先定義一個臨時變量,用來存儲起始空間的地址,之后再斷言。
2.以count--為循環條件,決定了要拷貝的次數,并且讓source中的字符拷貝到destination中,一個字符拷貝完之后,++,直到count被減完,才停止賦值。
?memmove使用和模擬實現(可以實現自己給自己追加)
void * memmove ( void * destination, const void * source, size_t num );
其實memmove的用法與memcpy基本一樣,就以下不同點:
1.和memcpy的差別就是memmove函數處理的源內存塊和目標內存塊是可以重疊的。
?2.如果源空間和目標空間出現重疊,就得使用memmove函數處理。?
來看它的模擬實現:
?memset函數的使用
void * memset ( void * ptr, int value, size_t num );
memset是用來設置內存的,將內存中的值以字節為單位設置成想要的內容。?
?memcmp函數的使用
int memcmp ( const void * ptr1, const void * ptr2, size_t num );
比較從ptr1和ptr2指針指向的位置開始,向后的num個字節 ,這個其實也是比較類的函數,與strcmp,strncmp差不多。
下面來看它的返回值:
再來看一個例子:
相信大家對這個函數也已經理解了吧。
以上內容是我個人理解,若有不對,還請指出!謝謝!
本篇完...............