A typical string of C (28)

        We introduced the concepts related to strings in the C language in the previous blog, so let's take a look at typical problems in strings today.

        A. Let's first take a look at what the following sample code will output. The code is as follows

#include <stdio.h>

intmain()
{
    char buf[15] = {0};
    char src[] = "hello %s";
    
    snprintf(buf, sizeof(buf), src);
    
    printf("buf = %s\n", buf);
    
    return 0;
}

        Let's talk about the snprintf function first, which itself is a variable parameter function. The prototype is as follows: int snprintf(char* buf, int buf_size, const char* fomart, ...). When the function has only 3 parameters, if the third parameter does not contain formatting information, there is no problem with the function call; on the contrary, if the third parameter contains formatting information, but the subsequent corresponding parameters are missing, the program behavior is unstable. Line 8 of the above program calls the snprintf function, but if %s is included in the src character array defined on line 6, its behavior is undefined. Let's take a look at the compilation resultspicture.png

        We see that the compilation has actually been prompted, and the printed result is indeed uncertain. Then we add the fourth parameter string "world" to the snprintf function and try (or directly change the %s after line 6 to world, which has the same effect). The compilation result is as follows

picture.png

        Then we see that it compiles without warnings and the program runs perfectly.

        B. Let's take a look at the following sample code

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

intmain()
{
    #define STR "Hello, \0World\0"
    
    char* src = STR;
    char buf[255] = {0};
    
    snprintf(buf, sizeof(buf), src);
    
    printf("strlen(STR) = %d\n", strlen(STR));
    printf("sizeof(STR) = %d\n", sizeof(STR));
    
    printf("strlen(src) = %d\n", strlen(src));
    printf("sizeof(src) = %d\n", sizeof(src));
    
    printf("strlen(buf) = %d\n", strlen(buf));
    printf("sizeof(buf) = %d\n", sizeof(buf));
    
    printf("src = %s\n", src);
    printf("buf = %s\n", buf);
    
    return 0;
}

        Let's analyze this program first. Line 6 defines a macro, but there are two \0s in it, which are actually three, because the compiler will automatically assign a \0 to the string. Copy the contents of src to buf on line 11 of the program. We said in the last session that character arrays are \0-terminated, so line 13 prints a length of 7. But line 14 prints the length of its entire macro definition, so it's 15. Line 16 prints 7, and the length of the pointer printed on line 17 is 4. The length of the content in buf printed on line 19 is also 7, and the length of the array buf printed on line 20 is 255. Lines 22 and 23 print the contents of src and buf respectively, which is hello. Let's take a look at the compilation resultspicture.png

        The result is consistent with our analysis, the essence of string literals is arrays.

        C. Let's look at the third sample program, the code is as follows

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

intmain()
{
    #define s1 "hello world"
    #define s2 "hello world"
    
    if( s1 == s2 )
    {
        printf("Equal\n");
    }
    else
    {
        printf("Non Equal\n");
    }
    
    if( strcmp(s1, s2) == 0)
    {
        printf("Equal\n");
    }
    else
    {
        printf("Non Equal\n");
    }
    
    return 0;
}

        Let's analyze it first. We define two macro strings on lines 6 and 7 respectively (but their content is the same). Next, we directly judge whether s1 and s2 are equal. Then in this block we should judge the addresses of the two of them. They are arrays in this block. How can two arrays be compared for equality. If it is an address, the first if statement should print unequal. The following if statement is judged by the strcmp function, so of course this is equal, because this function judges the contents of the two. So after our analysis, the first if statement prints Non Equal, and the second if statement prints Equal. Let's see how the compiler handles it

picture.png

        We see that the first one is different from what we analyzed, so let's look at the BCC compiler again

picture.png

        Then the results of the BCC compiler are consistent with our analysis. In the gcc compiler it is optimized, when we define s1, when we define s2. The compiler finds that they are the same, and points s2 to the address of s1, because it thinks you are wasting memory. We add a statement to print the addresses of s1 and s2 in the program, and gcc prints the result as follows

picture.png

        The gcc compiler really puts them in the same address. But let's look at BCC

picture.png

        We see that BCC is like this, so we can't write code that depends on a certain compiler in the future, so the portability of the code is reduced. Therefore, we need to use strcmp to complete the equality comparison between strings, and we cannot directly use == to compare strings directly. The exact same daughter-in-law eats the literal == comparison is false. Some modern compilers are able to map the same string literal to the same array of unnamed chars, so == compares true.

        D. Finally, let's take a look at a question about the right-shifting of strings, which is also a written test interview question. code show as below

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

void right_shift_r(const char* src, char* result, unsigned int n)
{
    const unsigned int len = strlen(src);
    int i = 0;
    
    for(i=0; i<len; i++)
    {
        result[(i+n) % len] = src[i];
    }
    
    result [len] = '\ 0';
}

intmain()
{
    char result[255] = {0};
    
    right_shift_r("abcde", result, 2);
    
    printf("%s\n", result);
    
    right_shift_r("abcde", result, 5);
    
    printf("%s\n", result);
    
    right_shift_r("abcde", result, 8);
    
    printf("%s\n", result);
    
    return 0;
}

        We can use the remainder method to assign strings. Then we use a for loop to complete the right shift, and its time complexity is O(n), which is undoubtedly the highest efficiency.


        Welcome to learn C language together , you can add me QQ: 243343083 .

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324575308&siteId=291194637
28