??前面的話??
本篇博客是關于C語言庫函式指標的介紹,關于??庫函式詳解??,來看看這些C語言必備庫函式你都會了嗎,大家可以根據目錄尋找哦,
👋Hi~ o( ̄▽ ̄)ブ這里是豬豬程式員
👀 很高興見到你O(∩_∩)O!
🌱 現在正在發芽中…
💞? 博主水平有限,如果發現錯誤,一定要及時告知作者哦 o( ̄︶ ̄)o!感謝感謝!
📫博主的碼云 gitee,平常博主寫的程式代碼都在里面,
??庫函式詳解??
- 📌求字串長度
- ????1. strlen
- 📌長度不受限制的字串函式
- ????2. strcpy
- ????3. strcat
- ????4. strcmp
- 📌長度受限制的字串函式介紹
- ????5. strncpy
- ????6. strncat
- ????7. strncmp
- 📌字串查找
- ????8. strstr
- ????9. strtok
- 📌錯誤資訊報告
- ????10.strerror
- 📌記憶體操作函式
- ????11. memcpy
- ????12. memmove
- ????13. memset
- ????14. memcmp
📌求字串長度
????1. strlen
🌿語法:
size_t strlen ( const char * str )
🌿用處:strlen是一個計數器的作業,它從記憶體的某個位置(可以是字串開頭,中間某個位置,甚至是某個不確定的記憶體區域)開始掃描,直到碰到第一個字串結束符’\0’為止,然后回傳計數器值,
🌿注意事項:
strlen計算字串str的(unsigned int型)長度,不包括’\0’在內
🌿舉例:
##include <stdio.h>
#include <string.h>
int main(void){
char str [50] = "HelloWorld'\0'Hi";//定義字符陣列str容量:50
int len = strlen(str);//定義整數型別int len,然后把strlen(str)計算出來的長度賦值給len
printf("len的長度:%d\n",len);
return 0;
}
🌿輸出結果:
len的長度:11//計算長度"HelloWorld"+'共11個,不包括\0'
🌿實作自己的mystrlen
int mystrlen(char c[])
{
int i = 0;
while (c[i]) //c[i]!=NULL
{
i++;
}
return i;
}
int main()
{
char c[20] = "abcdef";
int t = mystrlen(c);
printf("%d", t);
return 0;
}//🌿🌿🌿輸出結果:6
📌長度不受限制的字串函式
????2. strcpy
🌿語法:
char * strcpy ( char * destination, const char * source )
🌿用處:把 source 所指向的字串復制到destination
🌿注意事項:
- 源字串必須以 ‘\0’ 結束,
- 會將源字串中的 ‘\0’ 拷貝到目標空間,
- 目標空間必須足夠大,以確保能存放源字串,
- 目標空間必須可變,
🌿舉例:
/* strcpy example */
#include <stdio.h>
#include <string.h>
int main ()
{
char str1[]="Sample string";
char str2[40];
char str3[40];
strcpy (str2,str1);
strcpy (str3,"copy successful");
printf ("str1: %s\nstr2: %s\nstr3: %s\n",str1,str2,str3);
return 0;
}
🌿輸出結果:
str1: Sample string
str2: Sample string
str3: copy successful
🌿實作自己的mystrcpy
void mystrcpy(char to[], char from[])
{
int i = 0;
while (from[i]) //from[i]!=NULL
{
to[i] = from[i];
i++;
}
to[i] = 0; //將陣列to[]的最后一個字符的后面加上結束符
}
int main()
{
char to[20] = "abcdef";
char from[20] = "ghijk";
mystrcpy(to, from);
printf("%s", to);
return 0;
}//🌿🌿🌿輸出結果:ghijk
????3. strcat
🌿語法:
char * strcat ( char * destination, const char * source )
🌿用處:將一個字串source追加到另一個字串destination的結尾處,構成一個新的字串
🌿注意事項:
- 源字串
source必須以 ‘\0’ 結束, - 目標空間
destination必須有足夠的大,能容納下源字串的內容, - 目標空間
destination必須可修改,
🌿舉例:
int main()
{
char dest[30] = { "hello" };
char src[] = {"world"};
strcat(dest, src);
printf("%s", dest);
return 0;
}
輸出結果:
helloworld
🌿實作自己的mystrcat
char* my_strcat(char* dest, const char* src)
{
char* ret = dest;
while (*dest)//找到目標函式結尾的‘\0’
{
dest++;
}
while (*dest++ = *src++)//追加到源字串
{
;
}
return ret;
}
int main()
{
char a1[30] = { "abc" };
char a2[] = { "def" };
my_strcat(a1, a2);
printf("%s", a1);
return 0;
}
????4. strcmp
🌿語法:
int strcmp ( const char * str1, const char * str2 )//注意!!!這里比較的是字串的內容而非長度
🌿用處:比較兩個字串的大小
這個庫函式有什么用呢?
🌿🌿使用場景:當我們要比較輸入的密碼是否相等時就可以使用~
🌿標準規定:
從第一個字符開始進行比較,若相同則比較下一個字符:
- 若第一個字串大于第二個字串,則回傳
大于0的數字 - 若第一個字串等于第二個字串,則
回傳0 - 若第一個字串小于第二個字串,則回傳
小于0的數字
🌿舉例:
#include <stdio.h>
#include <string.h>
int main(void)
{
char *a = "English";
char *b = "ENGLISH";
char *c = "english";
//strcmp()只能比較字串, 其他形式的引數不能比較
printf("strcmp(a, b):%d\n", strcmp(a, b));//字串之間的比較
printf("strcmp(a, c):%d\n", strcmp(a, c));
return 0;
}
🌿🌿輸出結果:
strcmp(a, b):1
strcmp(a, c):-1
🌿實作自己的mystrcmp
int mystrcmp(const char* str1, const char* str2)
{
while ( *str1 == *str2)
{
if (*str1 == '\0')
return 0;
str1++; str2++;
}
return *str1 - *str2;
}
int main()
{
char str1[] = { "hello" };
char str2[] = { "world" };
int t = mystrcmp(str1 , str2);
printf("%d", t);
return 0;
}//🌿🌿🌿輸出結果:-15
📌長度受限制的字串函式介紹
🍂🍂🍂相信大家發現字串受限制的函式與不受限制的函式相比多了一個變數num,這樣來說函式相對安全一點,因為有個個數限制
????5. strncpy
🌿語法:
char * strncpy ( char * destination, const char * source, size_t num )
🌿用處:把從source地址開始且含有NULL結束符的字串復制到以destination開始的地址空間
🌿注意事項:
拷貝num個字符從源字串到目標空間,
如果源字串的長度小于num,則拷貝完源字串之后,在目標的后邊追加0,直到num個,
🌿舉例:
/* strncpy example */
#include <stdio.h>
#include <string.h>
int main ()
{
char str1[]= "To be or not to be";
char str2[40];
char str3[40];
strncpy ( str2, str1, sizeof(str2) );
strncpy ( str3, str2, 5 );
str3[5] = '\0'; /* null character manually added */
puts (str1);
puts (str2);
puts (str3);
return 0;
}
🌿🌿輸出結果:
To be or not to be
To be or not to be
To be
🌿實作自己的mystrncpy
char* mystrncpy(char *dest, const char *src, size_t count)
{
char *tmp = dest;
while (count) {
if ((*tmp = *src) != 0)
src++;
tmp++;
count--;
}
return dest;
}
????6. strncat
🌿語法:
char * strncat ( char * destination, const char * source, size_t num )
🌿用處:將一個字串追加到另一個字串的結尾處
🌿注意事項:
如果num大于可以追加的字串個數,那么就只追加到 ' \0 ' 就結束
🌿舉例:
/* strncat example */
#include <stdio.h>
#include <string.h>
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;
}
🌿🌿輸出結果:
To be or not to be
🌿實作自己的mystrncat
char* mystrncat(char* dest, const char* src, int n)
{
char* ret = dest;
while (*dest != '\0')
{
dest++;
}
while (n && (*dest++ = *src++) != '\0')
{
n--;
}
dest = '\0';
return ret;
}
int main()
{
char dest[20] = "abcedf" ;
char src[20] = "ghijk";
char* t = mystrncat(dest, src,3);
printf("%s", t);
return 0;
}
//🌿🌿🌿運行結果:abcedfghi
????7. strncmp
🌿語法:
int strncmp ( const char * str1, const char * str2, size_t num );
🌿用處:比較兩個字串的大小
🌿注意事項:
🌿🌿比較到出現另個字符不一樣或者一個字串結束或者num個字符全部比較完,
從第一個字符開始進行比較,若相同則比較下一個字符:
- 若第一個字串大于第二個字串,則回傳
大于0的數字 - 若第一個字串等于第二個字串,則
回傳0 - 若第一個字串小于第二個字串,則回傳
小于0的數字
🌿舉例:
/* strncmp example */
#include <stdio.h>
#include <string.h>
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)
{
printf ("found %s\n",str[n]);
}
return 0;
}
🌿🌿輸出結果:
Looking for R2 astromech droids...
found R2D2
found R2A6
🌿實作自己的mystrncmp
int mystrncmp(const char* str1, const char* str2,int num)
{
char* ret = str1;
while ( *str1 == *str2 && num>0)
{
if (*str2 == '\0')
*ret = '\0';
str1++; str2++; num--;
}
return ret;
}
📌字串查找
????8. strstr
🌿語法:
char * strstr ( const char *str2, const char * str1);
🌿用處:strstr(str1,str2) 函式用于判斷字串str2是否是str1的子串,如果是,則該函式回傳str2在str1中首次出現的地址;否則,回傳NULL,
🌿注意事項:
🌿🌿比較到出現另個字符不一樣或者一個字串結束或者num個字符全部比較完,
從第一個字符開始進行比較,若相同則比較下一個字符:
1.若第一個字串大于第二個字串,則回傳大于0的數字
2.若第一個字串等于第二個字串,則回傳0
3.若第一個字串小于第二個字串,則回傳小于0的數字
🌿舉例:
/* strstr example */
#include <stdio.h>
#include <string.h>
int main ()
{
char str[] ="This is a simple string";
char * pch;
pch = strstr (str,"simple");
if (pch != NULL)
strncpy (pch,"sample",6);
puts (str);
return 0;
}
🌿🌿輸出結果:
This is a sample string
🌿實作自己的mystrstr
char* mystrstr(const char* str1, const char* str2)
{
char* s1;
char* s2;
char* cp = str1;
if ( *str2 == '\0')
return str1;
while (*cp)
{
s1 = cp;
s2 = str2;
while (*s1 != '\0' && *s2!= '\0' && * s1 == *s2)
{
s1++; s2++;
}
if (*s2 == '\0')
{
return cp;
}
cp++;
}
return NULL;
}
int main()
{
char str1[] = { "helloworld" };
char str2[] = { "world" };
char* t = mystrstr(str1 , str2);
printf("%s", t);
return 0;
}
????9. strtok
🌿語法:
char * strtok ( char * str, const char * delimiters )
🌿用處:
作用于字串str,以delimiters中的字符為分界符,將str切分成一個個子串;如果,str為空值NULL,則函式保存的指標SAVE_PTR在下一次呼叫中將作為起始位置,
回傳值:分隔符匹配到的第一個子串
🌿注意事項:
1、函式的作用是分解字串,所謂分解,即沒有生成新串,只是在s所指向的內容首次出現分界符的位置,將分界符修改成了’/0’,故第一次用strtok回傳第一個子串
2、第一次提取子串完畢之后,繼續對源字串str進行提取,應在其后(第二次,第三次…第n次)的呼叫中將strtok的第一個引數賦為空值NULL(表示函式繼續從上一次呼叫隱式保存的位置,繼續分解字串;對于前一次次呼叫來說,第一次呼叫結束前用一個this指標指向了分界符的下一位)
3、當this指標指向“\0” 時,即沒有被分割的子串了,此時則回傳NULL
4、可以把delimiters理解為分隔符的集合,delimiters中的字符均可以作為分隔符,
5、strtok在呼叫的時候,如果起始位置即為分隔符,則忽略了起始位置開始的分隔符
6、strtok函式找到str中的下一個標記,并將其用 \0 結尾,回傳一個指向這個標記的指標,(注:strtok函式會改變被操作的字串,所以在使用strtok函式切分的字串一般都是臨時拷貝的內容并且可修改,)
🌿舉例:
/* strtok example */
#include <stdio.h>
#include <string.h>
int main ()
{
char str[] ="- This, a sample string.";
char * pch;
pch = strtok (str," ,.-");
while (pch != NULL)
{
printf ("%s\n",pch);
pch = strtok (NULL, " ,.-");//這里填 NULL即可,因為函式會記住之前已經查找完的字符的下一個起始位置
}
return 0;
}
🌿🌿輸出結果:
This
a
sample
string
📌錯誤資訊報告
????10.strerror
🌿語法:
char * strerror ( int errnum )
🌿用處:
strerror()用來依引數errnum 的錯誤代碼來查詢其錯誤原因的描述字串, 然后將該字串指標回傳
🌿注意事項:
在程式代碼中包含 #include <errno.h>,然后每次程式呼叫失敗的時候,系統會自動用用錯誤代碼填充errno這個全域變數,只需要讀errno這個全域變數就可以獲得失敗原因了,
🌿🌿每個錯誤碼都有對應的錯誤資訊:
🌿🌿🌿如下列印0,1,2,3的錯誤碼:
int main()
{
printf("%s\n", strerror(0));
printf("%s\n", strerror(1));
printf("%s\n", strerror(2));
printf("%s\n", strerror(3));
return 0;
}
🌿🌿🌿結果分別如下顯示:
No error
Operation not permitted
No such file or directory
No such process
🌿舉例:
/* strerror example : error list */
#include <stdio.h>
#include <string.h>
#include <errno.h>
int main ()
{
FILE * pFile;
pFile = fopen ("unexist.ent","r");
if (pFile == NULL)
printf ("%s\n",strerror(errno));
return 0;
}
🌿🌿輸出結果:
No such file or directory
📌記憶體操作函式
????11. memcpy
🌿語法:
void * memcpy ( void * destination, const void * source, size_t num )
🌿用處:
以source指向的地址為起點,將連續的num個位元組資料,復制到以 destination指向的地址為起點的記憶體中,函式有三個引數,第一個是目標地址,第二個是源地址,第三個是資料長度
回傳值:分隔符匹配到的第一個子串
🌿注意事項:
1.函式memcpy從source的位置開始向后復制num個位元組的資料到destination的記憶體位置,
2.這個函式在遇到 ‘\0’ 的時候并不會停下來,
3.如果source和destination有任何的重疊,復制的結果都是錯誤的,此時就要用到另一個庫函式memmove,
🌿舉例:
int main()
{
int a[10] = { 1,2,3,4,5,6,7,8,9 };
int b[20] = { 0 };
memcpy(b, a, 40); //這里的40相當于10*sizeof(int)
for (int i = 0; i < 20; i++)
{
printf("%d ", b[i]);
}
return 0;
}
🌿🌿輸出結果:
1 2 3 4 5 6 7 8 9 0 0 0 0 0 0 0 0 0 0 0
🌿實作自己的memcpy
void* mymemcpy(void* dest, const void* src, size_t count)
{
void* ret = dest;
while (count--)
{
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
return ret;
}
int main()
{
int a[10] = { 1,2,3,4,5,6,7,8,9 };
int b[20] = { 0 };
mymemcpy(b, a, 40);
for (int i = 0; i < 20; i++)
{
printf("%d ", b[i]);
}
return 0;
}
????12. memmove
🌿語法:
void * memmove ( void * destination, const void * source, size_t num )
🌿用處:
當使用memcpy時,存在記憶體重疊問題時可能會出錯(比如把自身字串后面一截復制到前面一截),memmove解決了此問題,解決問題的方法是當出現記憶體重疊時,從后往前開始拷貝
🌿注意事項:
- memmove和memcpy的差別就是memmove函式處理的源記憶體塊和目標記憶體塊是可以重疊的,
- 如果源空間和目標空間出現重疊,就得使用memmove函式處理,
🌿舉例:
/* memmove example */
#include <stdio.h>
#include <string.h>
int main ()
{
char str[] = "memmove can be very useful......";
memmove (str+20,str+15,11);
puts (str);
return 0;
}
🌿🌿輸出結果:
memmove can be very very useful.
🌿實作自己的memmove
void* mymemmove(void* dest, const void* src, size_t count)
{
void* ret = dest;
if (dest < src)
{
while (count--)
{
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
}
else
{
while (count--)
{
*((char*)dest + count) = *((char*)src + count);
}
}
return ret;
}
int main()
{
int a[10] = { 1,2,3,4,5,6,7,8,9 };
mymemmove(a+2, a, 16);
for (int i = 0; i < 10; i++)
{
printf("%d ", a[i]);
}
return 0;
}
????13. memset
🌿語法:
void *memset(void *s, int ch, size_t n);
🌿用處:
將某一塊記憶體中的內容全部設定為指定的值, 這個函式通常為新申請的記憶體做初始化作業,
🌿注意事項:
-
memset() 函式常用于記憶體空間初始化,
-
memset()的深刻內涵: 用來對一段記憶體空間全部設定為某個字符,一般用在對定義的字串進行初始化
例如:memset(a,’\0’,sizeof(a));
- memset可以方便的清空一個結構型別的變數或陣列,
🌿舉例:
/* memset example */
#include <stdio.h>
#include <string.h>
int main ()
{
char str[] = "almost every programmer should know memset!";
memset (str,'-',6);
puts (str);
return 0;
}
🌿🌿輸出結果:
------ every programmer should know memset!
????14. memcmp
🌿語法:
int memcmp(const void *buf1, const void *buf2, unsigned int count);
🌿用處:
-
當buf1<buf2時,回傳值<0
-
當buf1=buf2時,回傳值=0
-
當buf1>buf2時,回傳值>0
🌿注意事項:
- 該函式是按位元組比較的,
🌿🌿🌿例如:
s1,s2為字串時候memcmp(s1,s2,1)就是比較s1和s2的第一個位元組的ascII碼值;
memcmp(s1,s2,n)就是比較s1和s2的前n個位元組的ascII碼值;
char *s1="abc";
char *s2="acd";
int r=memcmp(s1,s2,3);
就是比較s1和s2的前3個位元組,第一個位元組相等,第二個位元組比較中大小已經確定,不必繼續比較第三位元組了所以r=-1.
- 對于memcmp(),如果兩個字串相同而且count大于字串長度的話,memcmp不會在\0處停下來,會繼續比較\0后面的記憶體單元.
- 如果想使用memcmp比較字串,要保證count不能超過最短字串的長度,否則結果有可能是錯誤的,
🌿舉例:
/* memcmp example */
#include <stdio.h>
#include <string.h>
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);
re
🌿🌿輸出結果:
'DWgaOtP12df0' is greater than 'DWGAOTP12DF0'.
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/301995.html
標籤:其他
