AndreKR
AndreKR

Reputation: 33678

Assign part of a string to a char array

Edit: After asking this question I was informed about the question How to initialize a char array without the null terminator? which is almost identical. (I'm building a network packet as well.)

I'll keep this question open anyway, because I'm just assigning and not initializing.


I have a fixed size array that I would like to assign a fixed text to:

char text[16];
text = "0123456789abcdef";

Of course this doesn't work because the right hand side contains the null terminator.

error: incompatible types in assignment of 'const char [17]' to 'char [16]'

The text is human-readable, so I would prefer to keep it in one piece, i.e. not write {'0', '1', ...}.

Can I make the assignment work somehow?

By the way, I only have a few hundred bytes of RAM, so preferably (but second to the human-readability requirement) the solution shouldn't use twice the RAM for a temporary copy or something like that.

Upvotes: 0

Views: 284

Answers (2)

aafulei
aafulei

Reputation: 2205

First of all, in case you have any misunderstanding -- "0123456789abcdef" is a string literal. Its type is const char [17], not const char [16], because this string literal has a null terminator \0 in the end.

Then I assume you do mean assignment not initialization. They are different.

I can think of multiple ways to do the assignment. You may choose based on your needs.

#include <cstddef>
#include <cstring>
#include <iostream>
#include <string>
#include <string_view>

using std::size_t;

template<size_t N>
void print(const char (&a)[N])
{
    for (size_t i = 0; i != N; ++i)
        putchar(a[i]);
    putchar('\n');
}

void foo1()
{
    char text[16];
    std::memcpy(text, "0123456789abcdef", sizeof text);
    print(text);
}

void foo2()
{
    char text[16];
    std::string("0123456789abcdef").copy(text, sizeof text);
    print(text);
}

void foo3()
{
    char text[16];
    std::string_view("0123456789abcdef").copy(text, sizeof text);
    print(text);
}

// programmer needs to make sure access with src is valid
template<size_t N>
void assign(char (& dest)[N], const char * src)
{
    for (size_t i = 0; i != N; ++i)
        dest[i] = *src++;
}

void foo4()
{
    char text[16];
    assign(text, "0123456789abcdef");
    print(text);
}

int main()
{
    foo1();    // 0123456789abcdef
    foo2();    // 0123456789abcdef
    foo3();    // 0123456789abcdef
    foo4();    // 0123456789abcdef
    return 0;
}

Some remarks:

  • std::memcpy is the traditional memory copy way from C
  • std::string_view is a light-weight view on a string, introduced in C++17
  • Or you may write your own function like assign() -- with a template you can tell the size of an array at compile time. Depending on your needs, you may decide whether or not to implement bounds checking.

Upvotes: 0

fsquirrel
fsquirrel

Reputation: 832

If you write in C:

char text[16];
strncpy(text, "0123456789abcdef", sizeof(text));

Note that text will not have the null-terminator and won't be compatible with the standard C functions like strlen. If the text if human-readable, I recommend to include the terminator. It is only one character but it will make your life much easier.

Example:

char text[17];
strncpy(text, "0123456789abcdef", sizeof(text));

Upvotes: 2

Related Questions