目錄
10年專注成都網站制作,成都企業網站建設,個人網站制作服務,為大家分享網站制作知識、方案,網站設計流程、步驟,成功服務上千家企業。為您提供網站建設,網站制作,網頁設計及定制高端網站建設服務,專注于成都企業網站建設,高端網頁制作,對成都會所設計等多個領域,擁有多年建站經驗。
函數介紹:
字符串函數:
strlen
一道迷惑筆試題:
strcpy
strcat
strcmp
strncpy
strncat
strncmp
strstr
strtok
strerror
字符分類函數:
iscntrl?
isspace
isdigit
isxdigit
islower
isupper
isalpha
isalnum
ispunct
isgraph
isprint
tolower
toupper
內存函數:
memcpy
memmove
memcmp
memset
庫函數的模擬實現
模擬實現strlen
模擬實現strcpy
模擬實現strcat
模擬實現strstr
模擬實現strcmp
模擬實現memcpy
模擬實現memmove
函數介紹: 字符串函數:對C語言中的幾個常用的庫函數進行解釋說明
并徹底了解如何使用
了解原理,并進行模擬實現
strlen計算字符串長度函數
函數原型:size_t? strlen(const char* str)
返回值:size_t? ?就是??unsigned int 無符號整型
?返回的是'\0‘之前字符的個數?
參數:const char* str??
?是一個char*的指針 且用const修飾
?const修飾的是*str
表示指針指向的內容是不可被修改的
函數作用:計算的是字符串長度
計算'\0'之前字符的個數
函數的用途:看以下代碼:
一道迷惑筆試題:#include
#include int main() { //創建一個數組 用來封裝字符串 char str[] = "abcdefghjk"; //調用strlen函數,用一個size_t 無符號整型來接收 //將str數組名表示首元素地址,也就是字符串的首地址傳過去 size_t len = strlen(str); //打印,從傳過去的位置開始,遇到'\0'之前,字符的個數 printf("%u\n", len); return 0; } #include
#include 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"); } //在判斷的時候,strlen(str2)的值為3 //strlen(str1)的值為6 //而 3 和 6 都是size_t類型 //3-6 的實際結果為:-3 // -3 : // 原碼:10000000 00000000 00000000 00000011 // 反碼:11111111 11111111 11111111 11111100 // 補碼:11111111 11111111 11111111 11111101 // //但因為是無符號整型,將-3的補碼實際解讀的時候 //是按照無符號數來解讀的,因為正數的 原碼,反碼,補碼相同 //所以將-3的補碼當做原碼解讀,是一個很大的數 //該數必定大于0 所以必定指向if里面的語句 return 0; } 解析:
答案:str2>str1
在判斷的時候,strlen(str2)的值為3
strlen(str1)的值為6
而 3 和 6 都是size_t類型
3-6 的實際結果為:-3
-3 :
原碼:10000000 00000000 00000000 00000011
反碼:11111111 11111111 11111111 11111100
補碼:11111111 11111111 11111111 11111101
但因為是無符號整型,將-3的補碼實際解讀的時候
是按照無符號數來解讀的,因為正數的 原碼,反碼,補碼相同
所以將-3的補碼當做原碼解讀,是一個很大的數
該數必定大于0 所以必定指向if里面的語句
strcpy字符串拷貝函數
函數原型:char * strcpy ( char * destination, const char * source );
參數:char * destination, const char * source
將source指向的字符串復制到destination指向的數組中
包括終止字符'\0’也要賦值過去
返回值:char*??
返回的是sourec指向的那一片空間的地址
函數作用:將源頭src指向字符串的內容賦值到目的地dest指向字符串中
?在賦值的時候會將字符'\0’也賦值過去
???????為避免溢出,destination指向的數組的大小應足夠長
以包含與source相同的字符串(包括終止空字符),
并且不應與source在內存中重疊。
函數的使用:看以下代碼:
#include
#include int main() { //將str2的內容拷貝到str1中 //拷貝的時候會將'\0'也拷貝過去 //str1的空間要足夠大要裝的下str2的內容! char str1[20] = "zzzzzzzzzzzzzz"; char str2[] = "abcde"; strcpy(str1, str2); printf("%s\n", str1); //將s2的內容拷貝到s1中 //拷貝的時候會將'\0'也拷貝過去 //s1的空間要足夠大要裝的大s2的內容 char s1[] = "xxxxxxxxxx"; char s2[] = "fghijk"; strcpy(s1, s2); printf("%s\n", s1); //將p2指向的常量字符串的內容拷貝到p2中 //拷貝的時候會將'\0'也拷貝過去 //p1的空間要足夠大要裝的大p2的內容 char p1[20] = "yyyyyyyyyyyyyyyyyy"; char* p2 = "lmnopq"; strcpy(p1, p2); printf("%s\n", p1); return 0; }
strcat字符串追加函數
函數原型:char * strcat ( char * destination, const char * source );
返回值:char*
返回的是追加完成之后
destination的首地址
參數:char * destination, const char * source
?destination是目的地字符串的首地址
?source 是源頭字符串的首地址
函數作用:
將source指向的字符串內容
追加到destination指向的字符串后面
追加時:destination中的'\0'被source的第一個字符覆蓋
destination指向的空間要足夠大
要容納下追加之后的新字符串
函數用途:看以下代碼? ? ? ?
#include
#include int main() { //將str2的內容追加到str1的后面 //在追加的時候str1最后的‘\0’字符被str2的第一個字符覆蓋 //然后進行追加,追加時會將str2的'\0'也追加進去 //str1的空間要足夠大,要能容納下追加后的新字符串 char str1[50] = "abcdefg"; char str2[] = "hijklmn"; strcat(str1, str2); printf("%s\n", str1); //將p2指向的常量字符串內容追加到p1的后面 //追加時p1的'\0'字符被p2的首字符覆蓋 //追加時會將p2的'\0'也追加進去 //p1的空間要足夠大,能容納下追加后的新字符串 char p1[20] = "abc"; char* p2 = "defgk"; strcat(p1, p2); printf("%s\n", p1); return 0; } ?
strcmp字符串比較函數
函數原型:int strcmp ( const char * str1, const char * str2 );
返回值:int
???返回的是一個有符號整型數
?可返回負數,0,正數
參數:const char * str1, const char * str2
?str1指向一個字符串,
?str1里面存放的是字符串的首地址
?用const修飾說明字符串的內容不可被修改
?str2也指向一個字符串,
?str2里面存放的是字符串的首地址
?用const修飾說明字符串的內容不可被修改
?
函數的作用:
?????str1字符串與str2字符串從首字符的位置開始
?????一個字符一個字符對應向后一一比較,
?????在比較字符的時候比較的是其ASCII碼值,
?????若對應比較兩個字符相等則一直向后比較,
?????直到碰到字符不等的情況就停止比較,
?????然后返回這兩個不等字符的比較結果,
?????當str1的字符大于str2的字符 則返回大于0的數字,
?????若兩個字符串比較完了,各字符都相同,
?????且長度相等的情況下,則這兩個字符串相等
?????str1等于str2時返回0,
?????str1的字符小于str2的字符時 返回小于0的數
函數用途:如下代碼:
#include
#include int main() { //字符串比較 //str1 與 str2 進行比較 //從首字符開始向后一一比較 //在比較的時候比較的是字符的ASCII碼值 //若對應的字符相等,則繼續向后比較 //若不等,則停止比較,返回他們的比較結果 //若兩個字符串比較完都相等,且長度一樣長,說明str2和str2相等 //返回值: //第一個字符串大于第二個字符串,則返回大于0的數字 //第一個字符串等于第二個字符串,則返回0 //第一個字符串小于第二個字符串,則返回小于0的數字 char str1[] = "abcde"; char str2[] = "abcfk"; int n = strcmp(str1, str2); if (n == 0) { printf("str1 == str2"); } else if (n >0) { printf("str1 >str2"); } else { printf("str1< str2"); } return 0; }
strncpy字符串拷貝函數(指定字節數拷貝)
函數原型:char * strncpy ( char * destination, const char * source, size_t num );
返回值:char *
?返回的是一個char* 的指針
?返回的是拷貝完成后的destination指向的空間
參數:char * destination, const char * source, size_t num
?目的地字符串:
?destination 是指向一個字符串空間的指針
?源頭字符串:
?soure是一個指向一個字符串空間的指針
?const修飾說明soure指向的字符串不可被修改
?num是一個sizt_t 無符號整型的數字
函數的作用:
?????將soure指向的字符串中num個字節的內容
?????復制到destination指向的字符串空間
?????如果source指向的字符串的長度小于num,
?????則拷貝完源字符串之后,在目標的后邊追加0,
?????直到追加夠num個結束
?????destination 指向的空間要足夠大
?????至少能容納下拷貝后新的字符串
函數用途:如下代碼:
#include
#include int main() { //拷貝num個字符從源字符串到目標空間。 //如果源字符串的長度小于num,則拷貝完源字符串之后, //在目標的后邊追加0,直到num個 char str1[] = "yyyyyyyyyyyyyyyyyyy"; char str2[] = "hello"; strncpy(str1, str2, 5); printf("%s\n", str1); //當s2的長度
strncat字符串追加函數(指定字節數追加)
函數原型:char * strncat?( char * destination, const char * source, size_t num );
返回值:char *
??返回的是一個char*的指針
返回追加完成之后destination指向的空間
參數:char * destination, const char * source, size_t num
?目的地字符串:
?destination 是指向一個字符串空間的指針
?源頭字符串:
?soure是一個指向一個字符串空間的指指針
?const修飾 說明soure指向的字符串不可被修改
?num是一個sizt_t 無符號整型的數字
函數的作用:
?????將soure指向的字符串中num個字節的內容
? 追加到destination指向的字符串空間
?????destination指向字符串的最后的'\0'字符
?????會被soure指向的字符串的首字符所覆蓋
?????如果source指向的字符串的長度大于num,
?????則追加完num個字符之后,在后邊自動加上'\0'
?????如果source指向的字符串的長度小于num,
? 則只追加完source指向的字符串內容(包含'\0’)
?????就結束結束追加
?????destination 指向的空間要足夠大
?????至少能容納下追加后新的字符串
函數用途:如下代碼:
#include
#include int main() { //str2 大于 num 的情況 //會自動在末尾加上'\0' //在追加的時候,str1的'\0'會被str2的首字符所覆蓋 char str1[50] = "uvwxy"; char str2[] = "abcdefg"; strncat(str1, str2, 5); printf("%s\n", str1); //str2 小于 num 的情況 //只追加完str2包含'\0’字符就結束追加 //在追加的時候,s1的'\0'會被s2的首字符所覆蓋 char s1[50] = "wasche"; char s2[] = "hello world"; strncat(s1, s2, 13); printf("%s\n", s1); return 0; }
strncmp字符串比較函數(指定字節數比較)
函數原型:int strncmp ( const char * str1, const char * str2, size_t num );
返回值:int
???返回的是一個有符號整型數
?可返回負數,0,正數
參數:const char * str1, const char * str2, size_t num
?str1指向一個字符串,
?str1里面存放的是字符串的首地址
?用const修飾說明字符串的內容不可被修改
?str2也指向一個字符串,
?str2里面存放的是字符串的首地址
?用const修飾說明字符串的內容不可被修改
?num是一個無符號整數,表示字節數
函數的作用:
? 對str1和str2字符串,指定num個字節進行比較
?????str1字符串與str2字符串從首字符的位置開始
? 比較到num個字節結束
?????一個字符一個字符對應向后一一比較,
?????在比較字符的時候比較的是其ASCII碼值,
?????若對應比較兩個字符相等則一直向后比較,
?????直到碰到字符不等的情況就停止比較,
?????然后返回這兩個不等字符的比較結果,
?????當str1的字符大于str2的字符 則返回大于0的數字,
?????若兩個字符串比較num個字節之后,
?????各字符都相同,則這兩個字符串相等
?????str1等于str2時返回0,
?????str1的字符小于str2的字符時 返回小于0的數
?????若字符串的長度小于num,則比較完字符'\0'就結束比較
函數用途:如下代碼:
#include
#include int main() { char str1[] = "abcdefghijklm"; char str2[] = "abcdefgxyz"; //比較前六個字符是否相等 int n = strncmp(str1, str2, 6); if (n == 0) { printf("str1 == str2\n"); } else if (n >0) { printf("str1 >str2\n"); } else { printf("str1< str2\n"); } //比較前8個字符是否相等 n = strncmp(str1, str2, 8); if (n == 0) { printf("str1 == str2\n"); } else if (n >0) { printf("str1 >str2\n"); } else { printf("str1< str2\n"); } //比較前11個字符是否相等 n = strncmp(str1, str2, 11); if (n == 0) { printf("str1 == str2\n"); } else if (n >0) { printf("str1 >str2\n"); } else { printf("str1< str2\n"); } return 0; }
strstr字符串找子串函數
函數原型:char * strstr ( const char *str1, const char * str2);
返回值:char *
返回一個字符指針
?返回找到子串的首字符的地址找不到返回NULL
參數:const char *str1, const char * str2
?str1指向一個字符串,
?str1里面存放的是字符串的首地址
?用const修飾說明字符串的內容不可被修改
?str2也指向一個字符串,
?str2里面存放的是字符串的首地址
?用const修飾說明字符串的內容不可被修改
函數的作用:
? 尋找在str1指向的常量字符串里
?????是否包含str2指向的字符串
?????若包含則返回str2第一次出現的地址
?????若不包含則返回NULL
函數用途:如下代碼:
#include
#include int main() { //查找str2是否是str1的子串 //若是則返回str2第一次出現的位置 //若不是則返回NULL char str1[] = "abcdefgjklcdefgmn"; char str2[] = "cdef"; char* p = strstr(str1, str2); if (p == NULL) { printf("str2 不是 str1 的子串\n"); } else { printf("str2 是 str1 的子串\n"); //用%s打印的時候會從str2在str1中第一次出現的位置開始,直到遇到'\0'結束 printf("%s\n", p); } return 0; }
strtok字符串分割函數
函數原型:char * strtok ( char * str, const char * sep );
返回值:char *
??返回一個字符指針
??返回用分割符號分割后字符串的首地址
參數:char * str, const char * sep
str是一個指向要被分割的字符串的空間
sep指向的是分割符號的字符串空間
用const修飾說明sep指向的內容不可被修改
函數的作用:
sep里面傳過來的是分隔符的字符串
在第一次調用的時候
str里面傳過來的是要被分割字符串的首地址
在查找分隔符的時候會將分隔符的位置改為'\0'
在第二次調用的時候
str里面傳入一個空指針,
此時查找分隔符的位置會在第一次分隔符的下一個字符開始查找
會找到下一個分隔符,再將分隔符的位置改為'\0‘
以此類推有幾個分隔符就查找幾次
sep參數是個字符串,定義了用作分隔符的字符集合
第一個參數指定一個字符串,它包含了0個或者多個由sep字符串中一個或者多個分隔符分割的標記。
strtok函數找到str中的下一個標記,并將其用 \0 結尾,
返回一個指向這個標記的指針。
(注:
??? strtok函數會改變被操作的字符串,????????? ?所以在使用strtok函數切分的字符串
????????一般都是臨時拷貝的內容并且可修改。)
strtok函數的第一個參數不為 NULL ,函數將找到str中第一個標記,
strtok函數將保存它在字符串中的位置。
strtok函數的第一個參數為 NULL ,函數將在同一個字符串中被保存的位置開始,
查找下一個標記。
如果字符串中不存在更多的標記,則返回 NULL 指針函數用途:如下代碼:
#include
#include int main() { char str[] = "hello@world&string#strtok";//被分割的字符串 char ep[] = "@";//分隔符字符串 //第一次調用 會將找到的分割符的位置改為'\0' char* p = strtok(str, ep); printf("%s\n", p); //第二次調用傳入空指針 會將找到的分割符的位置改為'\0' p = strtok(NULL, ep); printf("%s\n", p); //第三次調用也傳入空指針 會將找到的分割符的位置改為'\0' p = strtok(NULL, ep); printf("%s\n", p); //第四次調用也傳入NULL 會將找到的分割符的位置改為'\0' p = strtok(NULL, ep); printf("%s\n", p); 上述我們打印分割的字符串總共調用了四次 代碼寫的有點繁瑣,我們可以用一個for循環直接調用打印 //char* ret = NULL; //for (ret = strtok(str, ep);ret!=NULL; ret = strtok(NULL, ep)) //{ // printf("%s\n", ret); //} return 0; }
strerror獲取錯誤信息函數
函數原型:char * strerror ( int errnum );
返回值:char *
? 返回一個字符指針
??返回的是錯誤信息是字符串
參數:int errnum
參數是一個整數
傳入的是一個錯誤碼
函數的作用:
? 返回一個字符串,而這個字符串
? 就是一串錯誤信息
? 而參數是一個整數,是一個錯誤碼
? 每一個錯誤碼都有一個對應的錯誤信息
函數用途:如下代碼:
#include
#include #include int main() { //隨便傳入一個錯誤碼,打印出其錯誤信息 printf("%s\n", strerror(12)); //具體應用 //FILE是一個文件指針,fopen是打開文件 //在當前目錄下打開text.txt文件進行讀操作 //若打開失敗返回NULL FILE* pf = fopen("text.txt", "r"); if (pf == NULL) { printf("打開失敗錯誤信息為:%s",strerror(errno)); } else { printf("打開成功\n"); } return 0; }
字符分類函數:頭文件包含:#include
iscntrl?字符控制函數
函數原型:int iscntrl ( int c );
函數的作用:
? 傳入一個字符,
判斷是否是控制字符
若是則返回非0數(也就是ture)
若不是則返回0(也就是false)
函數用途:
isspace#include
#include int main() { char c = 0; scanf("%c", &c); int ret = iscntrl(c); if (ret == 0) { printf("%c不是控制字符\n", c); } else { printf("%c 是控制字符\n", c); } return 0; } 空白字符:‘空格’,‘\f’換頁,'\n'換行,
?????'\r'回車,制表符‘\t’,垂直制表符'\v'
函數原型:int isspace ( int c );
函數作用:
? 傳入一個字符,
判斷是否是空白字符
若是則返回非0數(也就是ture)
若不是則返回0(也就是false)
函數用途:
#include
#include int main() { //空白字符:‘空格’,‘\f’換頁,'\n'換行,'\r'回車,制表符‘\t’,垂直制表符'\v' char c = '\n'; int ret = iscntrl(c); if (ret == 0) { printf("%c不是空白字符\n", c); } else { printf("%c 是空白字符\n", c); } return 0; }
isdigit內存函數:十進制數字0~9
函數原型:int isdigit ( int c );
函數作用:
? 傳入一個字符,
判斷是否是0~9的字符
若是則返回非0數(也就是ture)
若不是則返回0(也就是false)
函數用途:
isxdigit#include
#include int main() { char c = 0; scanf("%c", &c); int ret = isdigit(c); if (ret == 0) { printf("%c不是0~9字符\n", c); } else { printf("%c 是0~9字符\n", c); } return 0; }
十六進制數字,包括所有十進制數字,小寫字母a~f,大寫字母A~F 函數原型:int isdigit ( int c );
函數作用:
? 傳入一個字符,
判斷是否是十六進制數
小寫字母a~f,大寫字母A~F的字符
若是則返回非0數(也就是ture)
若不是則返回0(也就是false)
函數用途:
islower#include
#include int main() { char c = 0; scanf("%c", &c); int ret = isxdigit(c); if (ret == 0) { printf("%c NO is 十六進制\n", c); } else { printf("%c YES 十六進制\n", c); } return 0; } 小寫字母:a~z
函數原型:int islower?( int c );
函數作用:
? 傳入一個字符,
判斷是否是小寫字母:a~z
若是則返回非0數(也就是ture)
若不是則返回0(也就是false)
函數用途:
isupper#include
#include int main() { char c = 0; scanf("%c", &c); int ret = islower(c); if (ret == 0) { printf("%c NO is 小寫字母\n", c); } else { printf("%c YES 小寫字母\n", c); } return 0; } 大寫字母A~Z
函數原型:int isupper?( int c );
函數作用:
? 傳入一個字符,
判斷是否是大寫字母:A~Z
若是則返回非0數(也就是ture)
若不是則返回0(也就是false)
函數用途:
isalpha#include
#include int main() { char c = 0; scanf("%c", &c); int ret = isupper(c); if (ret == 0) { printf("%c NO is 大寫字母\n", c); } else { printf("%c YES 大寫字母\n", c); } return 0; } 字母a~z或者A~Z
函數原型:int isalpha?( int c );
函數作用:
? 傳入一個字符,
判斷是否是大寫或者小寫字母
若是則返回非0數(也就是ture)
若不是則返回0(也就是false)
函數用途:
isalnum#include
#include int main() { char c = 0; scanf("%c", &c); int ret = isalpha(c); if (ret == 0) { printf("%c NO is 字母\n", c); } else { printf("%c YES 字母\n", c); } return 0; } 字母或者數字,A~Z ,a~z,0~9
函數原型:int isalnum?( int c );
函數作用:
? 傳入一個字符,
判斷是否是
大寫或者小寫字母或者是數字字符
若是則返回非0數(也就是ture)
若不是則返回0(也就是false)
函數用途:
ispunct#include
#include int main() { char c = 0; scanf("%c", &c); int ret = isalnum(c); if (ret == 0) { printf("%c NO is 字母或數字\n", c); } else { printf("%c YES 字母或數字\n", c); } return 0; } 標點符號,任何不屬于數字或者字母的圖形字符(可打印)
函數原型:int ispunct?( int c );
函數作用:
? 傳入一個字符,
判斷是否是
? 不屬于數字或者字母的圖形字符
若是則返回非0數(也就是ture)
若不是則返回0(也就是false)
函數用途:
isgraph#include
#include int main() { char c = 0; scanf("%c", &c); int ret = ispunct(c); if (ret == 0) { printf("%c NO is 它屬于數字或字母\n", c); } else { printf("%c YES 它不屬于字母或數字\n", c); } return 0; } 任何圖形字符
函數原型:int isgraph?( int c );
函數作用:
? 傳入一個字符,
判斷是否是圖形字符
若是則返回非0數(也就是ture)
若不是則返回0(也就是false)
函數用途:
isprint#include
#include int main() { char c = 0; scanf("%c", &c); int ret = isgraph(c); if (ret == 0) { printf("%c NO is 它不是圖形字符\n", c); } else { printf("%c YES 它是圖形字符\n", c); } return 0; } 任何可打印字符,包括圖形字符和空白字符
函數原型:int isprint?( int c );
函數作用:
? 傳入一個字符,
判斷是否是可打印的字符
? 包含圖形字符和空白字符
若是則返回非0數(也就是ture)
若不是則返回0(也就是false)
函數用途:
tolower#include
#include int main() { char c = 0; scanf("%c", &c); int ret = isprint(c); if (ret == 0) { printf("%c NO is 它不是可打印的字符\n", c); } else { printf("%c YES 它是可打印的字符\n", c); } return 0; } 字母大寫轉小寫
函數原型:int tolower?( int c );
函數作用:
? 傳入一個字符,
判斷是否是大寫字母A~Z
? 若是將其轉為對應小寫字母
函數用途:
toupper#include
#include #include int main() { //將字符串的大寫字母全部轉為小寫字母 char str[] = "abcDEfGjK"; int i = 0; for (i = 0; i< strlen(str); i++) { if (isupper(str[i])!=0)//判斷是否是大寫字母 { str[i] = tolower(str[i]);//大寫轉小寫 } } printf("%s\n", str); return 0; } 字母小寫轉大寫
函數原型:int toupper?( int c );
函數作用:
? 傳入一個字符,
判斷是否是小寫字母a~z
? 若是將其轉為對應大寫字母
函數用途:
#include
#include #include int main() { //將字符串的小寫字母全部轉為大寫字母 char str[] = "abcDEfGjK"; int i = 0; for (i = 0; i< strlen(str); i++) { if (islower(str[i])!=0)//判斷是否是小寫字母 { str[i] = toupper(str[i]);//小寫轉大寫 } } printf("%s\n", str); return 0; }
memcpy內存拷貝函數
函數原型:void * memcpy ( void * destination, const void * source, size_t num );
返回值:void?*
? 返回值是一個任意類型的指針
?返回拷貝好的內存空間的起始地址
參數:void * destination, const void * source, size_t num
目的地:
destination是一個任意類型的指針
源頭:
source是一個任意類型的指針
? 用const修飾,
說明source指向的內存空間的內容不可修改
字節數:
num是一個無符號整型
函數的作用:
將source 指向的空間
里面的num個字節的數據
復制到destination指向的空間中
返回值,返回的是:
拷貝好之后 destination指向的空間的地址
? destination指向的內存空間要足夠大
? 至少能容納下拷貝之后的數據
? 這個函數遇到'\0'時根本就不會停下來
? 直到拷貝夠num字節數就停止
? memcpy函數不能勝任重疊拷貝
? 自己拷貝自己
函數用途:如下代碼:
#include
#include // 定義結構體 struct { char name[40]; int age; } person, person_copy; //創建結構體全局變量 person,和 per_copy int main() { char myname[] = "Pierre de Fermat"; //創建一個字符串 //將myname整個字符串的內容,拷貝到結構體變量person 的成員變量 name 空間中 memcpy(person.name, myname, strlen(myname) + 1); //再給變量person的成員變量 age 賦值為46 person.age = 46; //將變量person 的空間的內容,全部拷貝 到變量 person_copy的空間中 memcpy(&person_copy, &person, sizeof(person)); //將變量 person_copy 空間中的內容打印出來 printf("person_copy: %s, %d \n", person_copy.name, person_copy.age); return 0; }
memmove內存拷貝函數(指定字節數)
函數原型:void * memmove ( void * destination, const void * source, size_t num );
返回值:void?*
? 返回值是一個任意類型的指針
?返回拷貝好的內存空間的起始地址
參數:void * destination, const void * source, size_t num
目的地:
destination是一個任意類型的指針
源頭:
source是一個任意類型的指針
? 用const修飾,
說明source指向的內存空間的內容不可修改
字節數:
num是一個無符號整型
函數的作用:
將source 指向的空間
里面的num個字節的數據
復制到destination指向的空間中
返回值,返回的是:
拷貝好之后 destination指向的空間的地址
? destination指向的內存空間要足夠大
? 至少能容納下拷貝之后的數據
? 這個函數遇到'\0'時根本就不會停下來
? 直到拷貝夠num字節數就停止
? memmove函數可以勝任重疊拷貝
? 自己可以拷貝自己
函數用途:如下代碼:
#include
#include int main() { //創建字符串數組并初始化 char str[] = "memmove can be very useful......"; //str+20 取到的是字符u的地址 //str+15 取到的是字符v的地址 //從v字符還是往后拷貝11個字節的數據到 str+20的位置 //自己拷貝自己 重疊拷貝 memmove(str + 20, str + 15, 11); //打印重疊拷貝后的str puts(str); return 0; }
memcmp內存比較函數
函數原型:int memcmp ( const void * ptr1,const void * ptr2,size_t num );
返回值:int
返回一個有符號整數
返回小于0的數
返回等于0的數
返回大于0的數
參數:const void * ptr1,const void * ptr2,size_t num
目的地:
ptr1指向任意類型的一塊內存空間
用const修飾
說明ptr1指向的空間的內容不可被修改
源頭:
ptr2指向任意類型的一塊內存空間
用const修飾
說明ptr2指向的空間的內容不可被修改
num是一個無符號整型
表示字節個數
函數作用:
從ptr1和ptr2分別指向空間首地址開始
一個字節一個字節,一一對應進行比較
比較num個字節,
當ptr1大于ptr2返回大于0的數
當ptr1等于ptr2返回數字0
當ptr1小于ptr2返回小于0的數
函數用途:如下代碼:
#include
#include int main() { //創建兩個字符串 char buffer1[] = "DWgaOtP12df0"; char buffer2[] = "DWGAOTP12DF0"; //將buffer1 跟 buffer2 的 前sizeof(buffer1) 個字節 進行比較 //一個字節 一個字節 往后一一比較 要是相同往后繼續比較 //只要遇到不等的字節 就停止比較,返回這兩個字節比較的結果 //buffer1 大于 buffer2 返回大于0的數字 //buffer1 等于 buffer2 返回數字0 //buffer1 小于 buffer2 返回小于0的數 int n = 0; 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; }
memset庫函數的模擬實現內存填充函數
函數原型:void * memset ( void * ptr, int value, size_t num );
返回值:void *
?返回任意類型的指針
?返回被修改后的內存空間的地址
參數:void * ptr, int value, size_t num
ptr是一個任意類型的指針
指向一片任意類型的空間
value是一個有符號整型
表示要修改的值
num是一個無符號整型
表示要修改的字節數
函數作用:
將ptr指向的內存塊
? 前num個字節的內容設置為value
? 從ptr的位置開始向后num個字節
? 的內容修改成value
函數用途:如下代碼
#include
#include int main() { int arr[] = { 1,2,3,4,5,6,7,8,9,10 }; int sz = sizeof(arr) / sizeof(arr[0]); //數組名表示數組首元素地址 //將arr指向的內存塊的前20個字節,每個字節的內容都設置為0 memset(arr, 0, 20); int i = 0; for (i = 0; i< sz; i++) { printf("%d ", arr[i]); } printf("\n"); char str[] = "xxxxxxxxx"; //將str指向的內存塊的前5個字節,每個字節的內容都設置為'a’ memset(str, 'a', 5); printf("%s\n", str); return 0; }
模擬實現strlen函數原型:size_t strlen(const char* str);
原理:strlen函數是計算字符串的長度
?也就是計算'\0'之前的字符的個數
模擬實現:
實現1:
#include
size_t my_strlen(const char* str) { size_t count = 0; while (*str != '\0') { count++; str++; } return count; } int main() { char str[] = "abcdefgh"; size_t len = my_strlen(str); printf("%d\n", len); return 0; } 實現2:
#include
//遞歸方式實現 size_t my_strlen(const char* str) { if (*str != '\0') { return 1 + my_strlen(str+1); } return 0; } int main() { char str[] = "abcdefgh"; size_t len = my_strlen(str); printf("%d\n", len); return 0; } 實現3:
#include
size_t my_strlen(const char* str) { char* p = str; while (*str++); return str - p - 1; } int main() { char str[] = "abcdefgh"; size_t len = my_strlen(str); printf("%d\n", len); return 0; }
模擬實現strcpy函數原型:char * strcpy ( char * destination, const char * source );
原理:strcpy就是將source指向空間的內容
?復制到destination指向的空間里
?在復制的同時會將source的'\0'也復制過去
?復制完成后將str1返回
模擬實現:
#include
#include //模擬實現strcpy char* my_strcpy(char* str1, const char* str2) { assert(str1 && str2); char* p = str1; while (*str1++ = *str2++); return p; } int main() { char str1[50] = "xxxxxxxxxxxxxxxxxxxx"; char str2[] = "abcdefg"; //將str2的內容賦值到str1中 //str1的空間要足夠大 my_strcpy(str1, str2); printf("%s\n", str1); return 0; }
模擬實現strcat函數原型:char * strcat ( char * destination, const char * source );
原理:將source指向的字符串的內容
?追加到destination指向的字符串的后面
?追加的時候destination字符串的'\0'字符
?會被source字符串的首字符覆蓋
?且會將source字符串的'\0'也追加上來
?且返回追加完成后的destination
模擬實現;
#include
#include //模擬實現 strcat char* my_strcat(char* dest, const char* src) { assert(dest && src); char* p = dest; while (*dest) { dest++; } while ((*dest++ = *src++)); return p; } int main() { char str1[50] = "abcdef"; char str2[] = "ghijklmn"; //將str2字符串的內容追加到str1后面 //在追加的時候會將str1字符串的'\0'覆蓋掉 my_strcat(str1, str2); printf("%s\n", str1); return 0; }
模擬實現strstr函數原型:const char * strstr ( const char * str1, const char * str2 );
原理:尋找str1這個字符串中是否包含str2字符串
若是包含則返回str2第一次出現的位置
否則返回NULL
也就是判斷str2是否是str1的子串
模擬實現:
#include
#include //模擬實現strstr函數 char* my_strstr(const char* str1, const char* str2) { assert(str1 && str2); char* p = (char*)str1; char* s1 = NULL; char* s2 = NULL; if (*str2 == '\0') { return (char*)str1; } while (*p) { s1 = p; s2 = (char*)str2; while (*s1 && *s2 && !(*s1 - *s2)) { s1++; s2++; } if (!*s2) { return p; } p++; } return NULL; } int main() { char str1[] = "kkkabcdefghijklmnabcdefgxyz"; char str2[] = "abcdef"; //查找str2是否是str1的子串 //若是返回str2第一次出現的位置 //不是則返回NULL char* p = my_strstr(str1, str2); if (p == NULL) { printf("不是子串\n"); } else { printf("是子串\n"); printf("從返回的地址處開始打?。?s\n", p); } return 0; }
模擬實現strcmp函數原型:int strcmp ( const char * str1, const char * str2 );
原理: 讓str1字符串與str2字符串
?從首字符開始一個字符一個字符向后比較
?若兩個字符相等則繼續向后比較
?直到出現兩個字符不等的情況下停止比較
?并且返回這兩個不同字符比較的結果
?若str1大于str2返回大于0的數
?若str1等于str2返回等于0的數
?若str1小于str2返回小于0的數
模擬實現:
#include
#include //模擬實現strcmp函數 int my_strcmp(const char* str1, const char* str2) { assert(str1 && str2); while (*str1 && *str2) { if (*str1 == *str2) { str1++; str2++; } else { return (*str1 - *str2); } } return (*str1 - *str2); } int main() { char str1[] = "abcdefg"; char str2[] = "abcdhjk"; int ret = my_strcmp(str1, str2); if (ret == 0) { printf("str1 = str2\n"); } else if (ret >0) { printf("str1 >str2\n"); } else { printf("str1< str2\n"); } return 0; }
模擬實現memcpy函數原型:void * memcpy ( void * destination, const void * source, size_t num );
原理:將source指向的內存塊中
?num個字節的內容復制到
?destination指向的內存塊中
?返回復制完成后的destination
一般情況下不能勝任重疊拷貝
也就是自己拷貝自己
模擬實現:
#include
#include //模擬實現memcpy void* my_memcpy(void* dest, void* src, size_t num) { assert(dest && src); void* p = dest; while (num--) { *(char*)dest = *(char*)src; ++(char*)dest; ++(char*)src; } return p; } int main() { //拷貝整型 int arr[] = { 1,2,3,4,5 }; int brr[] = { 6,7,8,9,10 }; int sz = sizeof(arr) / sizeof(arr[0]); my_memcpy(arr,brr,8); int i = 0; for (i = 0; i< sz; i++) { printf("%d ", arr[i]); } printf("\n"); //拷貝字符串 char str1[] = "xxxxxxxxxx"; char str2[] = "abcde"; my_memcpy(str1, str2, 5); printf("%s\n", str1); return 0; }
模擬實現memmove函數原型:void * memmove ( void * destination, const void * source, size_t num );
原理:將source指向的內存塊中
?num個字節的內容復制到
?destination指向的內存塊中
?返回復制完成后的destination
?完全勝任重疊拷貝
?可以自己拷貝自己
模擬實現:
#include
#include //模擬實現,memmove //可實現重疊拷貝 //當dest src時從后向前 //當dest=src時從前向后 從后向前 void* my_memmove(void* dest, void* src, size_t num) { void* p = dest; assert(dest && src); if (dest >src) { dest = (char*)dest + num-1; src = (char*)src + num-1; while (num--) { *(char*)dest = *(char*)src; dest=(char*)dest-1; src=(char*)src-1; } } else { while (num--) { *(char*)dest = *(char*)src; ++(char*)dest; ++(char*)src; } } return p; } int main() { //拷貝整型 int arr[] = { 6,7,8,9,10 }; int brr[] = { 1,2,3,4,5 }; int sz = sizeof(arr) / sizeof(arr[0]); my_memmove(arr, brr, 12); int i = 0; for (i = 0; i< sz; i++) { printf("%d ", arr[i]); } printf("\n"); //拷貝字符串 char str1[] = "yyyyyyyyyy"; char str2[] = "abcdef"; my_memmove(str1, str2, 4); printf("%s\n", str1); //重疊拷貝 int prr[] = { 1,2,3,4,5,6,7,8,9,10 }; int s = sizeof(prr) / sizeof(prr[0]); my_memmove(prr + 5, prr, 12); int j = 0; for (j = 0; j< s; j++) { printf("%d ", prr[j]); } return 0; }
你是否還在尋找穩定的海外服務器提供商?創新互聯www.cdcxhl.cn海外機房具備T級流量清洗系統配攻擊溯源,準確流量調度確保服務器高可用性,企業級服務器適合批量采購,新人活動首月15元起,快前往官網查看詳情吧
當前標題:字符串+內存函數(C語言)-創新互聯
文章來源:http://newbst.com/article10/dgidgo.html
成都網站建設公司_創新互聯,為您提供服務器托管、建站公司、網站策劃、外貿網站建設、用戶體驗、外貿建站
聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯