Self-implementation of various string manipulation functions in C language such as strlen, strcpy, strcmp, memcpy, etc.

1.str class

(1) strlen (length)

The parameter is the address of the first element of the string with the required length (the string must have'\0' at the end) .

int my_strlen(const char* arr)
{
    
    
	int count = 0;
	assert(arr);//断言,确保arr是非空指针
	while (*(arr++))
	{
    
    
		count++;
	}
	return count;
}

Calculate from the first element until it hits'\0'. At this time, it will only judge and not count++, so'\0' is not included in the length.

(2) strcpy (copy)

The two parameters are the address of the first element of the destination and source strings (the source string cannot be modified) .

void my_strcpy(char* dest, const char* src)
{
    
    
	char* ret = dest;
	while (*(dest++) = *(src++))
	{
    
    
		;
	}
}

Make a simplification in the while loop, copy from the source string to the target string character by character, when it encounters'\0', because the while statement will execute the judgment statement first, the'\0' will also be copied in.
About strncpy , the third parameter char *strncpy (char *strDest, const char *strSource, size_t count ) is actually added on the basis of strcpy ; the
number of bytes copied can be adjusted. Here is the source code under VS2013:

char * __cdecl strncpy (
        char * dest,
        const char * source,
        size_t count
        )
{
    
    
        char *start = dest;

        while (count && (*dest++ = *source++))    /* copy string */
                count--;

        if (count)                              /* pad out with zeroes */
                while (--count)
                        *dest++ = '\0';

        return(start);
}

(3) strcmp (comparison)

The two parameters are respectively the address of the first element of the two strings to be compared.

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;
	}
}

In the while loop, after each entry, first determine whether it is the end, if it is the end, the two are equal and return 0
About strncat ibid strncpy.

(4) strcat (additional)

The two parameters are the target and the first address of the string to be appended.

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

Find the \0 of the target and perform an operation similar to strcpy in the place of \0
It should be noted that the inability to perform strcat (arr, arr) is to append one 's own operation, the reason is that one's own \0 has been appended by the first character, causing itself to lose \0.
About strncat ibid strncpy

(5) strstr (find substring)

The two parameters are the address of the first element of the string to be found and to be found .
Here is the test code.

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<assert.h>
char* my_strstr(const char* str1, const char* str2)
{
    
    
	assert(str1&&str2);
	const char* cp = str1;
	while (*cp)
	{
    
    
		const char* s1 = cp;
		const char* s2 = str2;
		while (*s1 && *s2 && *s1 == *s2)//*s1和*s2二者有一个为'\0'则停止
		{
    
    
			s1++;
			s2++;
		}
		if (*s2 == '\0')//s2为‘\0'则找到了,返回起始地址。
		{
    
    
			return cp;
		}
		cp++;
	}
	return NULL;
}
int main()
{
    
    
	char* arr1 = "abcdefgh";
	char* arr2 = "cde";
	char* ret = my_strstr(arr1, arr2);
	if (ret == NULL)
	{
    
    
		printf("没有找到!\n");
	}
	else
	{
    
    
		printf("%s\n", ret);
	}
	return 0;
}

In order not to change str1 and str2 easily, first define two pointers instead of str1 and str2, define cp to remember the starting position, and then define s1 and s2 for comparison.

2.mem class

(1)memcpy

The three parameters are the destination, the source, and the number of bytes copied .

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

First, you need to put the start address of the copied target string into ret in advance, because with the while loop address will change, then you need to assert dest and src, and then force dest and src to char*. Points to note Yes, the ++ operation of dest and src must be after the forced conversion, so choose front ++; copy each byte until count– is 0. Finally, return ret.
This function is suitable for the situation where the copyer and the copyee are independent. If the content overlaps, a bug will occur, for example:

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

What we want is to put "0,1,2,3" in the position of 3,4,5,6, but the result is the following, the reason is that 3 and 3 overlap, because the copy is from left to right At the time, 0 has been copied to 3 places.
Insert picture description here
We can use "memmove" to overcome this kind of problem when we encounter the above situation.

(2)memmove

The three parameters are the destination, the source, and the number of bytes copied .

void* my_memmove(void* dest, const void*src, size_t count)
{
    
    
	void* ret = dest;
	assert(dest&&src);
	if (dest < src)
	{
    
    
		while (count--)
		{
    
    
			*(char*)dest = *(char*)src;
			++(char*)dest;
			++(char*)src;
		}
	}
	else
	{
    
    
		while (count--)
		{
    
    
			*((char*)dest + count) = *((char*)src + count);
		}
	}
	return ret;
}

The problem that memcpy can't solve just now can be handled at this time.

int main()
{
    
    
	int arr[] = {
    
     0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
	my_memmove(arr + 3, arr, 16);
	for (int i = 0; i < (sizeof(arr) / sizeof(arr[0])); i++)
	{
    
    
		printf("%d ", arr[i]);
	}
	return 0;
}

Insert picture description here

When the address of dest is in front of the src address, it should be copied from front to back, and when the address of dest is behind the src address, it should be copied from back to front.

Guess you like

Origin blog.csdn.net/qq_43560037/article/details/111838652