57

I have a a char array:

char* name = "hello";

I want to add an extension to that name to make it

hello.txt

How can I do this?

name += ".txt" won't work

Tyler Carter
  • 60,743
  • 20
  • 130
  • 150
user69514
  • 26,935
  • 59
  • 154
  • 188
  • You could copy and paste an answer here, or you could go read what our host Joel has to say about [strcat](http://www.joelonsoftware.com/articles/fog0000000319.html). – Will Feb 07 '10 at 21:03

7 Answers7

86

Have a look at the strcat function.

In particular, you could try this:

const char* name = "hello";
const char* extension = ".txt";

char* name_with_extension;
name_with_extension = malloc(strlen(name)+1+4); /* make space for the new string (should check the return value ...) */
strcpy(name_with_extension, name); /* copy name into the new var */
strcat(name_with_extension, extension); /* add the extension */
...
free(name_with_extension);
Mathyou
  • 651
  • 2
  • 10
  • 28
David Underhill
  • 15,896
  • 7
  • 53
  • 61
  • 36
    Don't forget to free name_with_extension! – Nick Presta Feb 07 '10 at 21:04
  • 3
    Can you please write `const char *name, *extension`? A string literal is *not* a `char *`. – ephemient Feb 07 '10 at 22:03
  • 11
    A little new to C but what is up with the +1+4 in malloc(strlen(name)+1+4) I am guessing the +4 is the 4 extra chars but what is the +1? – Jackie Jun 03 '13 at 20:38
  • 13
    The +1 is to account for the null terminator at the end of the string – lopsided98 Oct 15 '13 at 01:10
  • @lopsided98 why isn't `sizeof(char)` used that actual byte count? e.g. `malloc(strlen(name) + 4 * sizeof(char) + 1)` – Joseph Persico Jan 03 '17 at 13:47
  • @JosephPersie sizeof(char) is 1 by definition (interesting answer on this [here](https://stackoverflow.com/a/2215454/1611927)) – Michele Sep 06 '17 at 16:03
  • is this a joke? why using Const (4) ? – user25 May 20 '18 at 18:09
  • If you are new to C, note the comment by @Nick Presta. Without calling free name_with_extension this routine has a memory leak and will fill your memory and crash if called enough times. If you are going to call this many times you either need to free name_with_extension or see below for other methods. – Casey Dec 30 '20 at 19:22
  • Even though not a problem in this very specific sniplet, `strcpy()` and `strcat()` are buffer overflows waiting to happen and should thus be banned for security reasons. Do not use them. Do not teach them. In fact, do not even mention them! If you have to use C strings, use `strncpy()` and `strncat()` instead. – digitalarbeiter Feb 19 '21 at 13:20
33

I have a char array:

char* name = "hello";

No, you have a character pointer to a string literal. In many usages you could add the const modifier, depending on whether you are more interested in what name points to, or the string value, "hello". You shouldn't attempt to modify the literal ("hello"), because bad things can happen.

The major thing to convey is that C does not have a proper (or first-class) string type. "Strings" are typically arrays of chars (characters) with a terminating null ('\0' or decimal 0) character to signify end of a string, or pointers to arrays of characters.

I would suggest reading Character Arrays, section 1.9 in The C Programming Language (page 28 second edition). I strongly recommend reading this small book ( <300 pages), in order to learn C.

Further to your question, sections 6 - Arrays and Pointers and section 8 - Characters and Strings of the C FAQ might help. Question 6.5, and 8.4 might be good places to start.

I hope that helps you to understand why your excerpt doesn't work. Others have outlined what changes are needed to make it work. Basically you need an char array (an array of characters) big enough to store the entire string with a terminating (ending) '\0' character. Then you can use the standard C library function strcpy (or better yet strncpy) to copy the "Hello" into it, and then you want to concatenate using the standard C library strcat (or better yet strncat) function. You will want to include the string.h header file to declare the functions declarations.

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

int main( int argc, char *argv[] )
{
    char filename[128];
    char* name = "hello";
    char* extension = ".txt";

    if (sizeof(filename) < strlen(name) + 1 ) { /* +1 is for null character */
        fprintf(stderr, "Name '%s' is too long\n", name);
        return EXIT_FAILURE;
    }
    strncpy(filename, name, sizeof(filename));

    if (sizeof(filename) < (strlen(filename) + strlen(extension) + 1) ) {
        fprintf(stderr, "Final size of filename is too long!\n");
        return EXIT_FAILURE;
    }
    strncat(filename, extension, (sizeof(filename) - strlen(filename)) );
    printf("Filename is %s\n", filename);

    return EXIT_SUCCESS;
}
mctylr
  • 5,159
  • 20
  • 32
  • This is a better solution than the one selected by the OP: it doesn't use malloc (memory allocated in the stack will be reallocated after the routine is run) and it has lots of good error checking. – Casey Mar 03 '19 at 00:10
  • @nmnir You are exactly right. I'm was trying to say that the because the answer selected by the OP uses malloc it's not ideal, in part because it uses memory on the heap. In contrast, this answer is better because it does not use malloc and therefore it's memory will be allocated on the stack and will be reallocated after the routine is run. My use of parenthesis was ambiguous and it's too late to edit it. Consider this comment a clarification. – Casey Dec 30 '20 at 19:18
18

First copy the current string to a larger array with strcpy, then use strcat.

For example you can do:

char* str = "Hello";
char dest[12];

strcpy( dest, str );
strcat( dest, ".txt" );
Salv0
  • 1,069
  • 3
  • 11
  • 23
9

asprintf is not 100% standard, but it's available via the GNU and BSD standard C libraries, so you probably have it. It allocates the output, so you don't have to sit there and count characters.

char *hi="Hello";
char *ext = ".txt";
char *cat;

asprintf(&cat, "%s%s", hi, ext);
bk.
  • 6,068
  • 2
  • 24
  • 28
3

You can concatenate strings by using the sprintf() function. In your case, for example:

char file[80];
sprintf(file,"%s%s",name,extension);

And you'll end having the concatenated string in "file".

2

in rare cases when you can't use strncat, strcat or strcpy. And you don't have access to <string.h> so you can't use strlen. Also you maybe don't even know the size of the char arrays and you still want to concatenate because you got only pointers. Well, you can do old school malloc and count characters yourself like..

char *combineStrings(char* inputA, char* inputB) {
    size_t len = 0, lenB = 0;
    while(inputA[len] != '\0') len++;
    while(inputB[lenB] != '\0') lenB++;
    char* output = malloc(len+lenB);
    sprintf((char*)output,"%s%s",inputA,inputB);
    return output;
}

It just needs #include <stdio.h> which you will have most likely included already

Ol Sen
  • 3,163
  • 2
  • 21
  • 30
1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char *name = "hello";

int main(void) {
  char *ext = ".txt";
  int len   = strlen(name) + strlen(ext) + 1;
  char *n2  = malloc(len);
  char *n2a = malloc(len);

  if (n2 == NULL || n2a == NULL)
    abort();

  strlcpy(n2, name, len);
  strlcat(n2, ext, len);
  printf("%s\n", n2);

  /* or for conforming C99 ...  */
  strncpy(n2a, name, len);
  strncat(n2a, ext, len - strlen(n2a));
  printf("%s\n", n2a);

  return 0; // this exits, otherwise free n2 && n2a
}
DigitalRoss
  • 143,651
  • 25
  • 248
  • 329