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

C語言詳解如何應用模擬字符串和內存函數

 更新時間:2022年02月11日 10:58:35   作者:i跑跑  
這篇文章主要介紹了C語言詳解如何應用模擬字符串和內存函數,文章有點長,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步

1.strlen 求字符串長度

size_t strlen ( const char * str );
//返回值是unsigned int類型

使用案例:

#include <stdio.h>
int main()
{
	char arr[] = { "abcde" };
	printf("%d\n",strlen(arr));
	return 0;
}

我們知道在arr數組里,最后一個字符'e'后,默認是'\0',而strlen遇到'\0'則會結束運行,且返回的是在字符串中 '\0' 前面出現(xiàn)的字符個數(不包 含 '\0' )。

我們可以根據這個來對strlen進行模擬實現(xiàn):

1.計數法

#include <stdio.h>
#include <assert.h>
int my_strlen(const char* str)
{
	assert(str);
	int count = 0;    //計數
	while (*str)      //解引用判斷元素是否為'\0'
	{
		count++;
		str++;      //地址++
	}
	return count;   //返回計數
}
 
int main()
{
	int len = my_strlen("abcdef");
	printf("%d\n", len);
	return 0;
}

2.不創(chuàng)建臨時變量計數器-遞歸

#include <stdio.h>
#include <assert.h>
int my_strlen(const char * str)
{
	assert(str);
	if (*str == '\0')
		return 0;
	else
		return 1 + my_strlen(str + 1);
}
 
int main()
{
	char arr[] = {"abcdef"};
	int ret = my_strlen(arr);
	printf("%d\n", ret);
	return 0;
}

3.指針-指針的方式

#include <stdio.h>
#include <assert.h>
int my_strlen(char *s)
{
	char *p = s;
	while (*p != '\0')
		p++;
	return p - s;     //指針相減是長度
}
 
int main()
{
	char arr[] = {"abcdef"};
	int ret = my_strlen(arr);
	printf("%d\n", ret);
	return 0;
}

2.長度不受限制的字符串函數

1.strcpy

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

源字符串必須以 '\0' 結束。

會將源字符串中的 '\0' 拷貝到目標空間。

目標空間必須足夠大,以確保能存放源字符串。

目標空間必須可變。

使用案例:

#include <stdio.h>
#include <assert.h>
int main()
{
	char arr1[] = {'a', 'b', 'c', 'd', 'e', 'f', '\0'};
	char arr2[20] = "xxxxxxxxxxxx";
	strcpy(arr2, arr1);
	printf("%s\n", arr2);
	return 0;
}

模擬實現(xiàn):

#include <stdio.h>
#include <assert.h>
char* my_strcpy(char* dest, const char* src)
{
	char* ret = dest;
	//保留起始地址
	assert(dest && src);
	while (*dest++ = *src++)  //這里不打印'\0'之后的
	{
		;
	}
	return ret;
}
 
int main()
{
	char arr1[] = {'a', 'b', 'c', 'd', 'e', 'f', '\0'};
	char arr2[20] = "xxxxxxxxxxxx";
	my_strcpy(arr2, arr1);
	printf("%s\n", arr2);
	return 0;
}

2.strcat

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

源字符串必須以 '\0' 結束。

目標空間必須有足夠的大,能容納下源字符串的內容。

目標空間必須可修改。

使用案例:

#include <stdio.h>
#include <assert.h>
int main()
{
	char arr1[30] = "hello";//注意初始化方式,必須要包含'\0'
	char arr2[] = "world";
	strcat(arr1, arr2);
	printf("%s\n", arr1);
	return 0;
}

模擬實現(xiàn):

#include <stdio.h>
#include <assert.h>
char* my_strcat(char* dest, const char* src)
{
	char* ret = dest;
	//保留起始地址,方便找回打印
	assert(dest && src);
	//1. 找目標空間中的\0,打印的起點
	while (*dest)
	{
		dest++;
	}
	//2. 追加內容到目標空間
	while (*dest++ = *src++)
	{
		;
	}
	return ret;
}
int main()
{
	char arr1[30] = "hello";//注意初始化方式,必須要包含'\0'
	char arr2[] = "world";
	printf("%s\n", my_strcat(arr1, arr2));
	return 0;
}

3.strcmp-比較字符串首字母的大小

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

第一個字符串大于第二個字符串,則返回大于0的數字

第一個字符串等于第二個字符串,則返回0

第一個字符串小于第二個字符串,則返回小于0的數字

使用案例:

#include <stdio.h>
#include <assert.h>
int main()
{
	char arr1[] = "degh";
	char arr2[] = "bcdefx";
	int ret = strcmp(arr1, arr2);
	if (ret<0)
	{
		printf("arr1<arr2");
	}
	else if (ret >0)
	{
		printf("arr1>arr2");
	}
	else
	{
		printf("arr1==arr2");
	}
	return 0;
}

就是根據返回的值來判斷兩個字符串大小

模擬實現(xiàn):

//模擬實現(xiàn)strcmp-比較對應位置字符串大小
//相同的話地址各向后加一繼續(xù)比較
//注意strcmp返回的是大于等于或小于0的整型
#include <stdio.h>
#include <assert.h>
int my_strcmp(const char* str1, const char*str2)
{
	assert(str1 && str2);
	while (*str1 == *str2)
	{
		if (*str1 == '\0')
			return 0;
		//若相等,各向后+1繼續(xù)比較
		str1++;
		str2++;
	}
	return *str1 - *str2;
}
 
int main()
{
	char arr1[] = "degh";
	char arr2[] = "bcdefx";
	int ret = my_strcmp(arr1, arr2);
	if (ret<0)
	{
		printf("arr1<arr2");
	}
	else if (ret >0)
	{
		printf("arr1>arr2");
	}
	else
	{
		printf("arr1==arr2");
	}
	return 0;
}

3.長度受限制的字符串函數?

1.strncpy

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

相較于strcpy,strncpy函數有了對字符長度的限制,更加的靈活

使用案例:

#include <stdio.h>
#include <assert.h>
int main()
{
	char arr1[] = {'a', 'b', 'c', 'd', 'e', 'f', '\0'};
	char arr2[20] = "xxxxxxxxxxxx";
	strncpy(arr2, arr1,4);
	printf("%s\n", arr2);
	return 0;
}

2.strncat?

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

使用案例:

#include <stdio.h>
#include <assert.h>
int main()
{
	char arr1[30] = "hello";
	char arr2[] = "world";
	strncat(arr1, arr2,3);
	printf("%s\n", arr1);
	return 0;
}

若給的數字超過了arr2的長度,如:

strncat(arr1, arr2,7);

只會追加到arr2元素中的'\0'結束。

3.strncmp

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

使用案例:

#include <stdio.h>
#include <assert.h>
int main()
{
	char arr1[] = "degh";
	char arr2[] = "bcdefx";
	int ret = strncmp(arr1, arr2,3);
	if (ret<0)
	{
		printf("arr1<arr2");
	}
	else if (ret >0)
	{
		printf("arr1>arr2");
	}
	else
	{
		printf("arr1==arr2");
	}
	return 0;
}

這里的數字3表明比較的是前3個?字符串的大小。

4.strstr-找子串?

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

在字符串里找子串,返回找到子串的起始地址

找不到則返回空指針

使用案例:

#include <stdio.h>
int main()
{
	char arr1[] = "abbbcdef";
	char arr2[] = "bbcq";
 
	char* ret = strstr(arr1, arr2);  //因為返回的是地址,要用指針接收
 
	if (NULL == ret)
		printf("沒找到\n");
	else
		printf("%s\n", ret);
	return 0;
}

模擬實現(xiàn):

#include <stdio.h>
#include <assert.h>
char* my_strstr(const char* str, const char* substr)
{
	const char* s1 = str;
	const char* s2 = substr;
	const char* cur = str;   //記錄字符串起始位置,在改變
 
	assert(str && substr);
	if (*substr == '\0')
	{
		return (char*)str;
	}
	while (*cur)   //如果*cur為'\0',則找不到,返回空指針
	{
		s1 = cur;
		s2 = substr;
		while (*s1 &&  *s2 && *s1 == *s2) //*s1 *s2不為'\0'
		{
			s1++;
			s2++;
		}
		if (*s2 == '\0')    //找到了
			return (char*)cur;   //返回起始位置
		cur++;
	}
	return NULL;
}
 
int main()
{
	char arr1[] = "abbbcdef";
	char arr2[] = "bbcq";
 
	char* ret = my_strstr(arr1, arr2);
 
	if (NULL == ret)
		printf("沒找到\n");
	else
		printf("%s\n", ret);
	return 0;
}

5.strtok

應用:將字符串里面除了分隔符外的其他內容提出來

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

第一個參數指定一個字符串,包含了字符串和分隔符

sep參數是個字符串,定義了用作分隔符的字符集合

例如:

	const char* p = "*.-";
	char arr[] = "sukabulie*wula.wushi-baga";

sep=p? ? ? ?str=arr

注:strtok會改變第一個字符串里的內容(將分隔符改為\0),因此不能直接將源字符串傳過去,可以臨時拷貝一份

	char buf[50] = { 0 };
	strcpy(buf,arr);

那么接下來要傳參時第一個參數用buf就好。

注:strtok函數的第一個參數不為空指針?,函數將找到str中第一個標記,strtok函數將保存它在字符串中的位置。

strtok函數的第一個參數為空指針 ,函數將在同一個字符串中被保存的位置開始,查找下一個標記。

如果字符串中不存在更多的標記,則返回空指針。

用法:

	char* str = strtok(buf, p);//sukabulie
	printf("%s\n", str);
	str = strtok(NULL, p);//wula
	printf("%s\n", str);
	str = strtok(NULL, p);//wushi
	printf("%s\n", str);
	str = strtok(NULL, p);//baga
	printf("%s\n", str);

打印效果:

我們發(fā)現(xiàn)這樣的寫法很笨,當我們不知道一個字符串它有多少分段時就很麻煩,我們可以用for循環(huán)來解決這個問題。

改進:

#include <stdio.h>
#include <string.h>
int main()
{
	const char* p = "*.-";
	char arr[] = "sukabulie*wula.wushi-baga";
	char buf[50] = { 0 };
	strcpy(buf, arr);
	for (char* str = strtok(buf, p); str != NULL; str = strtok(NULL, p))
	{
		printf("%s\n",str);
	}
	return 0;
}

6.strerror

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

C語言中規(guī)定了一些錯誤碼及它所對應的意思(錯誤信息)

char * strerror ( int errnum );

int errnum 是錯誤碼? ? ? ? ?函數返回的是錯誤信息的起始地址

展示:

#include <stdio.h>
int main() 
{
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%s\n", strerror(i));
	}
	return 0;
}

使用方式:

當我們運行一個程序遇到錯誤,跑不過去時,可以在他執(zhí)行錯誤代碼段的下一行用

printf("%s\n",strerror(errno));
 
//注意要引用頭文件
#include <errno.h>

errno是c語言提供的一個全局變量,可直接使用,當程序發(fā)生錯誤時,他會改變?yōu)橄鄬腻e誤碼,我們就可以用strerror函數得到相對應的錯誤信息。

7.memcpy-不重復內存拷貝

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

將source里的元素通過字節(jié)數來拷貝到destination中

使用案例:

#include <stdio.h>
#include <string.h>
int main()
{
	int arr1[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
	int arr2[5] = { 0 };
	memcpy(arr2,arr1,5*sizeof(arr2[0]));
	int i = 0;
	for (i=0;i<5;i++)
	{
		printf("%d\n",arr2[i]);
	}
	return 0;
}

模擬實現(xiàn):

#include <stdio.h>
#include <string.h>
#include <assert.h>
 
void* my_memcpy(void* dest, const void*src, size_t num)
{
	void* ret = dest;   //保留要返回的起始地址
	assert(dest&&src);
	while (num--)       //先使用后--,一個字節(jié)一個字節(jié)的覆蓋
	{
		*(char*)dest = *(char*)src;//強制類型轉換是臨時的
		dest = (char*)dest+1;     //因此改變地址時也要強制類型轉換
		src = (char*)src+1;
	}
	return ret;
}
int main()
{
	int arr1[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
	int arr2[5] = { 0 };
	my_memcpy(arr2, arr1, 5 * sizeof(arr2[0]));
	int i = 0;
	for (i = 0; i<5; i++)
	{
		printf("%d\n", arr2[i]);
	}
	return 0;
}

注意:c語言中要求memcpy只要可以拷貝沒有重復的內存就可以了,但是在vs下memcpy也可以處理重復的內存。

若按我們寫的來舉例,我們的memcpy是不支持重復內存的處理:

int main()
{
	int arr1[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
	int arr2[5] = { 0 };
	my_memcpy(arr1+2, arr1, 5 * sizeof(arr1[0]));
	int i = 0;
	for (i = 0; i<9; i++)
	{
		printf("%d\n", arr1[i]);
	}
	return 0;
}

如若是這樣拷貝,那么我們想的打印出來的應該是1 2?1 2 3 4 5 8 9

實際上是:1 2 1 2 1 2 1 8 9

用memcpy來實現(xiàn):

int main()
{
	int arr1[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
	int arr2[5] = { 0 };
	memcpy(arr1+2, arr1, 5 * sizeof(arr1[0]));
	int i = 0;
	for (i = 0; i<9; i++)
	{
		printf("%d\n", arr1[i]);
	}
	return 0;
}

在vs下庫函數memcpy功能更加強大,可處理重復內存,c語言只要求它能處理不重復的內存即可,處理重復內存時用庫函數memmove,因此我們模擬的memcpy正確。

8.memmove-可處理重復內存拷貝

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

類型與memcpy相同

使用案例:

#include <stdio.h>
#include <string.h>
int main()
{
	int arr1[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
	int arr2[5] = { 0 };
	memmove(arr1 + 2, arr1, 5 * sizeof(arr1[0]));
	int i = 0;
	for (i = 0; i<9; i++)
	{
		printf("%d\n", arr1[i]);
	}
	return 0;
}

模擬實現(xiàn):

分析:

#include <stdio.h>
#include <string.h>
#include <assert.h>
void* my_memmove(void* dest,const void* src,size_t num)
{
	void* ret = dest;
	assert(dest&&src);
	if (dest < src) //前向后
	{
		while (num--)
		{
			*(char*)dest = *(char*)src;
			dest = *(char*)dest+1;
			src = *(char*)src + 1;
		}
	}
	else   //后向前
	{
		while (num--)
		{
			*((char*)dest+num)=*((char*)src + num); //   //根據圖來分析
		}
	}
 
}
int main()
{
	int arr1[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
	int arr2[5] = { 0 };
	my_memmove(arr1 + 2, arr1, 5 * sizeof(arr1[0]));
	int i = 0;
	for (i = 0; i<9; i++)
	{
		printf("%d\n", arr1[i]);
	}
	return 0;
}

9.memcmp

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

比較字節(jié)中數的大小

返回的是大于等于或小于0的無符號整型

使用方式與strncmp相似,但是比較的類型不局限于字符串,更加廣泛

案例:

#include <stdio.h>
#include <string.h>
int main()
{
	int arr1[] = { 1,2,7,4,5 };
	int arr2[] = { 1,2,3,4,5 };
	int ret = memcmp(arr1, arr2, 9);  //比較arr1和arr2前九個字節(jié)中數的大小
 
	printf("%d\n", ret);
	return 0;
}

10.memset

void* memset(void* dest,int c,size_t count)

第一個參數是目標地址,第二個參數是要被設置的內容,第三個參數是個數

以字節(jié)為單位修改

應用方式:

#include <stdio.h>
#include <string.h>
int main()
{
	char arr[20] = { 0 };
	memset(arr, 'x', 10);
	return 0;
}

到此這篇關于C語言詳解如何應用模擬字符串和內存函數的文章就介紹到這了,更多相關C語言 字符串 內存函數內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • C++中STL容器的主要使用及含義說明

    C++中STL容器的主要使用及含義說明

    這篇文章主要介紹了C++中STL容器的主要使用及含義說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-11-11
  • 基于Windows API分解路徑問題的詳解

    基于Windows API分解路徑問題的詳解

    本篇文章是對Windows API分解路徑進行了詳細的分析介紹,需要的朋友參考下
    2013-05-05
  • Prim(普里姆)算法求最小生成樹的思想及C語言實例講解

    Prim(普里姆)算法求最小生成樹的思想及C語言實例講解

    Prim算法能夠在帶權的圖中搜索出最小生成樹,這也是各大ACM和面試及考研題目中的熱點,下面我們就來詳細看一下Prim(普里姆)算法求最小生成樹的思想及C語言實例講解
    2016-06-06
  • C語言/C++如何生成隨機數

    C語言/C++如何生成隨機數

    這篇文章主要介紹了C語言/C++如何生成隨機數,C語言/C++產生隨機數主要用到的是rand()函數, srand()函數,C語言/C++里沒有自帶的random(int number)函數,如何解決?感興趣的小伙伴們可以參考一下
    2016-04-04
  • C++野指針的具體實現(xiàn)

    C++野指針的具體實現(xiàn)

    野指針就是指針指向的不是一個有效(合法)的地址,本文主要介紹了C++野指針的具體實現(xiàn),文中通過示例代碼介紹的非常詳細,需要的朋友們下面隨著小編來一起學習學習吧
    2024-03-03
  • C++實現(xiàn)智能柜管理系統(tǒng)

    C++實現(xiàn)智能柜管理系統(tǒng)

    這篇文章主要為大家詳細介紹了C++實現(xiàn)智能柜管理系統(tǒng),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • C語言中getopt()函數和select()函數的使用方法

    C語言中getopt()函數和select()函數的使用方法

    這篇文章主要介紹了C語言中getopt()函數和select()函數的使用方法,是C語言入門學習中的基礎知識,需要的朋友可以參考下
    2015-09-09
  • C語言進程程序替換的實現(xiàn)詳解

    C語言進程程序替換的實現(xiàn)詳解

    為什么要進程替換?因為父進程創(chuàng)建出來的子進程和父進程擁有相同的代碼段,所以,子進程看到的代碼和父進程是一樣的。當我們想要讓子進程執(zhí)行不同的程序時候,就需要讓子進程調用進程程序替換的接口,從而讓子進程執(zhí)行不一樣的代碼
    2022-08-08
  • C語言 運算符詳細介紹及示例代碼

    C語言 運算符詳細介紹及示例代碼

    本文介紹C語言 運算符,這里整理了運算符的基礎知識,并附示例代碼,希望能幫助剛剛開始學習 C語言的同學
    2016-08-08
  • Qt QWidget實現(xiàn)圖片旋轉動畫

    Qt QWidget實現(xiàn)圖片旋轉動畫

    這篇文章主要為大家詳細介紹了如何使用了Qt和QWidget實現(xiàn)圖片旋轉動畫效果,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學習一下
    2024-12-12

最新評論