Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++: Correct implementation for passing a std::string to a C function that wants to change the string?

I have a function in a third-party library written in C: char* fix_filename_slashes(char* path). This function expects a mutable C-string passed to it so it can change all the slashes in the path to the correct use based on the operating system. All the strings I'm using in my Facade are declared as std::strings. I attempted to simply use foo.c_str() as every other function that expects a C string doesn't change it and expects a const char *, but this function causes an error: Error: Argument of type "const char *" is incompatible with parameter of type "char *"

Is the result I came up with:

char* tempf = const_cast<char*>(filename.c_str());
filename = std::string(fix_filename_slashes(tempf));
tempf = NULL;

considered "correct" or are there other (more correct?) ways to accomplish the task?

EDIT

Whups. Apparently the function returns a COPY of the string. Still there are some nice answers already given.

like image 898
Casey Avatar asked Aug 02 '11 21:08

Casey


People also ask

Can you use std::string in C?

A std::string_view can refer to both a C++ string or a C-string. All that std::string_view needs to store is a pointer to the character sequence and a length. std::string_view provides the same API that std::string does, so it is a perfect match for C-style string literals.

How do you pass a string by reference to a function?

First, we have the function definition “DisplayString,” where a constant string reference is passed. The constant strings are defined and initialized in the main function as “str1” and “str2”. After that, pass these constant strings to the function “InputString”.

What is the difference between a C++ string and an std::string?

There is no functionality difference between string and std::string because they're the same type.

How are strings passed in C?

To pass a one dimensional string to a function as an argument we just write the name of the string array variable. In the following example we have a string array variable message and it is passed to the displayString function.


3 Answers

If the string length does not change, you can use a pointer to the first character of the string. This is undefined behavior in the C++03 standard, but all known implementations work properly and it is explicitly allowed under the C++11 standard.

fix_filename_slashes(&filename[0]);

If the size of the string may change, you'll have to do a little more work.

filename.resize(max_size, 0);
append_filename_suffix(&filename[0]);
filename.resize(strlen(filename.c_str()));
like image 76
Mark Ransom Avatar answered Oct 02 '22 19:10

Mark Ransom


Convert it into a null-terminated sequence of characters stored in a std::vector:

template <typename Character>
std::vector<Character> to_vector(std::basic_string<Character> const& s)
{
    std::vector<Character> v;
    v.reserve(s.size() + 1);
    v.insert(v.end(), s.begin(), s.end());
    v.push_back(0);
    return v;
}

Usage example:

std::string filename = get_filename();
std::vector<char> filename_cstr = to_vector(filename);
filename = std::string(fix_filename_slashes(&filename_cstr[0]));
like image 23
James McNellis Avatar answered Oct 02 '22 19:10

James McNellis


Since you are going to all the trouble you could just comply with the requirements of the C function and copy your string to a char array then after the function create a string from the char array or force a copy assignment on your original string.

    char* temp = new char[str.size() + 1]
    // Force a copy of the result into another string
    str = (const char*)fix_filename_slashes(strncpy(temp, str.c_str(), str.size() + 1));
    delete [] temp;
like image 24
Adrian Regan Avatar answered Oct 02 '22 18:10

Adrian Regan