boost to_upper char pointer in one expression - c++

Is it possible to do something like:
const char* str = "AaBbCc";
string str_up = boost::to_upper_copy(str); // str_up will be "AABBCC"
Last line doesn't compile.
Of course I can as below, but it less "canonical":
const char* str = "AaBbCc";
string str_up = str;
boost::to_upper(str_up);

The declaration of to_upper_copy is:
template<typename SequenceT>
SequenceT to_upper_copy(const SequenceT &, const std::locale & = std::locale());
From this it should be clear that SequenceT can't be a pointer to char, or even a char array, because there's no (good) way how the returned copy could have the same type.
You can explicitly force the type to be string:
string str_up = boost::to_upper_copy<string>(str);
Here's explanation what SequenceT and RangeT mean in the documentation: String Representation. In short, neither can be a const char*, but RangeT arguments accept arrays (char [X]).

Why not post the right solution as an answer to the question?
const char* str = "AaBbCc";
std::string str_up = boost::to_upper_copy(std::string(str));
Credits to Konrad.

Sure!
inline std::string to_upper_copy(std::string const & src) {
std::string res(src);
boost::to_upper(res);
return res;
}

Related

Can we assign const char* to a string in cpp?

Although my compiler doesn't throw an error while assigning const char* to a string, I am wondering if this assignment is really valid and will not throw some unexpected result
string name;
const char* name2 = "ABCD";
name = name2;
You absolutely can.
std::string was meant to replace the tedious and error-prone C strings const char* so for it to be a good replacement/successor it'd need backwards compatibility with const char* which it does.
name = name2; calls operator= so if we check basic_strings overloads for this operator we can see (3):
basic_string& operator=( const CharT* s );
Here CharT is of the type char so you get const char*
Which does what you'd expect it to do, it copies over the contents the const char* is pointing to, to the internal buffer of std::string:
Replaces the contents with those of null-terminated character string
pointed to by s as if by assign(s, Traits::length(s)).
In order to go the other route though, from a std::string to a const char*, you'd need to call its method c_str() on the std::string object.
I am wondering if this assignment is really valid
Yes it's valid:
string name;
const char *name2 = "ABCD";
name = name2;
Note name = name2 calls std::string assignment operator, after which the two variables are totally independent, ie you are free to change name, while name2 remains const (aka literal string).

Can I get a char * to a std::sregex_iterator match str()

string b="some string another string";
std::regex r("string");
std::sregex_iterator m(b.begin(),b.end(),r);
for (std::sregex_iterator end; m!=end; m++)
{
// want a char* to m->str() in here
}
I'm gettng totally lost trying to determine what's what because of the templates. I've tried
const char *c = m->str().c_str() // compiles but points to ""
Answer
Pointed out by lightness below
const char *c = &b[m->position()]; // length of str is m->length()
const char *c = m->str().c_str()
m->str() is a temporary value, not a reference to data inside m, so c is immediately dangling.
Just store the string first:
const std::string str = m->str();
const char* c = str.c_str();
Yes, the copy is unfortunate.
A cheaper way than the copy would be:
const std::string_view sv{
b.data() + m->position(),
m->length()
};
This is great if you can use string views. But it is not null-terminated! So, if you really do need a const char*, this won't work for you and you're pretty much stuck with a fresh buffer.

std::string to char*

I want to convert a std::string into a char* or char[] data type.
std::string str = "string";
char* chr = str;
Results in: “error: cannot convert ‘std::string’ to ‘char’ ...”.
What methods are there available to do this?
It won't automatically convert (thank god). You'll have to use the method c_str() to get the C string version.
std::string str = "string";
const char *cstr = str.c_str();
Note that it returns a const char *; you aren't allowed to change the C-style string returned by c_str(). If you want to process it you'll have to copy it first:
std::string str = "string";
char *cstr = new char[str.length() + 1];
strcpy(cstr, str.c_str());
// do stuff
delete [] cstr;
Or in modern C++:
std::vector<char> cstr(str.c_str(), str.c_str() + str.size() + 1);
More details here, and here but you can use
string str = "some string" ;
char *cstr = &str[0];
As of C++11, you can also use the str.data() member function, which returns char *
string str = "some string" ;
char *cstr = str.data();
If I'd need a mutable raw copy of a c++'s string contents, then I'd do this:
std::string str = "string";
char* chr = strdup(str.c_str());
and later:
free(chr);
So why don't I fiddle with std::vector or new[] like anyone else? Because when I need a mutable C-style raw char* string, then because I want to call C code which changes the string and C code deallocates stuff with free() and allocates with malloc() (strdup uses malloc). So if I pass my raw string to some function X written in C it might have a constraint on it's argument that it has to allocated on the heap (for example if the function might want to call realloc on the parameter). But it is highly unlikely that it would expect an argument allocated with (some user-redefined) new[]!
(This answer applies to C++98 only.)
Please, don't use a raw char*.
std::string str = "string";
std::vector<char> chars(str.c_str(), str.c_str() + str.size() + 1u);
// use &chars[0] as a char*
If you just want a C-style string representing the same content:
char const* ca = str.c_str();
If you want a C-style string with new contents, one way (given that you don't know the string size at compile-time) is dynamic allocation:
char* ca = new char[str.size()+1];
std::copy(str.begin(), str.end(), ca);
ca[str.size()] = '\0';
Don't forget to delete[] it later.
If you want a statically-allocated, limited-length array instead:
size_t const MAX = 80; // maximum number of chars
char ca[MAX] = {};
std::copy(str.begin(), (str.size() >= MAX ? str.begin() + MAX : str.end()), ca);
std::string doesn't implicitly convert to these types for the simple reason that needing to do this is usually a design smell. Make sure that you really need it.
If you definitely need a char*, the best way is probably:
vector<char> v(str.begin(), str.end());
char* ca = &v[0]; // pointer to start of vector
This would be better as a comment on bobobobo's answer, but I don't have the rep for that. It accomplishes the same thing but with better practices.
Although the other answers are useful, if you ever need to convert std::string to char* explicitly without const, const_cast is your friend.
std::string str = "string";
char* chr = const_cast<char*>(str.c_str());
Note that this will not give you a copy of the data; it will give you a pointer to the string. Thus, if you modify an element of chr, you'll modify str.
Assuming you just need a C-style string to pass as input:
std::string str = "string";
const char* chr = str.c_str();
To obtain a const char * from an std::string use the c_str() member function :
std::string str = "string";
const char* chr = str.c_str();
To obtain a non-const char * from an std::string you can use the data() member function which returns a non-const pointer since C++17 :
std::string str = "string";
char* chr = str.data();
For older versions of the language, you can use range construction to copy the string into a vector from which a non-const pointer can be obtained :
std::string str = "string";
std::vector<char> str_copy(str.c_str(), str.c_str() + str.size() + 1);
char* chr = str_copy.data();
But beware that this won't let you modify the string contained in str, only the copy's data can be changed this way. Note that it's specially important in older versions of the language to use c_str() here because back then std::string wasn't guaranteed to be null terminated until c_str() was called.
To be strictly pedantic, you cannot "convert a std::string into a char* or char[] data type."
As the other answers have shown, you can copy the content of the std::string to a char array, or make a const char* to the content of the std::string so that you can access it in a "C style".
If you're trying to change the content of the std::string, the std::string type has all of the methods to do anything you could possibly need to do to it.
If you're trying to pass it to some function which takes a char*, there's std::string::c_str().
Here is one more robust version from Protocol Buffer
char* string_as_array(string* str)
{
return str->empty() ? NULL : &*str->begin();
}
// test codes
std::string mystr("you are here");
char* pstr = string_as_array(&mystr);
cout << pstr << endl; // you are here
Conversion in OOP style
converter.hpp
class StringConverter {
public: static char * strToChar(std::string str);
};
converter.cpp
char * StringConverter::strToChar(std::string str)
{
return (char*)str.c_str();
}
usage
StringConverter::strToChar("converted string")
For completeness' sake, don't forget std::string::copy().
std::string str = "string";
const size_t MAX = 80;
char chrs[MAX];
str.copy(chrs, MAX);
std::string::copy() doesn't NUL terminate. If you need to ensure a NUL terminator for use in C string functions:
std::string str = "string";
const size_t MAX = 80;
char chrs[MAX];
memset(chrs, '\0', MAX);
str.copy(chrs, MAX-1);
You can make it using iterator.
std::string str = "string";
std::string::iterator p=str.begin();
char* chr = &(*p);
Good luck.
A safe version of orlp's char* answer using unique_ptr:
std::string str = "string";
auto cstr = std::make_unique<char[]>(str.length() + 1);
strcpy(cstr.get(), str.c_str());
char* result = strcpy((char*)malloc(str.length()+1), str.c_str());
Alternatively , you can use vectors to get a writable char* as demonstrated below;
//this handles memory manipulations and is more convenient
string str;
vector <char> writable (str.begin (), str.end) ;
writable .push_back ('\0');
char* cstring = &writable[0] //or &*writable.begin ()
//Goodluck
This will also work
std::string s;
std::cout<<"Enter the String";
std::getline(std::cin, s);
char *a=new char[s.size()+1];
a[s.size()]=0;
memcpy(a,s.c_str(),s.size());
std::cout<<a;
No body ever mentioned sprintf?
std::string s;
char * c;
sprintf(c, "%s", s.c_str());

How to store a const char* in std :: string?

char *buffer1 = "abc";
const char *buffer2 = (const char*) buffer;
std :: string str (buffer2);
This works, but I want to declare the std::string object i.e. str, once and use it many times to store different const char*.
What's the way out?
You can just re-assign:
const char *buf1 = "abc";
const char *buf2 = "def";
std::string str(buf1);
str = buf2; // Calls str.operator=(const char *)
Ah well, as I commented above, found the answer soon after posting the question :doh:
const char* g;
g = (const char*)buffer;
std :: string str;
str.append (g);
So, I can call append() function as many times (after using the clear()) as I want on the same object with "const char *".
Though the "push_back" function won't work in place of "append".
str is actually copying the characters from buffer2, so it is not connected in any way.
If you want it to have another value, you just assign a new one
str = "Hello";
Make a Class say MyString which compose String buffer.
Have a constant of that class.
and then u can reassign the value of the composed string buffer, while using the same constant.

What is the simplest way to convert a const char[] to a string in c++

Is there a simple way of creating a std::string out of an const char[] ?
I mean something simpler then:
std::stringstream stream;
stream << const_char;
std::string string = stream.str();
std::string has multiple constructors, one of which is string( const char* str );.
You can use it like this:
std::string myString(const_char);
You could also use assignment, if you need to set the value at some time later than when the variable is declared:
myString = const_char;
std::string has a constructor that takes a const char*, so you can just do:
const char* charArray;
std::string str(charArray);
std::string str = const_char;
Just use the std::string constructor. You can pass it a char*:
char* charArray = "My String";
std::string stdstr( charArray );