The strongest C language tutorial in history -- character function & string function

Posted by just1ncase on Tue, 11 Jan 2022 11:58:41 +0100

catalogue

1. Is there a string in C language?

2. Function introduction

2.1 strlen()

2.1.1 simulation implementation strlen() (implemented by three methods)

2.1.2 precautions

2.1.3 introduction to strlen() function

2.2 strcpy()

2.2.1 Simulation Implementation (strcpy)

2.2.2 precautions

2.3 strcat()

2.3.1 Simulation Implementation (strcat)

2.3.2 precautions

2.4 strcmp()

2.4.1 Simulation Implementation (StrCmp)

2.4.2 precautions

2.5 strncpy

2.5.1 simulation implementation of strncpy()

2.5.2 precautions

2.6 strncat()

2.6.1 simulation implementation strncat()

2.7 strncmp()

2.7.1 Simulation Implementation

2.8 strstr()

2.8.1 instructions and examples

2.8.2 Simulation Implementation (STR)

2.9 strtok()

2.9.1 instructions and examples

2.10 strerror()

2.10.1 instructions and examples

2.11 other functions

2.11.1 character classification function

2.11.2 character conversion function

3. Memory function

3.1 memcpy()

3.1.1 instructions and examples

3.1.2 simulation realization

3.2 memmove()

3.2.1 instructions and examples

3.2.2 simulation realization

3.3 memcmp()

3.3.1 instructions and examples

3.4 memset()

3.4.1 instructions and examples

1. Is there a string in C language?

The processing of characters and strings in C language is very frequent, but C language itself has no string type. Strings are usually placed in constant strings or character arrays. String constants are applicable to string functions that do not modify it!

2. Function introduction

2.1 strlen()

The strlen() function is used to find the length of a string.

2.1.1 simulation implementation strlen() (implemented by three methods)

(1) Counter method

#include<assert.h>
int my_strlen(const char* str)
{
	assert(str != NULL);
	int count = 0;
	while (*str != '\0')//While (* STR) -- ascii code value of '\ 0' is 0
	{
		count++;
		str++;
	}
	return count;
}

(2) Recursive implementation (methods that do not define temporary variables)

#include<stdio.h>
int my_strlen(const char* str)
{
	if (*str != '\0')
	{
		return 1+my_strlen(++str);
	}
	else
	{
		return 0;
	}
}

(3) Tail pointer - head pointer

#include<stdio.h>
#include<assert.h>
int my_strlen(const char* str)
{
	const char* ret = NULL;
	assert(*str != NULL);
	ret = str;
	while (*ret != "\0")
	{
		ret++;
	}
	return ret - str;
}

2.1.2 precautions

code:

#include<stdio.h>
#include<string.h>
int main()
{
	const char* str1 = "abcdef";
	const char* str2 = "bbb";
	if (strlen(str2) - strlen(str1) > 0)
	{
		printf("str2>str1\n");
	}
	else
	{
		printf("srt1>str2\n");
	}
	return 0;
}

Operation screenshot:

Reason:

The return type of the strlen() function is size_t is the unsigned int type. The data types on both sides of the operator are unsigned int, and the operation result type must also be unsigned int. this value is always greater than 0, so the above results will appear!

conclusion

When you implement it yourself, write the return type as size_t and int have their own advantages and disadvantages.

Int can effectively deal with the above special situation, but it is not easy to understand, because int includes negative numbers.

size_t is easier to understand, but it can't effectively deal with situations like the above.

2.1.3 introduction to strlen() function

(1) The string ends with '\ 0'. The strlen function returns the number of characters (excluding '\ 0') that appear before '\ 0' in the string.

(2) The string pointed to by the parameter must end with '\ 0'.

(3) Note that the return value of the function is size_t. Is unsigned (error prone)

2.2 strcpy()

The strcpy() function copies the contents of one string to another string (including '\ 0').

2.2.1 Simulation Implementation (strcpy)

#include<stdio.h>
#include<assert.h>
char*  my_strcpy(char* dest, const char* src)
{
	assert(dest != NULL);
	assert(src != NULL);
	char* ret = dest;
	//Copy the string pointed to by src to the space pointed to by dest, including '\ 0'
	while (*dest++ = *src++)
	{}
	//Returns the starting address of the destination space
	return ret;
}

2.2.2 precautions

(1) The source string must end with '\ 0'. For example, if the source string is defined like this, it cannot be copied normally:

char src[] = {'m','i','n'};

(2) Do you want to copy '\ 0' to the target space

(3) The destination space must be large enough to hold the source string

(4) The target space must be variable. For example, the target string cannot be defined in this way:

char *dest = "abcde";

Because the storage space of the target string is in the string constant area, the string here cannot be modified, and the program will crash.

2.3 strcat()

strcpy() appends strings.

2.3.1 Simulation Implementation (strcat)

#include<stdio.h>
#include<assert.h>
char* my_strcat(char* str1, const char* str2)
{
	assert(str1&&str2);
	char* ret = str1;
	//1. The position of '\ 0' in the destination string was found
	while (*str1 != '\0')
	{
		str1++;
	}
	//2. Append string (actually copy string)
	while (*str1++ = *str2++)
	{
		;
	}
	return ret;
}

2.3.2 precautions

(1) The source string must end with '\ 0'

(2) The target space must be large enough to hold the contents of the source string

(3) The target space must be modifiable

(4) You can't add it yourself, and the program will crash.

2.4 strcmp()

Compare the size of the ASCII code value corresponding to the corresponding character instead of the length of the string. Compare it character by character. If all characters are the same, an array equal to 0 will be returned. If the preceding character is less than the following character, a number less than 0 will be returned. If it is greater than the following character, a number greater than 0 will be returned.

2.4.1 Simulation Implementation (StrCmp)

The following is the simulation implementation of VS2019

#include<stdio.h>
#include<assert.h>
int my_strcmp(const char* str1, const char* str2)
{
	assert(str1 && str2);
	while (*str1 == *str2)
	{
		if (*str1 == '\0')
		{
			return 0;//equal
		}
		str1++;
		str2++;
	}
	if (*str1 > *str2)
	{
		//greater than
		return 1;
	}
	else
	{
		//less than
		return -1;
	}
}
int main()
{
	char *str1 = "abcde";
	char *str2 = "abcfg";
	int ret = my_strcmp(str1, str2);
	printf("%d", ret);
	return 0;
}

The following is the simulation implementation of linux

#include<stdio.h>
#include<assert.h>
int my_strcmp(const char* str1, const char* str2)
{
	assert(str1 && str2);
	while (*str1 == *str2)
	{
		if (*str1 == '\0')
		{
			return 0;//equal
		}
		str1++;
		str2++;
	}
	return (*str1-*str2);
}
int main()
{
	char *str1 = "abcde";
	char *str2 = "abcfg";
	int ret = my_strcmp(str1, str2);
	printf("%d", ret);
	return 0;
}

2.4.2 precautions

Standard provisions

(1) If the first string is greater than the second string, a number greater than 0 is returned

(2) If the first string is equal to the second string, 0 is returned

(3) If the first string is less than the second string, a number less than 0 is returned

be careful

strcpy(), strcat(),strcmp() are string functions that have nothing to do with length. They are not so safe and are only limited by '\ 0'.

2.5 strncpy

2.5.1 simulation implementation of strncpy()

#include<assert.h>
char* my_strncpy(char* str1, const char* str2,int count)
{
	assert(str1 && str2);
	char* ret = str1;
	int i = 0;
	for (i = 0; i < count; i++)
	{
		if (*str2 != '\0')
		{
			*str1++ = *str2++;
		}
		else
		{
			*str1++ = '\0';
		}
	}
	return ret;
}

2.5.2 precautions

(1) Copy num characters from the source string to the destination space.

(2) If the length of the source string is less than num, after copying the source string, append 0 to num after the destination.

2.6 strncat()

2.6.1 simulation implementation strncat()

#include<stdio.h>
#include<assert.h>
char* my_strncat(char* str1, const char* str2, int count)
{
	assert(str1 && str2);
	char* ret = str1;
	while (*str1++ != '\0');
	str1--;
	int i = 0;
	for (i = 0; i < count; i++)
	{
		if (*str2 != '\0')
		{
			*str1++ = *str2++;
		}
		else
		{
			*str1 = '\0';
			return ret;
		}
	}
	*str1 = '\0';
	return ret;
}

2.7 strncmp()

2.7.1 Simulation Implementation

#include<stdio.h>
#include<assert.h>
int my_strncmp(const char* str1, const char* str2, int count)
{
	assert(str1 && str2);
	int i = 0;
	for (i = 0; i < count; i++)
	{
		if (*str1 < *str2)
		{
			return -1;
		}
		else if (*str1 > *str2)
		{
			return 1;
		}
		else
		{
			str1++;
			str2++;
		}
	}
	return 0;
}

2.8 strstr()

Note: when reading a document, null is generally a null pointer, and NUL or null is' \ 0 '.

2.8.1 instructions and examples

(1) The string to be searched is preceded by the string to be searched.

(2) If it can be found, it returns the address of the following string that first appears in the previous string. If it does not appear, it returns a null pointer.

#include<stdio.h>
#include<string.h>
int main()
{
	char* str1 = "abcdefghijk";
	char* str2 = "def";
	char*ret = strstr(str1, str2);
	if (ret == NULL)
	{
		printf("String does not exist\n");
	}
	else
	{
		printf("%s\n",ret);
	}
	return 0;
}

Operation screenshot:

2.8.2 Simulation Implementation (STR)

#include<stdio.h>
#include<assert.h>
char* my_strstr(const char* str1,const char* str2)
{
	assert(str1 && str2);
	char* p1 = NULL;
	char* p2 = NULL;
	char* cur = str1;
	if (*str2 == '\0')
	{
		return (char*)str1;
	}

	while (*cur)
	{
		p1 = cur;
		p2 = (char*)str2;
		while ((*p1 != '\0') && (*p2 != '\0') && *p1 == *p2)
		{
			p1++;
			p2++;
		}
		if (*p2 == '\0')
		{
			return cur;//Substring found
		}
           if(*p1=='\0')
           {
                   return NULL;           
           }

		cur++;
	}
	return NULL;//Substring not found
}

2.9 strtok()

2.9.1 instructions and examples

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

(1) The sep parameter is a string that defines the set of characters used as delimiters

(2) The first parameter specifies a string that contains 0 or more tags separated by one or more separators in the sep string.

(3) The strtok function finds the next tag in str, ends it with \ 0, and returns a pointer to this tag. (Note: the strtok function will change the string to be manipulated, so the string segmented by the strtok function is generally a temporary copy and can be modified.)

(4) The first parameter of the strtok function is not NULL. The function will find the first tag in str, and the strtok function will save its position in the string.

(5) The first parameter of strtok function is NULL. The function will start at the position saved in the same string to find the next tag.

(6) If there are no more tags in the string, a NULL pointer is returned.

#include<stdio.h>
#include<string.h>
int main()
{
	char* arr = "123@456@abc.def.com";
	char* p = "@.";
	char str[500] = { 0 };
	strcpy(str, arr);
	char* ret = NULL;
	for (ret = strtok(str, p);ret != NULL;ret = strtok(NULL,p))
	{
		printf("%s\n", ret);
	}
	return 0;
}

Operation screenshot:

2.10 strerror()

2.10.1 instructions and examples

Return the error code and the corresponding error information.

Example:

#include<stdio.h>
#include<string.h>
int main()
{
	char* str0 = strerror(0);
	printf("%s\n", str0);
	return 0;
}

Operation screenshot:

0: No error

1:Operation not permitted

2:No such file or directory

3:No such process

......

The following is a more complete usage:

#include<stdio.h>
#include<errno.h>
#include<string.h>
int main()
{
	//errno is a global error code variable
	//When an error occurs during the execution of the library function of C language, the corresponding error code will be assigned to the errno variable
	char* str = strerror(errno);
	printf("%s\n", str);
	return 0;
}

2.11 other functions

2.11.1 character classification function

Note the header file < ctype, H >

function

If his parameters meet the following conditions, it returns true

iscntrl

Any control character

isspace

Blank characters: space ',' page feed '\ f', line feed '\ n', carriage return '\ r', tab '\ t' or vertical tab '\ v'

isdigit

Decimal digits 0 ~ 9

isxdigit

Hexadecimal digits, including all decimal digits, lower case letters a ~ F and upper case letters a ~ F

islower

Small letter a~z

isupper

Capital letters A~Z

isalpha

Letters a ~ Z or a ~ Z

isalnum

Letters or numbers, a~z,A~Z,0~9

ispunct

Punctuation mark, any graphic character not belonging to numbers or letters (printable)

isgraph

Any graphic character

isprint

Any printable character, including graphic characters and white space characters

If the judgment result is yes, a non-zero value is returned. If not, a zero value is returned.

2.11.2 character conversion function

int tolower ( int c );
int toupper ( int c );

Note: only one character can be converted one character at a time, not one string at a time!

Use example:

#include <stdio.h>
#include <ctype.h>
int main()
{
	int i = 0;
	char str[] = "Test String.\n";
	char c;
	while (str[i])
	{
		c = str[i];
		if (isupper(c))
			c = tolower(c);
		putchar(c);
		i++;
	}
	return 0;
}

Operation screenshot:

3. Memory function

3.1 memcpy()

3.1.1 instructions and examples

explain

(1) The function memcpy copies num bytes of data back to the memory location of destination from the location of source.

(2) This function will not stop when it encounters' \ 0 '.

(3) If there is any overlap between source and destination, the copied result is undefined.

Example:

#include<stdio.h>
#include<string.h>
int main()
{
	int arr1[] = { 1,2,3,4,5 };
	int arr2[5] = {0};
	memcpy(arr2, arr1, sizeof(arr1));
	for (int i = 0; i < 5; i++)
	{
		printf("%d ", arr2[i]);
	}
	return 0;
}

3.1.2 simulation realization

#include<stdio.h>
#include<assert.h>
void *my_memcpy(void* dest, const void* src, size_t num)
{
	assert(dest && src);
	void* ret = dest;
	int i = 0;
	while(num--)
	{
		*(char*)dest = *(char*)src;
		((char*)dest)++;
		((char*)src)++;
	} 
	return dest;
}

3.2 memmove()

3.2.1 instructions and examples

(1) The difference from memcpy is that the source memory block and target memory block processed by the memmove function can overlap.

(2) If the source space and target space overlap, you have to use the memmove function.

Example:

#include<stdio.h>
#include<string.h>
int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	memmove(arr + 2, arr, 20);
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

C language standard:

memcpy() can handle non overlapping memory copies.

memmove handles copies of overlapping memory.

3.2.2 simulation realization

#include<stdio.h>
#include<assert.h>
void *my_memmove(void* dest, void* src, size_t num)
{
	//Dest < SRC: copy from front to back
	//Dest > SRC & & dest < SRC + count: copy from back to front
	//Dest > SRC + count: from back to front and from front to back
	assert(dest && src);
	void* ret = dest;
	if (dest < src)
	{
		while (num--)
		{
			*(char*)dest = *(char*)src;
			((char*)dest)++;
			((char*)src)++;
		}
	}
	else
	{
		while (num--)
		{
			*((char*)dest+num )= *((char*)src+num);
		}
	}
	return dest;
}

3.3 memcmp()

3.3.1 instructions and examples

int memcmp ( const void * ptr1,  const void * ptr2, size_t num );

Example:

#include<stdio.h>
#include<string.h>
int main()
{
	int arr1[] = { 1,2,3,4,5 };
	int arr2[] = { 1,2,4,5,6 };
	int ret = memcmp(arr1, arr2, sizeof(arr1));
	printf("%d", ret);
	return 0;
}

3.4 memset()

3.4.1 instructions and examples

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

Function: set the buffer to a specific character.

dest: the starting position of the destination space.

c: The character to be set (whether C is a character).

count: the number of characters to be set (note that the number of characters is in bytes, because the memory space occupied by a character is one byte)

Use example:

#include<stdio.h>
#include<string.h>
int main()
{
	char arr[10] = "";
	memset(arr, '#', 10);
	for (int i = 0; i < 10; i++)
	{
		printf("%c ", arr[i]);
	}
	return 0;
}

Operation screenshot:

Topics: C Back-end