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
Executing a Stored Procedure Within a Stored Procedure
Modify Materialized View Query
Split/Explode Comma Delimited String with Sybase SQL Anywhere
How to Select Rows Where a Column Value Starts with a Certain String
How to Reuse a Common Table Expression
SQL Query to Join Two Tables Based Off Closest Timestamp
Use a Like Clause in Part of an Inner Join
Sync Between SQL Server and MySQL Server
How to Retrieve Same Column Twice with Different Conditions in Same Table
Time Zone Conversion in SQL Query
T-SQL Column Alias on Computed Column - Invalid Column Name