[fundamentals of C language 11: string function and memory function] string function simulation, character function explanation and memory function simulation

Posted by Mr. R on Sun, 27 Feb 2022 05:17:39 +0100

String function

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. A constant string applies to string functions that do not modify it

/*
 * character string
 * - A string of characters ending with '\ 0'. 0 is the same as' \ 0 ', but different from' 0 '.
 * - 0 Marks the end of the string, but it is not part of the string.
 *   '\ 0' is not included when calculating the length of the string
 * - Most strings exist in the form of arrays and are accessed in the form of arrays or pointers
 *   More in the form of pointers.
 * - string.h There are many functions that handle strings.
 */
  • String properties

    int main()
    {
        //In C language, if there is nothing between two adjacent strings, it will be regarded as a string.
        printf("abc""def\n");//abcdef
    
        char a[] = "a""c";
        printf("%s",a);//ac
    
        // Here \, in the string, indicates line feed. The space before the string after line feed is also included in the string
        printf("abc\
               def\n");//acabc           def
    
       printf("abc\
    def");//acabcdef
    }
    
  • string constant

    int main()
    {
        int i;
        char *s = "hello world";
        char *s2 = "hello world";
    
        //Both s and s2 are pointers, which are initialized to point to a string constant.
        //Because of the location of this constant, s and s2 are actually const char *. However, if const is not written, the compiler will not report an error.
        //So we need to pay attention to ourselves that we can't modify constants
        //*s = 'B';     // This operation is to modify constants, which are not allowed to be modified, so an error is reported during compilation.
    
        //We found that the storage location of string constants is different from that of local variables.
        //The address of the local variable is far from the address of the long face of the string.
        //And s and s2 point to the same string constant. This is because string constants exist in code snippets.
        //And for the data in the code segment, we only have the permission to read, but not to write, which is why constants cannot be modified once they are defined.
        //Because s points to the same string constant as s2, they actually point to the same string constant.
        printf("%p\n",&i);  //000000A53B9FF72C
        printf("%p\n",s);   //00007FF7967BA000
        printf("%p\n",s2);  //00007FF7967BA000
    
        //If the defined string needs to be modified, an array should be used
        char s3[] = "Hello world!";
        
        return 0;
    }
    
  • Is char * a string?

    /*
     * 1.The string can be expressed as char *
     * 2.char*Not necessarily a string
     *   char*The original meaning is a pointer to a character, which may point to a character array
     *   Only when the character array pointed to by char * has a string terminator, can it be said that it points to a string.
     */
    
  • Empty string

    //'' is an empty string, which ends with \ 0, that is, buffer[0] = ' buffer [0] = '\ 0''
    char buffer[100] = "";
    
    //The length of the array is 1, in which a string terminator is stored \ 0
    char buffer[] = "";
    
  • The main() function has two arguments

    //Indicates that the array argv has argc elements.
    int main(int argc,char const* argv[])
    {
        //argv[0] is the command itself. When using Unix symbolic links, the name of the symbolic link is reflected.
        int i;
        for(i=0 ; i<argc ; i++)
        {
            printf("%d-%s\n",i,argv[i]);
            //Under windows: 0 -- D: \ program files (x86) \ clion 2021.3.2 \ project \ first \ cmake build debug \ first exe
    
        }
    }
    
    //In fact, it is used in Linux system. When inputting instructions to run the program, all input contents are separated by spaces and stored in argv() array
    //For example, input the instruction to call the above program (the above program is written into the file, the file name is a.out, and the executable program under linux takes. Out as the suffix).
    //Instruction:/ a.out 123 abc haha hehe 
    //Program execution output: 0 -/ a.out 1——123 2——abc 3——haha 4——hehe
    

Find string length function

strlen() function

  • Function prototype

    /*
     * strlen()function
     * Function prototype: size_t strlen(const char* str);
     * Function: returns the length of string str. The length of the string is determined by the terminating null character '\ 0'. Only count the number of characters until \ 0 appears, excluding the terminator '\ 0'.
     * Parameter - str: the string whose length is to be calculated.
     * Return value: returns the length of the string.
     * Note: the string pointed to by the parameter must end with \ 0. If there is no \ 0, it will be taken back until it touches the \ 0 position. Because the position where \ 0 appears later cannot be determined, the length of the string at this time is a random value.
     *      size_t Service number integer
     */
    
  • The strlen() function uses

    #include <string.h>
    #include <stdio.h>
    
    int main()
    {
        //There are actually four elements in the arr1 array: a b c  a B C \ 0
        char arr1[] = "abc";
        //No terminator in arr2 array \ 0
        char arr2[] = {'a','b','c'};
    
        int len1 = strlen(arr1);
        int len2 = strlen(arr2);
    
        printf("%d\n",len1);//3
        //At this time, the length is a random value, because if you don't touch \ 0, it will always be taken back.
        printf("%d\n",len2);//6
        return 0;
    }
    
  • Simulation of strlen() function

    Counter mode, using intermediate variables

    #include <string.h>
    #include <stdio.h>
    #include <assert.h>
    
    int my_strlen(const char * str)  //Because it only calculates the length, a non modifiable attribute is added to the str pointer.
    {
        assert(str);  //Execute the program when str is not a null pointer
        int count = 0;
        while(*str != '\0')
        {
            count++;
            str++;
        }
        return count;
    }
    
    int main()
    {
        char arr1[] = "abcdddef";
        char arr2[] = {'a','b','c'};
        //Simulate the implementation of strlen function
        int len1 =  my_strlen(arr1);
        int len2 =  my_strlen(arr2);
    
        printf("%d\n",len1);//8
        printf("%d\n",len2);//11, this 11 is a random value
        return 0;
    }
    

    Recursive implementation

    /*
     * The following procedure is performed:
     * - main()Function call, create char array, where data dog, printf ('% d \ n', my_strlen (ARR)); implement
     * - my_strLen(arr)Execute, where the memory address of the first element of the array is stored, where'd '! =\ 0 ', output and execute return 1+my_strLen(str+1);
     *   Note that str is passed in here, that is, dog' dog '\ 0'', the pointer variable used in comparison, * str indicates that it is the first element address, that is, the first character.
     * - 1+my_strLen(str+1)Execution, str+1 indicates the next memory address of'd '. At this point, str in the function becomes og' og '\ 0'', * str is' o '! =\ 0'
     *   Output and execute return 1+my_strLen(str+1);
     * - 1+my_strLen(str+1)Execution, str+1 indicates the next memory address of 'o'. At this point, str in the function becomes g' G '\ 0'', * str is' g '! =\ 0'
     *   Output and execute return 1+my_strLen(str+1);
     * - 1+my_strLen(str+1)Execution, str+1 indicates the next memory address of 'g'. At this time, str in the function becomes' \ 0 ', * str is' \ 0' = '\ 0'
     *   At this time, the condition in if is 0, and function recursion is no longer performed. return0
     * - return 0+1 Then return 1+1 again and return 1+2 again to return 3.
     */
    #include <stdio.h>
    
    //Because it is to calculate the number of characters in the array, it should return a number. Because you want to read the array itself, the parameter needs to be passed into the pointer variable.
    int my_strLen(char* str)
    {
        //If the address passed in does not correspond to the character at the end of the '\ 0' string, it will be called recursively
        //*str means the memory address of the element we passed in. If it is written as str, it is
        if(*str != '\0')
        {
            //Because str is a pointer variable, which stores the memory address of the first element of the array
            //Because the memory addresses of the elements stored in the array are continuous, str+1 represents the memory address of the next element.
            //This is not * str, because str+1 itself is the address. After we pass it in, the function can operate directly.
            return 1+my_strLen(str+1);
        }
    
        //If what is read in str is \ n, that is, it is read to the end of the string, then 0 is returned
        return 0;
    }
    
    int main()
    {
        char arr[] = "dog";
        printf("%d\n",my_strLen(arr));
    }
    

    Pointer pointer

    #include <stdio.h>
    
    //Method of subtracting array pointer to find length
    int myStrLen(char * str)
    {
        //Save the address of the first element of the array to s
        char * s = str;
        //If it is not \ 0, it loops until the address corresponding to str is the address of the last element
        while(*str != '\0')
        {
            str++;
        }
        //The address of the last element - the address of the first element is the number between the two elements, that is, the length of the string
        return str-s;
    }
    
    int main()
    {
        char arr[] ="abcdef";
        int len = myStrLen(arr);
        printf("%d\n",len);
        return 0;
    }
    
  • Note: the strlen() function returns size_ Type T, which is an unsigned integer

    #include <string.h>
    #include <stdio.h>
    
    int main()
    {
        //Because the return type of strlen is size_t. These two unsigned values are added and subtracted to return an unsigned number.
        //The first length is 3 and the second length is 6. 3-6 should have been - 3. However, because it is an unsigned integer, the highest 1 is resolved to a numeric bit.
        //-3 original code: 10000000 00000000 00000011
        //-3 inverse code: 11111111111111111111111111111100
        //-3. Complement: 11111111111111111111111111111111111101
        //-3 is stored as a complement in memory. If it is an unsigned integer, the highest 1 is parsed into numeric bits. 4294967293. This number is much greater than 0, so the output is greater than.
        if(strlen("abc")-strlen("abcdef") >0)
        {
            //%u print in unsigned shape.
            printf("%u\n",strlen("abc")-strlen("abcdef"));//4294967293
            printf("greater than");
        }
        else
        {
            printf("less than");
        }
    }
    

String function whose length cannot be set

strcpy() function

  • Function prototype

    /*
     * strcpy()function
     * Function prototype: char *strcpy(char *dest,const char *src)
     * Function: copy the C string pointed to by src to the array pointed to by dest, including terminated null characters (and stop at this point).
     * Parameter: dest -- target array for copying content; src -- string to copy
     * Note:
     * - If dest of the target array is not large enough and the length of the string in src is too long, it may cause buffer overflow. Make sure dest is large enough to put down the source string
     * - The target space must be variable. For example, dest is an array space and cannot be a pointer to a constant string, because the constant string is a constant and cannot be modified.
     * - If there is any content in the target array, it will be overwritten by the source string.
     * - The source string must end with '\ 0' because the copy will not stop until '\ 0' is encountered. If there is no '\ 0', unexpected results may be obtained.
     * Return value: returns a pointer to the final target string dest
     */
    
  • use

    #include <stdio.h>
    #include <string.h>
    
    int main()
    {
        //Array copy
        char arr1[20] = {0};
        char arr2[] = "hello world!";
    
        strcpy(arr1,arr2);
        printf("%s\n",arr1);//hello world!
    
        //String copy
        char arr3[20] = {0};
    //    char* p ="abcdefg";
    //    strcpy(arr3,p);
        //It can be simplified to:
        strcpy(arr3,"you are good");
        printf("%s\n",arr3);
    
        //The program will hang up because the constant string cannot be modified.
    //    char* str = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
    //    char* p ="abcd";
    //    strcpy(str,p);
    //    printf("%s\n",str);
    
        //If there is any content in the target string, it will be overwritten by the source string.
        char arr4[20] = {'c','c','c'};
        char arr5[] = {'a','b','c'};
        //If the source string does not end with '\ 0', it will be copied until it meets \ 0.
        strcpy(arr4,arr5);
        printf("%s\n",arr4);//Abcabc. If there is \ 0 after c, the normal copy should be abc, but there is no \ 0, so abcabc appears. abc is followed by random characters.
        return 0;
    }
    
  • Simulation Implementation of strcpy() function

    #include <stdio.h>
    
    void myStrCpy(char* dest,char* src)
    {
        //Copy when not at the end of the string
        while(*src != '\0')
        {
            *dest++ = *src++;
        }
        //At this point, the data stored in * src is \ 0 and * dest is + +. Although the loop stops at this time, we can manually copy \ 0 to dest
        *dest =*src;
    }
    int main()
    {
        char arr1[20] = "abcdefgh";
        char arr2[] = "hello";
        myStrCpy(arr1,arr2);
        printf("%s",arr1);
        return 0;
    }
    

    simplify

    #include <stdio.h>
    
    void myStrCpy(char* dest,char* src)
    {
        //When the end of the string is not reached, the loop continues. Here is the post + +, which is assigned first and then calculated.
        //The result of the expression in () is the result of * src. For example, the result of the expression b=3 and a=b should be a, but a=b, that is, b is the result of the expression.
        //When src points to 'h', its corresponding ASCII code is: 104. If the non-zero condition is true, execute the empty statement. At this point, the post + + takes effect and continues to judge the results in ()
        //Only when src=' SRC = '\ 0'', that is, dest=' DeST = '\ 0'', the string terminator '\ 0' is copied, and the string copy is completed. The ascii code of '\ 0' is 0, that is, the condition is false and the loop ends.
        while(*dest++ = *src++);
    
        //reference resources:
        //int i = 1;
        //printf("%d\n",i='\0'); //0
    }
    int main()
    {
        char arr1[20] = "abcdefgh";
        char arr2[] = "hello";
        myStrCpy(arr1,arr2);
        printf("%s",arr1);
        return 0;
    }
    

    Use assertions and const modifiers

    #include <stdio.h>
    #include <assert.h>
    
    //The string copy function in the library function is char * strcpy (char * destination, const char * source);
    //Its formal parameter adds a const before the source array. Why add this?
    //We copy to put the content pointed by src into the space pointed by dest. In essence, we want the content pointed by DeST to be modified, while the content pointed by src is not modified.
    //That is, * src cannot be modified, so const is added to the left of * to indicate that * src cannot be modified.
    void myStrCpy(char* dest,const char* src)
    {
        //When the program executes to the position of the assertion, the corresponding assertion should be true. If the assertion is not true, the program will abort execution and give an error message.
        //When one of the two arrays passed in is a null pointer, an error message is output
        assert(dest != NULL);
        assert(src != NULL);
        //const indicates that the modified variable cannot be modified. Prevent us from writing backwards in the process of writing.
        // In other words, if we write it backwards here, the compilation will not pass and an error will be reported: assignment of read only location '* SRC + +'
        //while(*src++ = *dest++);
        while(*dest++ = *src++);
    
    }
    int main()
    {
        char arr1[20] = "abcdefgh";
        char arr2[] = "hello";
        myStrCpy(arr1,arr2);
        printf("%s",arr1);
        return 0;
    }
    

    Final edition

    #include <stdio.h>
    #include <assert.h>
    //The string copy function in the library function is char * strcpy (char * destination, const char * source);
    //The return type of the library function is a pointer, which returns the starting address of the target.
    char* myStrCpy(char* dest,const char* src)
    {
        assert(dest);
        assert(src);
        //We define a pointer to receive the target starting address of the incoming function and save it to the variable.
        //Use ret to change the copy address.
        char* ret = dest;
        while(*ret++ = *src++);
        //After the copy is completed, return to the starting address.
        return dest;
    }
    int main()
    {
        char arr1[20] = "abcdefghjklmn";
        char arr2[] = "hi baby!";
        printf("%s",myStrCpy(arr1,arr2));
        return 0;
    }
    

strcat() function

  • Function prototype

    /*
     * String splicing function strcat()
     * Function prototype: char * strcat(char* dest,const char* src);
     * Function: append the string pointed to by src to the end of the string pointed to by dest. The first string terminator in dest string is overwritten by the first character of src.
     *      Splice the entire source string, including the terminator \ 0, into the dest string. If the spliced source string has no terminator \ 0, the program will go down.
     *      It is reasonable to say: if an array, copy yourself. The string terminator \ 0 stored in the array will be replaced, but it is not replaced when running. It is copied normally, and the copied string has an end character. But if you copy a character array without a terminator, the program will go down.
     * Parameter: dest: refers to the target array, which contains a C string and is enough to hold the appended string. src: the string to append, which does not overwrite the target string.
     * Return value: returns dest string pointer
     * Note: dest must be modifiable and cannot be a pointer to a constant string. The source string must have a string terminator \ 0
     */
    
  • use

    #include <string.h>
    #include <stdio.h>
    
    int main()
    {
        char arr1[20] = "hello \0";
        strcat(arr1,"word!");
    
        printf("%s\n",arr1);//hello word!
        return 0;
    }
    
  • Simulation Implementation of strcat() function

    #include <string.h>
    #include <stdio.h>
    
    char* my_strcat(char* dest,const char* src)
    {
        //Because we want to return the target pointer, we save its pointer before attaching.
        char* ret = dest;
        //1. Find the \ 0 in the string dest
        while(*dest) //When * dest is not \ 0, the loop runs all the time. When it points to \ 0, * dest= dest = \ 0,, the result of this expression is 0 and the loop ends.
        {
            dest++;
        }
        //Append a string containing '\ 0'. When * src=' SRC = '\ 0'', * dest = '\ 0', and \ 0 is 0, and the loop ends. When the string terminator is copied, the loop also stops.
        while(*dest++ = *src++);
        return ret;
    }
    
    int main()
    {
        char arr1[20] = "hello \0";
        printf("%s\n",my_strcat(arr1,"world!"));//hello word!
        return 0;
    }
    

strcmp() function

  • Function prototype

    /*
     * strcmp()function
     * - Used to compare two strings
     * - Syntax: int StrCmp (const char * STR1, const char * STR2);
     *   Parameter str1 and parameter str2 are two strings involved in the comparison
     * - strcmp()Each character in str1 and str2 is compared in sequence according to ASCII encoding until an unexpected character appears or reaches the end of the string (encounter \ 0)
     * - Return value:
     *     -If the return value < 0, it means STR1 < STR2
     *     -If the return value > 0, it means STR1 > STR2
     *     -If the return value = 0, it means str1 = str2
     * - Compare the ASCII codes of the characters in the same position of the two strings. Once there is a mismatch, compare the two characters. ASCII code is small when it is low and large when it is high.
     * - If abcq is compared with adc, the first character of the two strings is the same. Comparing the second character, d is larger than b, so adc > abcq. The size of the character in the corresponding position is compared, not the length of the string.
     */
    
  • use

    #include <stdio.h>
    #include <string.h>
    
    int main()
    {
        char* p = "obc";
        char* q = "abcdef";
        //String comparison cannot use operator comparison, but use the corresponding string function.
        //Compare the ASCII code of the character at the corresponding position of two strings.
        int ret = strcmp(p,q);
        if(ret > 0)
        {
            printf("p large");
        }
        else if(ret < 0)
        {
            printf("q large");
        }
        else
        {
            printf("p=q")
        }
        return 0;
    }
    
  • Simulation of strcmp() function

    #include <stdio.h>
    #include <string.h>
    #include <assert.h>
    
    int my_strcmp(const char* s1 ,const char* s2)
    {
        assert(s1 && s2);//If either s1 or s2 is a null pointer, the program will not continue.
        //If the characters in the corresponding position are equal, the address + 1 points to the next character. Until the two characters are not equal or the comparison is complete.
        while(*s1 == *s2)
        {
            //If one of them is a string terminator, the two strings are exactly equal. Equal returns 0.
            if(*s1 == '\0')
            {
                return 0;
            }
            s1++;
            s2++;
        }
    
        //If abc is compared with abcd, then after c is compared. If D is compared with \ 0, d must be greater than 0, so it is abcd > abc
        //If the characters pointed to are not equal, compare them to see which is larger.
        //If s1 is larger than s2, the number > 0 is returned// If s1 < s2, the number < 0 is returned.
        return *s1 - *s2;
    }
    
    int main()
    {
        char* p = "abce";
        char* q = "abcdef";
        //Compare the ASCII code of the character at the corresponding position of two strings.
        int ret = my_strcmp(p,q);
        if(ret > 0)
        {
            printf("p large");
        }
        else if(ret < 0)
        {
            printf("q large");
        }
        else
        {
            printf("p=q");
        }
        return 0;
    }
    

String function with settable length

strncpy() function

  • Function prototype

    /*
     * strcnpy()function
     * Function prototype char* strncpy(char* dest,const char* src,size_t num);
     * Function: copy the first num characters of src to dest. If num > src length, fill the excess with \ 0 until a total of num characters are written. If num < SRE, the null character is not implicitly appended to the end of the target.
     * Parameters:
     * - dest: Pointer to the target array to store the copied content.
     * - src: String to copy
     * - num: The maximum number of characters to copy from src. size_t is an unsigned integer.
     * be careful:
     * - dest Cannot overlap src. In other words, you can't copy yourself.
     * - If there is content in DeST, and there is no empty character in src, src > num, then the first num characters of DeST are copied from src, and the rest is the content in dest.
     *   Unless the null character \ 0 is copied from src, the part longer than src in dest will not be displayed.
     * Return value: dest
     */
    
  • use

    #include <string.h>
    #include <stdio.h>
    
    int main()
    {
        char arr1[20] = "abcdef";
        char arr2[] = "qwer";
        //Copy qw to arr2. Because there is no empty character, the first two characters of arr1 become: qw, followed by the cdef already in arr1. Become: qwcdef
        strncpy(arr1,arr2,2);
        printf("%s\n",arr1); //qwcdef
        return 0;
    }
    
  • Simulation Implementation of strncpy() function

    #include <stdio.h>
    char* my_strncpy(char* dest,const char* src,size_t num)
    {
        //Save dest and return at last
        char* start = dest;
        //Condition: copy when num is not 0 and * src does not reach \ 0
        //Case 1: when num is not 0, when * src=' SRC = '\ 0'', * dest = ' dest = '\ 0'', \ 0 is 0, and the cycle stops// Because the copy \ 0 is also a copy, but it is copied once, and the loop is not executed, Num is reduced once.
        //Case 2: when * src is not 0 and num is 0, it indicates that the number of times to copy has been completed.
        //Post + +. After each copy, dest and src point back to a position to facilitate copying.
        while(num && (*dest++ = *src++))
        {
            num--;//Each time the loop is executed, num-1
        }
    
        //When num is 0, it indicates that the number of copies has been completed, and there is no need to operate again
        //If num is not 0 and * src is the string terminator \ 0. At this time, if num is a few, you need to append a few \ 0 later.
        //1. If num is not 0 and 1 is subtracted from num in our above program, an additional \ 0 will be added if post + + is used
        //2. Use pre + +, subtract 1 before executing the program, and add 0 after dest. This seems reasonable. But when num=0, 0-1 = - 1, because num is an unsigned integer- 1 is parsed into a large number, and the loop always appends \ 0. At this time, the program will fall into an endless loop.
        //Therefore, we can't operate directly. Instead, we need to judge whether num is 0 before operation. If not, we can operate again
        //while(++num){*dest++ = '\0';}
        if(num)
        {
            //If num is not 0, continue to append null characters to dest
            while(--num){
                //In this case, num is not 0, but * dest=*src= dest = * SRC = \ 0.. Because it is post + +, DeST at this time points to the back of the copied \ 0, and directly * appends \ 0
                //The post + + is also for the convenience of the next addition.
                *dest++ = '\0';
            }
        }
    	return start;
    }
    int main()
    {
        char arr1[20] = "abcdefg";
        char arr2[] = "qwe";
        //Copy qw to arr2. Because there is no empty character, the first two characters of arr1 become: qw, followed by the cdef already in arr1. Become: qwcdefg
        my_strncpy(arr1,arr2,2);
        printf("%s\n",arr1); //qwcdefg
    
        //When num > SRC, if you want to verify whether the number of \ 0 copies is correct, you can add a breakpoint and Debug to check.
        return 0;
    }
    

strncat() function

  • Function prototype

    /*
     * String splicing function with specified length strncat()
     * Function prototype: char * strncat(char* dest,const char* src,size_t num);
     * Function: will src Before num Characters appended to dest ending. dest The first string terminator in the string is src The first character is overwritten. And add the string terminator at the end of the spliced string
     *      If src The length of the string in is less than num,Then only the contents of the empty string are copied until it is terminated(Include termination string). 
     * Note: because when the length<num When, strncat No terminator will be added to it. It will end only when it meets the terminator. At this time, if the appended character array has no terminator\0 When, the content after adding the characters of its length is random, because only the terminator is encountered\0 It will end. So when we add it, src The string must have\0. 
     * Parameters:
     * - dest: Point to the target array, which should contain a C String, and enough to accommodate the appended string, including additional null characters
     * - src: String to append
     * - num: The maximum number of bytes to attach. size_t Unsigned integer.
     * Return value: returns a string that only wants the final target dest Pointer.
     *
    
  • use

    #include <string.h>
    #include <stdio.h>
    
    int main()
    {
        char arr1[20] = "hello ";
        char arr2[] ="world!";
    
        //Append the first three characters of arr2 to the end of arr1. The first string terminator in arr1 is overwritten by the first character in arr2. And add the string terminator \ 0 at the end of the spliced string
        strncat(arr1,arr2,3);
        printf("%s\n",arr1); //hello wor
    
        char arr3[20] = "hi ";
        char arr4[] ="baby!";
        //If the length of the string in arr4 is less than 20, only the contents of the empty string (including the termination string) are copied until termination.
        strncat(arr3,arr4,20);
        printf("%s\n",arr3); //hi baby!
        return 0;
    }
    
  • Simulation Implementation of strncat() function (implementation method of simulation library function)

    #include <stdio.h>
    
    char* my_strncat(char* dest, char* src, size_t num)
    {
        //Save dest and return
        char* start = dest;
        //First position dest to its string terminator \ 0.
        //*When dest= dest = \ 0,, the condition is 0 and the cycle ends. Post + +, where dest points to the position after \ 0.
        while(*dest++);
        //dest-1, let dest point to the string terminator \ 0.
        dest--;
        //The number of num cycles several times
        while(num--)
        {
            //Copy.
            //*dest++ = *src++;
            //If num > SRC length, how does it end? Add judgment and end the method when * src ==  SRC = = \ 0
            //if(*src == '\0'){return start;}
    
            //Simplification: the end method ends only when the string terminator is copied.
            //Case 1: when num < SRC length, after chasing num characters, the cycle will end. A string terminator is added to it when it is finished.
            //Case 2: num > SRC length, end the method when * src ==  SRC = = \ 0..
            if((*dest++ = *src++) == '\0')
            {
                return start;
            }
        }
    
        //Add string terminator to end \ 0
        *dest = '\0';
    
        //Return dest.
        return start;
    }
    
    int main()
    {
        char arr1[20] = "hello ";
        char arr2[] ="world!";
    
        //Append the first three characters of arr2 to the end of arr1. The first string terminator in arr1 is overwritten by the first character in arr2. And add the string terminator \ 0 at the end of the spliced string
        my_strncat(arr1,arr2,3);
        printf("%s\n",arr1); //hello wor
    
        char arr3[20] = "hi ";
        char arr4[] ="baby!";
        //If the length of the string in arr4 is less than 20, only the contents of the empty string (including the termination string) are copied until termination.
        my_strncat(arr3,arr4,20);
        printf("%s\n",arr3); //hi baby!
    
        return 0;
    }
    

    Implementation notes:

    /*
     * - Because when the length is < num, strncat will not add a terminator for it, and it will end only when it meets the terminator.
     *   At this time, if the appended character array has no terminator \ 0, the content after the appended character of its length is random, because it will end only when it meets the terminator \ 0.
     *   Therefore, when we append it, the src string must contain \ 0.
     * - Solution: re implement strncat
     *
     * - Implementation idea: add a parameter to pass the number of elements of character array / the length of string.
     *   In this way, judgment is added when implementing.
     *   - If the len gt h > specifies the number of additional characters num, the loop will be carried out under the condition of num -
     *   - If the length is less than num, we will cycle with (length --) as the condition, and then add the terminator \ 0 to it after the cycle ends.
     *
     * - char * my_strncat(char* dest,const char* src,size_t length,size_t num);
     *   dest: Point to the target array, which should contain a C string and enough to accommodate the appended string, including additional null characters
     *   src: String / character to append
     *   length: String / character array length
     *   num: The maximum number of bytes to attach. size_t unsigned integer.
     *   Return value: returns a pointer to the final target string dest.
     */
    

strncmp() function

  • Function prototype

    /*
     * strncmp()function
     * Function prototype: int strncmp(const char* str1,const char* str2,size_t num);
     * Function: compare the first n characters of str1 and str2. Compare the corresponding characters of each string. If they are equal, compare the characters at the next position until the characters are different / reach the terminating null character / reach the num character.
     * Parameter: str1 -- string to compare; str2 -- string to compare; num -- maximum number of characters to compare, size_t is an unsigned integer.
     * Return value:
     * - If the return value < 0, the value of the first mismatched character in STR1 is lower than that in STR2. str1 < str2
     * - If the return value > 0, the value of the first mismatched value in STR1 is greater than that in STR2. str1 > str2
     * - If the return value = 0, it means that the first num characters of the two strings are equal. str1 = str2
     */
    
  • use

    #include <string.h>
    #include <stdio.h>
    
    int main()
    {
        char* p = "abcdef";
        char* q ="abcqwe";
        int ret = strncmp(p,q,3);
        printf("%d\n",ret);//0 means the first three characters are equal
    
        int ret1 = strncmp(p,q,4);
        printf("%d\n",ret1);//-1. Indicates the first three characters of i, P < Q
    
        char* p1 = "abc";
        char* q1 ="abc";
        int ret2 = strncmp(p1,q1,6);
        printf("%d\n",ret2);//0 means equal. Num > length, and it stops when the string terminator is compared.
    
        char* p2 = "aec";
        char* q2 ="abc";
        int ret3 = strncmp(p2,q2,6);
        printf("%d\n",ret3);//1 means P2 > Q2. Although num is 6, a mismatched character appears when the second character is compared. The size is compared, so stop.
        return 0;
    }
    

Find characters in string

strchr()

/*
 * strchr()function
 * Function prototype: csont char* strchr(const char* str,int char);
 * Function: locate the first character in the string
 * - Returns a pointer to the character that first appears in the C string str.
 *   Terminated null characters are considered part of the C string. Therefore, it can also be positioned to retrieve the pointer to the end of the string.
 * Parameters:
 * - str: C character string
 * - char: The character to be located is passed as an int integer promotion, but is internally converted to char for comparison.
 * Return value: pointer to the first occurrence of this character in str. If the character is not found, the function returns a null pointer.
 *
 */

int main()
{
    char s[] = "hello";
    //Find the first l
    char *p = strchr(s,'l');
    printf("%s\n",p);//llo

    //Find the second l
//    p = strchr(p+1,'l');
//    printf("%s\n",p);//lo

    //Copy all characters after the found character to another string
    char *t = (char*)malloc(strlen(s)+1);
    strcpy(t,p);
    printf("%s\n",t);//llo

    //Copy all characters before the found character to another string
    *p = '\0';
    strcpy(t,s);
    printf("%s\n",t);//he

    return 0;
}

strrchr()

/*
 * strrchr()
 * Function prototype: const char* strrchr(const char* str,int char);
 * Function: find the last character in the string
 * - Returns a pointer to the last char character in the string str.
 *   The terminating null character is considered part of the C string. Therefore, you can also locate it to retrieve a pointer to the end of the string.
 * Parameters:
 * - str: character string
 * - char: The character to be located is passed as an int integer promotion, but is internally converted to char for comparison.
 * Return value: pointer to the last occurrence of this character in str. If the character is not found, the function returns a null pointer.
 */

int main()
{
    char s[] = "world dlrow";
    char *p = strrchr(s,'r');
    printf("%s\n",p);//row
    return 0;
}

String lookup function

strstr function

  • Function prototype

    /*
     * Locate substring function str ()
     * Function prototype: const char* strstr(const char* str1,const char* str2); Or char* strstr(char* str1,const char* str2);
     * Function: find the pointer of str2 for the first time in str1. If str2 is not part of str1, return null pointer. The string terminator '\ 0' is not included in the matching process, but it will stop there.
     * Parameters: - str1: long string to scan- str2: short string. Find out whether the string appears in str1
     * Return value: this function returns the pointer that str2 first appears in str1. If str2 is not in str2, that is, str2 is not found in str1, NULL is returned.
     */
    
  • use

    #include <string.h>
    #include <stdio.h>
    
    int main()
    {
        char arr1[] = "abcdefabcdef";
        char arr2[] = "bcd";
        char* ret = strstr(arr1,arr2);
        ret == NULL? printf("Can't find"): printf("eureka:%s\n",ret);
        return 0;
    }
    
  • Simulation Implementation of STR function

    #include <stdio.h>
    #include <assert.h>
    
    char* my_strstr(const char* str1,const char* str2)
    {
        assert(str1 && str2);
    
        //strstr specifies that if you want to find an empty string ("") in a string: where the string terminator is stored, you will return str1 string
        if(*str2 == '\0')
        {
            return (char*)str1;
        }
    
        /*
         * Comparison logic:
         * - You need to compare the first character of the short string (bbc) with the first character of the long string (acbbbcdef): a ≠ b. The pointer points back 1
         * - bbc The first character is compared with the second character in acbbbcef: b ≠ c. The pointer points back 1
         * - bbc Comparison between the first character and the third character in acbbbcef: b=b; The pointer points back 1
         *   Continue to compare: compare the second character of bbc with the fourth character in acbbbcef, b=b; The pointer points back 1
         *   Continue to compare: compare the third character of bbc with the fifth character in acbbbcef, c ≠ b. The pointer returns the address at which the comparison started.
         *   Note here: acbbbcef refers to the pointer of the fifth character. In this case, it needs to point to the fourth character. In other words, we need a pointer to save the position that str1 points to before each comparison.
         * - bbc Comparison between the first character and the fourth character in acbbbcef: b=b; The pointer points back 1
         *   Continue to compare: compare the second character of bbc with the fifth character in acbbbcef, b=b; The pointer points back 1
         *   Continue to compare: compare the third character of bbc with the sixth character in acbbbcef, c=c; The pointer points back 1
         *   Continue comparison: compare the ending character in bbc with the sixth character in acbbbcef, and return the address of the fourth pointer in acbbbcef.
         */
    
        //When there is no match, it is used to walk backward one position at a time, and s1 is used for comparison when matching.
        //If only the first few characters match, when there is a mismatch character, point the repeat to the next position and assign it to s1.
        //If all matches, it means that the position pointed by the repeat is the position where str2 first appears in str1. Just return.
        const char* repeat = str1;
        //Because to find a substring, you need to return the pointer of the substring. So we assign it to s1 and s2. Operate s1 and s2 so that the values in str1 and str2 will not be changed.
        const char* s1 = str1;//Long string pointer for each comparison
        const char* s2 = str2;//Short string pointer to be used for each comparison.
    
        //repeat points back to 1 each time until the long string matches (matches to the terminating null character), and the loop ends
        while(*repeat)
        {
            //In each cycle, s1 points to the position that repeat points to.
            s1 = repeat;
            //s2 points to a short string.
            s2 = str2;
    
            //Match. If * s1=*s2, both s1 and s2 point to the next position.
            //Case 1: find cd in abcd. c=c, d=d, \ 0 = \ 0. At this time, both s1 and s2 + + point to the content after \ 0. Join judgment
            //Case 2: find efg in abcde, e=e, \ 0 ≠ f, and then jump out of the loop repeat + +, until repeat= repeat = \ 0,, and the loop stops.
            //We can add judgment: if s1= S1 = \ 0,, NULL will be returned. So you don't have to judge.
    //        while(*s1 == *s2)
    //        {
    //            s1++;
    //            s2++;
    //        }
            //After s2 + +, if s2 is a string terminator, it means that s1 contains s2, then we add a condition after the loop to return the repeat pointer
            /*
            while(*s2 && *s1 == *s2)
            {
                s1++;
                s2++;
            }
            if(*s2 == '\0')
            {
                return repeat;
            }*/
    
            while(*s1 == *s2)
            {
                s1++;
                s2++;
                //When * s1=*s2, if s2 + + is empty, it indicates that s2 has reached the end of the string.
                //That is, the pointer stored in the repeat is where s2 first appears in s1.
                /*
                 * Note: this judgment should be within the cycle.
                 * For example, when looking for cd in abcd, if it is judged to be outside the loop. Then c=c,d=d, C = C, d = D, \ 0 = \ 0,= C = C, d = D, \ 0 = \ 0,, and then s1 and s2 + +. At this time, they all point to the position after the string terminator
                 * - When the loop comes out, s2 points to the position of the terminator. So the judgment should be put in the cycle.
                 */
                if(*s2 == '\0')
                {
                    return repeat;
                }
            }
            /*
             * - Case 1: cd is found in abcd. Both s1 and s2 are \ 0, but the pointer has been returned when s2 is \ 0. This case is not considered.
             * - Case 2: find def, d=d, \ 0 ≠ e in abcd. Jump out of the loop and enter the judgment. Because s1 has found the end of the string, it is certainly impossible to find the def string after that
             *   So we return NULL directly. This judgment is added only to improve efficiency. You can also skip the loop without adding, repeat+1, and then pass in s1. It will only judge several times and return NULL
             */
            if(*s1 == '\0')
            {
                return NULL;
            }
            repeat++;
        }
        return NULL;
    }
    
    int main()
    {
        char arr1[] = "acbbbcef";
        char arr2[] = "bbc";
        char* ret = my_strstr(arr1,arr2);
        ret == NULL? printf("Can't find"): printf("eureka:%s\n",ret);
        return 0;
    }
    

strtok() function

  • Function prototype

    /*
     * strtok()function
     * Function prototype: char* strtok(char* str,const char* delimiters);
     * Function: split str into tags. These tags are a sequence of consecutive characters separated by any character in the delimiters.
     * - In the first call, the function needs a string as the str parameter, and the first character of STR is used as the starting position of scanning.
     * - The function first scans the first character that is not a separator from the start position, and then scans the separator from this character.
     *   For example: ##abc#def#ggg#haha#abc#def#ggg#haha \ 0  splits a string with # as the separator, then the subsequent separator will be scanned from a.
     * - The first delimiter scanned later, which is replaced by the string terminator \ 0, and the starting scanning position is returned by the function; Or the scanning will stop when the null character is terminated.
     *   For example: ##abc#def#ggg#haha#abc#def#ggg#haha \ 0  split the string with # as the separator, scan the separator from a to # after c, and replace it with \ 0 to become: ##abc#abc \ 0def#ggg#haha \ 0def#ggg#haha#abc \ 0def#ggg#haha \ 0
     *   At this time, the starting position of the scan is returned by the function, that is, the pointer to the first non separator character 'a' of str.
     * - If a delimiter is scanned, in subsequent calls, the function needs a null pointer and uses the position after the previous delimiter as the new scanning position.
     *   Example: in ##abc#abc \ 0def#ggg#haha \ 0,def#ggg#haha#abc \ 0def#ggg#haha \ 0,, the position after the empty character \ 0 after c will be saved to the function for use in the next call (no specific library implementation is required to avoid data contention)
     * - If the delimiter is scanned, the first parameter of strtok function will be NULL in subsequent calls, and the function will start at the position saved in the same string to find the next delimiter.
     *   For example: ##abc#abc \ 0def#ggg#haha \ 0,def#ggg#haha#abc \ 0def#ggg#haha \ 0,, continue to call strtok(NULL, "#"), at this time, the separator will be scanned from d after \ 0 after c, and the pointer to D will be returned.
     *   Scan to the position # after F, replace it with empty character \ 0, and become: ##abc#abc \ 0def \ 0ggg#haha \ 0.def#abc \ 0def \ 0ggg#haha \ 0.ggg#haha#abc \ 0def \ 0ggg#haha \ 0.. Then the position after f \ 0 will be saved in the function for use in the next call.
     *   ......Go through strtok again (null, "#"), and it becomes: ##abc#abc \ 0def \ 0ggg \ 0haha \ 0.def#abc \ 0def \ 0ggg \ 0haha \ 0.ggg#abc \ 0def \ 0ggg \ 0haha \ 0.haha#abc \ 0def \ 0ggg \ 0haha \ 0.. The position after \ 0 after g is saved in the function.
     * - Once the str termination null character is found, all subsequent calls to the function (with null pointer as the first parameter) will return null pointer.
     *   For example: ##abc#abc \ 0def \ 0ggg \ 0haha \ 0,def#abc \ 0def \ 0ggg \ 0haha \ 0,ggg#abc \ 0def \ 0ggg \ 0haha \ 0,haha#abc \ 0def \ 0ggg \ 0haha \ 0,, start scanning from h, scan to \ 0 after haha, return the pointer to h, and the scanning stops.
     *   After that, all calls to strtok(NULL, "#") will return null pointers.
     *
     * be careful:
     * - strtok The string to be manipulated will be changed, so when using this function to split a string, it is generally to make a function call to the copied string after copying the source string.
     * - strtok When the first parameter of the function is not NULL, the function finds the first delimiter in str and saves its position in the string.
     *   Inside the function, there is a static variable to save its location. In the next call, use the position after this position as the starting position to continue scanning the separator.
     * - You can also use spaces as separators. strtok(str," ");
     *   However, you cannot use \ 0 as the delimiter, because if you encounter the \ 0strtok function, you will think that you have encountered the string terminator, and the next call will return a null pointer.
     *
     * Parameters:
     * - str: String to be decomposed. Note: this string is modified by splitting it into smaller strings (tags). Alternatively, you can specify a null pointer, in which case the function continues to scan where the previous successful call ended.
     * - delimiters: C string containing split characters.
     *
     * Return value:
     * - This function returns the first substring decomposed. If there is no retrievable string, it returns a null pointer.
     *   If a tag is found, a pointer to the beginning of the tag will be displayed; Otherwise, a null pointer is returned. In a scanned string, a null pointer is always returned when the string terminator is reached.
     */
    
  • use

    #include <string.h>
    #include <stdio.h>
    
    int main()
    {
        char arr[] = "##abc#def#ggg#haha";
        char* p = "#";
    
        //strtok will change the string to be manipulated, so when using this function to split the string, we copy the arr array into the tmp array and call the tmp function.
        char tmp[20] = {};
        strcpy(tmp,arr);
        //The strtok function returns the pointer to the starting character of each segmented string. We use the char * type pointer variable q to receive it
        char* q = NULL;
    
    //    q = strtok(tmp,p);
    //    printf("%s\n",q);//abc
    //
    //    q = strtok(NULL,p);
    //    printf("%s\n",q);//def
    //
    //    q = strtok(NULL,p);
    //    printf("%s\n",q);//ggg
    //
    //    q = strtok(NULL,p);
    //    printf("%s\n",q);//haha
    
        //simplify
        //Initialization: q=strtok(tmp,p)
        //Judgment condition: when q is not a null pointer, it indicates that it has not been separated to the end of the string.
        //Update: update q=strtok(NULL,p) every time the split string is printed
        //When the string terminator \ 0 in tem is encountered, the scanning stops and the next strtok(NULL,p) call returns a null pointer. At this time, q is a null pointer and the loop ends.
        for(q=strtok(tmp,p) ; q!=NULL; q=strtok(NULL,p))
        {
            printf("%s\n",q);
        }
    
        //The update expression in the loop has been executed, but the condition is false. The loop ends. At this point, we print and check and find that q is indeed a null pointer
        //printf("%s\n",q);//(null)
        return 0;
    }
    

Error message report

strerror() function

  • Function prototype

    /*
     * strerror()function
     * Function prototype: char* strerror(int errnum);
     *
     * effect:
     * - When using a library function, if the library function call fails, an error code will be set: there is a global variable int errno in its function;
     * - strerror()Search the error number errnum from the internal array to generate a string with error information. The error string generated by strerror depends on the development platform and compiler.
     *   The returned pointer points to a statically allocated string, which cannot be modified by the program. Further calls to this function may overwrite its contents (no specific library implementation is required to avoid data contention)
     * Parameters:
     * - errnum: Error number, usually errno.
     * - error It is a global variable. It is a global variable defined in C language and can be used by everyone. Need to import header file < error h>
     * Return value: returns a pointer to the error string describing the error number errnum.
     */
    
  • use

    #include <stdio.h>
    #include <string.h>
    #include <errno.h>
    
    int main()
    {
    //    printf("%s\n",strerror(0));//No error - no error
    //    printf("%s\n",strerror(1));// Operation not allowed -- operation not allowed: Operation rejected
    //    printf("%s\n",strerror(2));//No such file or directory -- no such file / folder
    //    printf("%s\n",strerror(3));//No such process -- no such process
    //    printf("%s\n",strerror(4));//Interrupted function call -- function call interrupted
    //    printf("%s\n",strerror(5));//Input/output error -- input / output error
    
        //fopen() function is used to open the file, test Txt is the file name, r means it is opened as read-only.
        FILE* pf = fopen("test.txt","r");
        if(pf == NULL)
        {
            //Error is a global error code and a global variable. When the fopen function call fails, error will be set to the corresponding value.
            //When we pass error into strerror() function, the corresponding error message will be printed.
            //Because the file name passed in when we open the file is a file that has not been created, the error message is: there is no such file
            printf("%s\n",strerror(errno));//No such file or directory
        }
        return 0;
    }
    

perror() function

  • Function prototype

    /*
     * perror()Difference between strerror() function and strerror() function:
     * - strerror()Function is to convert the error code into error information and print its corresponding error information when necessary
     * - perror()The error message will be printed directly, and you can also choose to add the executed custom message before its message.
     * perror()function
     * Function prototype: void perror(const char* str);
     * effect:
     * - Interpret the value of error as an error message and print it to the standard error output stream, usually to the console. You can choose to prefix it with the custom message specified in str.
     * - errno Is an integer variable whose value describes the error condition or diagnostic information generated by calling the library function.
     *   C Any function in the standard library can set a value for errno (even if it is not explicitly specified, even if there is no error).
     * - The error information generated is related to the development platform and compiler used.
     * - If str passes in NULL null pointer, the error message will be printed directly, followed by line feed \ n.
     *   If str is not a null pointer, print the string pointed to by str, followed by an English colon (:), followed by a space (), and then add the error message and line feed character \ n.
     * - perror It should be called immediately after the error message is generated, otherwise the error may be overwritten when calling other library functions.
     *
     * Parameter - str: the custom string to print before the error message. If a null pointer is passed in, there will be no custom information and the error information will be printed directly.
     * Return value: no return value.
     */
    
  • use

    #include <stdio.h>
    
    int main()
    {
        //fopen() function is used to open the file, test Txt is the file name, r means it is opened as read-only.
        FILE* pf = fopen("test.txt","r");
        if(pf == NULL)
        {
            //Because the file name passed in when we open the file is a file that has not been created, the error message is: there is no such file
            //If a null pointer is passed in, the error message will be printed directly followed by a newline \ n.
            perror(NULL);//No such file or directory
            //If a string is passed in, it is str + colon + space + error message + line feed \ n
            perror("fopen");//fopen: No such file or directory
    
        }
        return 0;
    }
    

Character function

Character classification function

functionIf yes, return true; Conversely, return false
iscntrl()Is it a control character
isspace()Whether it is a blank character: space ', \ f', \ n ', \ r', \ t ', vertical tab' \ v '
isdigit()Whether it is a numeric character: 0 ~ 9 (decimal). Note that it is numeric characters, not numbers.
isxdigit()Whether it is a hexadecimal digit. Including all hexadecimal digits, lowercase AF, uppercase AF
islower()Whether it is lowercase: a~z
isupper()Capital letters: A~Z
isalpha()Is it a letter: AZ, AZ
isalnum()Are they letters or numbers: AZ, AZ, 0 ~ 9
ispunct()Whether it is a punctuation mark. Any printable graphic character that is not a number or letter
isgraph()Is it a graphic character
isprint()Is it printable characters, including graphic characters and white space characters
  • Simple use

    #include <stdio.h>
    #include <ctype.h>
    
    int main()
    {
        //isdigit(), if it is a numeric character, returns a value other than 0; if it is not a numeric character, returns 0.
        char ch = '1';
        printf("%d\n",isdigit(ch));
    
        //islower(), if it is a lowercase character, returns a value other than 0; if not, returns 0.
        ch = 'a';
        printf("%d\n",islower(ch));
        return 0;
    }
    

Character conversion function

Tower() function

  • Function prototype

    /*
     * tolower()function
     * Function prototype: int tower (int c)
     * effect:
     * - If c is an uppercase letter and has its lowercase letter, c is converted to the corresponding lowercase letter.
     *   If this conversion is not possible, the returned value c remains unchanged
     * - Note: what is considered a letter may depend on the locale in which it is used. In the default "C" locale.
     *   Capital letters can be any of the following: A B C D E F G H J K L M N O P Q R S T U V W X Y Z
     *   They are transformed into: a b c d e f g h i j k l m n o p q r s t u v w x y z
     * - In other locales, if an uppercase character has more than one corresponding lowercase character, this function always returns the same character for the same c value.
     *
     * Parameter c: the character to be converted to lowercase.
     * Return value: if c has a corresponding lowercase letter, the function returns the lowercase letter of c; otherwise, it returns the unchanged c. This value is returned as an int value and can be implicitly converted to char type
     */
    
  • use

    #include <stdio.h>
    #include <ctype.h>
    
    int main()
    {
        char arr[20] = {0};
        scanf("%s",arr);
        int i =0;
        //You can add a judgment. If it is an uppercase letter, it will be converted to lowercase and put into the array.
    //    while(arr[i] != '\0')
    //    {
    //        if(isupper(arr[i]))
    //        {
    //            arr[i] = tolower(arr[i]);
    //        }
    //        printf("%c ",arr[i]);
    //        i++;
    //    }
        //If its value cannot be converted to lowercase or is already lowercase, its value will not be changed. So we can also omit judgment.
        while(arr[i] != '\0')
        {
            arr[i] = tolower(arr[i]);
            printf("%c ",arr[i]);
            i++;
        }
        printf("%s",arr);
        return 0;
    }
    

toupper() function

  • Function prototype

    /*
     * toupper()function
     * Function prototype: int toupper(int c)
     * effect:
     * - If c is a lowercase letter and has its uppercase letter, c is converted to the corresponding uppercase letter.
     *   If this conversion is not possible, the returned value c remains unchanged
     * - Note: what is considered a letter may depend on the locale in which it is used. In the default "C" locale.
     *   The lowercase letters are: a b c d e f g h i j k l m n o p q r s t u v w x y z
     *   They are converted into: a B C D E F G H J K L M n o p q r st U V W x y Z
     * - In other locales, if a lowercase character has more than one corresponding uppercase character, this function always returns the same character for the same c value.
     *
     * Parameter c: the character to be converted to uppercase.
     * Return value: if c has a corresponding capital letter, the function returns the capital letter of c; Otherwise, the unchanged c is returned. This value is returned as an int value and can be implicitly converted to char type
     */
    
  • use

    #include <stdio.h>
    #include <ctype.h>
    
    int main()
    {
        char arr[20] = "aAbBcCdDEe12EeDdgG";
        int i =0;
        //If its value cannot be converted to uppercase or is already uppercase, its value will not be changed. Therefore, we can also omit the judgment of whether it is lowercase or not, and if it is re conversion.
        while(arr[i] != '\0')
        {
            arr[i] = toupper(arr[i]);
            i++;
        }
        printf("%s",arr);//AABBCCDDEE12EEDDGG
        return 0;
    }
    

Memory function

memcpy() function

  • Function prototype

    /*
     * memcpy()function
     * Function prototype: void* memcpy(void* dest,const void* src,size_t num);
     * effect:
     * - Copy the first num bytes in src to the memory block pointed to by dest. The type of data pointed to by the pointer is independent of the function.
     * - This function does not check any terminating null characters in the source. It always copies num bytes exactly. To avoid overflow, the array size pointed to by dest and src should be at least num bytes.
     *   And dest and src cannot point to the same memory block. memmove is a safer method for overlapping memory blocks.
     *
     * Parameters:
     * - dest: Pointer to the target array where the copied content is stored, and the type is cast to void * pointer.
     * - src: Only the pointer of the data source you want to copy. The type is cast to void * pointer.
     * - num: Number of bytes to copy. size_t is an unsigned integer.
     *
     * Return value: this function returns a pointer to dest.
     */
    
  • use

    #include <memory.h>
    
    int main()
    {
        int arr1[10] = {0,1,2,3,4,5,6,7,8,9};
        int arr2[10] = {0};
        //
        //memcpy(arr2,arr1,20);
        //Specify breakpoints, debug and view execution results
        return 0;
    }
    
  • Simulation Implementation

    #include <assert.h>
    
    void* my_memcpy(void* dest,const void* src,size_t num)
    {
        assert(dest && src);
        void* ret = dest;
        while(num--)
        {
            //void * has no specific type. It needs to be cast to char * type and then dereferenced. Copy a byte.
            *(char*)dest = *(char*)src;
            //After copying, if the pointer moves back one byte, it needs to be converted to char * type first, and then + 1.
            dest = (char*)dest + 1;
            src = (char*)src + 1;
        }
        return ret;
    }
    
    int main()
    {
        int arr1[10] = {0,1,2,3,4,5,6,7,8,9};
        int arr2[10] = {0};
        my_memcpy(arr2,arr1,20);
        //Put the first five elements 0,1,2,3,4 in arr1 at the position of 2,3,4,5,6. The expected results are 0,1,0,1,2,3,4,7,8,9
        my_memcpy(arr1+2,arr1,20);//0,1,0,1,0,1,0,0,7,8,9. If we implement this in the library function, dest and src cannot point to the same array when using.
        
        //Specify breakpoints, debug and view execution results
        return 0;
    }
    

memmove() function

  • Function prototype

    /*
     * memmove()function
     * Function prototype: void* memmove(void* dest,const void* src,size_t num);
     * Function: copy the first num bytes in src to the memory block pointed to by dest. Copying is done just like using an intermediate buffer. Allow src to overlap dest.
     * Parameters:
     * Parameters:
     * - dest: Pointer to the target array where the copied content is stored, and the type is cast to void * pointer.
     * - src: Only the pointer of the data source you want to copy. The type is cast to void * pointer.
     * - num: Number of bytes to copy. size_t is an unsigned integer.
     *
     * Return value: this function returns a pointer to dest.
     */
    
  • use

    #include <string.h>
    
    int main()
    {
        int arr[10] = {1,2,3,4,5,6,7,8,9,10};
        //Put 1,2,3,4,5 in the arr array at the position of 3,4,5,6,7
        memmove(arr+2,arr,20);
        //Add breakpoints, debug and view results
        //1,2,1,2,3,4,5,8,9,10
        return 0;
    }
    
  • Simulation of memmove() function

    #include <assert.h>
    
    /*
     * Realization idea:
     * - dest If it does not overlap with src, it can be copied in any way.
     *   dest It points to different positions of the same array as src, and the first num bytes of src contain the position pointed to by dest. At this time, you need to pay attention to whether the contents of the last few bytes in src are modified when copying the contents of src to dest.
     *   For example, put the first five elements a[0]~a[4] in a[10] at the position of a[2]~a[6],
     *   If you copy from front to back: a[2]=a[0],a[3]=a[1],a[4] should = the original value of a[2], but because a[2]=a[0],
     *   src The content in has not been copied to dest, it has been changed, and the result is not what we want.
     * - dest Overlap with src, DeST < src, and the first num bytes of src overlap with dest.
     *   For example: 1 2 3 4 5 6 7 8 9 copy 6 7 8 to 5 6 7, copy from front to back
     *   6 Put it in the position of 5 and become: 1 2 3 4 6 6 7 8 9
     *   7 Put it in the position of 6 and become: 1 2 3 4 6 7 8 9
     *   8 Put it in the position of 7 and become: 1 2 3 4 6 7 8 9
     * -dest Overlap with src, src < DeST, and the first num bytes of src overlap with dest.
     *   For example, 1 2 3 4 5 6 7 8 9 copies 5 6 7 to 6 7 8, and the expected result is 1 2 3 5 6 7 9
     *   At this time, if you copy from front to back, the position of 5 to 6 becomes: 1 2 3 4 5 7 8 9 (the 6 in SRC has not been copied yet.)
     *   6 Place the data of position into position 7: 1 2 3 4 5 5 8 9
     *   7 The data of position is put into position 8: 1 2 3 4 5 5 9. Different from the 70000 result, the data in src is modified before being copied to the corresponding position in dest.
     *   If we copy from back to front, that is, put 7 in position 8: 1 2 3 4 5 6 7 9
     *   6 Position of 7: 1 2 3 4 5 6 7 9
     *   5 Place 6: 1 2 3 4 5 6 7 9, which is the same as the expected result
     * - If dest overlaps src, DeST < src or dest > src. However, the first num bytes of src do not overlap dest.
     *   At this time, you can copy from front to back or from back to front. Because there is no overlap, the contents in src will not be modified and can be completely copied to dest
     * - If dest and src point to different arrays, it can be forward, backward or backward.
     *
     * Conclusion:
     * - dest<src When, copy from front to back. That is * (char*)dest=*(char*)src. After copying, DeST and src go back one byte, and then continue copying
     * - src<=dest When copying, copy from back to front, that is * ((char*)dest+num) = *((char*)src+num). After copying, DeST and src go forward one byte, and then continue to copy
     */
    char* my_memmove(void* dest,const void* src,size_t num)
    {
        assert(dest && src);
        void* ret = dest;
        if(dest < src)
        {
            //Front - > rear
            while(num--)
            {
                *(char*)dest = *(char*)src;
                dest = (char*)dest + 1;
                src =(char*)src + 1;
            }
        }
        else
        {
            //Rear - > front.
            while(num--)
            {
                //After each copy, move forward one byte, which is - 1. However, num is reduced by 1 every time, so there is no need to operate again.
                *((char *) dest + num) = *((char *) src + num);
            }
        }
        return ret;
    }
    
    int main()
    {
        int arr[10] = {1,2,3,4,5,6,7,8,9,10};
        my_memmove(arr+2,arr,20);
        //Add breakpoints, debug and view the results.
        return 0;
    }
    

memcmp() function

  • Function prototype

    /*
     * memcmp()function
     * Function prototype: int memcmp(const void* ptr1,const void* ptr2,size_t num);
     * Function: compare the first num bytes of prt1 and prt2. Unlike strcmp, this function does not stop comparing when it finds a null character.
     * Parameters:
     * - ptr1: Pointer to a memory block.
     * - ptr2: Pointer to a memory block.
     * - num: Number of bytes to compare
     * Return value:
     * - The return value < 0 indicates that the first byte in the two memory blocks does not match. The value in prt1 is lower than ptr2, that is, PTR1 < ptr2.
     * - The return value is equal to 0, and the first num bytes of the two memory blocks are the same.
     * - The return value > 0 indicates that the first byte in the two memory blocks does not match. The value in prt1 is greater than ptr2, that is, PTR1 > ptr2.
     */
    
  • use

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

memset() function

  • Function prototype

    /*
     * memset()function
     * Function prototype: void * memset(void * ptr,int value,size_t num);
     * Function: set the first num byte of the memory block pointed to by ptr to the specified value.
     *  - ptr: Pointer to the memory block to fill
     *  - value: The value to set. The value is passed as an int, but the function fills the memory block with the unsigned character conversion of the value.
     *  - num: The number of bytes set to the value value. size_t is an unsigned integer type.
     */
    
  • use

    #include <string.h>
    #include <stdio.h>
    
    int main()
    {
        char arr[] ="hello world";
        //Replace the first 5 bytes of the arr array with x
        memset(arr,'x',5);
        printf("%s",arr); //xxxxx world
    
        int arr1[10] = {0};
        memset(arr1,1,20);//Set memory in bytes
        //Debug and check the storage of arr array in memory. You will find that the first 20 bytes of arr array are 01 for each byte
        return 0;
    

Topics: C Back-end