🥰歡迎關注?輕松拿捏C語言系列,來和 小哇 一起進步!?
🎉創作不易,請多多支持🎉
🌈感謝大家的閱讀、點贊、收藏和關注💕
🌹如有問題,歡迎指正 感謝
目錄
一、 strlen的使用和模擬實現
二、strcpy的使用和模擬實現
三、strcat的使用和模擬實現
四、strcmp的使用和模擬實現
五、strncpy的使用和模擬實現
六、strncat的使用和模擬實現
七、strncmp的使用和模擬實現
八、strstr的使用和模擬實現
九、strtok的使用和模擬實現
十、strerror的使用和模擬實現
一、 strlen的使用和模擬實現
size_t strlen ( const char * str );
注意:?
? 字符串以 '\0' 作為結束標志,strlen函數返回的是在字符串中 '\0' 出現前面的字符個數(不包含 '\0' )。
? 參數指向的字符串必須要以 '\0' 結束。
? 注意函數的返回值為 size_t,是無符號的( 易錯 )
? strlen的使用需要包含頭文件?
#include <stdio.h>
#include <string.h>
int main()
{const char* str1 = "abcdef";const char* str2 = "bbb";if(strlen(str2)-strlen(str1)>0){printf("str2>str1\n");} else{printf("srt1>str2\n");}return 0;
}
因為strlen返回值為無符號整型,所以if條件中的不是 3 - 6 = -3,而應該是-3的補碼 一個大于0的數字,所以打印 str2>str1?
#include <stdio.h>
#include <string.h>
int main()
{//char arr[] = "abcdef";char arr[] = { 'a', 'b','c' };size_t len = strlen(arr);printf("%zd\n", len);return 0;
}
無\0,打印出的是隨機值?
模擬實現
法一:計算器方式
//計數器?式
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;elsereturn 1+my_strlen(str+1);
}
法三:指針相減
size_t my_strlen(const char* str)
{const char* start = str;assert(str != NULL);while (*str != '\0'){str++;}return str - start;
}
二、strcpy的使用和模擬實現
char* strcpy(char * destination, const char * source );
注意:
? 源字符串必須以 '\0' 結束。
? 會將源字符串中的 '\0' 拷貝到目標空間。
? 目標空間必須足夠大,以確保能存放源字符串。
? 目標空間必須可修改。?
正確使用:
#include <stdio.h>
#include <string.h>
int main()
{char arr1[] = "hello world";char arr2[20] = {0};//1個元素strcpy(arr2, arr1);printf("%s\n", arr2);return 0;
}
錯誤使用:
#include<stdio.h>
#include<string.h>
int main()
{char arr1[] = "hello world";char* p = "xxxxxxxxxxxxxxxxxxxx";//常量字符串-不能修改strcpy(p, arr1);//errprintf("%s\n", p);return 0;
}
模擬實現:?
strcpy函數返回的是目標空間的起始地址
char* my_strcpy(char* dest, const char* src)
{//assert(dest != NULL);//assert(src != NULL);assert(dest && src);char* ret = dest;while (*src != '\0'){*dest = *src;src++;dest++;}*dest = *src;//拷貝\0return ret;//返回目標空間的起始地址
}
優化:
char* my_strcpy(char* dest, const char* src)
{//assert(dest != NULL);//assert(src != NULL);assert(dest && src);char* ret = dest;while (*dest++ = *src++)//拷貝過去字符后,判斷表達式的值,當\0拷貝過去后,判斷為假,停止循環{;}return ret;//返回目標空間的起始地址
}
三、strcat的使用和模擬實現
char * strcat ( char * destination, const char * source );
注意:
? 源字符串必須以 '\0' 結束。
? 目標字符串中也得有 \0 ,否則沒辦法知道追加從哪里開始。
? 目標空間必須有足夠的大,能容納下源字符串的內容。
? 目標空間必須可修改。
? 字符串自己給自己追加,如何?不能保證?
使用:
int main()
{char arr1[20] = "he\0lloxxxxx";char arr2[] = "world";strcat(arr1, arr2);//字符串追加printf("%s\n", arr1);return 0;
}
從第一個\0開始追加
?
模擬實現:
#include<stdio.h>
#include<assert.h>
//要返回目標空間的起始地址
char* my_strcat(char* dest, const char* src)
{char* ret = dest;assert(dest && src);//1. 找目標空間的\0while (*dest != '\0')dest++;//2. 拷貝while (*dest++ = *src++);return ret;
}
四、strcmp的使用和模擬實現
int strcmp ( const char * str1, const char * str2 );
注意:
第?個字符串大于第?個字符串,則返回大于0的數字 ?
第?個字符串等于第?個字符串,則返回0 ?
第?個字符串小于第?個字符串,則返回小于0的數字 ?
(在vs上,大于0返回的1,小于0返回的-1)
那么如何判斷兩個字符串? 比較兩個字符串中對應位置上字符ASCII碼值的大小。?
使用:
#include<stdio.h>
#include<string.h>int main()
{char arr1[] = "abq";char arr2[] = "abcdef";int ret = strcmp(arr1, arr2);//printf("%d\n", ret);if (ret >0){printf(">\n");}else{printf("<=\n");}return 0;
}
打印 >
模擬實現 :
#include<stdio.h>
#include<assert.h>
int my_strcmp(const char* str1, const char* str2)
{assert(str1 && str2);while (*str1 == *str2){if (*str1 == '\0'){return 0;}str1++;str2++;}return (*str1 - *str2);
}
五、strncpy的使用和模擬實現
?char * strncpy ( char * destination, const char * source, size_t num );
注意?:
? 拷貝num個字符從源字符串到目標空間。
? 如果源字符串的長度小于num,則拷貝完源字符串之后,在目標的后邊追加0,直到num個。
?
使用:
#include <stdio.h>
#include <string.h>
int main()
{char arr1[20] = "abcdef";char arr2[20] = "xxxxxxxxxxx";strncpy(arr2, arr1, 8);printf("%s\n", arr2);return 0;
}
模擬實現(如有問題,歡迎指正):
//用函數實現strncpy的功能
#include<stdio.h>
#include<assert.h>
#include<string.h>
char* my_strncpy(char* dest, char* source,size_t n)
{assert(dest && source);char* ret = dest;char* temp = source;while((*dest++ = *source++ )&&(source<temp + n)){;}return ret;
}
int main()
{char arr1[20] = "abcdef";char arr2[20] = "xxxxxxxxxx";size_t num;while(scanf("%zd", &num)!=EOF)//多次循環輸入{/*strncpy(arr2, arr1, num);printf("%s\n", arr2);*/char* ret = my_strncpy(arr2, arr1, num);printf("%s\n", ret);}return 0;
}
?
六、strncat的使用和模擬實現
char * strncat ( char * destination, const char * source, size_t num );
注意:
?將source指向字符串的前num個字符追加到destination指向的字符串末尾,再追加?個 \0 字 符。
?如果source 指向的字符串的長度小于num的時候,只會將字符串中到 \0 的內容追加到destination指向的字符串末尾?
使用:
int main()
{char arr1[20] = "abcdef\0yyyyyyyy";char arr2[20] = "xxxxxxxx";strncat(arr1, arr2, 3);printf("%s\n", arr1);return 0;
}
模擬實現(如有問題,歡迎指正):
#include<stdio.h>
//實現strncat的功能
#include<assert.h>
char* my_strncat(char* dest,const char* source, int num)
{assert(dest && source);char* ret = dest;char* temp = source;while (*dest){dest++;}while ((*dest++ = *source++) && (source < temp+num)){;}return ret;
}
int main()
{char a[20] = "abcdef";char* b = "hhhhhh";int n;scanf("%d", &n);char* ret = my_strncat(a,b,n);printf("%s\n", ret);return 0;
}
七、strncmp的使用
int strncmp ( const char * str1, const char * str2, size_t num );
比較str1和str2的前num個字符,如果相等就繼續往后比較,最多比較num個字?,如果提前發現不? 樣,就提前結束,大的字符所在的字符串大于另外?個。如果num個字符都相等,就是相等返回0.?
#include<stdio.h>
#include<string.h>
int main()
{char arr1[20] = "abcdef";char arr2[20] = "ab";int ret = strncmp(arr1, arr2, 4);printf("%d\n", ret);return 0;
}
八、strstr的使用和模擬實現
char * strstr ( const char * str1, const char * str2);
在str1中找str2字符串第一次出現的位置, 找到了就返回第一次出現的起始地址,找不到返回NULL;
注意:?
?函數返回字符串str2在字符串str1中第?次出現的位置;
字符串的比較匹配不包含 \0 字符,以 \0 作為結束標志。
使用:
#include<string.h>
int main()
{char arr[] = "abcdefabcdef";char* p = "cdefa";char* ret = strstr(arr, p);if (ret == NULL){printf("不存在\n");}else{printf("%s\n", ret);}return 0;
}
?
模擬實現(如有問題,歡迎指正):
#include<stdio.h>
//模擬實現strstr
#include<assert.h>
const 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 str1;while (*cur){s1 = cur;s2 = str2;while (*s1 && *s2 && *s1 == *s2){s1++;s2++;}if (*s2 == '\0')return cur;cur++;}return NULL;
}
int main()
{char arr[] = "KIKU is JJY,an Idol and actress ";char* p = "JJY";const char* ret =my_strstr(arr, p);if (ret == NULL)printf("找不到");elseprintf("%s\n", ret);return 0;
}
九、strtok的使用
char * strtok ( char * str, const char * sep);
?注意:
? sep參數指向?個字符串,定義了用作分隔符的字符集合
? 第?個參數指定?個字符串,它包含了0個或者多個由sep字符串中?個或者多個分隔符分割的標 記。
? strtok函數找到str中的下?個標記,并將其用\0 結尾,返回?個指向這個標記的指針。(注: strtok函數會改變被操作的字符串,所以被strtok函數切分的字符串?般都是臨時拷貝的內容并且 可修改。)
? strtok函數的第?個參數不為 NULL ,函數將找到str中第?個標記,strtok函數將保存它在字符串 中的位置。
? strtok函數的第?個參數為 NULL ,函數將在同?個字符串中被保存的位置開始,查找下?個標 記。
? 如果字符串中不存在更多的標記,則返回 NULL 指針
?
什么意思呢?通俗來講就是,
第一次使用strtok函數時,
在第一個參數指向的字符串中去找分隔符sep,找到后把這個分隔符變成\0,
記住\0的地址即要查找的下一部分的起始地址,返回值就是\0前面這部分的地址。
然后后面再調用的話,第一個參數變成NULL,從記住的\0位置開始往后繼續找分隔符,
找到了就又把這個分隔符變成\0并記住它的地址,返回值時這個\0前的這部分字符串的地址。
使用:
1、不用循環
#include <stdio.h>
#include <string.h>
//strtok函數使用
int main()
{char arr[] = "BaoGengXiaoWa@yeah.net@hehe.haha#ttttt";char buf[256] = { 0 };strcpy(buf, arr);//"BaoGengXiaoWa@yeah.net@hehe.haha#ttttt"//char sep[] = "@.";char* sep = "@.";/*char* ret = NULL;for (ret = strtok(buf, sep); ret != NULL; ret = strtok(NULL, sep)){printf("%s\n", ret);}*/char* ret = strtok(buf, sep);printf("%s\n", ret);ret = strtok(NULL, sep);printf("%s\n", ret);ret = strtok(NULL, sep);printf("%s\n", ret);ret = strtok(NULL, sep);printf("%s\n", ret);ret = strtok(NULL, sep);printf("%s\n", ret);return 0;
}
?
2、使用循環
#include<stdio.h>
#include<string.h>
//strtok函數使用
int main()
{char arr[] = "BaoGengXiaoWa@yeah.net@hehe.haha#ttttt";char buf[256] = { 0 };strcpy(buf, arr);//"BaoGengXiaoWa@yeah.net@hehe.haha#ttttt"//char sep[] = "@.";char* sep = "@.";char* ret = NULL;for (ret = strtok(buf, sep); ret != NULL; ret = strtok(NULL, sep)){printf("%s\n", ret);}/*char* ret = strtok(buf, sep);printf("%s\n", ret);ret = strtok(NULL, sep);printf("%s\n", ret);ret = strtok(NULL, sep);printf("%s\n", ret);ret = strtok(NULL, sep);printf("%s\n", ret);ret = strtok(NULL, sep);printf("%s\n", ret);*/return 0;
}
?
十、strerror的使用和模擬實現
char* strerror ( int errnum );
strerror 函數可以把參數部分錯誤碼對應的錯誤信息的字符串地址返回來。
在不同的系統和C語言標準庫的實現中都規定了?些錯誤碼,?般是放在 errno.h 這個頭文件中說明的
C語言程序啟動的時候就會使用?個全局的變量errno來記錄程序的當前錯誤碼,只不過程序啟動的時候errno是0,表示沒有錯誤
當我們在使用標準庫中的函數的時候發生了某種錯誤,就會將對應的錯誤碼,存放在errno中,而?個錯誤碼的數字是整數很難理解是什么意思,所以每?個錯誤碼都是有對應的錯誤信息的。
strerror函數就可以將錯誤對應的錯誤信息字符串的地址返回。?
我們打印?下0~10這些錯誤碼對應的信息:
#include <errno.h>
#include <string.h>
#include <stdio.h>
int main()
{int i = 0;for (i = 0; i <= 10; i++) {printf("%s\n", strerror(i));}return 0;
}
舉例:?
#include<stdio.h>
#include <string.h>
#include <errno.h>
int main()
{//打開文件FILE* pf = fopen("data.txt", "r");//"r"- 讀,以讀文件的形式,打來文件,如果這個文件不存在,就打開失敗if (pf == NULL){printf("打開文件失敗,原因是: %s", strerror(errno));return 1;}else{printf("打開文件成功\n");//.....fclose(pf);pf = NULL;}return 0;
}
也可以使用 perror 函數,perror函數相當于?次將上述代碼中的代碼
????????printf("打開文件失敗,原因是: %s", strerror(errno));
完成了,直接將錯誤信息打印出來。
perror函數打印完參數部分的字符串后,再打印?個冒號和?個空格,再打印錯誤信息。?
?
int main()
{//打開文件FILE* pf = fopen("data.txt", "r");//"r"- 讀,以讀文件的形式,打來文件,如果這個文件不存在,就打開失敗if (pf == NULL){perror("打開文件失敗,原因是");// //perror == printf + strerrorreturn 1;}else{printf("打開文件成功\n");//.....fclose(pf);pf = NULL;}return 0;
}
?🎉🎉🎉本文內容結束啦,希望各位大佬多多指教!
🌹🌹感謝大家三連支持
💕敬請期待下篇文章吧~
?