首頁 > 軟體

C語言詳細分析常見字串函數與模擬實現

2022-03-30 13:01:15

一. strlen(求長度)

size_t  strlen ( const char * str )

函數的返回值型別為size_t,為無符號數,且strlen返回值為字串中‘’前的字元個數。

猜猜這個程式的輸出

if (strlen("abc") - strlen("abcdef"))
	{
		printf(">");
	}
	else
	{
		printf("<");
	}

沒錯,是 > 

因為strlen的返回值為無符號數,-3變成了一個很大的正整數。

二. strcpy(拷貝)

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

使用時,源字串必須以結尾,並且''也會拷過去

strcpy:"我不管你放不放得下,我就拷。" 

目標地址必須夠大且可修改,不然的話,雖然可以放進去,但是程式會崩潰

strcpy的模擬實現

char* my_strcpy(char* dest,const char* source)
{
	assert(dest && source);
	char* ret = dest;
	while (*dest++ = *source++);
	return ret;
}

三.strcat(追加)

char  * strcat ( char * destination , const char * souce)

源字串必須有'',目標字串也得有'' 

追加後,目標空間的''無了,源字串的''新增上

目標地址必須夠大且可修改

strcat的模擬實現

char* my_strcat(char* dest,char* source)
{
	assert(dest && source);
	char* ret = dest;
	while (*dest)
	{
		dest++;
	}
	while (*dest++ = *source++);
	return ret;
}

四.strcmp

int strcmp(const char* string1, const char * string2)

strcmp函數比較的不是字串的函數長度`

而是比較字串中對應位置上的字元的大小,如果相同,就比較下一對字元,知道不同,或者遇到''.

若相同則返回0,若大於則返回大於零的數。若小於則返回小於零的數

strcmp的模擬實現

int my_strcmp(const char* str, const char* qtr)
{
	assert(str && qtr);
	while (*str == *qtr)
	{
		if (*str == '')
			return 0;
		str++;
		qtr++;
	}
	if (*str > *qtr)
		return 1;
	else
		return -1;
}

五.strncpy

char * strncpy ( char * dest, const char * source , size_t count)

作用是將源字串的前count個字元拷貝到目標字串

char a[] = "abcd";
char b[] = "qwer";
strncpy(a,b,1);

如以上修改後字串為qbcd

strncpy的模擬實現

#define _CRT_SECURE_NO_WARNINGS 1
#include<string.h>
#include<stdlib.h>
#include<stdio.h>
 
void my_strncat(char*dest,char*src,size_t n)
{
	int t = strlen(dest);
	int f = strlen(src);
	for (int i = 0; i < n; i++)
	{
		*(dest + i) = *src;
		src++;
	}
}
 
 
 
int main()
{
	int n;
	scanf("%d", &n);
	char src[50], dest[50];
	strcpy(dest, "NICE");
	strcpy(src, "SHOOT");
	my_strncat(dest,src,n);
	printf("%s", dest);
}

六.strncat

char * strncat ( char * dest , const char * source ,size_t  count) 

作用是將源字串的前count個字元追加到dest後面、

並且會在結尾加上‘’

char arr1[]="abcdefxx";
char arr2[]="qwer";
strncat(arr1,arr2,2);

修改後為abcdefqw

strncat的模擬實現

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<string.h>
#include<assert.h>
void my_strncpy(char* str, char* qtr, int size)
{
	assert(str && qtr);
	int t = strlen(str);
	for (int i = 0; i < size ; i++)
	{
		*(str + t + i) = *qtr;
		qtr++;
	}
	*(str + t + size) = '';
}
int main()
{
	char src[50], dest[50];
	strcpy(src, "A nice");
	strcpy(dest, " BOYYYYYYY");
	int n = 0;
	scanf("%d", &n);
	my_strncpy(src, dest, n);
	printf("%s", src);
}

七.strncmp

int strncm ( const char * str , const char * qtr , size_t num )

指定比較前num個字元,其他同strcmp一樣

八.strstr

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

用於查詢子串,返回第一次找到的地址

 九.strtok

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

引數sep是由分隔符組成的一個字串

str為一個字串,包含sep中零個或者多個分隔符.

strtok會找到str中第一個分隔符,並把其替換成'',返回一個指向這個分隔符的指標

若第一個引數為''',則從上一波儲存的位置向後查詢另一個分隔符

若字串中不存在更多的分隔符,則返回NULL指標

	char a[] = "A@nice.boy";
	char sep[] = "@.";
	printf("%s", strtok(a, sep));
	printf("%s", strtok(NULL, sep));

如以上結果為Anice

    char a[] = "A@nice.boy";
	const char sep[] = "@.";
	char arr[30];
	char* str = NULL;
	strcpy(arr, a);
	for (str = strtok(arr, sep); str != NULL; str = strtok(NULL, sep))
	{
		printf("%s", str);
	}

以上輸出為Aniceboy

十.strerror

char * strerror (int errnum )

errno是一個全域性變數,記錄最後的錯誤程式碼,程式剛剛啟動的時候,errno 被設定為 0;程式在執行過程中,任何一個函數發生錯誤都有可能修改 errno 的值,讓其變為一個非零值,用以告知使用者發生了特定型別的錯誤。

十一.memcpy

void * memcpy ( void* dest , const void * source ,size_t count)

作用是將源字串的前count個位元組拷貝到dest上

int a1[20] = {1,2,3,4,5,6,7,8};
int a2[5] = {0};
memcpy(a1,a2,20);

執行後,a1陣列前五個元素變成0

memcpy的模擬實現:

由於memcpy的拷貝是一個位元組一個位元組進行的

可用以下程式碼模擬實現

void* my_memcpy(void* dest, const void* source, size_t count)
{
	assert(source && dest);
	void* ret = dest;
	while (count--)
	{
		*(char*)dest = *(char*)source;
		source=(char*)source+1;
		dest=(char*)dest+1;
	}
	return ret;
}

十二.memmove

void * memmove (void * dest ,const void * source ,size_t count)

可以實現重疊記憶體拷貝

模擬實現:

void* my_memmove(void* dest, const void* source, size_t count)
{
	if (dest < source)
	{
		while(count--)
		{
		*(char*)dest = *(char*)source;
		dest = (char*)dest + 1;
		source = (char*)source + 1;
		}
	}
	else
	{
		while (count--)
		{
			*((char*)dest + count )= *((char*)source + count);
		}
	}
}

十三.memcmp

void * memcpy ( void * str , const void * qtr , size_t count)

比較str和qtr的前count個位元組,注意是一個位元組一個位元組比較

這就很有意思了

請看以下程式碼

int a[5] = { 1,2,3,4,5 };
int b[5] = { 1,2,3,4,0x11223305};
memcmp(a,b,16);

很明顯陣列的前十六個位元組相同,會返回0,但如果是前十七個呢

這是因為       

5儲存為  05 00 00 00 

0x11223305為   05 33 22 11

十四.memset

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

作用是將前count個位元組改成引數c

int a[]={0,0x22222222};
memset(a,1,8);

如以上a陣列變為0x01010101,0x0101010101

到此這篇關於C語言詳細分析常見字串函數與模擬實現的文章就介紹到這了,更多相關C語言 常見字串函數內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com