d3pd
d3pd

Reputation: 8315

making a new char* out of two old char*s

I am open to using intermediary C++ code, though C code is the preference.

I have code like the following:

char *fileName1 = "graph";
char *extension1 = ".eps";

I want to create a new char* variable called fileName1WithExtension1 which would correspond to "graph.eps", formed from the two char* variables given above. How can this be done?

Upvotes: 0

Views: 510

Answers (6)

hyde
hyde

Reputation: 62787

I did a bit of C brush-up for fun, here's an alternative (C90 and C++ compatible code) for joining an array of C strings with separator. It should be very efficient with any decently optimizing compiler, too:

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

/* **parts are strings to join, a NULL-terminated array of char*
 * sep is separator string, use "" for no separator, must not be NULL
 * returns malloc-allocated buffer which must be freed
 * if len_out!=NULL, sets *len_out to strlen of result string */
char *astrjoin(int *len_out, const char *sep, char **parts) {

    int part_count;
    int parts_total_len = 0;

    for(part_count = 0; parts[part_count]; ++part_count) {
        parts_total_len += strlen(parts[part_count]);
    }
    if (part_count > 0) {
        int malloc_size = (part_count - 1) * strlen(sep) + parts_total_len + 1;
        char *result = (char*)malloc(malloc_size);
        char *dest = result;   
        for(;;) {
            const char *src;
            for(src=*parts; *src; ++src) *dest++ = *src;
            if (!*++parts) break;
            for(src=sep ; *src; ++src) *dest++ = *src;
        }
        *dest = 0;
        if (len_out) *len_out = malloc_size - 1;
        return result;
    } else {
        if (len_out) *len_out = 0;
        return strdup("");
    }
}

Example usage:

int main(int argc, char *argv[]) {
    /* argv is NULL-terminated array of char pointers */
    char *commandline = astrjoin(NULL, " ", argv);
    printf("argc: %d\nargv: %s\n", argc, commandline);
    free(commandline);
    return 0;
}

To call that in context of your question, it could be something like:

char *tmparr[] = { fileName1, exteansion1, NULL };
char *fileName1WithExtension1 = astrjoin(NULL, "", tmparr);

It would be trivial to create a version with sep and/or len_out dropped, or a version supporting "varargs", with signature looking something like:

char *astrjoin_va(int *len_out, const char *sep, ...);

Which would be nicer to call in context of your question:

char *fileName1WithExtension1 = astrjoin_va(NULL, "", fileName1, extension1, NULL);

Upvotes: 1

user1497579
user1497579

Reputation:

If you want to go REALLY low-level, with ugly loops and such, you can do this: (Tested, it compiles and gives the expected and desired results)

char* filename1 = "graph";
char* extension1 = ".eps";
char* filename1WithExtension1 = combine(filename1, extension1);

where:

char* combine(char* str1, char* str2)
{
    int str1len = 0, str2len = 0;
    while(str1[str1len] != '\0') {
        str1len++;
    }
    while(str2[str2len] != '\0') {
        str2len++;
    }
    int outputlen = str1len + str2len + 1;
    char* output = new char[outputlen];
    for(int i = 0; i < str1len; i++)
    {
        output[i] = str1[i];
    }
    for(int i = str1len; i < outputlen; i++)
    {
        output[i] = str2[i - str1len];
    }
    return output;
}

Upvotes: 1

hyde
hyde

Reputation: 62787

If you use C++, have those as std::string strings:

std::string fileName1 = "graph";
std::string extension1 = ".eps";

And then simply

std::string fileName1WithExtension1 = filename1 + extension1;

If you then need to pass that to a C library function expecting a C string, get char pointer with fileName1WithExtension1.c_str()

There really is no reason to muck about with plain C strings in C++ code. It is so error-prone and tedious, that it should be actively avoided.

Upvotes: 4

DarenW
DarenW

Reputation: 16906

char *joined;
joined = (char*)malloc(strlen(fileName1) + strlen(extension1) + 1);
strcpy(joined, fileName1)
strcat(joined, extension1)

For a small performance increase, if the compiler is smart enough at optimizing, change the last line to

strcpy(joined+strlen(fileName1), extension1)

Even better, store the length of fileName1 in a variable the first time you determine it, and use it in the final strcpy().

Upvotes: 2

MOHAMED
MOHAMED

Reputation: 43518

You can use the asprintf() function

char *buffer;
asprintf (&buffer, "%s%s", fileName1, extension1);

When the buffer variable become useless in your code, you have to free the memory allocated for buffer by asprintf with

free(buffer);

Upvotes: 2

Valeri Atamaniouk
Valeri Atamaniouk

Reputation: 5163

char *new_string;

new_string = malloc(strlen(fileName1) + strlen(extension1) + 1);
sprintf(new_string, "%s%s", fileName1, extension1);

...

free(new_string)

Upvotes: 4

Related Questions