国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

手撕C語言進階---字符串和內存函數(詳解+實現+原碼)

vslam / 1009人閱讀

摘要:自己實現時返回值可根據實際情況而定源字符串必須以結束。語言中給了一些長度受限的字符串函數,而前面的函數是長度不受限的字符串函數。拷貝個字符從源字符串到目標空間。

目錄

字符函數和字符串函數

函數介紹

strlen

strcpy

strcat

strcmp

strncpy

?strncat

strncmp

strstr

strtok

strerror

memcpy

memmove

memcmp


字符函數和字符串函數

本章重點

重點介紹處理字符和字符串的庫函數的使用和注意事項
求字符串長度
  • strlen
長度不受限制的字符串函數
  • strcpy
  • strcat
  • strcmp
長度受限制的字符串函數介紹
  • strncpy
  • strncat
  • strncmp
字符串查找
  • strstr
  • strtok
錯誤信息報告
  • strerror
字符操作
內存操作函數
  • memcpy
  • memmove
  • memset
  • memcmp

?前言

C 語言中對字符和字符串的處理很是頻繁,但是 C 語言本身是沒有字符串類型的,字符串通常放在 常量字符串 中 或者 字符數組 中。 字符串常量 適用于那些對它不做修改的字符串數。

函數介紹

strlen

size_t strlen ( const char * str );

  • 字符串已經 "/0" 作為結束標志,strlen函數返回的是在字符串中 "/0" 前面出現的字符個數(不包含 "/0" )。
  • 參數指向的字符串必須要以 "/0" 結束。
  • 注意函數的返回值為size_t,是無符號的( 易錯 )
  • 學會strlen函數的模擬實現

?注:size_t 即無符號整型(unsigned int)

strlen使用:

#include#includeint main(){	char arr1[] = "abcdef";	char arr2[] = { "a","b","c","d","e","f","/0"};//計算字符數組長度時末尾必須加"/0",                                                  //否則計算出的長度為隨機值.	printf("%d/n", strlen(arr1));	printf("%d/n", strlen(arr2));	return 0;}

?strlen模擬實現:

//方法一:使用計數器size_t my_strlen(char* str){	assert(str);//檢查指針有效性	int count = 0;//計數器	//while (*str != "/0")	//{		//count++;		//str++;	//}		//簡化	while(*str++)	{		count++;	}	return count;}//方法二:遞歸size_t my_strlen2(char* str){	assert(str);	if (!*str)	{		return 0;	}	else	{		return 1 + my_strlen(str + 1);	}}//方法三:指針減指針size_t my_strlen3(char* str){	assert(str);	char* cur = str;	while (*cur)	{		cur++;	}	return cur - str;//兩指針相減,結果為他們之間的元素個數}

注:下面的代碼結果如何?

#include #include int main(){    const char*str1 = "abcdef";    const char*str2 = "bbb";    if(strlen(str2)-strlen(str1)>0)//由于strlen函數的返回值為無符號整型,                                   //所以在計算時,會恒為正數。自己實現時返回值可根據實際情況而定    {        printf("str2>str1/n");    }    else    {        printf("srt1>str2/n");    }    return 0;}

strcpy

char* strcpy(char * destination, const char * source );

  • Copies the C string pointed by source into the array pointed by destination, including the terminating null
  • character (and stopping at that point).
  • 源字符串必須以 "/0" 結束。
  • 會將源字符串中的 "/0" 拷貝到目標空間。
  • 目標空間必須足夠大,以確保能存放源字符串。
  • 目標空間必須可變。
  • 學會模擬實現

?strcpy使用:

#include#includeint main(){	char arr1[10] = "xxxxxxxxx";	char arr2[] = "abcdef";	printf("%s/n", strcpy(arr1, arr2));//將arr2字符串中的內容拷貝到arr1中(包括"/0)	return 0;                          //需保證arr1的空間大于等于arr2的空間}

strcpy模擬實現:

#include//用assert函數需包含此頭文件char* my_strcpy(char* dest, const char* src)//返回值為目標空間的起始地址,src中的字符串                                           //不需要改變,為避免被修改所以再它前面加上const{	assert(dest && src);//檢查指針的有效性	char* ret = dest;//保存目標空間的起始地址,dest后面會移動	//while (*src!="/0")	//{	//	*dest = *src;	//	dest++;	//	src++;	//}	//簡化	while (*dest++ = *src++)//src先將值賦給dest,然后dest和src才++	{		;	}	return ret;}

strcat

char * strcat ( char * destination, const char * source );

  • Appends a copy of the source string to the destination string. The terminating null character indestination is overwritten by the first character of source, and a null-character is included at the end ofthe new string formed by the concatenation of both in destination.
  • 源字符串必須以 "/0" 結束。
  • 目標空間必須有足夠的大,能容納下源字符串的內容。
  • 目標空間必須可修改。
  • 字符串自己給自己追加,如何?

?strcat使用:

#include#includeint main(){	char arr1[10] = "abcd";	char arr2[] = "efgh";	printf("%s", strcat(arr1, arr2));//將arr2中的字符串追加到arr1中的字符串后面	return 0;                        //需保證arr1的空間容納連接后的字符串}

strcat模擬實現:

#includechar* my_strcat(char* dest, const char* src){	assert(dest && src);	char* ret = dest;	while (*dest)//因為是將src中的字符串追加到dest的后面所以需先找到dest中"/0"的位置	{		dest++;	}	while (*dest++ = *src++)//同strcpy	{		;	}	return ret;}

其中大概步驟如圖:?

?

strcmp

int strcmp ( const char * str1, const char * str2 );

  • ?This function starts comparing the first character of each string. If they are equal to each other, itcontinues with the following pairs until the characters differ or until a terminating null-character isreached.

  • 標準規定:
  • 第一個字符串大于第二個字符串,則返回大于0的數字
  • 第一個字符串等于第二個字符串,則返回0
  • 第一個字符串小于第二個字符串,則返回小于0的數字
  • 那么如何判斷兩個字符串?

strcmp使用 :

#include#includeint main(){	char arr1[] = "abcdef";	char arr2[] = "abcdxx";	int ret = strcmp(arr1, arr2);	if (ret > 0)	{		printf("arr1 > arr2/n");	}	else if (ret < 0)	{		printf("arr1 < arr2/n");	}	else	{		printf("arr1 = arr2/n");	}	return 0;}

strcmp模擬實現

#includeint my_strcmp(const char* str1, const char* str2)//str1和str2都不需要被改變{	assert(str1 && str2);	while (*str1 == *str2)//如果找到不相等的字符直接返回他們的ascll碼值之差,                          //而不是將所有的字符全部比較完之后再返回.	{		if (*str1 == "/0")		{			return 0;		}		str1++;		str2++;	}	return *str1 - *str2;}

前面學習了這些字符串函數之后,大家是否有些許收獲呢?

其實這些函數中有些是不安全的,比如:strcpy中如果目標空間的大小不能夠容納原空間的字符串,就會造成數組越界訪問,strcat中也是同樣的道理。還有如果字符串自己給自己追加,是不能使用strcat函數的;如果我們只想比較字符串中的部分字符串的大小,而不是全部,也不能使用strcmp。C語言中給了一些長度受限的字符串函數,而前面的函數是長度不受限的字符串函數

strncpy

char * strncpy ( char * destination, const char * source, size_t num );

  • Copies the first num characters of source to destination. If the end of the source C string (which issignaled by a null-character) is found before num characters have been copied, destination is paddedwith zeros until a total of num characters have been written to it.
  • 拷貝num個字符從源字符串到目標空間。
  • 如果源字符串的長度小于num,則拷貝完源字符串之后,在目標的后邊追加0,直到num個。

?strncpy使用:

#include#includeint main(){	char arr1[] = "xxxxxxxxxx";	char arr2[] = "xx";	char arr3[] = "abcdef";	printf("%s/n", strncpy(arr1, arr3, 8));//拷貝了8個字符,所以字符串中的"/0"也會被拷貝	printf("%s/n", strncpy(arr2, arr3, 1));//拷貝了1個字符,"/0"不會被拷貝	return 0;}

strncpy模擬實現:

#includechar* my_strncpy(char* dest, const char* src, int count)//參數count為需要拷貝的字節數{	assert(dest && src);	char* ret = dest;	while(count--)	{		*dest++ = *src++;	}	return ret;}

?strncat

char * strncat ( char * destination, const char * source, size_t num );

  • Appends the first num characters of source to destination, plus a terminating null-character.
  • If the length of the C string in source is less than num, only the content up to the terminating nullcharacter is copied.

?strncat使用:

/* strncat example */#include #include 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;}

?strncat模擬實現:

char* my_strncat(char* dest, const char* src, int count){	assert(dest && src);	char* ret = dest;	while (*dest)//找到目標字符串中"/0"的位置	{		dest++;	}	while (count--)	{		*dest++ = *src++;//從"/0"處開始追加	}        *dest = "/0";//末尾需"/0"	return ret;}

strncmp

int strncmp ( const char * str1, const char * str2, size_t num );

  • ?比較到出現另個字符不一樣或者一個字符串結束或者num個字符全部比較完。

strncmp使用:?

/* strncmp example */#include #include 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;}

strncmp模擬實現:

int my_strncmp(char* str1, char* str2, int count){	assert(str1 && str2);	while (*str1 == *str2)	{		if (count <= 0)		{			return 0;		}		str1++;		str2++;			}    return *str1 - *str2;}

strstr

char * strstr ( const char *str1, const char *str2 );?

  • 在str1中查找 是否存在str2字符串,如果有則返回str2第一次出現的位置的地址,否則返回NULL;

strstr使用:

/* strstr example */#include #include int main (){    char str[] ="This is a simple string";    char * pch;    pch = strstr (str,"simple");    strncpy (pch,"sample",6);    puts (str);    return 0;}

strstr模擬實現:

char* my_strstr(const char* str1, const char* str2){	assert(str1 && str2);	while (*str1)	{		char* cur1 = str1;		char* cur2 = str2;		while (*cur1 == *cur2)		{			cur1++;			cur2++;			if (*cur2 == "/0")			{				return str1;			}		}		str1++;	}	return NULL;}

?

?此情況下可直接判斷str2是否是str1的子串,并且返回相應的值。

?

當比較到第三個字符時,兩字符不相等,而str1并未結束,后續還需比較,所以cur2需回到起始地址,而cur1會回到第一個相等字符的下一個字符的地址處(即第二個b的地址)?。

?

strtok

char * strtok ( char * str, const char * sep );

  • sep參數是個字符串,定義了用作分隔符的字符集合。
  • 第一個參數指定一個字符串,它包含了0個或者多個由sep字符串中一個或者多個分隔符分割的標記。
  • strtok函數找到str中的下一個標記,并將其用 /0 結尾,返回一個指向這個標記的指針。(注:strtok函數會改
  • 變被操作的字符串,所以在使用strtok函數切分的字符串一般都是臨時拷貝的內容并且可修改。)
  • strtok函數的第一個參數不為 NULL ,函數將找到str中第一個標記,strtok函數將保存它在字符串中的位置。
  • strtok函數的第一個參數為 NULL ,函數將在同一個字符串中被保存的位置開始,查找下一個標記。
  • 如果字符串中不存在更多的標記,則返回 NULL 指針。

strtok使用:

/* strtok example */#include #include int main (){    char str[] ="- This, a sample string.";    char * pch;    printf ("Splitting string /"%s/" into tokens:/n",str);    pch = strtok (str," ,.-");    while (pch != NULL)    {        printf ("%s/n",pch);        pch = strtok (NULL, " ,.-");    }    return 0;}

strerror

char * strerror ( int errnum );

返回錯誤碼,所對應的錯誤信息。

/* strerror example : error list */#include #include #include //必須包含的頭文件int main (){    FILE * pFile;    pFile = fopen ("unexist.ent","r");    if (pFile == NULL)    printf ("Error opening file unexist.ent: %s/n",strerror(errno));    //出現錯誤時,會將錯誤碼(一種錯誤對應一個錯誤碼)放進errno中,strerror會將這個錯誤碼對應的內容打印出來    //errno: Last error number    return 0;}

例如:?

#include#include#includeint main(){	printf("%s/n", strerror(0));	printf("%s/n", strerror(1));	printf("%s/n", strerror(2));	printf("%s/n", strerror(3));	return 0;}

對應錯誤碼結果為:

memcpy

void * memcpy ( void * destination, const void * source, size_t num );

  • 函數memcpy從source的位置開始向后復制num個字節的數據到destination的內存位置。
  • 這個函數在遇到 "/0" 的時候并不會停下來。
  • 如果source和destination有任何的重疊,復制的結果都是未定義的。
  • 返回值為目標空間首地址。
    ?

memcpy使用:

#include#includeint main(){	int arr1[] = { 1,2,3,4,5,6,7,8,9 };	int arr2[10] = { 0 };	int* ret = memcpy(arr2, arr1, 16);	int i = 0;	for (i = 0; i < 10; i++)	{		printf("%d ", ret[i]);	}	return 0;}

memcpy模擬實現:

#includevoid* my_memcpy(void* dest, const void* src, size_t count)//以字節為單位拷貝{	assert(dest && src);	void* ret = dest;	while (count--)	{		*(char*)dest = *(char*)src;		dest = (char*)dest + 1;		src = (char*)src + 1;	}	return ret;}

memmove

void * memmove ( void * destination, const void * source, size_t num );

  • 和memcpy的差別就是memmove函數處理的源內存塊和目標內存塊是可以重疊的。
  • 如果源空間和目標空間出現重疊,就得使用memmove函數處理。

memmove使用:

/* memmove example */#include #include int main (){    char str[] = "memmove can be very useful......";    memmove (str+20,str+15,11);    puts (str);    return 0;}

memmove模擬實現:

情況一:不存在內存重疊,可直接將內容移動。?

情況二:存在內存重疊,且目標空間地址大于源空間地址,?如圖將1移動到3的位置之后,3就會被覆蓋,在移動3時實際移動的是1.

?解決方法:從后往前移動,先移動4,再移動3直到所有字節移動完。

?

情況三:存在內存重疊,且目標空間地址小于源空間地址,如果再從后向前移動也會導致前面的內容被覆蓋。

解決方法:從前往后移動,先移動3,再移動4直到所有字節移動完。

?實現代碼:

void* my_memmove(void* dest, const void* src, size_t count){	assert(dest && src);	void* ret = dest;	if (dest > src)//情況二	{		void* cur1 = (char*)src + count - 1;//從后往前移動,需先找到兩個空間的末尾地址		void* cur2 = (char*)dest + count - 1;//減1是因為加count之后會直接跳到目標空間和源空間的尾地址的下一個字節的地址		while (count--)		{			*(char*)cur2 = *(char*)cur1;//void*內型指針不能直接加減或解引用操作,需強制類型轉換			cur2 = (char*)cur2 - 1;//指針移動			cur1 = (char*)cur1 - 1;		}	}	else//情況1一,三	{		void* cur1 = (char*)src;		void* cur2 = (char*)dest;		while (count--)		{			*(char*)cur2 = *(char*)cur1;			cur2 = (char*)cur2 + 1;			cur1 = (char*)cur1 + 1;		}	}	return ret;}

memcmp

int memcmp ( const void * ptr1,
? ? ? ? ? ? ? ? ? ? ? ?const void * ptr2,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ?size_t num );

  • 比較從ptr1和ptr2指針開始的num個字節
  • 返回值如下:
    ?

?memcmp使用:

/* memcmp example */#include #include 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);    return 0;}

memcmp模擬實現:

int my_memcmp(const void* str1, const void* str2, int count){	assert(str1 && str2);	while (*(char*)str1 == *(char*)str2)	{		count--;		if (count <= 0)		{			return 0;		}		str1 = (char*)str1 + 1;		str2 = (char*)str2 + 1;	}	return (char*)str1 - (char*)str2;}

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/120819.html

相關文章

  • C語言進階第一問:數據在內存中是如何存儲的?(手把手帶你深度剖析數據在內卒中的存儲,超全解析,碼住不

    摘要:在符號位中,表示正,表示負。我們知道對于整型來說,內存中存放的是該數的補碼。在計算機系統中,數值一律用補碼來表示和存儲。表示有效數字,。規定對于位的浮點數,最高的位是 ...

    ghnor 評論0 收藏0
  • C語言進階】??數據類型&amp;&amp;整型在內存中的存儲

    目錄 ? ?一、數據類型介紹 二、類型的意義 三、類型的基本歸類 整型家族 浮點數家族 構造類型(自定義類型) 指針類型 空類型 四、整形在內存中的存儲 原碼、反碼、補碼 大小端字節序 為什么有大端和小端? 一道經典筆試題 ?一、數據類型介紹 數據從大的方向分為兩類: 內置類型自定義類型內置類型我們前面已經學習過,如下: char? ? ? ? ? ? //字符數據類型 short? ? ? ...

    Xufc 評論0 收藏0
  • C語言進階學習】一、數據的存儲 (深度剖析數據在內存中的存儲)

    摘要:的理解和區別代表有符號,整數在內存中存儲的二進制位的最高位為符號位,表示負數,表示正數。那接下來我們來學習數據在所開辟的內存空間時如何存儲的。請看下面例子為什么內存中存儲的是補碼對于整數來說數據存放內存中其實存放的是補碼。 ...

    AprilJ 評論0 收藏0
  • 詳解c語言整形浮點數在內存中的存儲

    摘要:目錄數據在計算機的存儲方式補碼,反碼,原碼數據在計算機的存儲方式補碼,反碼,原碼整形在內存中的存儲整形在內存中的存儲整形類型整形類型大端字節序和小端字節序大端字節序和小端字節序浮點數在內存的儲存浮點數在內 目錄 數據在計算機的存儲方式(補碼,反碼,原碼) 整形在內存中的存儲: ? ?整形...

    不知名網友 評論0 收藏0
  • 玩轉指針,手撕c語言——(指針進階

    摘要:函數的返回值為指針就按照字面意思,指針函數的定義顧名思義,指針函數即返回指針的函數。 目錄 前言指針與函數函數的返回值為指針作為函數參數的指針指針函數可以改變變量...

    genedna 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<