Related
According to this:
strcpy vs strdup,
strcpy could be implemented with a loop, they used this while(*ptr2++ = *ptr1++). I have tried to do similar:
#include <stdio.h>
#include <stdlib.h>
int main(){
char *des = malloc(10);
for(char *src="abcdef\0";(*des++ = *src++););
printf("%s\n",des);
}
But that prints nothing, and no error. What went wrong?
Thanks a lot for answers, I have played a bit, and decided how best to design the loop to see how the copying is proceeding byte by byte. This seems the best:
#include <stdio.h>
#include <stdlib.h>
int main(){
char *des = malloc(7);
for(char *src="abcdef", *p=des; (*p++=*src++); printf("%s\n",des));
}
In this loop
for(char *src="abcdef\0";(*des++ = *src++););
the destination pointer des is being changed. So after the loop it does not point to the beginning of the copied string.
Pay attention to that the explicit terminating zero character '\0' is redundant in the string literal.
The loop can look the following way
for ( char *src = "abcdef", *p = des; (*p++ = *src++););
And then after the loop
puts( des );
and
free( des );
You could write a separate function similar to strcpy the following way
char * my_strcpy( char *des, const char *src )
{
for ( char *p = des; ( *p++ = *src++ ); );
return des;
}
And call it like
puts( my_strcpy( des, "abcdef" ) )'
free( des );
You are incrementing des so naturally at the end of the cycle it will be pointing past the end of the string, printing it amounts to undefined behavior, you have to bring it back to the beginning of des.
#include <stdio.h>
#include <stdlib.h>
int main(){
int count = 0;
char *des = malloc(10);
if(des == NULL){
return EXIT_FAILURE; //or otherwise handle the error
}
// '\0' is already added by the compiler so you don't need to do it yourself
for(char *src="abcdef";(*des++ = *src++);){
count++; //count the number of increments
}
des -= count + 1; //bring it back to the beginning
printf("%s\n",des);
free(dest); //to free the allocated memory when you're done with it
return EXIT_SUCCESS;
}
Or make a pointer to the beginning of des and print that instead.
#include <stdio.h>
#include <stdlib.h>
int main(){
char *des = malloc(10);
if(des == NULL){
return EXIT_FAILURE; //or otherwise handle the error
}
char *ptr = des;
for(char *src="abcdef";(*des++ = *src++);){} //using {} instead of ;, it's clearer
printf("%s\n",ptr);
free(ptr) // or free(dest); to free the allocated memory when you're done with it
return EXIT_SUCCESS;
}
printf("%s\n",des); is undefined behavior (UB) as it attempts to print starting beyond the end of the string written to allocated memory.
Copy the string
Save the original pointer, check it and free when done.
const char *src = "abcdef\0"; // string literal here has 2 ending `\0`,
char *dest = malloc(strlen(src) + 1); // 7
char *d = dest;
while (*d++ = *src++);
printf("%s\n", dest);
free(dest);
Copy the string literal
const char src[] = "abcdef\0"; // string literal here has 2 ending `\0`,
char *dest = malloc(sizeof src); // 8
for (size_t i = 0; i<sizeof src; i++) {
dest[i] = src[i];
}
printf("%s\n", dest);
free(dest);
You just need to remember the original allocated pointer.
Do not program in main. Use functions.
#include <stdio.h>
#include <stdlib.h>
size_t strSpaceNeedeed(const char *str)
{
const char *wrk = str;
while(*wrk++);
return wrk - str;
}
char *mystrdup(const char *str)
{
char *wrk;
char *dest = malloc(strSpaceNeedeed(str));
if(dest)
{
for(wrk = dest; *wrk++ = *str++;);
}
return dest;
}
int main(){
printf("%s\n", mystrdup("asdfgfd"));
}
or even better
size_t strSpaceNeedeed(const char *str)
{
const char *wrk = str;
while(*wrk++);
return wrk - str;
}
char *mystrcpy(char *dest, const char *src)
{
char *wrk = dest;
while((*wrk++ = *src++)) ;
return dest;
}
char *mystrdup(const char *str)
{
char *wrk;
char *dest = malloc(strSpaceNeedeed(str));
if(dest)
{
mystrcpy(dest, str);
}
return dest;
}
int main(){
printf("%s\n", mystrdup("asdfgfd"));
}
You allocate the destination buffer des and correctly copy the source string into place. But since you are incrementing des for each character you copy, you have moved des from the start of the string to the end. When you go to print the result, you are printing the last byte which is the nil termination, which is empty.
Instead, you need to keep a pointer to the start of the string, as well as having a pointer to each character you copy.
The smallest change from your original source is:
#include <stdio.h>
#include <stdlib.h>
int main(){
char *des = malloc(10);
char *p = des;
for(char *src="abcdef";(*p++ = *src++););
printf("%s\n",des);
}
So p is the pointer to the next destination character, and moves along the string. But the final string that you print is des, from the start of the allocation.
Of course, you should also allocate strlen(src)+1 worth of bytes for des. And it is not necessary to null-terminate a string literal, since that will be done for you by the compiler.
But that prints nothing, and no error. What went wrong?
des does not point to the start of the string anymore after doing (*des++ = *src++). In fact, des is pointing to one element past the NUL character, which terminates the string, thereafter.
Thus, if you want to print the string by using printf("%s\n",des) it invokes undefined behavior.
You need to store the address value of the "start" pointer (pointing at the first char object of the allocated memory chunk) into a temporary "holder" pointer. There are various ways possible.
#include <stdio.h>
#include <stdlib.h>
int main (void) {
char *des = malloc(sizeof(char) * 10);
if (!des)
{
fputs("Error at allocation!", stderr);
return 1;
}
char *tmp = des;
for (const char *src = "abcdef"; (*des++ = *src++) ; );
des = temp;
printf("%s\n",des);
free(des);
}
Alternatives:
#include <stdio.h>
#include <stdlib.h>
int main (void) {
char *des = malloc(sizeof(char) * 10);
if (!des)
{
fputs("Error at allocation!", stderr);
return 1;
}
char *tmp = des;
for (const char *src = "abcdef"; (*des++ = *src++) ; );
printf("%s\n", tmp);
free(tmp);
}
or
#include <stdio.h>
#include <stdlib.h>
int main (void) {
char *des = malloc(sizeof(char) * 10);
if (!des)
{
fputs("Error at allocation!", stderr);
return 1;
}
char *tmp = des;
for (const char *src = "abcdef"; (*tmp++ = *src++) ; );
printf("%s\n", des);
free(des);
}
Side notes:
"abcdef\0" - The explicit \0 is not needed. It is appended automatically during translation. Use "abcdef".
Always check the return of memory-management function if the allocation succeeded by checking the returned for a null pointer.
Qualify pointers to string literal by const to avoid unintentional write attempts.
Use sizeof(char) * 10 instead of plain 10 in the call the malloc. This ensures the write size if the type changes.
int main (void) instead of int main (void). The first one is standard-compliant, the second not.
Always free() dynamically allocated memory, since you no longer need the allocated memory. In the example above it would be redundant, but if your program becomes larger and the example is part-focused you should free() the unneeded memory immediately.
I am very new to programming with C and I can't find a way to add to this program in order to spell "Hello, World!" without deleting any lines of code here.
#include <stdio.h>
#include <string.h>
void modify_1(char *c);
void modify_2(char *c);
int main()
{
char str1[10];
char str2[15];
printf("%s, %s!\n", str1, str2);
}
void modify_1(char *c)
{
char *a_string = "hello";
}
void modify_2(char *c)
{
char *a_string = "world";
}
Consider the following code (see here in onlineGDB):
#include <stdio.h>
#include <string.h>
void modify_1(char *c);
void modify_2(char *c);
int main(void)
{
char str1[10];
char str2[15];
modify_1(str1);
modify_2(str2);
printf("%s, %s!\n", str1, str2);
}
void modify_1(char *c)
{
strcpy(c, "hello");
}
void modify_2(char *c)
{
strcpy(c, "world");
}
There are a few changes:
You actually call modify_1 and modify_2 (otherwise, why would they affect anything?)
Within the functions, you use strcpy to copy the content of the literal to the address.
I can't find a way to add to this program in order to spell "Hello, World!"
without deleting any lines of code here.
Given that you cannot delete any lines, you need only add 2-lines of code to each of your modify_1 and modify_2 functions to (1) copy the string-literals to your array, and then (2) change the first characters from lowercase to uppercase, and then just call modify_1 and modify_2 before you print.
For example:
void modify_1 (char *c)
{
char *a_string = "hello";
strcpy (c, a_string); /* copy a_string to your array */
c[0] = c[0] + 'A' - 'a'; /* change 1st character to uppercase */
}
void modify_2 (char *c)
{
char *a_string = "world";
strcpy (c, a_string); /* same thing */
c[0] = c[0] + 'A' - 'a';
}
After making the changes, you simply call the functions before your print statement in main(), e.g.
int main()
{
char str1[10];
char str2[15];
modify_1 (str1);
modify_2 (str2);
printf("%s, %s!\n", str1, str2);
}
Example Use/Output
$ ./bin/modify_12
Hello, World!
See ASCII Table and Description to understand how the conversion from lowercase to uppercase takes place.
This is probably not what is intended by the person that gave you the assignment but the simplest solution is to add two lines in main and leave the rest unchanged (and unused :-)
int main()
{
char str1[10];
char str2[15];
strcpy(str1, "Hello"); // Add this line
strcpy(str2, "World"); // Add this line
printf("%s, %s!\n", str1, str2);
}
I have recently begun working on learning the C language and have repeatedly run into an error in which calling the strcat function from the <string.h> module results in a segmentation fault. I've searched for the answers online, including on this stackoverflow post, without success. I thought this community might have a more personal insight into the problem, as the general solutions don't seem to be working. Might be user error, might be a personal issue with the code. Take a look.
#include <stdio.h>
#include <string.h>
char * deblank(const char str[]){
char *new[strlen(str)];
char *buffer = malloc(strlen(new)+1);
for (int i=0; i<strlen(*str); i++){
if(buffer!=NULL){
if(str[i]!=" "){
strcat(new,str[i]); //Segmentation fault
}
}
}
free(buffer);
return new;
}
int main(void){
char str[] = "This has spaces in it.";
char new[strlen(str)];
*new = deblank(str);
puts(new);
}
I've placed a comment on the line I've traced the segmentation fault back to. The following is some Java to make some sense out of this C code.
public class deblank {
public static void main(String[]args){
String str = "This has space in it.";
System.out.println(removeBlanks(str));
}
public static String removeBlanks(String str){
String updated = "";
for(int i=0; i<str.length(); i++){
if(str.charAt(i)!=' '){
updated+=str.charAt(i);
}
}
return updated;
}
}
Any insights into this error will be much appreciated. Please point out typos as well... I've been known to make them. Thanks.
OK, let's do this.
#include <stdio.h>
#include <string.h>
char * deblank(const char str[]){
char *new[strlen(str)];
^ This line creates an array of pointers, not a string.
char *buffer = malloc(strlen(new)+1);
malloc is undeclared. Missing #include <stdlib.h>. Also, you should check for allocation failure here.
strlen(new) is a type error. strlen takes a char * but new is (or rather evaluates to) a char **.
for (int i=0; i<strlen(*str); i++){
strlen(*str) is a type error. strlen takes a char * but *str is a char (i.e. a single character).
i<strlen(...) is questionable. strlen returns size_t (an unsigned type) whereas i is an int (signed, and possibly too small).
Calling strlen in a loop is inefficient because it has to walk the whole string to find the end.
if(buffer!=NULL){
This is a weird place to check for allocation failure. Also, you don't use buffer anywhere, so why create/check it at all?
if(str[i]!=" "){
str[i]!=" " is a type error. str[i] is a char whereas " " is (or rather evaluates to) a char *.
strcat(new,str[i]); //Segmentation fault
This is a type error. strcat takes two strings (char *), but new is a char ** and str[i] is a char. Also, the first argument to strcat must be a valid string but new is uninitialized.
}
}
}
free(buffer);
return new;
new is a local array in this function. You're returning the address of its first element, which makes no sense: As soon as the function returns, all of its local variables are gone. You're returning an invalid pointer here.
Also, this is a type error: deblank is declared to return a char * but actually returns a char **.
}
int main(void){
char str[] = "This has spaces in it.";
char new[strlen(str)];
*new = deblank(str);
This is a type error: *new is a char but deblank returns a char *.
puts(new);
puts takes a string, but new is essentially garbage at this point.
}
You can't use strcat like you did, it is intended to catenate a C-string at the end of another given one. str[i] is a char not a C-string (remember that a C-string is a contiguous sequence of chars the last being the NUL byte).
You also cannot compare strings with standard comparison operators, if you really need to compare strings then there is a strcmp function for it. But you can compare chars with standard operators as char is just a kind of integer type.
This should do the trick:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char * deblank(const char str[]) {
char *buffer = malloc(strlen(str)+1); // allocate space to contains as much char as in str, included ending NUL byte
for (int i=0, j=0; i<strlen(str)+1; i++) { // for every char in str, included the ending NUL byte
if (str[i]!=' ') { // if not blank
buffer[j++] = str[i]; // copy
}
}
return buffer; // return a newly constructed C-string
}
int main(void){
char str[] = "This has spaces in it.";
char *new = deblank(str);
puts(new);
free(new); // release the allocated memory
}
So, not sure whether this helps you, but a C code doing the same as your Java code would look like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static char *removeBlanks(const char *str)
{
char *result = malloc(strlen(str) + 1);
if (!result) exit(1);
const char *r = str;
char *w = result;
while (*r)
{
// copy each character except when it's a blank
if (*r != ' ') *w++ = *r;
++r;
}
*w = 0; // terminate the result to be a string (0 byte)
return result;
}
int main(void)
{
const char *str = "This has spaces in it.";
char *new = removeBlanks(str);
puts(new);
free(new);
return 0;
}
I would'nt recommend to name a variable new ... if you ever want to use C++, this is a reserved keyword.
I tried compiling with warnings enabled, here are some you should fix.
You need to include stdlib.h
char *new[strlen(str)] creates an array of char* not of char, so not really a string. Change it to char new[strlen(str)].
To check if str[i] is a space, you compare it to the space character ' ', not a string whose only character is a space " ". So change it to str[i]!=' '
strcat takes a string as the second argument and not a character, like you're giving it with str[i].
Also, what are you using buffer for?
Another mistake, is that you probably assumed that uninitialized arrays take zero values. The new array has random values, not zero/null. strcat concatenates two strings, so it would try to put the string in its second argument at the end of the first argument new. The "end" of a string is the null character. The program searches new for the first null character it can find, and when it finds this null, it starts writing the second argument from there.
But because new is uninitialized, the program might not find a null character in new, and it would keep searching further than the length of new, strlen(str), continuing the search in unallocated memory. That is probably what causes the segmentation fault.
There can be three approaches to the task.
The first one is to update the string "in place". In this case the function can look something like the following way
#include <stdio.h>
#include <ctype.h>
#include <iso646.h>
char * deblank( char s[] )
{
size_t i = 0;
while ( s[i] and not isblank( s[i] ) ) ++i;
if ( s[i] )
{
size_t j = i++;
do
{
if ( not isblank( s[i] ) ) s[j++] = s[i];
} while( s[i++] );
}
return s;
}
int main(void)
{
char s[] = "This has spaces in it.";
puts( s );
puts( deblank( s ) );
return 0;
}
The program output is
This has spaces in it.
Thishasspacesinit.
Another approach is to copy the source string in a destination character array skipping blanks.
In this case the function will have two parameters: the source array and the destination array. And the size of the destination array must be equal to the size of the source array because in general the source array can not have blanks.
#include <stdio.h>
#include <ctype.h>
#include <iso646.h>
char * deblank( char *s1, const char *s2 )
{
char *t = s1;
do
{
if ( not isblank( *s2 ) ) *t++ = *s2;
} while ( *s2++ );
return s1;
}
int main(void)
{
char s1[] = "This has spaces in it.";
char s2[sizeof( s1 )];
puts( s1 );
puts( deblank( s2, s1 ) );
return 0;
}
The program output will be the same as shown above.
Pay attention to this declaration
char s2[sizeof( s1 )];
The size of the destination string in general should be not less than the size of the source string.
And at last the third approach is when inside the function there is created dynamically an array and pointer to the first element of the array is returned from the function.
In this case it is desirable at first to count the number of blanks in the source array that to allocated the destination array with the appropriate size.
To use the functions malloc and free you need to include the following header
#include <stdlib.h>
The function can be implemented as it is shown in the demonstrative program.
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <iso646.h>
char * deblank( const char *s )
{
size_t n = 1; /* one byte reserved for the terminating zero character */
for ( const char *t = s; *t; ++t )
{
if ( not isblank( *t ) ) ++n;
}
char *s2 = malloc( n );
if ( s2 != NULL )
{
char *t = s2;
do
{
if ( not isblank( *s ) ) *t++ = *s;
} while ( *s++ );
}
return s2;
}
int main(void)
{
char s1[] = "This has spaces in it.";
char *s2 = deblank( s1 );
puts( s1 );
if ( s2 ) puts( s2 );
free( s2 );
return 0;
}
The program output is the same as for the two previous programs.
As for the standard C function strcat then it cats two strings.
For example
#include <stdio.h>
#include <string.h>
int main(void)
{
char s1[12] = "Hello ";
char *s2 = "World";
puts( strcat( s1, s2 ) );
return 0;
}
The destination array (in this case s1) must have enough space to be able to append a string.
There is another C function strncat in the C Standard that allows to append a single character to a string. For example the above program can be rewritten the following way
#include <stdio.h>
#include <string.h>
int main(void)
{
char s1[12] = "Hello ";
char *s2 = "World";
for ( size_t i = 0; s2[i] != '\0'; i++ )
{
strncat( s1, &s2[i], 1 );
}
puts( s1 );
return 0;
}
But it is not efficient to use such an approach for your original task because each time when the function is called it has to find the terminating zero in the source string that to append a character.
you can try recursively
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
void deblank(const char* str, char *dest) {
if (!*str) {*dest = '\0';return;}
// when we encounter a space we skip
if (*str == ' ') {
deblank(str+1, dest);
return;
}
*dest = *str;
deblank(str+1, dest+1);
}
int main(void) {
const char *str = "This has spaces in it.";
char *output = malloc(strlen(str)+1);
deblank(str, output);
puts(output);
free(output);
}
There are a lot of find/replace functions available on the internet, but i can't find why this is not working...( my own solution )
Here is what i tried
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* strrpl(char *str, char* find, char *replace)
{
int i;
char *pt = strstr(str, find), *firstStr;
firstStr = (char* )malloc(100 * sizeof(char));
// copy just until i find what i need to replace
// i tried to specify the length of firstStr just with pt - str
strncpy(firstStr, str, strlen(str) - strlen(pt));
strcat(firstStr, replace);
strcat(firstStr, pt + strlen(find));
for(i = 0; i < strlen(firstStr); i++)
str[i] = firstStr[i];
return str;
}
int main()
{
char *s, *s1, *s2;
s = (char* )malloc(100 * sizeof(char));
s1 = (char* )malloc(100 * sizeof(char));
s2 = (char* )malloc(100 * sizeof(char));
scanf("%s", s1);
scanf("%s", s2);
scanf("%s", s);
printf("%s", strrpl(s, s1, s2));
return 0;
}
The compilation gives me the error "segmentation fault" but i can't figure what memmory is he trying to alloc and he can't. I overrided a memory block or something? Please help :)
Thanks
I overrided a memory block or something?
You have:
A potential buffer overflow when you allocate firstStr. Who says the result will be less than 100 characters?
Another potential buffer overflow when you copy the answer back to the input string. Who says it will fit?
A potential buffer overflow each time you use scanf.
A memory leak each time you call malloc.
An inefficient implementation of strcpy just before return str;.
A crash (formally, undefined behaviour) when the input string does not contain the replacement string. strstr returns NULL when there is no match and you never check for it.
A potential issue with strncpy which leaves your string not NUL-terminated if there's not enough space for NUL.
Here is the immediate problem: when strstr returns NULL, your code does not pay attention. Add this line:
char *pt = strstr(str, find), *firstStr;
if (!pt) return str;
Another problem is that the call of strncpy is incorrect:
strncpy(firstStr, str, strlen(str) - strlen(pt));
it will leave firstStr unterminated, because str is longer than the substring being copied. The subsequent call
strcat(firstStr, replace);
will operate on a string that is not null-terminated, causing undefined behavior.
"Shotgun" approach to fixing it would be to use calloc instead of malloc to put zeros into firstStr. A more precise approach would be placing '\0' at the end of the copied substring.
With these fixes in place, your code runs OK (demo). However, there are several issues that need to be addressed:
You do not free any of the resources that you allocate dynamically - this results in memory leaks.
You do not compute how much memory to allocate - If a 5-character string is replaced for a 100-character string in a 100-character string, you overrun the temporary buffer.
You are using strncpy incorrectly - the function is intended for fixed-length strings. Use memcpy instead.
You are using strcat instead of memcpy or strcpy - this is inefficient.
You have not checked for the return value of strstr.
Try the below code.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* strrpl(char *str, char* find, char *replace)
{
int i;
char *pt = strstr(str, find);
char *firstStr;
if(pt == NULL){
printf("cannot find string \n");
return NULL;
}
firstStr = (char* )malloc(100 * sizeof(char));
// copy just until i find what i need to replace
// i tried to specify the length of firstStr just with pt - str
strncpy(firstStr, str, strlen(str) - strlen(pt));
strcat(firstStr, replace);
strcat(firstStr, pt + strlen(find));
for(i = 0; i < strlen(firstStr); i++)
str[i] = firstStr[i];
return str;
}
int main()
{
char *s, *s1, *s2, *s3;
s = (char* )malloc(100 * sizeof(char));
s1 = (char* )malloc(100 * sizeof(char));
s2 = (char* )malloc(100 * sizeof(char));
s3 = (char* )malloc(100 * sizeof(char));
scanf("%s", s);//input string
scanf("%s", s1);//string to find
scanf("%s", s2);//string to replace
s3 = strrpl(s, s1, s2);
if(s3 != NULL)
printf("%s \n",s3);
return 0;
}
How do I add two strings?
I tried name = "derp" + "herp";, but I got an error:
Expression must have integral or enum type
C does not have the support for strings that some other languages have. A string in C is just a pointer to an array of char that is terminated by the first null character. There is no string concatenation operator in C.
Use strcat to concatenate two strings. You could use the following function to do it:
#include <stdlib.h>
#include <string.h>
char* concat(const char *s1, const char *s2)
{
char *result = malloc(strlen(s1) + strlen(s2) + 1); // +1 for the null-terminator
// in real code you would check for errors in malloc here
strcpy(result, s1);
strcat(result, s2);
return result;
}
This is not the fastest way to do this, but you shouldn't be worrying about that now. Note that the function returns a block of heap allocated memory to the caller and passes on ownership of that memory. It is the responsibility of the caller to free the memory when it is no longer needed.
Call the function like this:
char* s = concat("derp", "herp");
// do things with s
free(s); // deallocate the string
If you did happen to be bothered by performance then you would want to avoid repeatedly scanning the input buffers looking for the null-terminator.
char* concat(const char *s1, const char *s2)
{
const size_t len1 = strlen(s1);
const size_t len2 = strlen(s2);
char *result = malloc(len1 + len2 + 1); // +1 for the null-terminator
// in real code you would check for errors in malloc here
memcpy(result, s1, len1);
memcpy(result + len1, s2, len2 + 1); // +1 to copy the null-terminator
return result;
}
If you are planning to do a lot of work with strings then you may be better off using a different language that has first class support for strings.
#include <stdio.h>
int main(){
char name[] = "derp" "herp";
printf("\"%s\"\n", name);//"derpherp"
return 0;
}
David Heffernan explained the issue in his answer, and I wrote the improved code. See below.
A generic function
We can write a useful variadic function to concatenate any number of strings:
#include <stdlib.h> // calloc
#include <stdarg.h> // va_*
#include <string.h> // strlen, strcpy
char* concat(int count, ...)
{
va_list ap;
int i;
// Find required length to store merged string
int len = 1; // room for NULL
va_start(ap, count);
for(i=0 ; i<count ; i++)
len += strlen(va_arg(ap, char*));
va_end(ap);
// Allocate memory to concat strings
char *merged = calloc(sizeof(char),len);
int null_pos = 0;
// Actually concatenate strings
va_start(ap, count);
for(i=0 ; i<count ; i++)
{
char *s = va_arg(ap, char*);
strcpy(merged+null_pos, s);
null_pos += strlen(s);
}
va_end(ap);
return merged;
}
Usage
#include <stdio.h> // printf
void println(char *line)
{
printf("%s\n", line);
}
int main(int argc, char* argv[])
{
char *str;
str = concat(0); println(str); free(str);
str = concat(1,"a"); println(str); free(str);
str = concat(2,"a","b"); println(str); free(str);
str = concat(3,"a","b","c"); println(str); free(str);
return 0;
}
Output:
// Empty line
a
ab
abc
Clean-up
Note that you should free up the allocated memory when it becomes unneeded to avoid memory leaks:
char *str = concat(2,"a","b");
println(str);
free(str);
I'll assume you need it for one-off things. I'll assume you're a PC developer.
Use the Stack, Luke. Use it everywhere. Don't use malloc / free for small allocations, ever.
#include <string.h>
#include <stdio.h>
#define STR_SIZE 10000
int main()
{
char s1[] = "oppa";
char s2[] = "gangnam";
char s3[] = "style";
{
char result[STR_SIZE] = {0};
snprintf(result, sizeof(result), "%s %s %s", s1, s2, s3);
printf("%s\n", result);
}
}
If 10 KB per string won't be enough, add a zero to the size and don't bother, - they'll release their stack memory at the end of the scopes anyway.
You should use strcat, or better, strncat. Google it (the keyword is "concatenating").
You cannot add string literals like that in C. You have to create a buffer of size of string literal one + string literal two + a byte for null termination character and copy the corresponding literals to that buffer and also make sure that it is null terminated. Or you can use library functions like strcat.
Concatenate Strings
Concatenating any two strings in C can be done in atleast 3 ways :-
1) By copying string 2 to the end of string 1
#include <stdio.h>
#include <string.h>
#define MAX 100
int main()
{
char str1[MAX],str2[MAX];
int i,j=0;
printf("Input string 1: ");
gets(str1);
printf("\nInput string 2: ");
gets(str2);
for(i=strlen(str1);str2[j]!='\0';i++) //Copying string 2 to the end of string 1
{
str1[i]=str2[j];
j++;
}
str1[i]='\0';
printf("\nConcatenated string: ");
puts(str1);
return 0;
}
2) By copying string 1 and string 2 to string 3
#include <stdio.h>
#include <string.h>
#define MAX 100
int main()
{
char str1[MAX],str2[MAX],str3[MAX];
int i,j=0,count=0;
printf("Input string 1: ");
gets(str1);
printf("\nInput string 2: ");
gets(str2);
for(i=0;str1[i]!='\0';i++) //Copying string 1 to string 3
{
str3[i]=str1[i];
count++;
}
for(i=count;str2[j]!='\0';i++) //Copying string 2 to the end of string 3
{
str3[i]=str2[j];
j++;
}
str3[i]='\0';
printf("\nConcatenated string : ");
puts(str3);
return 0;
}
3) By using strcat() function
#include <stdio.h>
#include <string.h>
#define MAX 100
int main()
{
char str1[MAX],str2[MAX];
printf("Input string 1: ");
gets(str1);
printf("\nInput string 2: ");
gets(str2);
strcat(str1,str2); //strcat() function
printf("\nConcatenated string : ");
puts(str1);
return 0;
}
Without GNU extension:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
const char str1[] = "First";
const char str2[] = "Second";
char *res;
res = malloc(strlen(str1) + strlen(str2) + 1);
if (!res) {
fprintf(stderr, "malloc() failed: insufficient memory!\n");
return EXIT_FAILURE;
}
strcpy(res, str1);
strcat(res, str2);
printf("Result: '%s'\n", res);
free(res);
return EXIT_SUCCESS;
}
Alternatively with GNU extension:
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
const char str1[] = "First";
const char str2[] = "Second";
char *res;
if (-1 == asprintf(&res, "%s%s", str1, str2)) {
fprintf(stderr, "asprintf() failed: insufficient memory!\n");
return EXIT_FAILURE;
}
printf("Result: '%s'\n", res);
free(res);
return EXIT_SUCCESS;
}
See malloc, free and asprintf for more details.
#include <string.h>
#include <stdio.h>
int main()
{
int a,l;
char str[50],str1[50],str3[100];
printf("\nEnter a string: ");
scanf("%s",str);
str3[0]='\0';
printf("\nEnter the string which you want to concat with string one: ");
scanf("%s",str1);
strcat(str3,str);
strcat(str3,str1);
printf("\nThe string is %s\n",str3);
}
using memcpy
char *str1="hello";
char *str2=" world";
char *str3;
str3=(char *) malloc (11 *sizeof(char));
memcpy(str3,str1,5);
memcpy(str3+strlen(str1),str2,6);
printf("%s + %s = %s",str1,str2,str3);
free(str3);
my here use asprintf
sample code:
char* fileTypeToStr(mode_t mode) {
char * fileStrBuf = NULL;
asprintf(&fileStrBuf, "%s", "");
bool isFifo = (bool)S_ISFIFO(mode);
if (isFifo){
asprintf(&fileStrBuf, "%s %s,", fileStrBuf, "FIFO");
}
...
bool isSocket = (bool)S_ISSOCK(mode);
if (isSocket){
asprintf(&fileStrBuf, "%s %s,", fileStrBuf, "Socket");
}
return fileStrBuf;
}
In C, you don't really have strings, as a generic first-class object. You have to manage them as arrays of characters, which mean that you have to determine how you would like to manage your arrays. One way is to normal variables, e.g. placed on the stack. Another way is to allocate them dynamically using malloc.
Once you have that sorted, you can copy the content of one array to another, to concatenate two strings using strcpy or strcat.
Having said that, C do have the concept of "string literals", which are strings known at compile time. When used, they will be a character array placed in read-only memory. It is, however, possible to concatenate two string literals by writing them next to each other, as in "foo" "bar", which will create the string literal "foobar".