最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C語(yǔ)言的字符串函數(shù),內(nèi)存函數(shù)筆記詳解

 更新時(shí)間:2021年09月16日 15:34:41   作者:我還是學(xué)習(xí)吧  
這篇文章主要給大家介紹了關(guān)于C語(yǔ)言字符串/內(nèi)存的相關(guān)函數(shù),文中通過(guò)示例代碼總結(jié)的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用C語(yǔ)言具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

strlen

此函數(shù)接收一個(gè)char*類型參數(shù),返回字符串\0前字符數(shù),注意返回類型是size_t型的

//關(guān)于strlen返回值的一個(gè)易錯(cuò)點(diǎn)
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模擬實(shí)現(xiàn)

法一

使用計(jì)數(shù)器

size_t my_strlen1(const char* str)
{
	assert(str);
	int count = 0;
	while (*str++)
	{
		count++;
	}
	return count;
}

法二

指針相減

size_t my_strlen2(const char* str)
{
	assert(str);
	char* start = str;
	while (*str!='\0')//注意這種寫(xiě)法不能寫(xiě)*str++;這里要先判斷再++;*str++的寫(xiě)法在'\0'的地方也+1了
	{
		str++;
	}
	return str - start;//\0與起始位置的差就是字符數(shù)
}

法三

遞歸,不適用臨時(shí)變量

size_t my_strlen3(const char* str)
{
	if ('\0' == *str)
		return 0;
	else
		return 1 + my_strlen3(str + 1);
}

strcpy

此函數(shù)接收兩個(gè)char*類型參數(shù),把后一個(gè)字符串拷貝到前一個(gè)字符串中,包括\0,注意前一個(gè)指針指向的數(shù)組空間要足夠大,被拷貝的內(nèi)容必須包含\0

strcpy的模擬實(shí)現(xiàn)

char* my_strcpy(char* dest, const char* src)
{
	assert(dest && src);
	char* ret = dest;
	while (*dest++ = *src++)
	{
		;
	}
	return ret;
}
int main()
{
	char arr1[20] = "hello underworld";//注意寫(xiě)成數(shù)組
	char arr2[20] = "hello world";

	printf("%s\n", arr2);
	printf("%s\n", my_strcpy(arr2, arr1));

	return 0;
}

strcat

此函數(shù)接收兩個(gè)char*參數(shù),在前一個(gè)字符串\0的位置開(kāi)始拷貝后一個(gè)字符串,直到后一個(gè)字符串的\0,返回前一個(gè)字符串首地址。注意要保證前一個(gè)指針指向的空間足夠大

strcat的模擬實(shí)現(xiàn)

char* my_strcat(char* dest, const char* src)
{
	char* ret = dest;
	assert(dest && src);
	while (*dest)//讓dest到達(dá)str1的\0位置
	{
		dest++;
	}
	while (*dest++ = *src++)//這一部分和strcpy同
	{
		;
	}
	return ret;
}
int main()
{
	char arr1[20] = "hello ";
	char arr2[20] = "underworld";

	printf("%s\n", my_strcat(arr1, arr2));

	return 0;
}

strcmp

接收兩個(gè)char*參數(shù),依次比較每個(gè)字符,在第一個(gè)不相等的字符處比較他們的編碼值,前者大則返回一個(gè)大于0的數(shù),前者小則返回一個(gè)小于0的數(shù),字符串完全相等則返回0

strcmp模擬實(shí)現(xiàn)

int my_strcmp(const char* str1, const char* str2)
{
	while (*str1 == *str2)
	{
		if (*str1 == '\0')//說(shuō)明兩個(gè)字符串同時(shí)到達(dá)結(jié)束標(biāo)記
			return 0;
		str1++;
		str2++;
	}
	return *str1 - *str2;//如果不是在循環(huán)內(nèi)部返回,就一定不相等,而字符相減可以反映大小
}
int main()
{
	char *str1 = "hello world";
	char *str2 = "hello underworld";

	printf("%d\n", my_strcmp(str1, str2));//w比u大

	return 0;
}

strstr

接收兩個(gè)char*參數(shù),返回第二個(gè)字符串在第一個(gè)字符串第一次出現(xiàn)的首位置指針

strstr模擬實(shí)現(xiàn)

char* my_strstr(const char* str1, const char* str2)
{
	assert(str1 && str2);

	char* s1;//s1維護(hù)str1
	char* s2;//s2維護(hù)str2
	char* cp = str1;//cp用來(lái)記錄比較開(kāi)始的位置

	if (*str2 == '\0')//特殊情況
		return str1;

	while (*cp)
	{
		s1 = cp;
		s2 = str2;

		while (*s1 != '\0' && *s2 != '\0' && *s1 == *s2)//其實(shí)*s1='\0'且*s2!='\0'時(shí)已經(jīng)沒(méi)有比較下去的必要了
			//*s1==*s2就讓兩個(gè)維護(hù)指針?lè)謩e+1;不等就讓cp+1,s1和s2分別重置		
		{
			s1++;
			s2++;
		}
		if (*s2 == '\0')//*s2=='\0'說(shuō)明找到了
		{
			return cp;
		}
		cp++;
	}

	return NULL;
}

應(yīng)用KMP算法的strstr

void get_next(char* str, int* next)
{
	int i, k;
	i = 0;
	k = -1;
	next[0] = -1;//這個(gè)值沒(méi)用;或者說(shuō)是為了使i增加而j不增加
	int len = strlen(str);
	while (i < len - 1)//next數(shù)組最大下標(biāo)是字符串長(zhǎng)度減1,數(shù)組長(zhǎng)度和字符串長(zhǎng)度相同
	{
		if (k == -1 || *(str + i) == *(str + k))
		{
			++i;
			++k;
			next[i] = k;
		}
		else
			k = next[k];
	}

	//測(cè)試打印next
	int z;
	printf("next:");
	for (z = 0; z < len; z++)
	{
		printf("%d ", next[z]);
	}
	printf("\n");
}

int Index_KMP(char* str1, char* str2, int pos)
{
	int i = pos;
	int j = 0;
	int next[255];
	get_next(str2, next);
	int len1 = strlen(str1);
	int len2 = strlen(str2);
	int count = 0;
	while (i < len1 && j < len2)//i從0到10(len1=11),共11次,但是考慮到走else的回溯,單字符查找一共循環(huán)22次
	{
		count++;
		if (j == -1 || *(str1 + i) == *(str2 + j))//先判斷,再把下標(biāo)加1
		{
			++i;
			++j;
		}
		else
		{
			j = next[j];
		}
	}
	printf("i=%d\n", i);
	printf("j=%d\n", j);
	printf("count=%d\n", count);//是存在回溯的,那么這個(gè)函數(shù)的時(shí)間復(fù)雜度還是O(m)嗎?
	//if ((len2!=1) && (j >=(len2-1)))//有缺陷,對(duì)于len2=1的情況無(wú)法處理
	if (j >= (len2 - 1))//單字符查找情形,while結(jié)束時(shí)j=0,而len2-1也=0,故不能作為找到了的標(biāo)志
		//對(duì)于單字符查找以外的情形,len2-1一定大于0,len2-1代表的就是目標(biāo)串最后一個(gè)字符的下標(biāo),既然j
		//到達(dá)了這個(gè)位置,就說(shuō)明完全匹配了
		return i - len2;//由于字符串長(zhǎng)度與數(shù)組下標(biāo)的差異造成len2=1時(shí)
	else
		return 0;
}
int main()
{
	char* str1 = "hello underworld!";
	char* str2 = "under";

	printf("%s\n", my_strstr(str1, str2));
	printf("%s\n", *(str1+Index_KMP(str1, str2, 0)));

	return 0;
}

strncpy

比strcpy多一個(gè)參數(shù),描述拷貝的字節(jié)數(shù),如果多于str2的長(zhǎng)度,則會(huì)補(bǔ)0

int main()
{
	char arr1[20] = "abcdefghi";
	char arr2[] = "xxxx";

	//strncpy(arr1, arr2, 6);//從arr2拷貝6個(gè)字符給arr1?如果arr2長(zhǎng)度不夠,則補(bǔ)0
	//strncpy(arr1, arr2, 3);//長(zhǎng)度不夠不拷貝\0
	//strncpy(arr1, arr2, 4);
	strncpy(arr1, arr2, 5);

	printf("%s\n", arr1);
	return 0;
}

strncat

比strcat多一個(gè)參數(shù),最多只拷貝完整的str2(包括\0)

int main()
{
	char arr1[20] = "abc\0xxxxxxx";
	char arr2[] = "def";

	//strncat(arr1, arr2, 6);//在arr1后面接上arr2的六個(gè)字符?最多只接arr2這么長(zhǎng)的字符串,包括\0
	//strncat(arr1, arr2, 3);//自己會(huì)加上\0
	strncat(arr1, arr2, 2);

	printf("%s\n", arr1);
	return 0;
}

strncmp

比strcmp多一個(gè)參數(shù),描述比較的字節(jié)數(shù)

int main()
{
	char arr1[] = "abcdew";
	char arr2[] = "abcdeqj";

	printf("%d\n",strncmp(arr1, arr2, 5));
	printf("%d\n",strncmp(arr1, arr2, 6));

	return 0;
}

strtok

字符串分割函數(shù),接收兩個(gè)char*參數(shù),第一個(gè)是要被分割的字符串,第二個(gè)是分割符,分割符順序不重要;第一個(gè)參數(shù)不為NULL時(shí),返回分割的第一段;第一個(gè)參數(shù)為NULL,將從上個(gè)位置開(kāi)始查找下一段

int main()
{
	char arr1[] = "cjh@scu.edu";
	char arr2[100] = { 0 };//保存臨時(shí)數(shù)據(jù)
	char sep[] = "@.";
	char* ret = NULL;//接收strtok的返回值
	strcpy(arr2, arr1);
	for (ret = strtok(arr2, sep); ret != NULL; ret = strtok(NULL, sep))
	{
		printf("%s\n", ret);
	}

	return 0;
}
int main()
{
	char str[] = "- This, a sample string.";
	char* pch;
	printf("Splitting string \"%s\" into tokens:\n", str);
	pch = strtok(str, ", .-");//分隔標(biāo)記的位置不重要
	while (pch != NULL)
	{
		printf("%s\n", pch);
		pch = strtok(NULL, " ,.-");//注意這里有空格
	}
	return 0;
}

memcpy

接收三個(gè)參數(shù),第一個(gè)是char的目標(biāo)位置,第二個(gè)是被拷貝的char的數(shù)據(jù)源,最后一個(gè)是size_t的拷貝字節(jié)數(shù)。注意標(biāo)準(zhǔn)未定義把自己的內(nèi)容拷貝被自己的結(jié)果。

memcpy模擬實(shí)現(xiàn)

void* my_memcpy(void* dest, void* src, size_t count)
{
	void* ret = dest;
	assert(dest && src);

	while (count--)
	{
		*(char*)dest = *(char*)src;
		dest = (char*)dest + 1;
		src = (char*)src + 1;
	}
	//printf("%d\n", count);//count=-1
	return ret;
}
int main()
{
	int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr2[20] = { 0 };

	my_memcpy(arr2, arr1, 10 * sizeof(int));

	int i;
	for (i = 0; i < 20; i++)
	{
		printf("%d ", arr2[i]);
	}

	return 0;

memmove

此函數(shù)原型和memcpy一樣,包含額memcpy的功能,且可以處理把自己的內(nèi)容拷貝給自己的情景

#include <stdio.h>
#include <string.h>
int main()
{
	char str[] = "memmove can be very useful......";
	printf("%c\n", *(str + 15));
	printf("%c\n", *(str + 20));

	memmove(str + 20, str + 15, 11);//注意memmove和memcpy不會(huì)遇到\0停下來(lái),什么時(shí)候停取決于第三個(gè)參數(shù)
	puts(str);
	return 0;
}

memmove模擬實(shí)現(xiàn)

void* my_memmove(void* dest, void* src, size_t count)//關(guān)鍵在于拷貝之前先判斷是否會(huì)出現(xiàn)overlap
{
	void* ret = dest;
	if (dest <= src || (char*)dest >= ((char*)src + count))
	{
		while (count--)
		{
			*(char*)dest = *(char*)src;
			dest = (char*)dest + 1;
			src = (char*)src + 1;
		}
	}
	else
	{
		dest = (char*)dest + count - 1;
		src = (char*)src + count - 1;
		while (count--)
		{
			*(char*)dest = *(char*)src;
			dest = (char*)dest - 1;
			src = (char*)src - 1;
		}
	}
	return ret;
}
int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };

	my_memmove(arr + 2, arr, 4 * sizeof(int));//1 2 1 2 3 4 7 8 9 10  
	//my_memcpy(arr + 2, arr, 4 * sizeof(int));//1 2 1 2 1 2 7 8 9 10

	int i;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

memcmp

接收三個(gè)參數(shù),前兩個(gè)是void*型,指向被比較的兩塊內(nèi)容,最后一個(gè)size_t的參數(shù)表示要比較多少字節(jié)

#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);
	return 0;
}

字符分類函數(shù)

函數(shù) 如果他的參數(shù)符合下列條件就返回真

  • iscntrl 任何控制字符
  • isspace 空白字符:空格‘ ',換頁(yè)‘\f',換行'\n',回車(chē)‘\r',制表符'\t'或者垂直制表符'\v'
  • isdigit 十進(jìn)制數(shù)字 0~9
  • isxdigit 十六進(jìn)制數(shù)字,包括所有十進(jìn)制數(shù)字,小寫(xiě)字母af,大寫(xiě)字母AF
  • islower 小寫(xiě)字母a~z
  • isupper 大寫(xiě)字母A~Z
  • isalpha 字母az或AZ
  • isalnum 字母或者數(shù)字,az,AZ,0~9
  • ispunct 標(biāo)點(diǎn)符號(hào),任何不屬于數(shù)字或者字母的圖形字符(可打?。?/li>
  • isgraph 任何圖形字符
  • isprint 任何可打印字符,包括圖形字符和空白字符

字符串換函數(shù)

  • tolower()
  • toupper()
#include <stdio.h>
int main ()
{
  int i=0;
  char str[]="Test String.\n";
  char c;
  while (str[i])
 {
    c=str[i];
    if (isupper(c)) 
        c=tolower(c);
    putchar (c);
    i++;
 }
  return 0; }

總結(jié)

本篇文章就到這里了,希望能夠給你帶來(lái)幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!

相關(guān)文章

  • C語(yǔ)言實(shí)現(xiàn)的程序員老黃歷實(shí)例

    C語(yǔ)言實(shí)現(xiàn)的程序員老黃歷實(shí)例

    這篇文章主要介紹了C語(yǔ)言實(shí)現(xiàn)的程序員老黃歷,涉及日期的判定及流程控制的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-07-07
  • 探究一下C語(yǔ)言生成隨機(jī)數(shù)的奧秘

    探究一下C語(yǔ)言生成隨機(jī)數(shù)的奧秘

    C語(yǔ)言中生成隨機(jī)數(shù)是一項(xiàng)非常重要的功能,因?yàn)樵S多現(xiàn)代應(yīng)用程序需要使用隨機(jī)數(shù)。本文就來(lái)帶大家一起探究一下C語(yǔ)言生成隨機(jī)數(shù)的奧秘吧
    2023-03-03
  • OpenCV 圖像金字塔的實(shí)現(xiàn)示例

    OpenCV 圖像金字塔的實(shí)現(xiàn)示例

    本文將結(jié)合實(shí)例代碼,介紹OpenCV 圖像金字塔,對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-06-06
  • C++泛型編程基本概念詳解

    C++泛型編程基本概念詳解

    這一篇介紹一下 C++ 編程中與面向?qū)ο蟛⒘械牧硪淮蠓种А盒途幊蹋@一篇主要介紹函數(shù)模板、類模板和成員模板三大部分,需要的朋友可以參考下
    2021-08-08
  • C++實(shí)現(xiàn)簡(jiǎn)單通訊錄

    C++實(shí)現(xiàn)簡(jiǎn)單通訊錄

    這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)簡(jiǎn)單通訊錄,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-12-12
  • C++ 中placement new 操作符使用方法

    C++ 中placement new 操作符使用方法

    這篇文章主要介紹了C++ 中placement new 操作符使用方法的相關(guān)資料,需要的朋友可以參考下
    2017-05-05
  • C++的std::transform()的實(shí)現(xiàn)

    C++的std::transform()的實(shí)現(xiàn)

    在 C++ 標(biāo)準(zhǔn)庫(kù)中,std::transform() 是一個(gè)非常有用的算法函數(shù),它能夠?qū)⒔o定范圍中的每個(gè)元素進(jìn)行變換,并將變換后的結(jié)果存儲(chǔ)到另一個(gè)范圍中,本文就詳細(xì)的介紹一下具體用法,感興趣的可以了解一下
    2023-08-08
  • C++11新特性之四種類型轉(zhuǎn)換cast說(shuō)明

    C++11新特性之四種類型轉(zhuǎn)換cast說(shuō)明

    類型轉(zhuǎn)換是項(xiàng)目中常使用的一種語(yǔ)法規(guī)則,幾乎每個(gè)編程語(yǔ)言都不可避免的涉及到這方面,下面這篇文章主要給大家介紹了關(guān)于C++11新特性之四種類型轉(zhuǎn)換cast說(shuō)明的相關(guān)資料,需要的朋友可以參考下
    2023-02-02
  • C語(yǔ)言實(shí)現(xiàn)三子棋游戲含完整代碼

    C語(yǔ)言實(shí)現(xiàn)三子棋游戲含完整代碼

    本文詳細(xì)講解了C語(yǔ)言實(shí)現(xiàn)三子棋游戲內(nèi)含完整代碼,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-11-11
  • VC6實(shí)現(xiàn)激活后臺(tái)窗口最佳方法

    VC6實(shí)現(xiàn)激活后臺(tái)窗口最佳方法

    這篇文章主要介紹了VC6實(shí)現(xiàn)激活后臺(tái)窗口最佳方法,實(shí)例分析了VC操作后臺(tái)窗口的技巧,需要的朋友可以參考下
    2015-06-06

最新評(píng)論

溆浦县| 即墨市| 巩留县| 宜兰市| 大同市| 综艺| 阿瓦提县| 个旧市| 彭州市| 阳曲县| 兴安县| 巩留县| 虹口区| 万州区| 河西区| 高淳县| 康定县| 横山县| 镇康县| 田阳县| 丁青县| 丰城市| 陕西省| 金坛市| 土默特左旗| 泰宁县| 昌平区| 田阳县| 任丘市| 阿拉善左旗| 鄂伦春自治旗| 永兴县| 铅山县| 牟定县| 海丰县| 永城市| 涿鹿县| 奎屯市| 龙门县| 延安市| 叶城县|