国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

C語言進(jìn)階---字符串+內(nèi)存函數(shù)

這篇具有很好參考價(jià)值的文章主要介紹了C語言進(jìn)階---字符串+內(nèi)存函數(shù)。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

本章重點(diǎn)

重點(diǎn)介紹處理字符和字符串的庫函數(shù)的使用和注意事項(xiàng)。

  • 求字符串長度
    • strlen()
  • 長度不受限制的的字符串函數(shù)
    • strcpy()
    • strcat()
    • strcmp()
  • 長度受限制的的字符串函數(shù)
    • strncpy()
    • strncat()
    • strncmp()
  • 字符串查找
    • strstr()
    • strtok()
  • 錯(cuò)誤信息報(bào)告
    • strerror()
  • 字符操作
  • 內(nèi)存操作函數(shù)
    • memcpy()
    • memmove()
    • memset()
    • memcmp()

前言

C語言中對(duì)字符的字符串的處理很頻繁,但是C語言本身是沒有字符串類型的,字符串通常放在常量字符串中或者字符數(shù)組中。

字符串常量適用于那些對(duì)它不做修改的字符串函數(shù)。

1、字符串函數(shù)

1.1、strlen()—統(tǒng)計(jì)字符串長度

//頭文件<string.h>

size_t strlen(const char* str);
  • 首先傳的參數(shù)需要是個(gè)指針類型的。
  • 字符串以'\0'作為結(jié)束標(biāo)志,strlen()函數(shù)返回的是在字符串中'\0'前面出現(xiàn)的字符個(gè)數(shù)(不包含'\0')。
  • 參數(shù)指向的字符串必須要以'\0'結(jié)束。
  • 注意函數(shù)的返回值為size_t,是無符號(hào)整型的
  • 學(xué)會(huì)strlen()函數(shù)的模擬實(shí)現(xiàn)。

1.2、strcpy()—字符串拷貝

//頭文件<string.h>

char* strcpy(char* destination, const char* source)
  • 源字符串必須以'\0'結(jié)束。
  • 會(huì)將源字符串中的'\0'拷貝到目標(biāo)空間。
  • 返回值為目標(biāo)字符串的首字符地址。
  • 目標(biāo)空間必須足夠大,以確保能存放源字符串。
  • 目標(biāo)空間必須可變。
  • 學(xué)會(huì)模擬實(shí)現(xiàn)。

簡單使用介紹:

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

int main()
{
	char name[20] = { 0 };
	strcpy(name, "zhangsan");
	printf("%s\n", name);
	return 0;
}

輸出:

C語言進(jìn)階---字符串+內(nèi)存函數(shù),C語言,c語言

1.3、strcat()—字符串追加

//頭文件<string.h>
char* strcat(char* destination, const char* source)
  • 源字符串必須以'\0'結(jié)束。
  • 源字符串在目標(biāo)字符串有\(zhòng)0的地方開始追加。并不是說只會(huì)在目標(biāo)字符串末尾處開始追加,只要目標(biāo)字符串中間某個(gè)位置有\0,那就直接從這個(gè)位置開始追加。
  • 目標(biāo)空間必須有足夠的大,能容納下源字符串的內(nèi)容。
  • 目標(biāo)空間必須可修改

1、簡單使用介紹:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main()
{
	char arr2[20] = "hello ";
	strcat(arr2, "world");
	printf("%s\n", arr2);
	return 0;
}

輸出:

C語言進(jìn)階---字符串+內(nèi)存函數(shù),C語言,c語言

2、這里說明一下:源字符串在目標(biāo)字符串有\(zhòng)0的地方開始追加。并不是說只會(huì)在目標(biāo)字符串末尾處開始追加,只要目標(biāo)字符串中間某個(gè)位置有\0,那就直接從這個(gè)位置開始追加。

如下代碼:“hel\0lo”,中間位置有個(gè)\0,所以在追加"world"是,就直接從"hel"初開始追加了。最后輸出結(jié)果就是:

“helworld”。

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>

int main()
{
	char arr2[20] = "hel\0lo ";
	strcat(arr2, "world");
	printf("%s\n", arr2);
	return 0;
}

輸出:

C語言進(jìn)階---字符串+內(nèi)存函數(shù),C語言,c語言

2、模擬實(shí)現(xiàn):

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

char* my_strcat(char* dest, const char* source)
{
	char* ret = dest;
	assert(dest && source);
	//1、找到目標(biāo)字符串的\0。
	while (*dest != '\0')
	{
		dest++;
	}
    //2、拷貝
	while (*dest++ = *source++)
	{
		;
	}
	return ret;
}

int main()
{
	char arr1[20] = "hello ";
	my_strcat(arr1, "world");
	printf("%s\n", arr1);
	return 0;
}

那能不能實(shí)現(xiàn)字符串自己給自己追加?如下:

答案:是不能的。

int main()
{
	char arr1[20] = "hello ";
	my_strcat(arr1, arr1);             //如何實(shí)現(xiàn)這樣的效果呢?
	printf("%s\n", arr1);
	return 0;
}

1.4、strcmp()—比較字符串大小

//頭文件<string.h>
int strcmp(const char* str1, const char* str2);

  • 返回值:
    • 第一個(gè)字符串<第二個(gè)字符串,就返回小于0的數(shù)字
    • 第一個(gè)字符串=第二個(gè)字符串,就返回0
    • 第一個(gè)字符串>第二個(gè)字符串,就返回大于0的數(shù)字

那具體是怎么比較的呢?是依次比較各個(gè)字符串中字符的ASCII值。

比如:首先arr1中的字符’a’和arr2中的字符’a’進(jìn)行比較,發(fā)現(xiàn)ASCII一樣,然后再比較字符’b’…

之后當(dāng)比較到arr1中的字符’d’和arr2中的字符’f’是,發(fā)現(xiàn)arr2中的’f’的ASCII值比arr1中的’d’的ASCII值大。

所以最終結(jié)果為arr2大。

char arr1[] = "abcd";
char arr2[] = "abcf";

1、簡單使用:

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

int main()
{
	char arr1[] = "abcd";
	char arr2[] = "abcf";
	int ret = strcmp(arr1, arr2);    //arr1小于arr2
	if (ret < 0)
		printf("<\n");
	else if (ret == 0)
		printf("=\n");
	else
		printf(">\n");
	return 0;
}

輸出:

C語言進(jìn)階---字符串+內(nèi)存函數(shù),C語言,c語言

2、模擬實(shí)現(xiàn):

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

int my_strcmp(const char* str1,const char* str2)
{
	assert(str1 && str2);
	while (*str1 == *str2)
	{
		if (*str1 == '\0')
			return 0;   //判斷相等
		str1++;
		str2++;
	}
	if (*str1 > *str2)
		return 1;
	else
		return -1;
}

int main()
{
	char arr1[] = "abcd";
	char arr2[] = "abcf";
	int ret = my_strcmp(arr1, arr2);
	if (ret < 0)
		printf("<\n");
	else if (ret == 0)
		printf("=\n");
	else
		printf(">\n");
	return 0;
}


//判斷>或者<的返回值還可以在優(yōu)化:
//將下面一段代碼替換為最后一行優(yōu)化的代碼
if (*str1 > *str2)
		return 1;
	else
		return -1;

//替換這個(gè)優(yōu)化的代碼
return *str1 - *str2;

關(guān)于以上庫函數(shù)不安全的說明

上面所說到了庫函數(shù),其實(shí)是相對(duì)不安全的,比如:

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

int main()
{
	char arr1[] = "abcd";
	char arr2[] = "abcdfr";
	//arr2的字符長度比arr1的字符長度長,當(dāng)讓arr2拷貝到arr1時(shí),arr1數(shù)組會(huì)放不下,
	//放不下編譯器也會(huì)放,那就呆滯了越界訪問,以至于改變了其它內(nèi)存中的數(shù)據(jù),這是相當(dāng)危險(xiǎn)的。
	strcpy(arr1, arr2);   
	return 0;
}

那這個(gè)時(shí)候,就應(yīng)用誕生了相對(duì)來說安全一點(diǎn)的庫函數(shù):長度受限制的的字符串函數(shù)。

長度受限制的字符串函數(shù)是什么意思呢?下面介紹:

1.5、strncpy()–長度受限制拷貝

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

多個(gè)參數(shù):num。這個(gè)參數(shù)就是限制長度的參數(shù),比如說讓arr2的字符串拷貝到arr1中去,但是只允許拷貝3個(gè)字節(jié)的字符:

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

int main()
{
	char arr1[] = "aaaaa";
	char arr2[] = "bbbbb";
	//讓arr2的數(shù)據(jù)拷貝到arr1中去,但是只拷貝3個(gè)字節(jié)。
	strncpy(arr1, arr2,3);   
	printf("%s\n", arr1);
	return 0;
}

輸出:

C語言進(jìn)階---字符串+內(nèi)存函數(shù),C語言,c語言

可以看到輸出結(jié)果:只會(huì)將arr2中的前3個(gè)字符拷貝到arr1中,arr1前3個(gè)也字符會(huì)改變,并且后面的字符不會(huì)改變。

1.6、strncat()—長度受限制追加

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

int main()
{
	char arr1[20] = "hello\0xxxxxx";
	char arr2[] = "world";
	strncat(arr1, arr2, 3);
	printf("%s\n", arr1);
	return 0;
}

輸出:這里有個(gè)點(diǎn)要注意以下:在使用strncat()時(shí),在追加完畢后,會(huì)自動(dòng)在目標(biāo)字符串末尾添加一個(gè)\0表示一個(gè)字符的結(jié)束。

這里采用調(diào)試查看:

C語言進(jìn)階---字符串+內(nèi)存函數(shù),C語言,c語言

1.7、strncmp()—長度受限制比較

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

int main()
{
	char arr1[] = "abcdef";
	char arr2[] = "abc";
	strncmp(arr1, arr2, 3);   //只比較3個(gè)字符,結(jié)果應(yīng)該為相等。
	return 0;
}

1.8、strstr()—查找子串

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

參數(shù)說明:

  • str1是母字符串的地址
  • str2是子串的地址

比如現(xiàn)在有兩個(gè)字符串:

char arr1[] = "abcdef";
char arr2[] = "cde"
strstr(arr1,arr2);

需要在arr1(母字符串)中尋找有沒有arr2(子串)的內(nèi)容。首先arr2中的字符串內(nèi)容為:“cde”,而arr1中的字符串:“abcdef”,正好全部包含"cde"。那么此時(shí)strstr()函數(shù)會(huì)返回arr1中包含子串的首字符地址。也就是會(huì)返回arr1中字符c的地址。那如果我們?cè)谝?code>%s打印時(shí),就會(huì)將arr1的"cdef"的值全部打印出來,因?yàn)閺钠鹗嘉恢谩痗’到’\0’結(jié)束,就是"cdef"。

所以strstr()函數(shù)的返回值是個(gè)char*類型的。

如果沒有查找到字串,就會(huì)返回一個(gè)NULL指針。

1、使用演示:

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

int main()
{
	char arr1[] = "abcdef";
	char arr2[] = "cde";
	char* ret = strstr(arr1, arr2);
	if (ret == NULL)
	{
		printf("沒有找到\n");
	}
	else
	{
		printf("%s\n", ret);
	}
	return 0;
}

輸出:

C語言進(jìn)階---字符串+內(nèi)存函數(shù),C語言,c語言

1.9、strtok()—切割字符串

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

  • sep參數(shù)是個(gè)字符串,定義了用作分隔符的字符集合。

    比如現(xiàn)在有一個(gè)字符串:“zhengbo@helloworld.com”,假如字符@和字符.就是我們分隔符,通過這兩個(gè)符號(hào),可以將字符串切割為一段一段的。那我們就可以這樣定義這個(gè)sep參數(shù):

    const char* sep = "@.";     
    
    
  • 第一個(gè)參數(shù)指定一個(gè)字符串,它包含了0個(gè)或者多個(gè)由sep字符串中一個(gè)或者多個(gè)分隔符分隔的標(biāo)記。

    這里的第一個(gè)參數(shù)就是要切割的字符串:

    char arr[] = "zhengbo@helloworld.com";
    
    
  • strtok函數(shù)找到了str中的下一個(gè)標(biāo)記,并將其用\0結(jié)尾,返回一個(gè)指向這個(gè)標(biāo)記的指針。(注:strtok函數(shù)會(huì)改變被操作的字符串,所以在使用strtok函數(shù)切分的字符串一般都是臨時(shí)拷貝的內(nèi)容沒那個(gè),并且可修改。)

    strtok函數(shù)找到了str中的下一個(gè)標(biāo)記這句話的意思就是說,strtok找到了@分隔符,就會(huì)把@分隔符變?yōu)?code>'\0',那arr數(shù)組就會(huì)變成如下的樣子:

    char arr[] = "zhengbo\0helloworld.com";
    
    

    然后返回一個(gè)指向這個(gè)標(biāo)記的指針,就是把分隔好的字符串:“zhengbo\0”,通過返回字符'z'的地址,作為指針返回過去。

    但是這樣我們會(huì)發(fā)現(xiàn)一個(gè)問題:就是會(huì)把a(bǔ)rr數(shù)組里面的內(nèi)容給修改。那如果下面程序還需要使用arr數(shù)組呢?那情況就不對(duì)。所以說我們先應(yīng)該使用strcmp()函數(shù)把a(bǔ)rr數(shù)組給臨時(shí)拷貝一份給另外一個(gè)數(shù)組,然后把臨時(shí)拷貝的數(shù)組交給strtok來進(jìn)行操作,那這樣既能提取出來分隔的字符串,又能不對(duì)原數(shù)組arr進(jìn)行修改。具體實(shí)現(xiàn)如下代碼:

    #include <stdio.h>
    #include <string.h>
    int mian()
    {
    	const char* sep = "@.";
    	char arr[] = "zhengbo@helloworld.com";
    	char cp[30] = { 0 };
    	strcmp(cp,arr);     //臨時(shí)拷貝一份
    	strtok(cp, sep);    //對(duì)臨時(shí)拷貝的數(shù)組進(jìn)行分隔
    	return 0;
    }
    
    
  • strtok函數(shù)的第一個(gè)參數(shù)不為NULL,函數(shù)將找到str中第一個(gè)標(biāo)記,strtok函數(shù)將保存它在字符串中的位置。

    這個(gè)是說,我們?cè)谑状问褂胹trtok函數(shù)時(shí),需要傳第一個(gè)參數(shù),因?yàn)榈谝粋€(gè)參數(shù)里面保存了分隔符的地址,有了一個(gè)參數(shù)后,函數(shù)將找到str中第一個(gè)標(biāo)記,也就是說找到了@標(biāo)記(分隔符),然后返回首字符z的地址,作為函數(shù)返回值,然后保存下來。

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

    到這一步,再次調(diào)用strtok函數(shù),需要找第二個(gè),第三個(gè),第四個(gè)分割符的時(shí)候就不需要傳第一個(gè)參數(shù)了,所以到這個(gè)地方我們就能明白,只有在找第一個(gè)分隔符的時(shí)候才傳第一個(gè)參數(shù)。好,那問題又來了:那不傳第一個(gè)參數(shù),如何找到,下一個(gè)需要分割為字符串的首字符地址呢?原因是這樣的:其實(shí)在找到第一個(gè)分隔符之后,NULL指針表示一種狀態(tài),NULL指針會(huì)記錄著上一個(gè)分割后的起始位置,也就已經(jīng)記著了第一個(gè)分隔符后面的字符地址了。然后在根據(jù)sep中記錄的分隔符,分割出一段字符串。

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

    到這一步,是說,在真?zhèn)€arr數(shù)組里面沒找到分隔符,那就直接strtok函數(shù)返回NULL指針。

1、效果演示:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
int main()
{
    //創(chuàng)建分隔符集合
	const char* sep = "@.";
    //待分割的字符串
	char arr[] = "zhengbo@helloworld.com";
    //創(chuàng)建一個(gè)臨時(shí)數(shù)組
	char cp[30] = { 0 };
	//拷貝一份臨時(shí)數(shù)據(jù)
	strcpy(cp,arr);
	//切割出zhengbo@,并把@換為\0了,且把z字符的地址,返回給了ret。
	char* ret = strtok(cp, sep);    
	//打印出:zhengbo
	printf("%s\n", ret);
	
    //打印helloworld,這里的NULL指針表示一種狀態(tài),NULL指針記錄了'h'的地址
	ret = strtok(NULL, sep);
	printf("%s\n", ret);
	
    //打印com,這里NULL指針記錄了'c'的地址
	ret = strtok(NULL, sep);
	printf("%s\n", ret);
	return 0;
}

輸出:

C語言進(jìn)階---字符串+內(nèi)存函數(shù),C語言,c語言

2、優(yōu)化:上面的代碼分割一個(gè)字符串就需要打印一次,其實(shí)這里可以寫個(gè)for循環(huán),來優(yōu)化下代碼:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
int main()
{
	const char* sep = "@.";
	char arr[] = "zhengbo@helloworld.com";
	char cp[30] = { 0 };
	//拷貝一份臨時(shí)數(shù)據(jù)
	strcpy(cp,arr);
	//切割出zhengbo@,并把@換為\0了,且把z字符的地址,返回給了ret。
	char* ret = NULL;
    //優(yōu)化部分
	for (ret = strtok(cp, sep); ret != NULL; ret = strtok(NULL, sep))
	{
		printf("%s\n", ret);
	}
	return 0;
}

1.10、strerror()

返回錯(cuò)誤碼,所對(duì)應(yīng)的錯(cuò)誤信息。

//頭文件:<errno.h>
char* strerror (int errnum);

在C語言中,庫函數(shù)在執(zhí)行失敗的時(shí)候,都會(huì)設(shè)置錯(cuò)誤碼。

雖說設(shè)置的都有錯(cuò)誤碼,但是我們?cè)趺礃硬拍苤厘e(cuò)誤碼所對(duì)應(yīng)的錯(cuò)誤信息呢?

這個(gè)時(shí)候strerror()函數(shù)就起作用了。只需要把錯(cuò)誤碼傳參進(jìn)去,這個(gè)函數(shù)就會(huì)返回錯(cuò)誤碼所對(duì)應(yīng)錯(cuò)誤信息字符串的首字符地址。

1、代碼演示:

//在X86平臺(tái)上運(yùn)行

#include <stdio.h>
#include <errno.h>

int main()
{
	printf("%s\n", strerror(0));
	printf("%s\n", strerror(1));
	printf("%s\n", strerror(2));
	printf("%s\n", strerror(3));
	return 0;
}

輸出:

C語言進(jìn)階---字符串+內(nèi)存函數(shù),C語言,c語言

2、情景演示

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <errno.h>

int main()
{
	//使用fopen()表示打開一個(gè)文件,并且r表示以只讀的方式進(jìn)行。
	//如果打開成功會(huì)返回一個(gè)指針,如果打開失敗會(huì)返回NULL指針。
	//現(xiàn)在本地沒有test.txt文件,所以會(huì)打開文件失敗,返回NULL指針。
	FILE* pf = fopen("test.txt", "r");
	if (pf == NULL)
	{
		//errno是C語言中設(shè)置一個(gè)全局變量,用來專門存放錯(cuò)誤碼的。
		printf("%s\n", strerror(errno));
        return 1;
	}
	return 0;
}

輸出:

C語言進(jìn)階---字符串+內(nèi)存函數(shù),C語言,c語言

2、字符分類函數(shù)

函數(shù) 如果它的參數(shù)符合下列條件就返回真
iscntrl 任何控制字符
isspace <ctype.h> 空白字符:空格’ ‘,換頁’\f’,換行’\n’,回車’\r’,制表符’\t’,垂直制表符’\v’
isdigit <ctype.h> 十進(jìn)制數(shù)字0~9
isxdigit 十六進(jìn)制數(shù)字,包括所有十進(jìn)制數(shù)字,小寫字母af,大寫字母AF
islower 小寫字母a-z
isupper 大寫字母A-Z
isalpha 字母az或AZ
isalnum 字母或數(shù)字,az、AZ、0~9
ispunct 標(biāo)點(diǎn)符號(hào),任何不屬于數(shù)字或字母的圖形字符(可打?。?/td>
isgraph 任何圖形字符
isprint 任何可打印字符,包括圖形字符和空白字符

3、字符轉(zhuǎn)換函數(shù)

字符轉(zhuǎn)換:

1、tolower()-------------將大寫字母轉(zhuǎn)為小寫

int tolower(int c);     //將大寫字母轉(zhuǎn)為小寫,如果傳參數(shù)表示大寫字母,給什么值,輸出什么值。

代碼演示:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <ctype.h>

int main()
{
	printf("%c\n", tolower('A'));
	return 0;
}

輸出:

C語言進(jìn)階---字符串+內(nèi)存函數(shù),C語言,c語言

2、toupper()----------------將小寫字母轉(zhuǎn)為大寫

int toupper(int c);     //將小寫字母轉(zhuǎn)為大寫,如果傳參數(shù)表示小寫字母,給什么值,輸出什么值。

代碼演示:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <ctype.h>

int main()
{
	printf("%c\n", toupper('g'));
	return 0;
}

輸出:

C語言進(jìn)階---字符串+內(nèi)存函數(shù),C語言,c語言

4、內(nèi)存操作函數(shù)

4.1、memcpy函數(shù)—內(nèi)存拷貝(不能用來拷貝重疊內(nèi)存)

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

  • 函數(shù)memcpy從source的位置開始向后復(fù)制num個(gè)__字節(jié)__的數(shù)據(jù)到destination的內(nèi)存位置。
  • 這個(gè)函數(shù)在遇到’\0’的時(shí)候并不會(huì)停下來。
  • 如果source和destination有任何的重疊,復(fù)制的結(jié)果都是未定義的。

上面講到字符函數(shù)也有兩個(gè)拷貝:strcpy、strncpy。

但是這兩個(gè)庫函數(shù)都是指針字符串進(jìn)行拷貝的。

那現(xiàn)在有兩個(gè)整型數(shù)組,如何拷貝呢?

比如:

  • int arr1[] = {1,2,3,4,5,6};
  • int arr2[10] = {0};

這個(gè)時(shí)候就需要使用memcpy()庫函數(shù)了。

在介紹這個(gè)庫函數(shù)前,先來思考一下這個(gè)庫函數(shù)誕生的原因:如果需要拷貝字符類型的數(shù)據(jù)用到了strcpy、strncpy函數(shù),那如果需要拷貝整型數(shù)據(jù)的呢?需要產(chǎn)生一個(gè)專用于整型拷貝的庫函數(shù)嗎?如果需要拷貝浮點(diǎn)型呢?如果需要拷貝結(jié)構(gòu)體呢?不可能說都會(huì)產(chǎn)生一個(gè)對(duì)應(yīng)的拷貝庫函數(shù)。

而是說直接用一個(gè)memcpy()函數(shù),這個(gè)函數(shù)是直接對(duì)內(nèi)存進(jìn)行操作的,它拷貝的是內(nèi)存塊里面的數(shù)據(jù)。而無論是字符還是整形,或者是浮點(diǎn)型,再或者是結(jié)構(gòu)體。它們的數(shù)據(jù)都是存放在內(nèi)存中的。所以說可以直接用memcpy()函數(shù)進(jìn)行統(tǒng)一拷貝操作。

1、參數(shù)介紹:

//頭文件   <string.h>
void * memcpy ( void * destination, const void * source, size_t num );

  • destination目標(biāo)地址
  • source 源地址
  • 參數(shù)num的單位是字節(jié)。

2、代碼演示:

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

int main()
{
	int arr1[] = { 1,2,3,4,5,6,7 };
	int arr2[10] = { 0 };
	//因?yàn)橐粋€(gè)整型是4個(gè)字節(jié),arr1里面有7個(gè)整型數(shù)字,所以是28個(gè)字節(jié),
	//memcpy的三個(gè)參數(shù)num的單位是字節(jié),所以應(yīng)傳參28
    //將arr1的數(shù)據(jù)拷貝到arr2中
	memcpy(arr2, arr1, 28);
	return 0;
}

調(diào)試查看:

C語言進(jìn)階---字符串+內(nèi)存函數(shù),C語言,c語言

3、模擬實(shí)現(xiàn)memcpy()函數(shù)

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

void* my_memcpy(void* dest, const void* src, size_t num)
{
	assert(dest && src);
	//用于返回目標(biāo)地址。
	void* ret = dest;
	while (num--)
	{
		*(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 };
	int arr2[10] = { 0 };
	//因?yàn)橐粋€(gè)整型是4個(gè)字節(jié),arr1里面有7個(gè)整型數(shù)字,所以是28個(gè)字節(jié),
	//memcpy的三個(gè)參數(shù)num的單位是字節(jié),所以應(yīng)傳參28
	my_memcpy(arr2, arr1, 28);
	return 0;
}

4.2、memmove函數(shù)------內(nèi)存拷貝(可以用來重疊內(nèi)存之間的拷貝)

memcpy函數(shù)和memmove函數(shù)基本功能大致一樣,但是memmove有個(gè)比memcpy強(qiáng)大的小功能:

1、memcpy函數(shù)是不能用來處理重疊的內(nèi)存之間的數(shù)據(jù)拷貝。

2、memmove函數(shù)是可以處理重疊內(nèi)存之間的數(shù)據(jù)拷貝的。

3、 memcpy只是memmove的一個(gè)子集。

memmove函數(shù)的參數(shù)和memmove函數(shù)的參數(shù)是一樣的:

//頭文件   <string.h>
void * memmove ( void * destination, const void * source, size_t num );

既然參數(shù)一樣,那兩個(gè)函數(shù)的用法也是一樣的。

假如如下是數(shù)組arr1重疊部分:

C語言進(jìn)階---字符串+內(nèi)存函數(shù),C語言,c語言

下面來實(shí)現(xiàn)內(nèi)存重疊的代碼演示:

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

int main()
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	memmove(arr1, arr1 + 2, 20);
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr1[i]);
	}
	return 0;
}

輸出:

C語言進(jìn)階---字符串+內(nèi)存函數(shù),C語言,c語言

4.3、memcmp—內(nèi)存比較

//頭文件   <string.h>
int memcmp ( const void * ptr1, const void * ptr2, size_t num );

  • num參數(shù)是字節(jié)。
  • 比較從ptr1和ptr2指針開始的num個(gè)__字節(jié)__。
  • 返回值如下:
    • ptr1內(nèi)存塊中存儲(chǔ)的數(shù)據(jù)比ptr1內(nèi)存塊中存儲(chǔ)的數(shù)據(jù)大,就返回>0的值
    • ptr1內(nèi)存塊中存儲(chǔ)的數(shù)據(jù)比ptr1內(nèi)存塊中存儲(chǔ)的數(shù)據(jù)小,就返回<0的值
    • 如果將所指定的num字節(jié)全部比較完畢后,還是一樣的大小,會(huì)返回0.

1、代碼演示:

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

int main()
{
	int arr1[] = { 1,2,3,4,5 };
	int arr2[] = { 1,3,2 };
	//這里num為12,表示比較12個(gè)字節(jié)的內(nèi)容,一個(gè)int占用4個(gè)字節(jié),所以一共比較3個(gè)數(shù)字。
	int ret = memcmp(arr1, arr2, 12);
	printf("%d\n", ret);
	return 0;
}

輸出:

C語言進(jìn)階---字符串+內(nèi)存函數(shù),C語言,c語言

分析:是如何比較出來大小的呢?

首先arr1中的數(shù)字在內(nèi)存中是這樣存儲(chǔ)的:
01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 05 00 00 00

然后arr2中的數(shù)字在內(nèi)存中是這樣存儲(chǔ)的:

01 00 00 00 03 00 00 00 02 00 00 00

因?yàn)槲覀冎付酥槐容^12個(gè)字節(jié)的數(shù)據(jù),所以兩個(gè)數(shù)組開始從頭比較,直到比較到第五個(gè)字節(jié)(如下圖):

arr1的數(shù)據(jù)是02,arr2的數(shù)據(jù)是03。這樣一來比較大小就有了結(jié)果。是arr2大。所以返回-1<0的值。

C語言進(jìn)階---字符串+內(nèi)存函數(shù),C語言,c語言

4.4、memset—內(nèi)存設(shè)置

void * memset ( void * ptr, int value, size_t num );

參數(shù)說明:

  • ptr:需要填充的內(nèi)存塊的地址。
  • value:要被填充的內(nèi)容,(看著是int類型的,其實(shí)可以傳char類型的數(shù)據(jù),因?yàn)樽址趦?nèi)存中存儲(chǔ)也是按照ASCII值存儲(chǔ)的)。
  • num:要被填充多少個(gè)字節(jié)。

1、代碼演示:

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

int main()
{
	char arr[] = "hello bbo";
	//表示,從整個(gè)字符數(shù)組首字符開始,一直填充5個(gè)'x'字符。
	memset(arr, 'x', 5);
	printf("%s\n", arr);
	return 0;
}

輸出:

C語言進(jìn)階---字符串+內(nèi)存函數(shù),C語言,c語言文章來源地址http://www.zghlxwxcb.cn/news/detail-522008.html

到了這里,關(guān)于C語言進(jìn)階---字符串+內(nèi)存函數(shù)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 【進(jìn)階C語言】字符函數(shù)和字符串函數(shù)(萬文詳解)

    【進(jìn)階C語言】字符函數(shù)和字符串函數(shù)(萬文詳解)

    前言 C語言中對(duì)字符和字符串的處理很是頻繁,但是C語言本身是沒有字符串類型的,字符串通常放在常量字符串中或者字符數(shù)組中。 字符串常量適用于那些對(duì)它不做修改的字符串函數(shù). 今天將帶來C語言函數(shù)的使用介紹 分為三部分供大家理解 如果這份博客對(duì)大家有幫助,希望

    2024年01月18日
    瀏覽(23)
  • c語言——字符串函數(shù)和內(nèi)存操作函數(shù)

    c語言——字符串函數(shù)和內(nèi)存操作函數(shù)

    包含在string.h頭文件里 功能:返回字符串中有效字符的個(gè)數(shù),遇到‘\\0’結(jié)束,不包括結(jié)束符‘\\0’. 函數(shù)的參數(shù)為------const char* str:字符指針 返回值的類型------size_t:無符號(hào)整數(shù)(即:unsigned int) 模擬實(shí)現(xiàn)strlen: 方法一:計(jì)數(shù)器的方法 方法二:不能創(chuàng)建臨時(shí)變量的計(jì)數(shù)器

    2024年02月14日
    瀏覽(28)
  • 【C語言進(jìn)階(三)】字符串操作函數(shù)

    【C語言進(jìn)階(三)】字符串操作函數(shù)

    ??博主CSDN主頁:杭電碼農(nóng)-NEO?? ? ?專欄分類:C語言學(xué)習(xí)分享? ? ??代碼倉庫:NEO的學(xué)習(xí)日記?? ? ??關(guān)注我??帶你學(xué)習(xí)更多C語言知識(shí) ? ???? C語言的標(biāo)準(zhǔn)庫為我們提供了豐富的字符串操作函數(shù)與內(nèi)存操作函數(shù),有我們熟悉的 strlen ,strcpy ,也有我們不熟悉的 strchr , strstr 等

    2024年02月09日
    瀏覽(26)
  • 【C語言】字符函數(shù)與字符串函數(shù)以及內(nèi)存函數(shù) { 超詳細(xì)攻略,一篇學(xué)會(huì) }

    【C語言】字符函數(shù)與字符串函數(shù)以及內(nèi)存函數(shù) { 超詳細(xì)攻略,一篇學(xué)會(huì) }

    今日分享:字符、字符串函數(shù)和內(nèi)存函數(shù) 內(nèi)存函數(shù) 就是對(duì)內(nèi)存進(jìn)行操作的函數(shù) 字符串函數(shù) 就是對(duì)字符串進(jìn)行操作的函數(shù) 字符函數(shù) 就是對(duì)字符進(jìn)行操作的函數(shù) str 前綴的函數(shù)是字符串函數(shù),頭文件string.h mem 前綴的函數(shù)是內(nèi)存函數(shù),頭文件stdlib.h 字符分類函數(shù)包含在 ctype.h 頭

    2024年03月18日
    瀏覽(30)
  • C語言之字符串,內(nèi)存操作函數(shù)詳解(一)

    C語言之字符串,內(nèi)存操作函數(shù)詳解(一)

    ??博主CSDN主頁:杭電碼農(nóng)-NEO?? ? ?專欄分類:C語言學(xué)習(xí)分享? ? ??代碼倉庫:NEO的學(xué)習(xí)日記?? ? ??關(guān)注我??帶你學(xué)習(xí)更多C語言知識(shí) ? ???? C語言的標(biāo)準(zhǔn)庫為我們提供了豐富的字符串操作函數(shù)與內(nèi)存操作函數(shù),有我們熟悉的 strlen ,strcpy ,也有我們不熟悉的 strchr , strstr 等

    2024年02月08日
    瀏覽(31)
  • 【c語言:常用字符串函數(shù)與內(nèi)存函數(shù)的使用與實(shí)現(xiàn)】

    【c語言:常用字符串函數(shù)與內(nèi)存函數(shù)的使用與實(shí)現(xiàn)】

    簡介:本篇文章是對(duì)C語言中常用的字符串函數(shù)和內(nèi)存函數(shù)的學(xué)習(xí)以及模擬實(shí)現(xiàn) 文檔內(nèi)容來自:https://legacy.cplusplus.com/ 字符串以 ‘\\0’ 作為結(jié)束標(biāo)志, strlen函數(shù)返回的是在字符串中 ‘\\0’ 前?出現(xiàn)的字符個(gè)數(shù)( 不包含 \\\'\\0\\\' )。 參數(shù)指向的字符串必須要以 ‘\\0’ 結(jié)束。 注意函

    2024年02月04日
    瀏覽(22)
  • c語言進(jìn)階部分詳解(詳細(xì)解析字符串常用函數(shù),并進(jìn)行模擬實(shí)現(xiàn)(下))

    c語言進(jìn)階部分詳解(詳細(xì)解析字符串常用函數(shù),并進(jìn)行模擬實(shí)現(xiàn)(下))

    上篇文章介紹了一些常用的字符串函數(shù),大家可以跳轉(zhuǎn)過去瀏覽一下:c語言進(jìn)階部分詳解(詳細(xì)解析字符串常用函數(shù),并進(jìn)行模擬實(shí)現(xiàn)(上))_總之就是非常唔姆的博客-CSDN博客 今天接著來介紹一些:? 目錄 一.字符串查找 1.strstr() 1.1示例 1.2注意事項(xiàng): 1.3模擬實(shí)現(xiàn) ?2.

    2024年02月07日
    瀏覽(20)
  • 一篇博客學(xué)會(huì)系列(1) —— C語言中所有字符串函數(shù)以及內(nèi)存函數(shù)的使用和注意事項(xiàng)

    一篇博客學(xué)會(huì)系列(1) —— C語言中所有字符串函數(shù)以及內(nèi)存函數(shù)的使用和注意事項(xiàng)

    目錄 1、求字符串長度函數(shù) 1.1、strlen 2、字符串拷貝(cpy)、拼接(cat)、比較(cmp)函數(shù) 2.1、長度不受限制的字符串函數(shù) 2.1.1、strcpy 2.1.2、strcat 2.1.3、strcmp 2.2、長度受限制的字符串函數(shù) 2.2.1、strncpy 2.2.2、strncat 2.2.3、strncmp 3、字符串查找函數(shù) 3.1、strstr 3.2、strtok 4、錯(cuò)誤信息報(bào)告函數(shù)

    2024年02月08日
    瀏覽(20)
  • 字符串函數(shù)+內(nèi)存函數(shù)(詳解)

    字符串函數(shù)+內(nèi)存函數(shù)(詳解)

    本期帶大家一起來學(xué)習(xí)字符串函數(shù)+內(nèi)存函數(shù)?? ?? ?? 1. 求字符串長度 strlen???? 字符串 已經(jīng) ‘\\0’ 作為結(jié)束標(biāo)志 ,strlen函數(shù)返回的是在字符串中 ‘\\0’ 前面出現(xiàn)的字符個(gè)數(shù)(不包含 ‘\\0’ )。 strlen在庫里面的參數(shù)是如此的 ???? 接下來我們來模擬實(shí)現(xiàn)strlen ,接下來

    2023年04月17日
    瀏覽(30)
  • 字符串函數(shù)和內(nèi)存操作函數(shù)

    字符串函數(shù)和內(nèi)存操作函數(shù)

    目錄 0.字符串回顧 1.函數(shù)介紹 1.1 strlen 1.2 strcpy 1.3 strcat 1.4 strcmp 1.5 strncpy 1.6 strncat 1.7 strncmp 1.8 strstr 1.9 strtok 1.10 strerror 1.11 memcpy 1.12 memmove 1.13 memcmp 1.14 memset 1.15 字符相關(guān)函數(shù) 字符分類函數(shù) 字符轉(zhuǎn)換函數(shù) 2.函數(shù)模擬實(shí)現(xiàn) 2.1模擬實(shí)現(xiàn)strlen 2.2模擬實(shí)現(xiàn)strcpy 2.3模擬實(shí)現(xiàn)strcat 2.4模擬

    2024年02月15日
    瀏覽(23)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包