String function + memory function

String function + memory function

The previous blog has introduced most of the string functions. This blog first supplements the remaining string functions, and then mainly introduces the memory functions.

1. String function

1. strtok

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

The sep parameter is a string, which defines the set of characters used as a separator, and the str parameter specifies a string that contains 0 or more characters specified by sep A tag separated by one or more delimiters in the string.

The strtok function finds the next token in str, ends it with \0, and returns a pointer to this token. (Note: The strtok function will change the string being manipulated, so the strings split using the strtok function are generally temporary copied content and can be modified.)

The first parameter of the strtok function is not NULL, the function will find the first token in str, and the strtok function will save it in the string position in .

The first parameter of the strtok function is NULL, and the function will start at the saved position in the same string and search for the next token.

If there are no more tokens in the string, a NULL pointer is returned.

int main()
{<!-- -->
char arr[] = "abcd hi,world.";
char buf[50] = {<!-- --> 0 };
strcpy(buf, arr);//Copy to the buf array without modifying the source string
const char* sep = " ,.";
char* str = NULL;
for (str=strtok(buf, sep); str!=NULL; str=strtok(NULL, sep))
{<!-- -->
printf("%s\\
", str);
}
return 0;
}

image-20230520204644049

2. strerror

char * strerror ( int errnum );

Return the error code and the corresponding error message.

int main()
{<!-- -->
printf("%s\\
", strerror(0));
printf("%s\\
", strerror(1));
printf("%s\\
", strerror(2));
printf("%s\\
", strerror(3));
//Print the error information corresponding to error code 0, 1, 2, 3
return 0;
}

image-20230520205254256

A global variable errno (error code) is introduced here.

#include <errno.h>
//Using errno needs to refer to the header file
int main()
{<!-- -->
    printf("%s\\
", strerror(errno));
    return 0;
}

errno is a global variable, so it can be changed. When a program has two errors, when the program reaches the first error, the return value of the strerror function is the error message of the error code. When the program reaches the second error, the return value of the strerror function is the error message corresponding to the second error code.

(Note: The perror function is introduced here, which can print out the error message directly)

int main()
{<!-- -->
    perror("errrno");
    return 0;
}

image-20230520210710440

(errno is typed by yourself, and you can also write other things. Then this function adds a colon and space after what we wrote, and then the error message)

2. Character classification function

image-20230520212214803

Character conversion:

#include<ctype.h>
int main()
{<!-- -->
char ch = 'A';
putchar(toupper(ch));//convert to uppercase
putchar(tolower(ch));//convert to lowercase
return 0;
}

image-20230520212638806

3. Memory function

1. memcpy

void * memcpy ( void * destination, const void * source, size_t num );

The function memcpy copies num bytes of data backward from the location of source to the memory location of destination.
The function doesn’t stop when it encounters ‘\0’.
If the source and destination overlap in any way, the result of the copy is undefined.

int main()
{<!-- -->
int arr1[] = {<!-- --> 1,2,3,4,5,6,7,8,9,10 };
int arr2[5] = {<!-- --> 0 };
memcpy(arr2, arr1, 20);
int sz = sizeof(arr2) / sizeof(arr2[0]);
int i = 0;
for (i = 0; i <sz; i ++ )
{<!-- -->
printf("%d ", arr2[i]);
}
return 0;
}

Simulate implementation of memcpy:

#include <assert.h>
#include <stdio.h>
void* my_memcpy(void* dest, const void* src, size_t num)
{<!-- -->
assert(dest & amp; & amp; src);
void* ret = dest;//Need to return the starting address of the target location, so create a variable to store the starting location
while (num--)
{<!-- -->
*(char*)dest = *(char*)src;//Assign the content string in the source memory block to the target memory block, but the variable of void* type cannot be used directly, so we force it into (char* ) type, making it a byte-by-byte assignment. void* also cannot directly + + .
dest = (char*) dest + 1;
src = (char*)src + 1;
}
return ret;
}
int main()
{<!-- -->
int arr1[] = {<!-- --> 1,2,3,4,5,6,7,8,9,10 };
int arr2[5] = {<!-- --> 0 };
my_memcpy(arr2, arr1, 20);
int sz = sizeof(arr2) / sizeof(arr2[0]);
int i = 0;
for (i = 0; i < sz; i ++ )
{<!-- -->
printf("%d ", arr2[i]);
}
return 0;
}

2. memmove

void * memmove ( void * destination, const void * source, size_t num );

The difference from memcpy is that the source memory block and target memory block processed by the memmove function can overlap.
If the source space and the target space overlap, you have to use the memmove function to deal with it

int main()
{<!-- -->
int arr1[] = {<!-- --> 1,2,3,4,5,6,7,8,9,10 };
    
memmove(arr1 + 2, arr1, 20);//Copy of overlapping content can be realized
int sz = sizeof(arr1) / sizeof(arr1[0]);
int i = 0;
for (i = 0; i < sz; i ++ )
{<!-- -->
printf("%d ", arr1[i]);
}
return 0;
}

image-20230521133609405

Simulate implementation of memmove:

image-20230521133719350

#include <assert.h>
#include <stdio.h>
void* my_memmove(void* dest, void* src, size_t num)
{<!-- -->
assert(dest & amp; & amp; src);
void* ret = dest;
if (dest < src)//corresponds to the second case
{<!-- -->
while (num--)
{<!-- -->
*(char*)dest = *(char*)src;
dest = (char*) dest + 1;
src = (char*)src + 1;
}
}
else
{<!-- -->
while (num--)
{<!-- -->
*((char*)dest + num) = *((char*)src + num);
//num is realized in the judgment condition of while --
}
}
//When there is no overlap, it can be forward and reverse
return ret;
}
int main()
{<!-- -->
int arr1[] = {<!-- --> 1,2,3,4,5,6,7,8,9,10 };
\t
my_memmove(arr1 + 2, arr1, 20);
int sz = sizeof(arr1) / sizeof(arr1[0]);
int i = 0;
for (i = 0; i < sz; i ++ )
{<!-- -->
printf("%d ", arr1[i]);
}
return 0;
}

3. memcmp

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

Compare num bytes starting from ptr1 and ptr2 pointers

image-20230521135313692

1. Use of memcmp:

int main()
{<!-- -->
int arr1[] = {<!-- --> 1,2,3,4,5 };
int arr2[] = {<!-- --> 1,2,3,4,0x11223305 };
int ret = memcmp(arr1, arr2,18);
printf("%d\\
", ret);
return 0;
}

image-20230521140356063

Running result: image-20230521140516601

4. memset

memset initializes the memory unit in bytes

image-20230521143712604