欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C語言中字符串庫函數(shù)的實(shí)現(xiàn)及模擬

 更新時間:2022年11月07日 10:30:16   作者:諾諾的包包  
C語言中有很多數(shù)據(jù)類型,比如int(整數(shù)類型)、char(字符類型)、以及浮點(diǎn)型的double(雙精度)等。但是有一點(diǎn)就是我們發(fā)現(xiàn)這里并沒有提到我們常見的有關(guān)字符串的類型。本文為大家介紹了C語言中字符串庫函數(shù)的實(shí)現(xiàn)及模擬,需要的可以參考一下

前言

我們已經(jīng)了解了C語言中很多數(shù)據(jù)類型,比如int(整數(shù)類型)、char(字符類型)、以及浮點(diǎn)型的double(雙精度)、float(單精度),但是有一點(diǎn)就是我們發(fā)現(xiàn)這里并沒有提到我們常見的有關(guān)字符串的類型。其實(shí)在C語言中,字符串通常是放在 常量字符串 中或者 字符數(shù)組 中的。(常量字符串是不可被修改的)

1.strlen的實(shí)現(xiàn)及模擬(求字符串長度)

字符串是雙引號" "引起來的,以 ‘\0’ 作為結(jié)束標(biāo)志,strlen是專門用來求字符串長度的,strlen函數(shù)返回的是在字符串中 ‘\0’ 前面出現(xiàn)的字符個數(shù)(不包含 ‘\0’ )。并且返回值必須是正數(shù),因?yàn)樽址麄€數(shù)不存在負(fù)數(shù)情況!

使用以及模擬實(shí)現(xiàn)

#include<stdio.h>//printf頭文件
#include<string.h>//strlen頭文件
#include<assert.h>//assert頭文件

//返回值為無符號類型(正數(shù))
//模擬實(shí)現(xiàn),這里盡量做到還原原函數(shù)的形式
size_t my_strlen(const char* str)
{
	assert(str);//斷言,如果str是NULL,編譯器報(bào)錯
	const char* start = str;//首字符地址賦給start以及end
	const char* end = str;
	while (*end != '\0')//當(dāng)end指向'\0'時結(jié)束
	{
		end++;
	}
	return end - start;//指針相減得到兩者之間元素個數(shù)
}
int main()
{
	char arr[] = "abcdef";
	printf("%d\n", strlen(arr));//arr是數(shù)組名,表示數(shù)組首元素地址,即a的地址,返回值為\0之前的字符個數(shù),即6
	int len=my_strlen(arr);
	printf("%d\n", len);//6
	return 0;
}

這里我是采用指針-指針=兩指針之間元素個數(shù)的方式,還有很多方式都可以模擬實(shí)現(xiàn),比如創(chuàng)建一個變量計(jì)數(shù)的方式等,如下:

size_t my_strlen(const char * str)
{
 assert(str);//斷言
 size_t count = 0;//無符號
 while(*str)
 {
  count++;//指針從起始位置開始往前走,每走一次count++一次
  str++;
 }
 return count;//最后返回count
}

2.strcmp的實(shí)現(xiàn)及模擬 (字符串比較)

strcmp是用來比較兩個字符串的。兩個字符串比較的其實(shí)是各字符所對應(yīng)的ASCII碼值,如下:

使用以及模擬實(shí)現(xiàn)

#include<string.h>//strcpy頭文件包含
#include<stdio.h>//printf頭文件包含
#include<assert.h>//斷言
int my_strcmp(const char* s1, const char* s2)
{
	assert(s1 && s2);//斷言
	while (*s1 == *s2)//如果兩個字符串中對應(yīng)的字符相等,則繼續(xù)往后找
	{
		if (*s1 == '\0')//當(dāng)s1到\0時,說明s2也是\0,字符串直到結(jié)束,兩者都相等
			return 0;//返回0
		//如果沒到\0,繼續(xù)往后走,進(jìn)行下一個字符比較	
		s1++;
		s2++;
	}
	//當(dāng)跳出循環(huán)時,說明s1與s2指向的字符不相等,直接返回兩者之差即可
	return *s1 - *s2;
	//*s1 -*s2>0  即 *s1>*s2,即字符數(shù)組arr1中的字符串>arr2中的
	              //反之則小于
}

int main()
{
    //字符串存放在字符數(shù)組
	char arr1[] = "abcdeaf";
	char arr2[] = "abcdef";
	//模擬實(shí)現(xiàn)
	int len=my_strcmp(arr1, arr2);
    //strcmp兩個參數(shù),arr1,arr2數(shù)組名,即首元素地址,即字符串首字符地址
	printf("%d\n", strcmp(arr1, arr2));//-5
	printf("%d\n", len);//-5         a對應(yīng)ASCII:97  f:102
	                                  //   97-102 ==-5
	return 0;
}

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

strncmp與strcmp很類似,也是用來比較兩個字符串的,唯一的區(qū)別就是strcmp是比較整個字符串,而strncmp可以指定比較的第多少個字符,比如說比較abcdef與abcdfg兩個字符串的前三個字符,結(jié)果返回值就是0。因?yàn)閮H僅比較的是前三個字符,即abc。

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

#include<string.h>
#include<stdio.h>
#include<assert.h>
int my_strncmp(const char* str1, const char* str2, size_t num)
{
	assert(str1 && str2);//斷言
	//比較前num個字符,兩者相等時,進(jìn)入循環(huán),繼續(xù)往后比,num限制比較字符數(shù)
	while (--num && (*str1) && (*str1 == *str2))
	{
		str1++;
		str2++;
	}
	//跳出循環(huán),說明num比完了,或者有一方遇到\0,或者兩字符不相等
	//直接返回兩者之差
	return *str1 - *str2;
}

int main()
{
	char arr1[] = "abcdef";
	char arr2[] = "abcbefgg";
	int num = 0;
	scanf("%d", &num);
	//比較字符串a(chǎn)rr1與arr2的前num個字符
	int len=my_strncmp(arr1, arr2,num);

	//printf("%d\n", strncmp(arr1, arr2,3));//0
	printf("%d\n", len);// num=3,len=0;num=4,len>0
	return 0;
}

3.strcpy的實(shí)現(xiàn)及模擬(字符串拷貝)

strcpy是用來拷貝字符串的

注意事項(xiàng)

  • !!! 源字符串必須以 ‘\0’ 結(jié)束。
  • !!! 會將源字符串中的 ‘\0’ 拷貝到目標(biāo)空間。
  • !!! 目標(biāo)空間必須足夠大,以確保能存放源字符串。
  • !!! 目標(biāo)空間必須可變。

使用及模擬實(shí)現(xiàn)

#include<stdio.h>
#include<string.h>
#include<assert.h>

char* my_strcpy(char*dest,char*src)
{
	//斷言
	assert(dest && src);
	char* ret = dest;//用來記住arr的起始地址
	while (*dest++ = *src++)//不斷地賦值,arr不斷地被覆蓋
	{
		;
	}
	//返回起始地址
	return ret;
}

int main()
{
	char arr[20] = "hello";
	char* p = "abcdef";
	//strcpy(arr, p);
	//模擬實(shí)現(xiàn)
	my_strcpy(arr, p);
	printf("%s", arr);//abcdef
	return 0;
}

strncpy的使用及模擬實(shí)現(xiàn)

strncpy與strcpy的使用相類似,但是strcpy是拷貝整個字符串,而strncpy是可以指定拷貝,即只拷貝num個字符,如果源字符串的長度小于num,則拷貝完源字符串之后,在目標(biāo)的后邊追加0,直到num個。

使用及模擬實(shí)現(xiàn)

#include<stdio.h>
#include<assert.h>

char* my_strncpy(char* dest, const char* sor, size_t num)
{
	//斷言
	assert(dest && sor);
	char* s = dest;//起始地址記住
	int i = 0;
	for (i = 0; i < (int)num; i++)
	{
		//開始拷貝,num次,每次拷貝一個字符,拷貝完后,兩指針往后走,繼續(xù)拷貝
		*dest++ = *sor++;
	}
	//返回起始地址
	return s;
}
int main()
{
	char arr1[20] = "abcdefghi";
	char arr2[20] = "xxxx";
	size_t n = 0;
	scanf("%d", &n);
	my_strncpy(arr1, arr2, n);
	//從arr2中拷貝n個字符到arr1去
	printf("%s", arr1);//n=4,xxxxefghi\0 ; n=5,xxxx\0fghi\0,但是打印的是xxxx,因?yàn)橛龅絓0字符串停止
	return 0;
}

4.strcat的實(shí)現(xiàn)及模擬(字符串追加)

strcat是字符串追加函數(shù),顧名思義就是在一個字符串后面再增加另外一個字符串。

注意事項(xiàng)

  • 源字符串必須以 ‘\0’ 結(jié)束。
  • 目標(biāo)空間必須有足夠的大,能容納下源字符串的內(nèi)容。
  • 目標(biāo)空間必須可修改。
  • 不能自己給自己追加

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

#include<stdio.h>
#include<string.h>
#include<assert.h>
char* my_strcat(char* dest, const char* src)
{
	//斷言
	assert(dest && src);
	char* sur = dest;//記住起始地址
	while (*sur != '\0')
	{
		sur++;
	}
	//走到這里,sur已經(jīng)指向了arr1的\0處,從這里開始,把src指向的字符即arr2的字符賦給sur
	while (*sur++ = *src++)
	{
		;
	}
	//最后返回arr1追加后的起始空間地址
	return dest;
}

int main()
{
	char arr1[20] = "hello ";
	char arr2[] = "world";
	//在arr1后面增加arr2
	//strcat(arr1, arr2);
	my_strcat(arr1, arr2);

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

strncat的使用及模擬實(shí)現(xiàn)

strncat與strcat很類似,只不過strcat是追加整個字符串,而strncat是追加指定的字符串,比如說可以給arr1追加4個字符

模擬實(shí)現(xiàn)及使用

#include<stdio.h>
#include<assert.h>
char* my_strncat(char* dest, const char* sor, size_t num)
{
	assert(dest && sor);
	char* p = dest;
	while (*p != '\0')
	{
		p++;
	}
	//此時已經(jīng)指向arr1中的\0
	//把num個字符賦給*p
	while (num--)
	{
		*p++ = *sor++;
	}
	return dest;
}
int main()
{
	char arr1[20] = "hello ";
	char arr2[20] = "world!!!!!";
	size_t n = 0;
	scanf("%d", &n);
	my_strncat(arr1, arr2, n);
	printf("%s", arr1);//n=5,hello world
	return 0;
}

5.strstr的實(shí)現(xiàn)及模擬(字符串查找)

strstr是實(shí)現(xiàn)字符串查找的一個函數(shù),即在一個字符串中查找該字符串是不是含有另一個字符串

使用及模擬

#include<stdio.h>
#include<string.h>
#include<assert.h>
//char* strstr(const char*str1,const char*str2)
char* my_strstr(const char* str1, const char* str2)
{
	assert(str1 && str2);
	const char* s1 = str1;
	const char* s2 = str2;
	const char* p = str1;
	while (*p)
	{
		s1 = p;
		s2 = str2;
		while (*s1 && *s2 && *s1 == *s2)
		{
			s1++;
			s2++;
		}
		if (*s2 == '\0')
			return (char*)p;
		p++;
	}

	return NULL;
}

int main()
{
	char arr1[] = "abbbcdef";
	char arr2[] = "bbpc";
	//char* p = strstr(arr1, arr2);
	char* p = my_strstr(arr1, arr2);
	if (p == NULL)
		printf("不存在");
	else
		printf("%s\n", p);//不包含,輸出結(jié)果為不存在
	return 0;
}

6.strtok函數(shù)(在字符串中定義用作分隔符的集合)

注意事項(xiàng)

1、strtok函數(shù)找到str中的下一個標(biāo)記,并將其用 \0 結(jié)尾,返回一個指向這個標(biāo)記的指針。(注:strtok函數(shù)會改變被其操作的字符串,所以在使用strtok函數(shù)切分的字符串一般都是臨時拷貝的內(nèi)容并且可修改。

2、strtok函數(shù)的第一個參數(shù)不為 NULL ,函數(shù)將找到str中第一個標(biāo)記,strtok函數(shù)將保存它在字符串中的位置。

3、strtok函數(shù)的第一個參數(shù)為 NULL ,函數(shù)將在同一個字符串中被保存的位置開始,查找下一個標(biāo)記。

4、如果字符串中不存在更多的標(biāo)記,則返回 NULL 指針。

舉例使用

#include<stdio.h>
#include<string.h>

int main()
{
	char arr[] = "zinuo@qq.com.qdy";
	char buf[200] = { 0 };
	//p是用作分隔符的字符串首字符地址
	const char* p = "@..";
	//由于strtok函數(shù)會改變原字符串的內(nèi)容,所以一般都會拷貝一個用來使用
	strcpy(buf, arr);
	char* str = NULL;
	for (str=strtok(buf,p); str != NULL; str=strtok(NULL,p) )
	{
		//用來做分隔符的字符都被改成了\0,下一次調(diào)用函數(shù)時,會從這個\0開始繼續(xù)往后查找分隔符,再次改為\0,一直到找完所有分隔符,返回NULL
		printf("%s\n", str);//zinuo
		                    //qq
			                //com
			               //qdy
	}
	return 0;
}

7.strerror函數(shù) (錯誤碼轉(zhuǎn)換錯誤信息)

#include<stdio.h>
#include<errno.h>//errno包含頭文件
#include<string.h>//strerror包含頭文件
int main()
{
	//打開文件操作
	FILE* pf = fopen("test.txt", "r");
	//打開文件失敗,返回空指針,strerror可以將錯誤碼轉(zhuǎn)換成讓我們看得懂的錯誤信息
	if (pf == NULL)
	{
		perror("lzn");//相當(dāng)于printf+strerror  
		//lzn: No such file or directory

		//沒有這個文件,錯誤碼轉(zhuǎn)換為錯誤信息打印出來
		printf("%s\n", strerror(errno));
		//No such file or directory
		return 1;
	}
	//關(guān)閉文件
	fclose(pf);
	pf = NULL;
	return 0;
}

以上就是C語言中字符串庫函數(shù)的實(shí)現(xiàn)及模擬的詳細(xì)內(nèi)容,更多關(guān)于C語言字符串庫函數(shù)的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 深入C++ 函數(shù)映射的使用詳解

    深入C++ 函數(shù)映射的使用詳解

    我比較喜歡用代碼結(jié)合實(shí)際來講解,下面我將以一段事例代碼來講解如何使用這幾種映射
    2013-07-07
  • C++實(shí)現(xiàn)批量圖片拼接

    C++實(shí)現(xiàn)批量圖片拼接

    這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)批量圖片拼接,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-07-07
  • c++string字符串的比較是否相等問題

    c++string字符串的比較是否相等問題

    這篇文章主要介紹了c++string字符串的比較是否相等問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-08-08
  • C++ random_shuffle()方法案例詳解

    C++ random_shuffle()方法案例詳解

    這篇文章主要介紹了C++ random_shuffle()方法案例詳解,本篇文章通過簡要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • 解讀C++11 原生字符串

    解讀C++11 原生字符串

    這篇文章主要介紹了C++11 原生字符串的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)c++11,感興趣的朋友可以了解下
    2020-08-08
  • C語言學(xué)習(xí)之鏈表的實(shí)現(xiàn)詳解

    C語言學(xué)習(xí)之鏈表的實(shí)現(xiàn)詳解

    鏈表是一種物理存儲結(jié)構(gòu)上非連續(xù)、非順序的存儲結(jié)構(gòu),數(shù)據(jù)元素的邏輯順序是通過鏈表中的指針鏈接次序?qū)崿F(xiàn)的。這篇文章主要介紹了C語言中鏈表的實(shí)現(xiàn),需要的可以參考一下
    2022-11-11
  • 利用Matlab繪制有趣圖像的示例代碼

    利用Matlab繪制有趣圖像的示例代碼

    這篇文章主要為大家總結(jié)了一些利用Matlab繪制的有趣好看的圖像的示例代碼。文中的示例代碼簡潔易懂,感興趣的小伙伴可以動手試一試
    2022-03-03
  • Visual Studio 2019下配置 CUDA 10.1 + TensorFlow-GPU 1.14.0

    Visual Studio 2019下配置 CUDA 10.1 + TensorFlow-GPU 1.14.0

    這篇文章主要介紹了Visual Studio 2019下配置 CUDA 10.1 + TensorFlow-GPU 1.14.0,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-03-03
  • C++靜態(tài)成員變量和靜態(tài)成員函數(shù)的使用方法總結(jié)

    C++靜態(tài)成員變量和靜態(tài)成員函數(shù)的使用方法總結(jié)

    下面小編就為大家?guī)硪黄狢++靜態(tài)成員變量和靜態(tài)成員函數(shù)的使用方法總結(jié)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-01-01
  • C語言return知識點(diǎn)總結(jié)

    C語言return知識點(diǎn)總結(jié)

    在本篇文章里小編給大家整理的是關(guān)于C語言return知識點(diǎn)總結(jié)內(nèi)容,需要的朋友們可以學(xué)習(xí)參考下。
    2020-02-02

最新評論