How to Concatenate Strings

How do I concatenate strings?

When you concatenate strings, you need to allocate memory to store the result. The easiest to start with is String and &str:

fn main() {
let mut owned_string: String = "hello ".to_owned();
let borrowed_string: &str = "world";

owned_string.push_str(borrowed_string);
println!("{}", owned_string);
}

Here, we have an owned string that we can mutate. This is efficient as it potentially allows us to reuse the memory allocation. There's a similar case for String and String, as &String can be dereferenced as &str.

fn main() {
let mut owned_string: String = "hello ".to_owned();
let another_owned_string: String = "world".to_owned();

owned_string.push_str(&another_owned_string);
println!("{}", owned_string);
}

After this, another_owned_string is untouched (note no mut qualifier). There's another variant that consumes the String but doesn't require it to be mutable. This is an implementation of the Add trait that takes a String as the left-hand side and a &str as the right-hand side:

fn main() {
let owned_string: String = "hello ".to_owned();
let borrowed_string: &str = "world";

let new_owned_string = owned_string + borrowed_string;
println!("{}", new_owned_string);
}

Note that owned_string is no longer accessible after the call to +.

What if we wanted to produce a new string, leaving both untouched? The simplest way is to use format!:

fn main() {
let borrowed_string: &str = "hello ";
let another_borrowed_string: &str = "world";

let together = format!("{}{}", borrowed_string, another_borrowed_string);

// After https://rust-lang.github.io/rfcs/2795-format-args-implicit-identifiers.html
// let together = format!("{borrowed_string}{another_borrowed_string}");

println!("{}", together);
}

Note that both input variables are immutable, so we know that they aren't touched. If we wanted to do the same thing for any combination of String, we can use the fact that String also can be formatted:

fn main() {
let owned_string: String = "hello ".to_owned();
let another_owned_string: String = "world".to_owned();

let together = format!("{}{}", owned_string, another_owned_string);

// After https://rust-lang.github.io/rfcs/2795-format-args-implicit-identifiers.html
// let together = format!("{owned_string}{another_owned_string}");
println!("{}", together);
}

You don't have to use format! though. You can clone one string and append the other string to the new string:

fn main() {
let owned_string: String = "hello ".to_owned();
let borrowed_string: &str = "world";

let together = owned_string.clone() + borrowed_string;
println!("{}", together);
}

Note - all of the type specification I did is redundant - the compiler can infer all the types in play here. I added them simply to be clear to people new to Rust, as I expect this question to be popular with that group!

Which is the preferred way to concatenate a string in Python?

The best way of appending a string to a string variable is to use + or +=. This is because it's readable and fast. They are also just as fast, which one you choose is a matter of taste, the latter one is the most common. Here are timings with the timeit module:

a = a + b:
0.11338996887207031
a += b:
0.11040496826171875

However, those who recommend having lists and appending to them and then joining those lists, do so because appending a string to a list is presumably very fast compared to extending a string. And this can be true, in some cases. Here, for example, is one
million appends of a one-character string, first to a string, then to a list:

a += b:
0.10780501365661621
a.append(b):
0.1123361587524414

OK, turns out that even when the resulting string is a million characters long, appending was still faster.

Now let's try with appending a thousand character long string a hundred thousand times:

a += b:
0.41823482513427734
a.append(b):
0.010656118392944336

The end string, therefore, ends up being about 100MB long. That was pretty slow, appending to a list was much faster. That that timing doesn't include the final a.join(). So how long would that take?

a.join(a):
0.43739795684814453

Oups. Turns out even in this case, append/join is slower.

So where does this recommendation come from? Python 2?

a += b:
0.165287017822
a.append(b):
0.0132720470428
a.join(a):
0.114929914474

Well, append/join is marginally faster there if you are using extremely long strings (which you usually aren't, what would you have a string that's 100MB in memory?)

But the real clincher is Python 2.3. Where I won't even show you the timings, because it's so slow that it hasn't finished yet. These tests suddenly take minutes. Except for the append/join, which is just as fast as under later Pythons.

Yup. String concatenation was very slow in Python back in the stone age. But on 2.4 it isn't anymore (or at least Python 2.4.7), so the recommendation to use append/join became outdated in 2008, when Python 2.3 stopped being updated, and you should have stopped using it. :-)

(Update: Turns out when I did the testing more carefully that using + and += is faster for two strings on Python 2.3 as well. The recommendation to use ''.join() must be a misunderstanding)

However, this is CPython. Other implementations may have other concerns. And this is just yet another reason why premature optimization is the root of all evil. Don't use a technique that's supposed "faster" unless you first measure it.

Therefore the "best" version to do string concatenation is to use + or +=. And if that turns out to be slow for you, which is pretty unlikely, then do something else.

So why do I use a lot of append/join in my code? Because sometimes it's actually clearer. Especially when whatever you should concatenate together should be separated by spaces or commas or newlines.

Most Efficient Method to Concatenate Strings in Python

Why don't you try it out? You can use timeit.timeit() to run a statement many times and return the overall duration.

Here, we use s to setup the variables a and b (not included in the overall time), and then run the various options 10 million times.

>>> from timeit import timeit
>>>
>>> n = 10 * 1000 * 1000
>>> s = "a = 'start'; b = ' end'"
>>>
>>> timeit("c = a + b", setup=s, number=n)
0.4452877212315798
>>>
>>> timeit("c = f'{a}{b}'", setup=s, number=n)
0.5252049304544926
>>>
>>> timeit("c = '%s%s'.format(a, b)", setup=s, number=n)
0.6849184390157461
>>>>
>>> timeit("c = ''.join((a, b))", setup=s, number=n)
0.8546998891979456
>>>
>>> timeit("c = '%s%s' % (a, b)", setup=s, number=n)
1.1699129864573479
>>>
>>> timeit("c = '{0}{1}'.format(a, b)", setup=s, number=n)
1.5954962372779846

This shows that unless your application's bottleneck is string concatenation, it's probably not worth being too concerned about...

  • The best case is ~0.45 seconds for 10 million iterations, or about 45ns per operation.
  • The worst case is ~1.59 seconds for 10 million iterations, or about 159ns per operation.

If you're performing literally millions of operations, you'll see a speed improvement of about 1 second.

Note that your results may vary quite drastically depending on the lengths (and number) of the strings you're concatenating, and the hardware you're running on.

How to concatenate strings formatted with sprintf in C

sprintf (buffer, "and %d minus %d is %d", 6, 3, 6-3); re-writes buffer instead of concatenating. The original result of the previous sprintf() is lost.

strcat(c, buffer);appends buffer to itself. As that overlaps, it is undefined behavior (UB). Do not do that.


Instead use the return value of sprintf() (number of characters printed) to determine the offset printing.

int offset = sprintf (buffer, "%d plus %d is %d", 5, 3, 5+3);
offset += sprintf (buffer + offset, " and %d minus %d is %d", 6, 3, 6-3);
offset += sprintf (buffer + offset, " even more");
printf ("[%s]",buffer);

Avoid strcat() as that requires code to iterate down the prior string, resulting in Schlemiel the Painter's Algorithm. Better to keep track of the string length and use that for the next sprintf().


Better code could use snprintf() to prevent buffer overrun.

// Pedantic example
char buffer [100];
size_t offset = 0;
size_t available = sizeof buffer;

int retval = snprintf (buffer, available, "%d plus %d is %d", 5, 3, 5+3);
if (retval < 0 || (unsigned) retval >= available) Handle_Overflow();
offset += retval;
available -= retval;

retval = snprintf (buffer + offset, available, " and %d minus %d is %d", 6, 3, 6-3);
if (retval < 0 || (unsigned) retval >= available) Handle_Overflow();
offset += retval;
available -= retval;

retval = snprintf (buffer + offset, available, " even more");
if (retval < 0 || (unsigned) retval >= available) Handle_Overflow();
offset += retval;
available -= retval;

printf ("[%s]",buffer);


length of the sentences and their count are unlimited.

Usually a large buffer is sufficient as unlimited is not really unlimited, just potentially large. C strings are limited to SIZE_MAX.

Alternative: research non-C standard asprintf().

How do I concatenate const/literal strings in C?

In C, "strings" are just plain char arrays. Therefore, you can't directly concatenate them with other "strings".

You can use the strcat function, which appends the string pointed to by src to the end of the string pointed to by dest:

char *strcat(char *dest, const char *src);

Here is an example from cplusplus.com:

char str[80];
strcpy(str, "these ");
strcat(str, "strings ");
strcat(str, "are ");
strcat(str, "concatenated.");

For the first parameter, you need to provide the destination buffer itself. The destination buffer must be a char array buffer. E.g.: char buffer[1024];

Make sure that the first parameter has enough space to store what you're trying to copy into it. If available to you, it is safer to use functions like: strcpy_s and strcat_s where you explicitly have to specify the size of the destination buffer.

Note: A string literal cannot be used as a buffer, since it is a constant. Thus, you always have to allocate a char array for the buffer.

The return value of strcat can simply be ignored, it merely returns the same pointer as was passed in as the first argument. It is there for convenience, and allows you to chain the calls into one line of code:

strcat(strcat(str, foo), bar);

So your problem could be solved as follows:

char *foo = "foo";
char *bar = "bar";
char str[80];
strcpy(str, "TEXT ");
strcat(str, foo);
strcat(str, bar);

Concatenating of Strings

Using the params keyword, you can pass an array into your method.

Reference https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/params

public static string ConcatenateStrings(params string[] str)
{
string concat;

foreach(string s in str)
{
concat = string.Concat(concat, s);
}

return concat;
}

How to concatenate a string with multiple quote escapes

There is no real guideline except that you need to prefix all strings with the verbatim string literal character (@) if they have escape characters that you want to include as part of the string (you are missing one in front of the last string in the example from the question):

var query1 = @"{""query"": ""mutation {create_item(board_id: 111, group_id:\""new_group\"", item_name: \""adding works\"", column_values: \"" {\\\""long_text\\\"": { \\\""text\\\"": \\\""" 
+ "SOME TEXT HERE"
+ @"\\\""}} \"") {id} }"" }";

C program to concatenate two strings

The program has undefined behavior because you did not allocate memory for entered strings.

char *s=(char *)malloc(sizeof(char *));
char *s2=(char *)malloc(sizeof(char *));
fgets(s,10,stdin);
fgets(s2,10,stdin);

You only allocated memory for two pointers ( sizeof(char *) ).

You need to allocate memory large enough that can contains entered strings and their concatenation in the first character array.

The function fgets can append the new line character '\n' to an entered string. You need to overwrite it.

Also you should not change the original pointers because you need to use them to free the allocated memory.

And take into account that the result string will contain at least 11 characters including the terminating zero character '\0' instead of 10 characters if you are going to enter "hello" and "world" and concatenate them. Though in general it is better to reserve 13 characters if the entered strings will not contain the new line character.

The program can look for example the following way

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

int main( void )
{
enum { N = 7 };
char *s1 = malloc( 2 * N - 1 );
char *s2 = malloc( N );
s1[0] = '\0';
s2[0] = '\0';

fgets( s1, N, stdin );
fgets( s2, N, stdin );

char *p1 = s1;

while (*p1 != '\n' && *p1 != '\0') ++p1;

for (char *p2 = s2; *p2 != '\n' && *p2 != '\0'; ++p2)
{
*p1++ = *p2;
}

*p1 = '\0';

puts( s1 );

free( s1 );
free( s2 );
}

The program output might be

hello
world
helloworld

Instead of these lines

char *s1 = malloc( 2 * N - 1 );
char *s2 = malloc( N );
s1[0] = '\0';
s2[0] = '\0';

you could write

char *s1 = calloc( 2 * N - 1, sizeof( char ) );
char *s2 = calloc( N, sizeof( char ) );

The arrays are zero initialized to keep empty strings in case when calls of fgets will be interrupted.



Related Topics



Leave a reply



Submit