[Advanced C language] The most commonly used library functions - from entry to proficiency

Table of contents

Foreword:

1. String functions

1. strlen - find the length of the string

strlen

2. String functions with unlimited length

a.strcpy - string copy

strcpy

 b.strcat - append string

screwed up

 c.strcmp - string comparison

strcmp

3. Length-limited string functions - strncpy, strncat, strncmp

Why do these functions appear?

The strncpy function:

strncpy

strncat function

strncat

The strncmp function:

strncmp

4. String lookup

a.strstr——judging whether it is a substring

strstr

b.strtok - a strange function

strtok

c.strerror - error message lookup

strerror

perror

The above are string-related functions, and the following are some character classification functions:

​Edit Character conversion function:

2. Memory function

1. Memory copy function

a.memcpy

b.memmove

2. Memory filling function - memset

3. Memory comparison function - memcmp

Summarize:


Blog homepage: Zhang Xurui's blog homepage

Welcome to pay attention: like + favorite + leave a message

Series of columns: c language learning

        It really takes time for family members to write blogs. Your likes and concerns are really important to me. I hope that friends who pass by can like and follow me more. I will keep in touch with each other at any time. Your private messages are welcome. , I also look forward to your forwarding!

       I hope you all follow me, and you will see more exciting content! ! !

Foreword:

        The processing of characters and strings in C language is very frequent, but C language itself does not have a string type, and strings are usually placed in constant strings or character arrays. String constants apply to string functions that do not modify them.

The following functions all need to refer to the header file <string.h>

1. String functions

1. strlen - find the length of the string

strlen

Function prototype:

 Function role:

  • The character string is '\0'marked as the end, and strlenthe return value of the function is the number of characters that appear in front of the character string'\0' (not included '\0')
  • The parameter is a char pointer variable
  • The string pointed to by the parameter must '\0'end with , otherwise the calculated length is a random value
  • Note that the return value of the function size_tis unsigned

Function notes:

        Because the return value is size_t, it is necessary to avoid the following code: strlen("abc") calculates the result is 3, strlen("abcde") calculates the result is 5, you may think of 3-5 to get -2 , in fact, this is not the case. The 3 and 5 calculated here are both unsigned integers, and the calculated -2 ​​is also an unsigned integer. -2 is stored in the memory in the form of complement code. From a perspective, this string of complements represents a large positive number.

3 methods of simulation:

recursion:

递归
int my_strlen1(const char* str)
{
	assert(str != NULL);
	if (*str != '\0')
		return 1 + my_strlen(str + 1);
	else
		return 0;
}

pointer-pointer 

指针-指针
int my_strlen2(const char* str)
{
	const char* start = str;
	assert(str != NULL);
	while (*str)
	{
		str++;
	}
	return str - start;

recursion 

int my_strlen(const char* str)
{
	assert(str != NULL);
	int count = 0;
	while (*str != '\0')
	{
		count++;
		str++;
	}
	return count;
}

2. String functions with unlimited length

a.strcpy - string copy

strcpy

Function prototype:

 Function role:

String copy function, copy the source string to the target space

Precautions:

The function has two parameters, source points to the string to be copied, also called the source string. destination is the address of the target space
The source string must end with '\0'

The target space must be large enough to ensure that the source string can be stored , otherwise illegal access will occur

Special case:
the '\0' in the source string will also be copied to the target space


The target space must be mutable, for example copying the source string into a string constant is not advisable

Simulation implementation:

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

 b.strcat - append string

screwed up

Function prototype :

 Function role:

        String append function, which appends the source string to the target string, and the terminating character '\0' in the target will be overwritten by the first character of the source string

Precautions:

The function has two parameters, where source points to the string to be appended, also called the source string, and destination is the address of the target space. There must be '\0' in the target space, and the source string must also
be used as the starting address of appending.
There must be '\0' as the end mark of appending.
The target space must be large enough to accommodate the contents of the source string.
The target space must be modifiable

The above is similar to strcpy, but there is a special point:
appending to yourself will fall into an endless loop!

Students can see from the code of the simulation implementation first that the essence of this function is to overwrite \0, and then add \0 at the end, but if you change it yourself, you will not overwrite \0, and finally cause an endless loop.

Simulation implementation:

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

 c.strcmp - string comparison

strcmp

Function prototype:

 Function role:

        Compare the size according to the ASCII value of the same position. is not longer than the string length

Precautions:

If the first string is greater than the second string, return a number greater than 0

If the first string is equal to the second string, return 0

The first string is less than the second string, returns a number less than 0

This function compares lexicographically.

 Simulation implementation:

int my_strcmp(const char* str1, const char* str2)
{
	assert(str1 && str2);
	while (*str1 == *str2)//如果相等就进去,两个指针加加,但是可能会出现两个字符串相等的情况,两个指针都指向'\0',此时比较就结束了
	{
		if (*str1 == '\0')
		{
			return 0;
		}
		str1++;
		str2++;
	}
	if (*str1 > *str2)
	{
		return 1;
	}
	else
	{
		return -1;
	}
}

3. Length-limited string functions - strncpy, strncat, strncmp

Why do these functions appear?

        The first three functions don't care about copying, appending, and comparing a few characters at all. They only care about finding a \0, and stop once a \0 is found. In this case, if the target space is not large enough, it will cause an out-of-bounds. These characteristics will make people decide that it is not safe, and we found that if we add to ourselves, there will be an infinite loop. Because of these shortcomings, the safer functions are introduced below.

The strncpy function:

strncpy

Function prototype:

 Function role:

length-limited copy of string

Precautions:

  • Copies num characters from source string to destination space.
  • If the length of the source string is less than num, after copying the source string, add 0 to the end of the target until num.

Simulation implementation:

char* my_strncpy(char* dest, const char* src, int num)
{
	assert(dest && src);
	char* ret = dest;
	while (num)
	{
		if (*src == '\0')//此时说明src指针已经指向了待拷贝字符串的结束标志'\0'处,src指针就不用再++了
		{
			*dest = '\0';
			dest++;
		}
		else
		{
			*dest = *src;
			dest++;
			src++;
		}
		num--;
	}
	return ret;
}

strncat function

strncat

Function prototype:

Precautions:

  • Append num characters from the first character of the source string to the end of the destination space, plus a terminating character.
  • If the length of the source string is less than num, only the content up to the terminating character is copied.

Simulation implementation:

char* my_strncat(char* dest, const char* src, int sz)
{
	assert(dest && src);
	char* ret = dest;
	//找目标空间的\0
	while (*dest != '\0')
	{
		dest++;
	}
	//追加
	while (sz)
	{
		*dest++ = *src++;
		sz--;
	}
	*dest = '\0';
	return ret;
}

The strncmp function:

strncmp

 Function prototype:

 

 Simulation implementation:

int my_strncmp(const char* str1, const char* str2, int sz)
{
	assert(str1 && str2);
	while (sz)
	{
		if (*str1 < *str2)
		{
			return -1;
		}
		else if (*str1 > *str2)
		{
			return 1;
		}
		else if(*str1 == '\0'||*str2 =='\0')//当有一个为'\0',说明比较就可以结束了
		{
			if (*str1 == '\0' && *str2 == '\0')//如果二者都是'\0',说明两个字符串相等
			{
				return 0;
			}
			else if(*str1 =='\0')//如果str1为'\0',说明str1小,str2大
			{
				return -1;
			}
			else//如果src为'\0',说明str1大,str2小
			{
				return 1;
			}
		}
		sz--;
		str1++;
		str2++;
	}
}

4. String lookup

a.strstr——judging whether it is a substring

strstr

Function prototype:

 Function role:

        Determine whether it is a substring

 

Precautions:

  • Find the string pointed to by str2 in the string pointed to by str1
  • Returns a pointer to the first occurrence of str2 in str1
  • If str2 is not part of str1, returns a null pointer NULL
  • The matching process does not include the terminating null character, but it stops there

BF algorithm (violent enumeration) simulation function implementation:

char* my_strstr(const char* str1, const char* str2)
{
	assert(str1 && str2);
	if (*str2 == '\0')
	{
		return (char*)str1;
	}
	const char* s1 = NULL;
	const char* s2 = NULL;
	const char* cp = str1;

	while (*cp)
	{
		s1 = cp;
		s2 = str2;
		while (*s1 !='\0' && *s2!='\0' && *s1 == *s2)
		{
			s1++;
			s2++;
		}
		if (*s2 == '\0')
		{
			return (char*)cp;
		}
		cp++;
	}

	return NULL;
}

KMP algorithm simulation implementation:

void Getnext(char* next, char* str2)
{
	next[0] = -1;
	next[1] = 0;
	int k = 0;
	int i = 2;
	while (i <= strlen(str2))
	{
		if (str2[k] == str2[i-1])
			next[i] = k + 1;
		else if (str2[i] != str2[0])
			next[k] = 0;
		else if (str2[i] == str2[0])
			next[k] = 1;
		k++;
		i++;
	}
}
char* KMP(const char* str1, const char* str2)
{
	assert(str1 && str2);
	int* next = (int*)malloc(sizeof(int) * strlen(str2));
	assert(next);
	Getnext(next, str2);
	int i = 0;
	int j = 0;
	while (i < strlen(str1) && j < strlen(str2))
	{
		if (j==-1||str1[i] == str2[j])
		{
			i++;
			j++;
		}
		else
		{
			j = next[j];
		}
	}
	free(next);
	if (i == strlen(str2))
		return &str1[i - j];
	return NULL;
}

About the KMP algorithm, you can learn about it through these two blogs:

An article to understand the KMP algorithm

About the next array

b.strtok - a strange function

strtok

Function prototype:

effect:

split string by delimiter

 Precautions:

1. The sep parameter is a string that defines the set of characters used as separators. The first parameter specifies a string that contains 0 or more tokens separated by one or more separators in the sep string.

2. The strtok function finds the next mark in str, ends it with \0, and returns a pointer to this mark. (Note: The strtok function will change the string being manipulated, so the strings split by the strtok function are generally temporary copied content and can be modified.) 3. If the first parameter of the strtok function is not
NULL, the function will Find the first token in str, the strtok function will save its position in the string.
4. The first parameter of the strtok function is NULL, the function will start at the saved position in the same string, and search for the next mark.
5. If there are no more tokens in the string, a NULL pointer is returned.

This function is very strange, let me give a chestnut:

Used to split strings. An example, such as my email is [email protected]. This mailbox initially consists of three parts, one is xxxxxx, one is 163, and the other is com. I now want to separate the three parts.

 

 Of course, we can use the for loop shorthand:

The simulation of this function is more complicated, so we will not simulate it first. 

c.strerror - error message lookup

strerror

Function prototype:

effect:

Convert error codes to error messages 

Precautions:

  • When the library function of C language is running, if an error occurs, the error code will be stored in a variable. This variable is: errno
  • The returned pointer points to a statically allocated string (error message string)

some chestnuts:

 usage:

int main()
{
	//打开文件
	FILE* pf = fopen("test.c", "r");
	if (pf == NULL)
	{
		printf("%s\n", strerror(errno));//需要包含头文件#include<errno.h>
		return 1;
	}
	//读文件
	//关闭文件
	fclose(pf);
	return 0;
}
//打开失败时屏幕显示:
No such file or directory

        Regarding errno here, when the library function of C language is running, if an error occurs, the error code will be stored in a variable, this variable is: errno, the error code is some numbers: 1 2 3 4 5, we need to say Error codes are translated into error messages.

perror function:

perror

It is actually a combination of printf and strerror!

The above are string-related functions, and the following are some character classification functions:

 Character conversion function:


tolower : Convert uppercase letters to lowercase letters
int tolower ( int c );
toupper : Convert lowercase letters to uppercase letters
int toupper ( int c );

        I will not explain these functions one by one. If family members are interested, you can go to the official website to find out!

2. Memory function

        Above we introduced functions for handling strings, but what about other types? Through the introduction of the following memory functions, I believe you will have some insights!

1. Memory copy function

a.memcpy

Function prototype:

Note:
 The destination here points to the target array where the content is to be assigned, the source points to the data source to be copied, and num is the number of bytes to be copied. Note that the type of the first two pointers and the return value of the function are both void *, this is because the memcpy function is a memory copy function, it is possible to copy various types of data such as integer, floating point, structure, etc... Although the return type is void*, it is also essential , void* also represents an address, and users can cast it into the type they need to use.

 The mock implementation of the function:

void* my_memcpy(void* dest, const void* src, size_t num)
{
	void* ret = dest;
	assert(dest && src);
	//前->后
	while (num--)
	{
		*(char*)dest = *(char*)src;
		dest = (char*)dest + 1;
		src = (char*)src + 1;
	}
	return ret;
}

 Note: ++ or -- cannot be used for (char*) dest here, because although the type is cast, its type essence has not changed.

However, this function has a flaw, that is, when it is copied to itself and there is an overlapping part, a bug will appear

        There will be problems if we only operate on a string. For example, I want to copy 1, 2, 3, 4, 5 in arr1 to 3, 4, 5, 6, 7. In theory, arr1[] should become 1, 2, 1, 2, 3, 4, 5, 8, 9.

But actually:

In order to modify this bug, the big guys wrote the memmove function again!

b.memmove

The function prototype is the same as memcpy, and the function is the same, the difference is that you can copy yourself, and overlapping will not cause bugs!

Why did the previous simulation implementation have this bug?

The reason is: when 1 is copied to 3, the original 3 has been replaced by 1, and when 2 is copied to 4, the original 4 has been replaced by 2. So when copying arr[2] to arr[4], the original 3 stored in arr[2] will be replaced by 1, similarly, so we get a result that does not meet our expectations. So how to solve this problem? Let’s first analyze the cause of this problem. This is because there is overlap between the source space and the target space. Here, arr[2], arr[3], and arr[4] are both the source space and the target space. When copying 1 and 2 At this time, the 3 and 4 that have not been copied in the source space are overwritten. At this time, the source spaces arr[2] and arr[3] are no longer 3 and 4, but 1 and 2, so At this time, the data in arr[2] and arr[3] are copied, in fact, 1 and 2 are copied. In order to solve this problem, we can copy from the back to the front, and this problem will not occur at this time

However, can we solve this problem by copying from the back to the front? The answer is of course not, for example:

So we need categories to discuss:

 Simulation implementation:

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

	return ret;
}

2. Memory filling function - memset

 Function role:

memory settings 

Precautions:

  • Set the data in the memory in bytes, and set the num bytes starting from ptr as value
  • The formal parameter value can also be a character, and the character is actually an integer, because the character is stored in memory in its ASCII
  • If the value is an integer, you need to pay attention to its value range, because a byte can store up to 255, and if it exceeds 255, it will be truncated
  • Since this function is a byte-by-byte change, some initializations are not valid. For example, it is impossible to initialize an integer array to 1, because each byte becomes 01. An integer is actually a very big numbers. Therefore, for integer array initialization, it is generally initialized to 0 or -1. Of course, for characters, don’t worry, he is also changed character by character!

3. Memory comparison function - memcmp

Function prototype:

 Precautions:

  • Compare num bytes starting from ptr1 and ptr2 pointers
  • The value of the first byte in the two memory blocks that does not match in ptr1 is lower than the value in ptr2 returns a number less than zero, equal returns zero, the first byte of the two memory blocks that do not match in ptr1 The value in is greater than the value in ptr2 returns a number greater than zero

Summarize:

This article uses the introduction of the function to learn initially, and the simulation implementation of the function to deeply understand the use of the library function. Thank you for your hard work, friends, move your little hands, and finally  , there are still many shortcomings in this article. Friends who have read the article carefully are welcome to communicate, criticize and correct by private message at any time!

Guess you like

Origin blog.csdn.net/qq_74310471/article/details/128718762