TSL_
TSL_

Reputation: 2079

convert from string to char* - passing function pointer

this post bases on the solution given here, a post on SO

I write a function to get a given file extension (string type), something like:

void GetFileExtension(string filename, char* extension)
{
    vector<string> rec;

    StrDelimit(filename, '.', rec);

    //cout << rec[rec.size()-2].c_str()[1] << endl;

    //extension = rec[rec.size()-2].c_str()[0];

    //extension = &rec[rec.size()-2].c_str()[0];

    string str = rec[rec.size()-2];

    // conversion from string to char*
    vector<char> writable(str.size() + 1);

    std::copy(str.begin(), str.end(), writable.begin());

    //cout << writable << endl;

    extension = &writable[0];
}

StrDelimit works fine already which receives a string and delimits to vector of substrings by the given delimiter

I use the "//conversion from string to char*" as shown to return the result to calling main program

There is no compile error but the result is a string of meaningless characters. What's it the problem?

any help would be appreciated!

Thank you!

Upvotes: 0

Views: 1994

Answers (4)

enhzflep
enhzflep

Reputation: 13089

char *extension is a temporary copy of the address of a string. To actually put new data into it, you'd have to copy data to the address that it holds.

Does this help?

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

void getStringInoExistingBufer(char* existingBufferOut)
{
    strcpy(existingBufferOut, "someData");
}

void getStringIntoNonExistingBuffer(char **newBufferOut)
{
    *newBufferOut = strdup("someOtherData");
}

int main()
{
    char buffer1[100] = {};
    char *buffer2 = NULL;

    printf("buffer1 (before): '%s'\n", buffer1);
    getStringInoExistingBufer(buffer1);
    printf("buffer1 (after): '%s'\n", buffer1);

    printf("\n\n");
    printf("buffer2 (before): '%s'\n", buffer2);
    getStringIntoNonExistingBuffer(&buffer2);
    printf("buffer2 (after): '%s'\n", buffer2);
}

Output:

buffer1 (before): ''
buffer1 (after): 'someData'


buffer2 (before): '(null)'
buffer2 (after): 'someOtherData'

Upvotes: 1

Joachim Isaksson
Joachim Isaksson

Reputation: 180867

Firstly, you're not really returning anything;

void GetFileExtension(string filename, char* extension)
{
    ...
    extension = &writable[0];  // Assignment to local variable
}

If you intend to update the char* passed in extension, you'll need to pass it as a char** (i.e. a pointer to your char*).

Secondly, even if you fix that, you're attempting to return a pointer to data in a local variable;

void GetFileExtension(string filename, char* extension)
{
    ...
    vector<char> writable(str.size() + 1);   // Local variable
    ...
    extension = &writable[0];       // writable disappears after this line
                                    // and extension will point to invalid memory
}

Just returning an std::string would simplify your code quite a bit.

Upvotes: 0

Why not just return extension as std::string?

For example:

std::string GetFileExtension(std::string filename)
{
    std::vector<string> rec;

    StrDelimit(filename, '.', rec);

    std::string extension = rec[rec.size() - 2];
    return extension;
}

Upvotes: 0

Roee Gavirel
Roee Gavirel

Reputation: 19445

your problem is you creating the data member writable on the stack, and then point to it with extension BUT the scope of writable is the function meaning that when the function returns writable is been cleared leaving extension pointing nothing.

you can allocated a dynamic buffer for the char* but that is more C approach than C++. If possible I would recommend changing the function type to return a string or a vector which will make it much easier, and you can change those types to char* whenever needed.

Upvotes: 0

Related Questions