简体   繁体   中英

copy a const char* into array of char (facing a bug)

I have following method

static void setName(const char* str, char buf[16])
{
    int sz = MIN(strlen(str), 16);
    for (int i = 0; i < sz; i++) buf[i] = str[i];
    buf[sz] = 0;
}


int main()
{
   const char* string1 = "I am getting bug for this long string greater than 16 lenght);
   char mbuf[16];
   setName(string,mybuf)
   // if I use buf in my code it is leading to spurious characters since length is greater than 16 . 

Please let me know what is the correct way to code above if the restriction for buf length is 16 in method static void setName(const char* str, char buf[16])

When passing an array as argument, array decays into the pointer of FIRST element of array. One must define a rule, to let the method know the number of elements.

You declare char mbuf[16] , you pass it to setName() , setName() will not get char[] , but will get char* instead.

So, the declaration should be

static void setName(const char* str, char* buf)

Next, char mbuf[16] can only store 15 chars, because the last char has to be 'null terminator', which is '\\0'. Otherwise, the following situation will occur:

// if I use buf in my code it is leading to spurious characters since length is greater than 16 .

Perhaps this will help you understand:

char str[] = "foobar"; // = {'f','o','o','b','a','r','\0'};

So the code should be

static void setName(const char* str, char* buf)
{
    int sz = MIN(strlen(str), 15); // not 16
    for (int i = 0; i < sz; i++) buf[i] = str[i];
    buf[sz] = '\0'; // assert that you're assigning 'null terminator'
}   

Also, I would recommend you not to reinvent the wheel, why don't use strncpy instead?

char mbuf[16];
strncpy(mbuf, "12345678901234567890", 15);

The following code passes the size of the memory allocated to the buffer, to the setName function.
That way the setName function can ensure that it does not write outside the allocated memory.
Inside the function either a for loop or strncpy can be used. Both will be controlled by the size parameter sz and both will require that a null terminator character is placed after the copied characters. Again, sz will ensure that the null terminator is written within the memory allocated to the buffer.

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

static void setName(const char *str, char *buf, int sz);

int main()
{
    const int a_sz = 16;
    char* string = "This bit is OK!! but any more than 15 characters are dropped";

    /* allocate memory for a buffer & test successful allocation*/
    char *mbuf = malloc(a_sz);
    if (mbuf == NULL) {
        printf("Out of memory!\n");
        return(1);
    }

    /* call function and pass size of buffer */
    setName(string, mbuf, a_sz);
    /* print resulting buffer contents */
    printf("%s\n", mbuf); // printed: This bit is OK!

    /* free the memory allocated to the buffer */
    free(mbuf);
    return(0);
}

static void setName(const char *str, char *buf, int sz)
{
    int i;

    /* size of string or max 15 */
    if (strlen(str) > sz - 1) {
        sz--;
    } else {
        sz = strlen(str);
    }

    /* copy a maximum of 15 characters into buffer (0 to 14) */
    for (i = 0; i < sz; i++) buf[i] = str[i];
    /* null terminate the string - won't be more than buf[15]) */
    buf[i] = '\0';
}

Changing one value const int a_sz allows different numbers of characters to be copied. There is no 'hard coding' of the size in the function, so reducing the risk of errors if the code is modified later on.

I replaced MIN with a simple if ... else structure so that I could test the code.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM