There are some questions on SO that are extremely similar:
How to convert pugi::char_t* to string
I have been struggling with this problem for awhile, and as a beginner I'm really not sure what else to do other than ask here so I am sorry if this counts as duplicate.
pugi::xml_node actors = source_file.child("scene").child("actors");
std::vector<const char*> actor_db;
for (pugi::xml_node actor = actors.first_child(); actor; actor = actor.next_sibling())
{
const char *a = *actor.child_value();
actor_db[actor.attribute("id").as_int()] = a;
}
a value of type "pugi::char_t" cannot be used to initialize an entity of type "const char *"
The line const char *a = *actor.child_value(); is my poor attempt to try to cast the return value of const char_t* xml_node::child_value() as a const char*.
I want the value of actor.child_value() to be stored in a const char* then put inside of the vector actor_db.
pugi::char_t is a type that is either a char or wchar_t depending on the configuration. I have set it up so that pugi::char_t will be a char.
I know this is probably a simple error, but even with my extensive searching and the similar SO questions I am still unable to resolve my issue.
I want the value of actor.child_value() to be stored in a const char* then put inside of the vector actor_db.
No, you don't. The only thing that can be stored "in" a const char* is the location of an array of characters. It's not actually a string, but a pointer to a string. Containers of pointers are fraught with problems.
Store a std::vector<std::string> instead then use the code in the answer1 to the question you linked to in order to obtain the std::strings.
1 Which, oddly enough, I've just noticed I wrote several years ago. :D
Related
I am currently writing code that will read an xml file using the pugixml module. In my xml file I have several shape nodes that are differentiated by a shape_id attribute that gets a number.
For a specific need I have the shape_id number stored in an integer although in xml file the value of the respective attribute is of course a string (or char, have to check).
In order to retrieve the specific shape node, e.g. that with the attribute shape_id = 2 (just to give an example) I have written the function below.
pugixml provides a function find_child_by_attribute() with this call definition:
PUGI__FN xml_node xml_node::find_child_by_attribute(const char_t* name_, const char_t* attr_name, const char_t* attr_value) const
As you can see it requests the attribute value as a char pointer.
I manage to make it work with the two lines as in the code:
char char_shape_id = static_cast<char>(shape_id);
char* shape_id_ptr = &char_shape_id;
First I cast the integer shape_id into a char and then I take the address of this char and store it into a char pointer. I think it is an awkward way to do but I cannot figure out how to do this in a more elegant way.
I've tried following but failed.
char* shape_id_ptr = &(static_cast<char>(shape_id));
This seems to be invalid code.
What seems also to work is when I have following function call in the return line:
return root_node.child(sNodeNames.case_def_name.c_str()).find_child_by_attribute(sNodeNames.shape_name.c_str(),"item_id", (char*)shape_id);
I also tried to have a unique_ptr or shared_ptr instead of the raw char pointer but somehow I cannot figure out how to make this pointer cooperate with the find_child_by_attribute(). My shared pointer definition is currently
char char_shape_id = static_cast<char>(shape_id);
std::shared_ptr<char> shape_id_ptr(&char_shape_id);
but as I said, this is not accepted by the function.
//returns the node shape with a given shape_id number
pugi::xml_node nXml::tXmlShape::GetShapeNode(const int shape_id, const pugi::xml_node& root_node)
{
char char_shape_id = static_cast<char>(shape_id);
char* shape_id_ptr = &char_shape_id;
nXml::sXmlNodeNames sNodeNames;
nXml::sXmlShapeTypes sShapeTypes;
return root_node.child(sNodeNames.case_def_name.c_str()).find_child_by_attribute(sNodeNames.shape_name.c_str(),"item_id", shape_id_ptr);
}
;
Apart from the pretty ugly return line phrasing is there a more elegant way to accomplish the transmission of a char pointer of an originally integer value to the function and how could I realize this with a unique_ptr respectively shared_ptr?
I tried to use a character Pointer go throw string character (iterate) but I found i can not say the below:
string Name = "Hello";
char *ch = Name;
like the previous statements i am getting error during execution.
However when I am doing like that:
char *ch = "Hello";
the program running without throwing any exception.
Why is that?
I have recently encountered similar problem and the simplest answer is that std::string is a different type from char*, more precisely std::string is an object which contains some characters (your text) and few methods, which allow you to do multiple operations with your text. You can imagine creating a class Integer for storing the value, but also a method allowing you to square and cube the number which is stored in the Ingerer class. Even though they could store the same numerical value, you will not be able to compare them (unless you overload the operator==), as their types are different.
If you wish to use the code you provided, you need to rewrite the second line as
const char *ch = Name.c_str();
it is allowed because std::string contains a method c_str() which "casts" itself to const char*. If you want to learn more about strings, be sure to visit C++ reference about strings.
So I have a string which contains "RGGB" and I need it to be in a char array to perform some operations. Then I need to replace certain characters for a blank space, for example the first 'G', so that my char array remains "R GB".
How can I do this? So far I tried this solution:
int main()
{
string problem="RGGB";
const char *p=problem.c_str();
p[1]=' ';
return p;
}
I get the error:
assignment of read only location *(p + ((sizetype)i))
To access the "interal string" (I mean a const char*) of a std::string, there are two member functions provided: std::string::c_str and std::string::data. Until C++11, the difference was that std::string::data wasn't bound to return a pointer to a null-terminated const char* while std::string::c_str was. Now, they are equivalent. And both return a const char*, even before C++11.
There are several approaches to your problem:
Use std::strdup or std::str(n)cpy to duplicate the string and write to the duplicate.
Use a const_cast. Pretty drastic, but, if it doesn't hurt any rules (FYI, it does), works.
Don't use std::string at all. Do what you want with a char* and then optionally convert it to a std::string later.
Just use the functionality of std::string.
string, a C++ class, does not provide directly alterable access to its innerds via a char *. While you could cast away the const, this is dangerous because compilers may use the const as an optimization path.
If you absolutely need to do this just use a char array, not a string or alter the contents of the string using string methods.
p[1]=' ';
is not valid as const char * is read-only pointer.
in other words, it is a const pointer.
remember:
When const appears to the left of the *, what's pointed to is constant, and if const appears to the right of the *, the pointer itself is constant. If const appears on both sizes, both are constants.
this code might work:
char problem[]="RGGB";
char* p = problem;
p[1]=' ';
cout<<problem;
The answer is in your question:
I need it to be in a char array
Then put it in a char array:
char problem[] = "RGGB";
problem[1] = ' ';
Problem solved.
If, on the other hand, you want to solve the problem using actual C++:
std::string problem = "RGGB";
problem.at(1) = ' ';
I am trying to make a new const char* b by adding a new string "hello" to original const char* a:
const char* a = some_code_here;
const char* b = (a + "_hello").c_str();
And the error I get is:
error: invalid operands of types const char* and const char [6] to binary operator+
Is there anything wrong I am doing?
Switch to strings, that is std::string.
Repeat after me, forget about using char or C-style strings.
As you have demonstrated, this is one of many issues.
Did I say switch to std::string?
Your char * is a pointer. Nothing more, nothing less, a pointer. A pointer to a single char; not a structure. The char data type doesn't have methods.
Switch to std::string.
You can add (concatenate) std::string.
Switch to std::string.
The std::string has the c_str() method. Don't use unless you understand the consequences; completely.
You can't arbitrarily add const char* in C++. These objects are just pointers to a contiguous section of memory, so adding them doesn't make sense. Instead, you should use the std::string class:
std::string a = "something";
std::string b = a + "_hello";
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What is the difference between char s[] and char *s in C?
Difference between char a[]=“string”; char *p=“string”;
Firstly, i would like to ask where can i learn all the basics of char* and char[].
Most of the time i find myself struggling with how to compare and how to declare.
Example 1 :
char *test = "hello world";
This will produce the following warning at compilation :
warning: deprecated conversion from string constant to ‘char*’
Example 2 :
vector<char*> test2;
test2.push_back("hello world");
This will produce an error of copying a string.
So the solution i come up with is :
(is this correct?)
vector<char*> test3;
char *str1 = "hello world"
test3.push_back(str1);
Thanks in advance! :)
============================================
Two good reads provided by people here :
What is the difference between char s[] and char *s?
Difference between char a[]="string"; char *p="string";
Your question "where can i learn all the basics of char* and char[]," is probably too general, but you can try reading the C++ spec.
Fix example 1 by changing it to
char const *test = "hello world";
Fix example 2 by changing it to
vector<std::string> test2;
test2.push_back("hello world");
Or if you really want a vector of non-owning pointers to c-strings:
vector<char const *> test2;
test2.push_back("hello world");
You can learn a lot about char*/char[] in your favorite book on C (not on C++, because C++ provides much better facilities for representing strings than C does).
The declaration/assignment
char *test = "hello world";
should be
const char *test = "hello world";
because string literals are pointers to constants. If you want a vector of strings in C++, you do it like this:
std::vector<std::string> test2;
test2.push_back("hello world");
This works, because string literals can be implicitly converted to std::string.
So the thing to remember is the difference between a pointer to a value and the value itself.
The value itself is the literal value that a variable represents as stored in memory.
A pointer is the address in memory that some value is stored at.
Pointers are useful because they allow you to access, change, and preserve changes in information across multiple functions / methods, which comes in handy when you realize you can only return one value from any function, but sometimes you want a lot more information than that.
The thing about arrays is that, while a lot of people don't realize this when first learning C++, they are pointers. A[0] isn't a variable, it's a pointer to a memory address. Arrays are handy because when declaring an array, you segment off a portion of memory reserved for use for that array. This is useful because it allows you to access the values stored in that block of memory very very quickly.
So really, there's not that much difference between declaring a pointer (char*) and an array (char[]) other than that the pointer will refer to a single location in memory while the array will refer to set of contiguous locations in memory.
To learn more about pointers and how to use them properly, visit http://www.cplusplus.com/doc/tutorial/pointers/ .