?????????Hi~!這里是奮斗的小羊,很榮幸各位能閱讀我的文章,誠請評論指點,歡迎歡迎~~? ? ?
????????????????????????????????????????????????💥個人主頁:小羊在奮斗
????????????????????????????????????????????????💥所屬專欄:C語言? ?
????????本系列文章為個人學習筆記,在這里撰寫成文一為鞏固知識,二為一些學友們展示一下我的學習過程及理解。文筆、排版拙劣,望見諒。?
????????????????????????????????6、strcmp 的使用和模擬實現
????????????????????????????????7、strncpy、strncat 和 strncmp
????????????????????????????????8、strtok 的使用和模擬實現
????????????????????????????????9、strstr 的使用和模擬實現
????????????????????????????????10、strerror 函數的使用
6、strcmp 的使用和模擬實現
? ? ? ? 6.1 strcmp 的用法
? ? ? ? 其實對于 strcmp 函數我們并不陌生,在之前的學習中已經不止一次用到過。
????????strcmp 函數的作用是比較兩個字符串的大小,當結果是大于時返回一個正值,小于時返回一個負值,等于時返回0。所以 strcmp 函數的返回值是int類型,我們在使用字符串函數的時候一定要清楚每個函數的返回值是什么。
????????要特別注意的是,strcmp 函數比較兩個字符串比較的不是字符串的長度,而是對應位置字符的ASCII碼值。?
? ? ? 可以看到,當對應位置字符的ASCII碼值前者大于后者時,strcmp 函數返回了1;當小于時,strcmp 函數返回了-1;當等于時,strcmp 函數返回了0。來看下面代碼示例:
? ? ? ? 這個代碼有沒有什么問題呢?其實,上面的代碼在VS中是沒有任何問題的,但是在其他編譯器中可能就會發生錯誤。其中的原因在 strcmp 函數的返回值上,我們說當前面的字符串大于后面的字符串時返回一個正值,但這個正值可以是任意正值,而在VS上規定這個正值為1,但是在其他編譯器上并不見得這個正值都為1。
? ? ? ? 6.2 strcmp 的模擬實現
? ? ? ? 有了前幾個模擬實現字符串函數的經驗,模擬 strcmp 函數難度也不是太大。?
#include <stdio.h>
#include <assert.h>int my_strcmp(const char* str1, const char* str2)
{assert(str1 != NULL);assert(str2 != NULL);while (*str1 == *str2){if (*str1 == '\0'){return 0;}str1++;str2++;}if (*str1 > *str2){return 1;}else{return -1;}
}int main()
{char str1[] = "abcdef";char str2[] = "abcijk";int ret = my_strcmp(str1, str2);printf("%d\n", ret);return 0;
}
? ? ? ? 特別的,還可以簡化成下面的形式。
7、strncpy、strncat 和 strncmp
? ? ? ? 出了 strcpy、strcat 和 strcmp 外,C語言還提供了更加靈活的 strncpy、strncat 和 strncmp,它們算是前三者的升級版,使用起來更加靈活。以 strncpy 為例:
? ? ? ? 可以看到 strncpy 相較于 strcpy 多了一個參數,用于指定拷貝多少個字符。另外兩個也是類似。
? ? ? ? 雖然它們的邏輯表面上看起來是一樣的,但是 strcnpy 和 strncat 之間還是有一點差異的。
?
?
? ? ? ? 可以看到 strncpy 不會給目標字符串主動添加 ‘\0’,但 strncat 就會主動給目標字符串添加 ‘\0’,這是兩個函數間的差異。?
? ? ? ? 那既然有了 strncat 函數,我們就能彌補上一小節中未能實現字符串自己拼接到自己后面的遺憾了。
8、strtok 函數的使用??????
? ? ? ? 更多詳細介紹請跳轉閱讀 —>?strtok, strtok_s - cppreference.com? ?
? ? ? ? ?看了上面的介紹好像還是云里霧里的,我用通俗的話來解釋一下。delim 指向一個字符串,定義了用作分隔符的字符集合;第一個參數指定一個字符串,它包含了0個或多個由delim字符串中的一個或多個分隔符分割的標記;strtok 函數找到str中的下一個標記,并將其用\0結尾,返回一個指向這個標記的指針(strtok 函數會改變被操作的字符串,所以被 strtok 函數切分的字符串一般都是臨時拷貝的內容并且可修改);strtok 函數的第一個參數不為NULL,函數將找到str中第一個標記,strtok 函數將保存它在字符串中的位置;strtok 函數的第一個參數為NULL,函數將在同一個字符串中被保存的位置開始,查找下一個標記;如果字符串中不存在更多標記,則返回NULL指針。也就是說,只需要傳遞一次指向字符串的非空指針,剩下的都傳空指針。
????????上面的描述其實說的是? strtok 函數是一個過濾指定字符,提取出你想要的部分的函數。比如,有一個郵箱地址?18655404590@163.com,我們想要剔除其中的特殊字符 ‘@’ 和 ‘.’ ,提取出18655404590、163和com,那我們就可以使用 strtok 函數來實現。其中字符指針str指向目標字符串“18655404590@163.com”,delim 指向指定的分隔符“@、.”。
? ? ? ? 但是,上面是我們事先知道字符串中有兩個分隔符,所以寫了三個打印函數,那如果我們不知道一個字符串中有多少個分隔符呢?這里可以用for循環來解決,之前我們在介紹for循環的文章中說過這么一句話,for循環通常用來解決循環次數未知的情況。
?
?9、strstr 的使用和模擬實現
? ? ? ? 9.1 strstr 的使用
? ? ? ? 更多詳細介紹請跳轉閱讀 —>?strstr - cppreference.com? ? ? ??? ? ? ? 簡單來說,strstr 函數的作用是在一個字符串中查找另一個字符串,找到了就返回這個字符串第一次出現的起始地址,沒找到就返回一個空指針。來看示例:
? ? ? ? 9.2 strstr 的模擬實現
? ? ? ? 模擬實現 strstr 函數之前,我們需要想清楚怎么在一個字符串中找另一個字符串是否存在呢?容易想到的是兩個字符串通過指針解引用來一個一個的比較來判斷是否存在一個相同的字符串,大致思路如下:
? ? ? ? (1)逐個字符地訪問被查找的字符串,當訪問到與目標字符串首字符相同的字符時記住這個可能的地址,方便后面返回;
? ? ? ? (2)當兩個字符串的字符兩兩比較一直到目標字符串訪問到 ‘\0’ 時說明找到了,返回之前記住的地址;
? ? ? ? (3)當被查找的字符串訪問到 ‘\0’ 時說明被查找的字符串不存在,返回一個空指針;
? ? ? ? (4)綜上,需要創建三個指針,其中兩個指向被查找字符串,一個用來逐個訪問字符,一個用來記住可能的地址,第三個指針指向目標字符串并且在改變了指針的指向后重新讓其指向目標字符串的首地址。
#include <stdio.h>
#include <assert.h>char* my_strstr(const char* str1, const char* str2)
{assert(str1 && str2);const char* s1 = NULL;const char* s2 = NULL;const char* cur = str1;//用于返回可能的地址if (*str2 == '0')//當目標字符串是空字符串時{return cur;}while (*cur != '\0'){ s1 = cur;s2 = str2;while (*s1 && *s2 && *s1 == *s2){s1++;s2++;}if (*s2 == '\0')//找到了目標字符串{return cur;}cur++;}return NULL;//沒找到
}int main()
{char str1[] = "abcdddeab";char str2[] = "deab";char* ps = my_strstr(str1, str2);if (NULL == ps){printf("不存在\n");}else{printf("%s\n", ps);}return 0;
}
10、 strerror 函數的使用
? ? ? ? 更多詳細介紹請跳轉閱讀 —>?strerror, strerror_s, strerrorlen_s - cppreference.com
?
?????????簡單地說,strerror 函數可以把參數部分錯誤碼對應的錯誤信息的字符串地址返回來。
? ? ? ? 在不同的系統和C語言標準庫的實現中都規定了一些錯誤碼,一般是放在 errno.h 這個頭文件中說明的,C語言程序啟動的時候就會使用一個全局的變量 errno 來記錄程序當前的錯誤碼,只不過程序啟動的時候 errno 是0,表示沒有錯誤,當我們在使用標準庫中的函數的時候發生了某種錯誤,就會將對應的錯誤碼存放在 errno 中,而一個錯誤碼的數字是整數很難理解是什么意思,所以每一個錯誤碼都是有對應的錯誤信息的,strerror 函數就可以將錯誤對應的錯誤信息字符串的地址返回來。
? ? ? ? ?整數0~10對應的錯誤信息如下:
?????????再來舉一個例子,其中涉及到一些我們之前還沒學到的內容,請不要在意,主要是 strerror 函數的用法。
?????????C語言函數中還有一個函數和 strerror 函數的功能是相似的,它就是 perror 函數。來看一下它的介紹:
? ? ? ? 它和 strerror 函數的區別在哪里呢?
????????strerror 函數的功能是將錯誤碼對應的錯誤信息的字符串的地址返回,而 perror 函數的功能是將 errno 中錯誤碼對應的錯誤信息打印出來。那它是怎樣打印的呢?perror 函數打印的規則是先打印字符指針s指向的字符串,再打印一個冒號和一個空格,然后打印錯誤碼對應的錯誤信息。?
?
? ? ? ? 可以看到上面 printf 函數和 perror 函數打印的內容是一樣的。
? ? ? ? 也就是說?perror == printf + strerror。我們可以根據自己的選擇選用這兩個函數。
????????如果覺得我的文章還不錯,請點贊、收藏 + 關注支持一下,我會持續更新更好的文章。??