This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
C String Concatenation
How do I concatenate multiple char strings in C ?
Example:
const char *bytes = "tablr=Hello%20World";
const char *bytes2 = "tablr=Hello%20World";
const char *bytes3 = "tablr=Hello%20World";
thanks
Here's a suggestion, that avoids the Painter's problem:
char const *bytes = "tablr=Hello%20World";
char const *bytes2 = "tablr=Hello%20World";
char const *bytes3 = "tablr=Hello%20World";
unsigned int const sz1 = strlen(bytes );
unsigned int const sz2 = strlen(bytes2);
unsigned int const sz3 = strlen(bytes3);
char *concat = (char*)malloc(sz1+sz2+sz3+1);
memcpy( concat , bytes , sz1 );
memcpy( concat+sz1 , bytes2 , sz2 );
memcpy( concat+sz1+sz2 , bytes3 , sz3 );
concat[sz1+sz2+sz3] = '\0';
/* don't forget to free(concat) when it's not needed anymore */
This avoids the painter's problem and should be more efficient (although sometimes not) because memcpy may copy byte-by-byte or word-by-word, depending on the implementation, which is faster.
If you can see a pattern here, this can easilly be transformed into a function that concatenates an arbitrary number of strings, if they are provided in an char const*[]
String literals can be concatenated simply by being adjacent:
const char *whole_string = "tablr=Hello%20World" "tablr=Hello%20World" "tablr=Hello%20World";
The above concatenation is done by the compiler and doesn't incur runtime overhead.
In general, you use the strcat function declared in <string.h>.
But you can concatenate string literals merely by writing them one after another. Example:
const char *p = "Hello, " "World"
"!";
p points to "Hello, World!".
In your case it would be like this:
const char* p =
"tablr=Hello%20World"
"tablr=Hello%20World"
"tablr=Hello%20World";
With string.h included (the easy but "slow" (not really very slow ;P) way):
char * result = calloc(strlen(bytes)+strlen(bytes2)+strlen(bytes3)+1,sizeof(char));
strcat(result, bytes);
strcat(result, bytes2);
strcat(result, bytes3);
Using an efficient loop:
int i, j, len = strlen(bytes)+strlen(bytes2)+strlen(bytes3)+1;
char * result = malloc(sizeof(char)*len);
for(i = 0; i < len && bytes[i] != '\0'; i++)
result[i] = bytes[i];
for(j = 0; i < len && bytes2[j] != '\0'; i++, j++)
result[i] = bytes2[j];
for(j = 0; i < len && bytes3[j] != '\0'; i++, j++)
result[i] = bytes3[j];
result[i] = '\0';
Use the strcat or strncat functions. Be careful with the memory allocations around those though.
If your compiler supports it use strcat_s or _tcscat_s. They will check the buffer length you're writing to.
I suggest to use memcpy function. It is quite efficient:
int l1 = strlen(bytes), l2 = strlen(bytes2), l3 = strlen(bytes3);
int length = l1+l2+l3;
char *concatenatedBytes = (char *)malloc((length+1)*sizeof(char));
memcpy(concatenatedBytes, bytes, l1);
memcpy(concatenatedBytes + l1, bytes2, l2);
memcpy(concatenatedBytes + l1 + l2, bytes3, l3);
concatenatedBytes[length] = 0;
Related
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 2 years ago.
Improve this question
I'm trying to make a function that concatenates a, b, and c in a single variable called result.
#include <stdio.h>
const char* concat(char* a, char* b, char* c) {
char *result; // Concatenated variable (A + B)
int i; // Index of A, B and C
int ir; // Index of result
// result = A
for(i=0; a[i] != '\0'; i++) {
ir = i;
result[ir] = a[i];
} // → for
// result = A + B
ir++;
for(i = 0; b[i] != '\0'; i++) {
if (i == 0)
ir = ir + i;
result[ir] = b[i];
} // → for
// result = A + B + C
ir++;
for(i = 0; c[i] != '\0'; i++) {
ir = ir + i;
result[ir] = c[i];
} // → for
return result;
} // → concatenate()
But when I compile and run with the following block it results in Segmentation fault (core dumped) error. I've already searched about it (What is a segmentation fault?) but the insight didn't come. What am I doing wrong?
int main() {
char* a = "1234567";
char* b = "abcdefg";
char* c = "_______";
printf("%s", concat(a, b, c));
}
ERROR:
Segmentation fault (core dumped)
The code shown is trying to store data into an undefined buffer (result), and that's not not kosher. SOMEBODY has to allocate the space, either your function, or the caller by passing in a bounded output buffer.
Using the allocate-memory mechanism, you have to get the full size of all the strings in advance so you can allocate the full chunk at once. After allocating the full chunk, copy in the strings one at a time.
char *concat3(const char *a, const char *b, const char *c)
{
// get the required size in advance
size_t n = 0;
for (const char *ap = a; *ap; ap++) n++;
for (const char *bp = b; *bp; bp++) n++;
for (const char *cp = c; *cp; cp++) n++;
char *result = malloc(n + 1);
char *op = result;
while (*op = *a++) op++;
while (*op = *b++) op++;
while (*op = *c++) op++;
return result;
}
Also note that the parameters are const char * rather than char * to make sure everybody knows that concat3 - I changed the name - will not write to these input buffers.
However, the return value cannot be const because you have to free it, which I hope you remember to do.
EDIT I added a different version that writes into a bounded output buffer so there's no memory allocation required in the function because the caller is responsible for it:
char *concat(char *obuf, size_t osize, const char *a, const char *b, const char *c)
{
char *obuf_save = obuf;
const char *obuf_max = obuf + osize - 1;
while (obuf < obuf_max && (*obuf = *a++)) obuf++;
while (obuf < obuf_max && (*obuf = *b++)) obuf++;
while (obuf < obuf_max && (*obuf = *c++)) obuf++;
*obuf = 0;
return obuf_save;
}
The key part is passing the output buffer and size, and it promises not to overwrite the end of the buffer.
Key downside: you can't tell if it truncated or not. Depends on your application if this matters.
You're never initializing result, so it will have a random value, so you've got UB (undefined behavior), which can result in a segfault.
You have to do a malloc for result. And, it needs to have enough space to hold the length of all the concatenated strings.
Here's some updated code. Note that I did not thoroughly check your for loops, but, at first glance they seem to be okay.
But, you have to add an EOS at the end of result because the for loops do not do that.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
size_t
mystrlen(const char *buf)
{
const char *bp;
for (bp = buf; *bp != 0; ++bp);
return bp - buf;
}
#if 0
const char *
concat(char *a, char *b, char *c)
#else
char *
concat(const char *a, const char *b, const char *c)
#endif
{
char *result; // Concatenated variable (A + B)
int i; // Index of A, B and C
int ir; // Index of result
// NOTE/BUG: result is _never_ given a value
#if 1
size_t totlen = 0;
// we need to determine the total length of the result string
totlen += mystrlen(a);
totlen += mystrlen(b);
totlen += mystrlen(c);
result = malloc(totlen + 1);
*result = 0;
#endif
// result = A
for (i = 0; a[i] != '\0'; i++) {
ir = i;
result[ir] = a[i];
}
// result = A + B
ir++;
for (i = 0; b[i] != '\0'; i++) {
if (i == 0)
ir = ir + i;
result[ir] = b[i];
}
// result = A + B + C
ir++;
for (i = 0; c[i] != '\0'; i++) {
ir = ir + i;
result[ir] = c[i];
}
result[totlen] = 0;
return result;
}
Edit: This was my original post. But, as others have pointed out, it was not the real issue.
So, disregard this section altogether!
I'm leaving it in because several responders here also misread the intent of your function at first glance. So, you may wish to add more comments to clarify the use of arguments and return value.
When you do:
char* a = "1234567";
You are creating a pointer that points to a string literal. On most/many systems, the literal will be placed in read only memory.
So, you will segfault on a protection exception [because you're trying to write to read only memory].
Also, the target buffer needs to be large enough to contain the size of all the concatenated strings. As you have it, a is too short/small.
You could try:
char a[100] = "1234567";
This creates a writable buffer of length 100 that is initialized with the string. But, you'll still have extra space to accomodate the concatenated strings [up to a total length of 100].
I've been doing this code wars challenge in which you have to take a string, and capitalize each letter, forming a Mexican wave-looking array of strings. For example, an input string like
hello
will result in ["Hello", "hEllo", "heLlo", "helLo", "hellO"]
I managed to complete it in JavaScript, and decided to attempt it in C. The actual code itself is working, as it prints the correct output, but the problem I am having is actually storing the string inside a double pointer.
This is my code:
#include <ctype.h>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
void wave(char *s, char **array);
int main(void)
{
char *s = malloc(6);
strcpy(s, "hello");
char **array = malloc(pow(strlen(s)+1, 2));
wave(s, array);
for (int i = 0; i < strlen(s); i++)
{
printf("s = %s\n", array[i]);
}
free(array);
free(s);
return 0;
}
void wave(char *s, char **array)
{
char s2[strlen(s)+1];
for (int i = 0; i < strlen(s); i++)
{
s[i] = tolower(s[i]);
}
int array_index = 0;
for (int i = 0; i < strlen(s); i++)
{
strcpy(s2, s);
if (s[i] != ' ')
{
s2[i] = toupper(s2[i]); // Printing out `s2` here results in the correct output
array[array_index++] = s2; // Adding it here works, but when trying to access it outside of this function, it gives the incorrect output
}
}
}
When printing the string inside the function, I get the following output (which is correct):
Hello
hEllo
heLlo
helLo
hellO
But when I try to print it out inside the main() function, I get the following:
s = hellO
s = hellO
s = hellO
s = hellO
s = hellO
It seems like it is adding/accessing only the last string in the array. I cannot understand why accessing the element inside the wave() function works, but accessing it outside of that function doesn't.
I've had this problem twice before, both in C and C++, and have been unable to solve it, and it is really annoying me.
I left this as a comment, but since it might not be clear, I'll post my answer in code...
As stated in my comment, there's no point allocating a pointer array - on a 64 bit machine, that would be 6 pointers, each requiring 8 bytes to point at a 7 byte long data block - a total of 104 bytes (ignoring the added allocator padding per allocation).
Instead, a single allocation could suffice, allocating 42 bytes to contain all the "wave" strings and their NUL byte in a single block of memory (saving memory while improving locality).
int main(void) {
/* Assuming string "hello" */
const char *org = "hello";
/* Calculate length only once and store value */
const size_t len = strlen(org);
const size_t len_with_nul = len + 1;
/* Allocate `len` strings in a single allocation */
char *buf = malloc(len * len_with_nul);
/* Copy each string to it's place in the buffer */
for (size_t i = 0; i < len; ++i) {
/* position in the buffer */
char *pos = buf + (i * len_with_nul);
/* copy the NUL as well */
memcpy(pos, org, len_with_nul);
/* Wave... */
pos[i] = toupper(pos[i]);
}
/* Print result */
for (size_t i = 0; i < len; i++) {
char *pos = buf + (i * len_with_nul);
printf("s = %s\n", pos);
}
/* Free buffer */
free(buf);
return 0;
}
EDIT - Why is using a single memory block better?:
In this case we allocate a single memory "block" (blob / slice). This offers a number of advantages:
We perform a single allocation and deallocation instead of a larger number of allocations and deallocations.
This improves speed by performing less actions.
We also improve memory locality, which minimizes CPU cache misses and improves performance.
We use less memory.
Each memory allocation comes with a price - we need a pointer to hold the memory address for the memory we allocated. A pointer "costs" 8 bytes on a 64bit machine and 4 bytes on a 32bit machine.
By using a single allocation, we "pay" less.
This is true even if we ignore the metadata attached to the memory block allocated (which requires memory from the memory allocator).
I should note that C doesn't really care about the contents of a memory block, it's all zeros and ones. The meaning given to these zeros and ones is left to the developer.
Even the printf function doesn't care about the contents of the memory it's reading - it simply reads the memory according to the formatting it was instructed to follow by the developer (the %s informs the function that the memory relates to a NUL terminated string).
There are some concerns about memory alignment which are CPU and system specific - but these don't apply to single byte strings. They apply to multi-byte types (such as short, int, and long). So we don't need to worry about them in this example.
In this sense, it basically means that the developer is free to manage the memory and the contents as they see fit (putting aside memory alignment).
This is not to say that it's always better to allocate a single block of memory (if you need to use realloc, you might prefer smaller chunks)... but usually a single block of memory is better.
For starters it is unclear why you are allocating dynamically memory for the string literal "hello".
char *s = malloc(6);
strcpy(s, "hello");
It does not make any sense.
Just write
const char *s = "hello";
This declaration
char **array = malloc(pow(strlen(s), 2));
also does not make sense. What you need is the following.
size_t n = strlen( s );
char **array = malloc( n * sizeof( char * ) );
for ( size_t i = 0; i < n; i++ )
{
array[i] = malloc( n + 1 );
}
The function wave can be defined the following way
void wave( const char *s, char **array )
{
size_t n = strlen( s );
for ( size_t i = 0; i < n; i++ )
{
strcpy( array[i], s );
array[i][i] = toupper( ( unsigned char )s[i] );
}
}
and then in main after the function call
for ( size_t i = 0; i < n; i++ )
{
puts( array[i] );
}
for ( size_t i = 0; i < n; i++ ) free( array[i] );
free( array );
Here is the full program.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
void wave( const char *s, char **array )
{
size_t n = strlen( s );
for ( size_t i = 0; i < n; i++ )
{
strcpy( array[i], s );
array[i][i] = toupper( ( unsigned char )s[i] );
}
}
int main(void)
{
const char *s = "hello";
size_t n = strlen( s );
char **array = malloc( n * sizeof( char * ) );
for ( size_t i = 0; i < n; i++ )
{
array[i] = malloc( n + 1 );
}
wave( s, array );
for ( size_t i = 0; i < n; i++ )
{
puts( array[i] );
}
for ( size_t i = 0; i < n; i++ ) free( array[i] );
free( array );
return 0;
}
Its output is
Hello
hEllo
heLlo
helLo
hellO
This question already has answers here:
Extra characters added to end of string in c
(3 answers)
Closed 5 years ago.
I am writing a function in C which takes two strings of the same length,
for example:-
S1 = "Hello" and S2 = "12345"
and returns a result that mixes the characters from the input strings so that the first char in the result string is the first char from S1, the second char is the first char from S2, the third char in r is the second char from S1 and the fourth char in r is the second char from S2, and so on....
So if:-
S1 = "Hello"
S2 = "12345"
Result = "H1e2l3l4o5"
My function looks like this:
#include <stdio.h>
#include <string.h>
char* mix(char *s1, char *s2)
{
int length = strlen(s1);
char* result = malloc(sizeof(char) * length * 2);
int i, j;
for(i = 0, j = 0; i < (length); i++, j = j + 2)
{
result[j] = s1[i];
result[j + 1] = s2[i];
}
return result;
}
For the values of S1 and S2 above it produces:
`H1e2l3l4o5:=C:\Uºt6▄╘º`
Which confuses me as I didn't allocate "result" enough memory for that many chars and wasn't warned of a segmentation fault or anything of that nature. Have I obviously done something wrong?
This happens because you did not null-terminated the string in the result. Add this line to fix this problem:
result[j] = '\0';
Another issue you need to fix is allocating the space for null terminator:
char* result = malloc(length * 2 + 1);
C standard requires sizeof(char) to be 1, so multiplying by it is not necessary.
Finally, you need to make sure that s2 has enough length to be copied into the result, i.e. strlen(s2) >= strlen(1).
You didn't allocate memory for the null character required to terminate a C string and, of course, you didn't put it after the string. This is why the code prints garbage from memory until it reaches the first null character.
char* mix(char *s1, char *s2)
{
int length = strlen(s1);
char* result = malloc(sizeof(char) * (length * 2 + 1));
int i, j;
for(i = 0, j = 0; i < length; i ++, j = j + 2)
{
result[j] = s1[i];
result[j + 1] = s2[i];
}
// Put the null character to end the the string
result[j] = 0;
return result;
}
Apparently the code should also check the length of s2 but, by chance, this is not needed.
If s1 is longer than s2, the null-terminating character of s2 is copied during the loop and the length of the resulting string is 2*strlen(s2). If s2 is longer than s1, the code copies only its first length characters.
I just want you to ask what did I do wrong with this code.
I wrote a function that take a char* in parameter, I want to modify it directly without returning smthg, and reverse the string.
#include <iostream>
void reverseString(char *p_string){
int length = strlen(p_string);
int r_it = length - 1;
char* tmp = (char*)malloc(length);
int last_it = 0;
for (int i = 0; i != length; i++){
tmp[i] = p_string[r_it];
r_it--;
last_it++;
}
tmp[last_it] = '\0';
strcpy_s(p_string, length + 1, tmp);
//free(tmp);
}
int main(){
char str[] = "StackOverflow";
reverseString(str);
std::cout << str << std::endl;
system("pause");
}
I'm used to C++ and don't often use C functions like malloc/free/strcpy...
Here, my problem is, when I alloc memory for my temporary char, I called mallec(length) for length = 13 in this case, char = 1 bytes so it should be allocate memory for 13 char is that right?
Problem is allocate more space than need so i need to use '\0' before my strcpy_s if not it breaks.
Did I do a mistake somewhere?
Also, when i call free(tmp), it breaks too and say heap corruption, but I didn't free the memory before that.
Thanks for helping !
I took your original code and added a simple '+1' to the size of the malloc and got a passing result.
Not sure if your exercise is related specifically to the use of malloc, but have you considered doing the reversal directly inside the original string?
For example:
void reverseString(char *p_string){
char* p_end = p_string+strlen(p_string)-1;
char t;
while (p_end > p_string)
{
t = *p_end;
*p_end-- = *p_string;
*p_string++ = t;
}
}
int main(){
char str[] = "StackOverflow";
reverseString(str);
std::cout << str << std::endl;
system("pause");
}
If you are required to use malloc, then you need to ensure that you allocate enough space for string which includes the '\0'
You must use
int length = strlen(p_string);
int r_it = length - 1;
char* tmp = (char*)malloc(length+1);
Since strlen doesn't count the \0 character. So this will fail if you don't use length+1:
tmp[last_it] = '\0';
The length of a C string is determined by the terminating
null-character: A C string is as long as the number of characters
between the beginning of the string and the terminating null character
(without including the terminating null character itself).
http://www.cplusplus.com/reference/cstring/strlen/
Btw. C99 support semi dynamic arrays. So could you try this:
char tmp[length+1];
Source:
http://en.wikipedia.org/wiki/Variable-length_array
float read_and_process(int n)
{
float vals[n];
for (int i = 0; i < n; i++)
vals[i] = read_val();
return process(vals, n);
}
Check the below C code:
The memory allocated to tmp should be length+1 as done below and also there are many unnecessary variables which can be avoided.
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
void reverseString(char *p_string){
int i;
int length = strlen(p_string);
int r_it = length - 1;
char* tmp = (char*)malloc(length+1);
for (i = 0; i != length; i++){
tmp[i] = p_string[r_it--];
}
tmp[i] = '\0';
strcpy(p_string, tmp);
return;
}
int main(){
char str[] = "StackOverflow";
reverseString(str);
printf("%s",str);
return 0;
}
There is nothing fundamentally wrong with your approach, just some of the details. Since I am not sure how you found out that the sizeof(tmp) is 32, I modified your code to the one below which includes a few printfs and some minor changes:
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
void reverseString(char *p_string)
{
size_t length = strlen(p_string);
size_t r_it = length - 1;
char* tmp = (char*)malloc(length+1);
int last_it = 0;
size_t i=0;
printf("strlen(p_string) = %d\n", strlen(p_string));
printf("Before: strlen(tmp) = %d\n", strlen(tmp));
for (i = 0; i != length; i++) {
tmp[i] = p_string[r_it];
r_it--;
last_it++;
}
tmp[last_it] = '\0';
printf("After: strlen(tmp) = %d\n", strlen(tmp));
strcpy(p_string, tmp);
free(tmp);
}
int main()
{
char str[] = "StackOverflow";
reverseString(str);
printf("%s\n", str);
return 0;
}
First, I have removed all C++ specific code - you can now compile this with gcc. Running this code yields this output:
sizeof(p_string) = 13
Before: strlen(tmp) = 0
After: strlen(tmp) = 13
wolfrevOkcatS
This is to be expected - strlen basically counts bytes until it hits the \0 character and so the first time we print the size using strlen, it returns 0 since we just allocated the memory. As another poster suggested, we have to allocate 1 extra byte to store the \0 in our new string.
Once the reverse is complete, 13 bytes would have been copied over to this memory and the second strlen returns the expected answer.
This question already has answers here:
Concatenating strings in C
(5 answers)
Closed 9 years ago.
I have a method that concatenates two c string. The method returns a new one. It works fine. Is there a way to make this method void, and just modify the first one?
EDIT: I cannot use strcopy or any other function from the string.h library. It is also suppose to be up to the caller to make sure s1 has enough space to accommodate s2.
char *str_glue(char *s1, char *s2)
{
char *r; //return string
int len1, len2;
int i, j;
len1 = str_length(s1);
len2 = str_length(s2);
if ((r=(char*)malloc(len1 + len2 + 1))==NULL)
{
return NULL;
}
for (i=0, j=0; i<len1; i++, j++) {
r[j] = s1[i];
}
for (i=0; i<len2; i++, j++)
{
r[j] = s2[i];
}
r[j] = '\0';
return r;
}
int main() {
char* x = "lightning";
char* y = "bug";
char *z = str_glue(x, y);
printf("%s\n", z);
}
Not really. *s1 is a char[] that already has a fixed length. If you write past that length you'll stomp on memory that is not inside of *s1. You have to create a new one that is the length of *s1 + *s2 to avoid this problem like you have done already.
Edit: I guess you could write a function that does what you want if *s1 is big enough to hold itself and *s2. But otherwise, no.
Use the standard function strcat():
The strcat() and strncat() functions append a copy of the null-terminated string s2 to the end of the null-terminated string s1,
then add a terminating `\0'. The string s1 must have sufficient space to hold the result.
You could consider using realloc of s1 provided you allocate the same on the heap. By modifying your code as this, I am able to achieve the same functionality as expected by you.
void str_glue(char **s1, char *s2)
{
int len1, len2;
int i;
char *curstr = *s1;
len1 = strlen(curstr);
len2 = strlen(s2);
curstr=(char*)realloc(curstr, (len1 + len2 + 1));
for (i=0; i<len2; i++)
{
curstr[(len1+i)] = s2[i];
}
curstr[(len1+len2)] = '\0';
}
and main function as
int main()
{
char* x;
char* y = "bug";
x = (char *)malloc(32);
strcpy(x, "lightning");
str_glue(&x, y);
printf("%s\n", x);
}
You would require to include stdlib.h for realloc definition.
P.S: I am assuming that you don't plan to use the standard C library functions like strcat or others.