Topic: Common functions in C language

Table of contents

Preface

1.strlen function 

(1) Basic usage of strlen()

(2) Return value type of strlen()

(3) Customize my_strlen()

2.strcpy function

(1) Basic usage of strcpy()

(2) Customize my_strcpy()

3. strcat function

(1) Basic usage of strcat()

(2) Customize my_strcat()

4.strcmp function

(1) Basic usage of strcmp()

(2) Customize my_strcmp()

5.str- and strn-

(1) String functions with unlimited length

(2) String functions with limited length

6.strstr function

(1) Basic usage of strstr()

(2) Customize my_strstr()

(3) strchr and strrchr functions

7.strtok function

(1) Basic usage of strtok()

8.strerror function

(1) Basic usage of strerror()

9. Other string manipulation functions

Input and output functions

Case conversion function

String search

10. Common character operation functions

Input and output functions

Case conversion function

Character classification function

11.memset function

(1) Basic usage of memset()

12.memcpy function

(1) Basic usage of memcpy()

(2) Customize my_memcpy()

13.memmove function

(1) Basic usage of memmove()

(2) Customize my_memcpy()

14.memcmp function

(1) Basic usage of memcmp()

Summarize



Preface

        After learning some C language functions, the author rarely uses them (except strlen) when solving problems. After observing the clever problem-solving ideas and methods of some big guys, he always sighs: I can understand all the codes . Why didn't I do this? Then I planned to do it again according to the boss's ideas, but found that I couldn't write it. I think there are not a few beginners like this, so I plan to learn it again and share my learning process here.

Note: This article mainly involves some common character (string) operation functions ( string ) and memory-related functions ( mem ory). We only need to master the most commonly used functions, and we can look for other functions when needed.

Recommended website for learning functions: cplusplus.com


1.strlen function 

(1) Basic usage of strlen()

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

int main()
{
	char arr1[] = "abcdefg";
	char arr2[] = "abc\0defg";
	char arr3[20] = "abcdef";
	char arr4[] = { 'a','b','c','d','e','f','g' };
	char* arr5 = "abcde";
	printf("%d\n", strlen(arr1));
	printf("%d\n", strlen(arr2));
	printf("%d\n", strlen(arr3));
	printf("%d\n", strlen(arr4));
	printf("%d\n", strlen(arr5));
	return 0;
}

Function: The strlen() function returns the number of characters appearing before '\0' in the string, excluding '\0'. The string pointed to by the parameter must end with '\0' to return normal results.


(2) Return value type of strlen()

int main()
{
	char arr1[] = "abcd";
	char arr2[] = "abcdefg";
	printf("part1:>");
	if (strlen(arr1) - strlen(arr2) < 0)
	{
		printf("arr1的长度小于arr2\n");
	}
	else
	{
		printf("arr1的长度大于等于arr2\n");
	}

	printf("part2:>");
	if ((int)strlen(arr1) - (int)strlen(arr2) < 0)
	{
		printf("arr1的长度小于arr2\n");
	}
	else
	{
		printf("arr1的长度大于等于arr2\n");
	}
	return 0;
}

Note: The subtraction of the lengths of the two strings calculated using the strlen() function is always greater than or equal to 0. It can be seen that the return value of the strlen() function is not the int type we imagined, but the unsigned type size_t

 

(3) Customize my_strlen()

自定义my_strlen()函数类型为 int 或 size_t 都可以,但它们各有优缺点
例如:如果为 int 类型,就比较方便理解 strlen(arr1) - strlen(arr2) 这样
的形式,但是如果出现意料之外的错误,就有可能导致计算的字符串长度为负数

//创建临时变量-计数器count
int my_strlen1(const char *arr)
{
	assert(arr != NULL);
	int count = 0;
	while (*arr != '\0')
	{
		count++;
		arr++;
	}
	return count;
}

//不创建临时变量-递归
int my_strlen2(const char* arr)
{
	assert(arr != NULL);
	if (*arr != '\0')
		return 1 + my_strlen2(arr + 1);
	else
		return 0;
}

int main()
{
	char arr[] = "abcdefghijk";
	int ret = my_strlen1(arr);
	printf("%d\n", ret);
	printf("%d\n", my_strlen2(arr));
	return 0;
}


2.strcpy function

(1) Basic usage of strcpy()

Parameter 1: Target string (must be modifiable); Parameter 2: Source string (defined as const type to prevent modification).

下面哪些代码可以正常运行?

	char arr1_src[] = "abcdef";
	char arr1_dest[] = { 0 };
	strcpy(arr1_dest, arr1_src);
	printf("%s\n", arr1_dest);
//arr1_dest 所占空间太小
	char arr2_src[] = { 'a','b','c','d','e','f' };
	char arr2_dest[20] = { 0 };
	strcpy(arr2_dest, arr2_src);
	printf("%s\n", arr2_dest);
//arr2_src 中没有 '\0' 
	char arr3_src[] = "abc\0def";
	char arr3_dest[20] = { 0 };
	strcpy(arr3_dest, arr3_src);
	printf("%s\n", arr3_dest);
//仅成功拷贝 \0 之前的 abc 三个字符
	char arr4_src[] = "abcdef";
	char* arr4_dest = "qwerty";
	strcpy(arr4_dest, arr4_src);
	printf("%s\n", arr4_dest);
//目标空间为 const char 类型,不可被修改
	char arr5_src[] = "abcdef";
	char arr5_dest[20] = { 0 };
	strcpy(arr5_dest, arr5_src);
	printf("%s\n", arr5_dest);
//拷贝成功

Function: Copy the source string and store it in the target string. The source string must end with '\0'; the '\0' in the source string will be copied to the target space; the target space must be large enough to Ensure that the source string can be stored; the destination space must be variable

(2) Customize my_strcpy()

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

int main()
{
	char arr1[] = "Practise makes perfect!";
	char arr2[30] = { 0 };
	my_strcpy(arr2, arr1);
	printf("%s", arr2);
	return 0;
}


3. strcat function

(1) Basic usage of strcat()

Parameter 1: main string; Parameter 2: additional string.

int main()
{
	char arr1_dest[20] = "hello ";
	char arr1_src[] = "world!";
	strcat(arr1_dest, arr1_src);
	printf("%s\n", arr1_dest);

	char arr2_dest[20] = "hello \0xxxxxx";
	char arr2_src[] = "world!";
	strcat(arr2_dest, arr2_src);
	printf("%s\n", arr2_dest);

	char arr3_dest[20] = { 'h','e','l','l','o',' '};
	char arr3_src[] = "world!";
	strcat(arr3_dest, arr3_src);
	printf("%s\n", arr3_dest);

	char arr4_dest[20] = "hello ";
	char arr4_src[] = { 'w','o','r','l','d', '!'};
	strcat(arr4_dest, arr4_src);
	printf("%s\n", arr4_dest);
	return 0;
}

Function: Connect the content of the source string (including '\0') to the end of the '\0' of the target string (cover the '\0' of the target string) to ensure that the target space is large enough and can be modified.

(2) Customize my_strcat()

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

int main()
{
	char arr1[30] = "hello ";
	char arr2[30] = "world!";
	my_strcat(arr1, arr2);
	printf("%s", arr1);
	return 0;
}

思考:
my_strcat(arr1, arr1);
可以达到如下效果吗?
arr1 = "hello hello ";


4.strcmp function

(1) Basic usage of strcmp()

char arr1[] = "compare";
char arr2[] = "compbre";
//可以这样比较字符串的大小吗?
if("compare" == "compbre")
    printf("相等\n");
//这里实际上比较的是它们的地址
//因此这种写法是不能满足我们的需要的



int main()
{
	char arr1[] = "abcde";
	char arr2[] = "abcde";
	char arr3[] = "abcdabcd";
	char arr4[] = "z";

	if (strcmp(arr1, arr2) > 0)
		printf("arr1 > arr2\n");
	else if (strcmp(arr1, arr2) == 0)
		printf("arr1 = arr2\n");
	else
		printf("arr1 < arr2\n");

	if (strcmp(arr1, arr3) > 0)
		printf("arr1 > arr3\n");
	else if (strcmp(arr1, arr3) == 0)
		printf("arr1 = arr3\n");
	else
		printf("arr1 < arr3\n");

	if (strcmp(arr1, arr4) > 0)
		printf("arr1 > arr4\n");
	else if (strcmp(arr1, arr4) == 0)
		printf("arr1 = arr4\n");
	else
		printf("arr1 < arr4\n");
	return 0;
}

Function: Compare the size of strings. First compare the size of the ASCII codes of the first elements of the two strings. If they are equal, compare the next elements backward. If all the elements of the two strings are equal, then you can judge the size. Two strings are equal

(2) Customize my_strcmp()

int my_strcmp(const char* arr1, const char* arr2)
{
	assert(arr1 && arr2);
	while (*arr1 == *arr2)
	{
		if (*arr1 == '\0')
			return 0;
		arr1++;
		arr2++;
	}
	return *arr1 - *arr2;
}

int main()
{
	char arr1[] = "compare";
	char arr2[] = "compbre";
	int ret = my_strcmp(arr1, arr2);

	if (my_strcmp(arr1, arr2) > 0)
		printf("arr1 > arr2\n");
	else if(my_strcmp(arr1, arr2) == 0)
		printf("arr1 = arr2\n");
	else
		printf("arr1 < arr2\n");
	return 0;
}


5.str- and strn-

(1) String functions with unlimited length

The length of the strings used as parameters in the strlen, strcpy, strcmp, and strcat functions we introduced earlier are not limited, which may leave security risks, such as:

(2) String functions with limited length

String functions with a limited length are only relatively safe. If a person wants to write a bug, no one can stop him! ! !

strnlen、strncpy、strncmp、strncat

For example:


6.strstr function

(1) Basic usage of strstr()

Parameter 1: parent string; Parameter 2: substring.

Function: Determine whether str2 is a substring of str1, and return the address of the first occurrence of str2 in str1.

(2) Customize my_strstr()

char* my_strstr(const char* arr1, const char* arr2)
{
	assert(arr1 && arr2);
	char* str1 = NULL;
	char* str2 = NULL;
	char* p = (char*)arr1;
	while (*p)
	{
		str1 = p;
		str2 = (char*)arr2;
		while (*str1 && *str2 && *str1++ == *str2++)
		{
			;
		}
		if (*str2 == '\0')
			return p;
		p++;
	}
	return NULL;
}

int main()
{
	char arr1[] = "qwereabcd";
	char arr2[] = "were";
	char* ret = my_strstr(arr1, arr2);
	if (ret == NULL)
	{
		printf("找不到\n");
	}
	else
	{
		printf("找到了:%s中存在字符串%s\n", ret, arr2);
	}
	return 0;
}

(3) strchr and strrchr functions

int main()
{
	char arr1[] = "abcdefgbcde";
	char arr2[] = "bcde";
	char* ret1 = strchr(arr1, 'b');
	if (ret1 == NULL)
	{
		printf("找不到\n");
	}
	else
	{
		printf("%s\n", ret1);
	}
	char* ret2 = strrchr(arr1, 'b');
	if (ret2 == NULL)
	{
		printf("找不到\n");
	}
	else
	{
		printf("%s\n", ret2);
	}
	return 0;
}

Summary: strchr returns the address of the first time the target character is encountered, strrchr returns the address of the last time the target character is encountered.


7.strtok function

(1) Basic usage of strtok()

Parameter 1: String to be split; Parameter 2: Constant string (set of split characters).

0

Function: Returns a "mark": a pointer to a segment of the string to be split (change the splitting character in the original string to '\0' to split the original string).

When the first parameter of strtok is not NULL, the function returns the first token and saves its position in the string;

When the first parameter of strtok is NULL, the function will search for the next mark starting from the saved position;

If there are no more tokens in the string, return NULL

I think it is enough to learn to use the strtok function for now

Interested students can try it on their own, and you are welcome to share your own my_strtok in the comment area!


8.strerror function

(1) Basic usage of strerror()

Parameters: error code

Function: Return the address of the first character of the error message corresponding to the error code (translate an error code into an error message)

Explanation: When a C language library function fails to call, it will store an error code in a variable called errno. When we want to know what error occurred, we can use strerror to translate the error code errno into an error message.

Next we give an example:


9. Other string manipulation functions

Input and output functions

gets reads a string of characters (including spaces)

puts outputs a string of characters

Case conversion function

strlwr convert to lower case

strupr Convert to uppercase

String search

strpbrk...

strspn ...

... ...


10. Common character operation functions

Input and output functions

getchar reads a character

putchar outputs a character

Case conversion function

tolower Convert to lowercase

toupper convert to uppercase

Character classification function

Return true if conditions are met

isalnum determines whether it is a letter or number
isdigit determines whether it is a number
isxdigit determines whether it is a hexadecimal number
isalpha determines whether it is a letter
isupper determines whether it is an uppercase letter
islower determines whether it is a lowercase letter
iscntrl determines whether it is a control character
isspace determines whether it is a space, Page feed, line feed, carriage return, tab character
ispunct determines whether it is a punctuation mark
isgraph determines whether it is a graphic character
isprint determines whether it is a printable character

... ...


11.memset function

(1) Basic usage of memset()

Parameter 1: Points to the location that needs to be modified (pointer/array name); Parameter 2: Modified data; Parameter 3: The size of the modified space (unit is bytes)

val is of type int

val is of type char

Summarize:

(1) If ptr points to a char type address, value can be any character value;
(2) If ptr points to a non-char type, such as an int type address, if the assignment is to be correct, the value of value can only be - 1 or 0, because - After 1 and 0 are converted into binary, each bit is the same, so we often use memset to initialize the array to all 0s.
 


12.memcpy function

(1) Basic usage of memcpy()

Parameter 1: Pointer to the target space (void type); Parameter 2: Pointer to the source space (void type); Parameter 3: Size of the copied space (unit is byte)

注意:当我们需要拷贝字符串的时候,是否可以使用memcpy呢?答案是当然可以,
但是我们为什么不直接使用更加方便的strcpy呢?

void test1()
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr2[20] = { 0 };
	memcpy(arr2, arr1, 32);
	for (int i = 0; arr2[i] != 0; i++)
	{
		printf("%d ", arr2[i]);
	}
	printf("\n");
}

void test2()
{
	float arr1[] = { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 };
	float arr2[48] = { 0.0 };
	memcpy(arr2, arr1, 32);
	for (int i = 0; arr2[i] != 0; i++)
	{
		printf("%.2f ", arr2[i]);
	}
	printf("\n");
}

int main()
{
	test1();
	test2();
	return 0;
}

(2) Customize my_memcpy()

void* my_memcpy(void* dest, const void* src, size_t num)
{
	assert(dest && src);
	void* ret = dest;
	while (num--)
	{
		//我们不知道使用者需要拷贝的类型,所以采用逐字节拷贝的方法
        *(char*)dest = *(char*)src;
		dest = (char*)dest + 1;
		src = (char*)src + 1;
	}
	return ret;
}

void test3()
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr2[20] = { 0 };
	my_memcpy(arr2, arr1, 32);
	for (int i = 0; arr2[i] != 0; i++)
	{
		printf("%d ", arr2[i]);
	}
	printf("\n");
}

int main()
{
	test3();
	return 0;
}


13.memmove function

(1) Basic usage of memmove()

Parameter 1: Pointer to the target space (void type); Parameter 2: Pointer to the source space (void type); Parameter 3: Size of the moved space (unit is bytes)

 

Can the following code achieve the results we expect?

why?

Note: Not all compilers cannot copy normally when memory overlaps, but memcpy does have the risk of overwriting memory! 

(2) Customize my_memcpy()

void* my_memmove(void* dest, const void* src, size_t num)
{
	assert(dest && src);
	void* ret = dest;
	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;
}


14.memcmp function

(1) Basic usage of memcmp()

Parameter 1: Pointer 1 of the space to be compared (void type); Parameter 2: Pointer 2 of the space to be compared (void type); Parameter 3: Size of the space to be compared (unit is byte)

void test1()
{
	int arr1[] = { 1,2,3,4,5,7 };
	int arr2[] = { 1,2,3,4,6,7 };
	int ret = memcmp(arr1, arr2, 16);
	printf("%d\n", ret);//0
}

void test2()
{
	int arr1[] = { 1,2,3,4,5 };
	int arr2[] = { 1,2,3,4,6 };
	int ret = memcmp(arr1, arr2, 20);
	printf("%d\n", ret);//-1
}

void test3()
{
	int arr1[] = { 1,2,3,4,5 };
	int arr2[] = { 1,2,3,4,6 };
	int ret = memcmp(arr1, arr2, 17);
	printf("%d\n", ret);//-1
}

int main()
{
	test1();
	test2();
	test3();
	return 0;
}


Summarize

        The above is what I want to talk about today. In fact, learning programming requires not only answering questions, but also thinking and summarizing. Many times we don’t have a flash of inspiration from a big boss (I think generally this requires a lot of effort before we can do it) ), record some problem-solving skills and ideas, so that you can have more methods when encountering problems. I hope this article can be helpful to everyone, and readers are welcome to criticize and correct me^W^

Guess you like

Origin blog.csdn.net/weixin_72501602/article/details/129194248