0

I have some methods that return a BSTR, and I need to concatenate those BSTRs, but it should have a space between each BSTR:

BSTR a + " " + BSTR b + " " + BSTR c + and so on...

I found a function that concatenates two BSTRs, however I cannot insert a space between each BSTR.

Sample code:

static BSTR Concatenate2BSTRs(BSTR a, BSTR b)  
{  
    auto lengthA = SysStringLen(a);  
    auto lengthB = SysStringLen(b);  

    auto result = SysAllocStringLen(NULL, lengthA + lengthB);  

    memcpy(result, a, lengthA * sizeof(OLECHAR));  
    memcpy(result + lengthA, b, lengthB * sizeof(OLECHAR));  

    result[lengthA + lengthB] = 0;  
    return result;  
}  

Also, I tried to wrap the first BSTR into a _bstr_t then use the += operator to insert a space, but the first BSTR value is lost.

Any help?

Update

@Remy Lebeau answer works.
However, I tried to do the same steps, but for 6 BSTRs, and it outputs empty string!

Code:

    memcpy(result, a, lengthA * sizeof(OLECHAR));
    result[lengthA] = L' ';
    memcpy(result + lengthA+1, b, lengthB * sizeof(OLECHAR));
    result[lengthB] = L' ';
    memcpy(result + lengthB+1, c, lengthC * sizeof(OLECHAR));
    result[lengthC] = L' ';
    memcpy(result + lengthC+1, d, lengthD * sizeof(OLECHAR));
    result[lengthD] = L' ';
    memcpy(result + lengthD+1, e, lengthE * sizeof(OLECHAR));
    result[lengthE] = L' ';
    memcpy(result + lengthE+1, f, lengthF * sizeof(OLECHAR));
    result[lengthE + 1 + lengthF] = L'\0';

Thank you very much.

Miles Budnek
  • 28,216
  • 2
  • 35
  • 52
  • 1
    Just a reminder that `atlbase.h` has [CComBSTR](https://learn.microsoft.com/en-us/cpp/atl/reference/ccombstr-class?view=msvc-170) in case you want safer code(as the question is tagged C++, and nothing about this code is C++ other than the auto). You can also inspect its internals to see how it implements operator+=(by right clicking on `CComBSTR` variable's type and going to "go to definition"). – Dmytro Jul 27 '22 at 19:54
  • if you have a new question, please ask a new question, with relevant [mcve] if possible (here it is possible). I mean, now it appears `lengthC`...`lengthE` are not even defined at all. – hyde Jul 27 '22 at 20:56

1 Answers1

1

Simply include room for the space character in your length calculation, and then assign the actual space character in the allocated memory, eg:

static BSTR Concatenate2BSTRs(BSTR a, BSTR b)  
{  
    auto lengthA = SysStringLen(a);  
    auto lengthB = SysStringLen(b);  

    auto result = SysAllocStringLen(NULL, lengthA + 1 + lengthB);
    if (result) {
        memcpy(result, a, lengthA * sizeof(OLECHAR));
        result[lengthA] = L' ';
        memcpy(result + lengthA + 1, b, lengthB * sizeof(OLECHAR));
        // no need to null-terminate manually, SysAllocStringLen() already did it...
        //result[lengthA + 1 + lengthB] = L'\0';
    }

    return result;  
}  

Online Demo


UPDATE: Your approach for 6 BSTRs does not work because your memcpy() calls are copying data to the wrong indexes within the result, thus overwriting previous data.

Use a variable to keep track of where you need to insert next, eg:

UINT offset = 0;
memcpy(result + offset, a, lengthA * sizeof(OLECHAR));
offset += lengthA;
result[offset++] = L' ';
memcpy(result + offset, b, lengthB * sizeof(OLECHAR));
offset += lengthB;
result[offset++] = L' ';
memcpy(result + offset, c, lengthC * sizeof(OLECHAR));
offset += lengthC;
result[offset++] = L' ';
memcpy(result + offset, d, lengthD * sizeof(OLECHAR));
offset += lengthD;
result[offset++] = L' ';
memcpy(result + offset, e, lengthE * sizeof(OLECHAR));
offset += lengthE;
result[offset++] = L' ';
memcpy(result + offset, f, lengthF * sizeof(OLECHAR));
offset += lengthF;
result[offset] = L'\0'; // <-- should not be needed

Alternatively:

OLECHAR *ptr = result;
memcpy(ptr, a, lengthA * sizeof(OLECHAR));
ptr += lengthA;
*ptr++ = L' ';
memcpy(ptr, b, lengthB * sizeof(OLECHAR));
ptr += lengthB;
*ptr++ = L' ';
memcpy(ptr, c, lengthC * sizeof(OLECHAR));
ptr += lengthC;
*ptr++ = L' ';
memcpy(ptr, d, lengthD * sizeof(OLECHAR));
ptr += lengthD;
*ptr++ = L' ';
memcpy(ptr, e, lengthE * sizeof(OLECHAR));
ptr += lengthE;
*ptr++ = L' ';
memcpy(ptr, f, lengthF * sizeof(OLECHAR));
ptr += lengthF;
*ptr = L'\0'; // <-- should not be needed
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770