In C++, I'm trying to print the address of a C-string but there seems to be some problem with my cast. I copied the code from a book but it just doesn't compile on my mac.
const char *const word = "hello";
cout << word << endl; // Prints "hello"
cout << static_cast< void * >(word) << endl; // Prints address of word
You are trying to cast away "constness": word points to constant data, but the result of static_cast<void*> is not a pointer to constant data. static_cast will not let you do that.
You should use static_cast<const void*> instead.
There is a demo
#include <iostream>
int main() {
void* Name1;
Name1 = static_cast<void*>(new std::string("Client 1"));
void* Name2;
std::string str1 = "Client 2";
Name2 = &str1;
return 0;
}
Related
I want to change the characters in a string passed by user, converted into a C-style string and passed as an argument to a function with a char * argument:
#include <string>
#include <cstring>
#include <iostream>
#include <stdlib.h>
void functoupper(char *myString)
{
int i=0;
char z;
do {
z= myString[i];
myString[i]=toupper(z);
++i;
} while(myString[i]!=0);
}
int main() {
std::string name;
std::cout << "Please, enter your full name in small caps: ";
std::getline (std::cin,name);
const char *myString = name.c_str();
std::cout << "Hello, " << functoupper(myString) << "!\n";
return 0;
}
I get error error: invalid conversion from 'const char*' to 'char*' [-fpermissive] when calling function functoupper(myString) in main().
The std::string::c_str() method returns a pointer to const char data, but your function expects a pointer to non-const char data. That is why you are getting an error.
You could use const_cast to cast away the const (but that is not really advisable):
char *myString = const_cast<char*>(name.c_str());
functoupper(myString);
std::cout << "Hello, " << name << "!\n";
You could use the non-const std::string::operator[] to access the string's underlying character data (just be careful because prior to C++11, characters were not required to be stored contiguously in memory, but most std::string implementations did):
functoupper(&name[0]);
std::cout << "Hello, " << name << "!\n";
In C++17 and later, you can use the non-const std::string::data() method instead:
functoupper(name.data());
std::cout << "Hello, " << name << "!\n";
That being said, heed this warning when using toupper():
Like all other functions from <cctype>, the behavior of std::toupper is undefined if the argument's value is neither representable as unsigned char nor equal to EOF. To use these functions safely with plain chars (or signed chars), the argument should first be converted to unsigned char ... Similarly, they should not be directly used with standard algorithms when the iterator's value type is char or signed char. Instead, convert the value to unsigned char first
With that said, try something more like this:
#include <string>
#include <iostream>
#include <cctype>
void functoupper(char *myString)
{
for (int i = 0; myString[i] != '\0'; ++i) {
unsigned char z = static_cast<unsigned char>(myString[i]);
myString[i] = static_cast<char>(std::toupper(z));
}
}
int main() {
std::string name;
std::cout << "Please, enter your full name in small caps: ";
std::getline(std::cin, name);
functoupper(&name[0]); // or name.data()
std::cout << "Hello, " << name << "!\n";
return 0;
}
That being said, you should just pass the entire std::string as-is into your function instead, and then you can manipulate it as needed, for instance with the std::transform() algorithm:
#include <string>
#include <iostream>
#include <algorithm>
#include <cctype>
void functoupper(std::string &myString)
{
std::transform(myString.begin(), myString.end(), myString.begin(),
[](unsigned char ch){ return std::toupper(ch); }
);
}
int main() {
std::string name;
std::cout << "Please, enter your full name in small caps: ";
std::getline(std::cin, name);
functoupper(name);
std::cout << "Hello, " << name << "!\n";
return 0;
}
Alternatively:
#include <string>
#include <iostream>
#include <algorithm>
#include <cctype>
std::string functoupper(std::string myString)
{
std::transform(myString.begin(), myString.end(), myString.begin(),
[](unsigned char ch){ return std::toupper(ch); }
);
return myString;
}
int main() {
std::string name;
std::cout << "Please, enter your full name in small caps: ";
std::getline(std::cin, name);
std::cout << "Hello, " << functoupper(name) << "!\n";
return 0;
}
As #Someprogrammerdude and #RemyLebeau comment, why not simply:
std::transform(std::begin(name), std::end(name), std::begin(name),
[](const unsigned char c)
{
return std::toupper(c);
});
But if you must do it via a char*, then you'll need to copy the data over first, something like:
char myString* = new char[name.size() + 1];
strcpy(myString, name.c_str());
EDIT: Thanks to the helpful comments by #RemyLebeau
Better still avoid all the memory management issues with the above by simply coping your std::string into a std::vector:
std::vector<char> myVec(std::begin(name), std::end(name));
myVec.push_back(`\0`);
and then call your char* function with:
functoupper(myVec.data());
I'm trying to convert an std::string into a c string (my real problem is closer to this; I'm trying a workaround).
How does one store an std::string as a character array?
Why do std::string.data() and std::string.c_str() return char [(<anonymous> + 1)] instead of the expected const char*? Or do I have these mixed up, and if so, how do I work with these types?
#include <string>
#include <iostream>
int main()
{
std::string sstring = "I'm an std string!";
char cstring[sstring.size()];
cstring = sstring.c_str();
std::cout << std::string(sstring.c_str());
return 0;
}
Compilation results in
scratch.cpp:10:11: error: incompatible types in assignment of ‘const char*’ to ‘char [(<anonymous> + 1)]’
I wasn't able to find a relevant, preexisting question.
Just use a const char *
std::string sstring = "I'm an std string!";
const char * cstring = sstring.c_str();
std::cout << cstring << std::endl;
As mentioned in the comments, this sound like an XY problem. But if you simply want to copy the string you can do it like so:
char cstring[sstring.size() + 1];
strcpy(cstring, sstring.c_str());
Just be aware that VLAs are not a part of C++ but g++ will 'go with it', see answers here.
A working way to assign your string to a char array is the following:
#include <iostream>
#include <string>
int main(int argc, char **argv) {
std::string s = "HELLO WORLD!";
char *cs = (char *)s.c_str();
std::cout << cs << '\n' << std::string(cs) << '\n';
return 0;
}
OUTPUT:
This works because it casts the const char * to char * and therefore allows the assignment to go through, and although this may not be the best way it is very simple.
I am trying to return a C string from a function. The function is suppose to concatinate the 3 integers with commas and return the result as a char array however I'm getting garbage values. I'm assuming I'm not calling malloc correctly. Can someone advise on what's the problem?
using namespace std;
const char * createCommand(int p1, int p2, int p3){
stringstream sstm;
std::string comma = ",";
sstm << p1 << comma << p2 << comma << p3;
std::string str = sstm.str();
const char *cstr = (const char *)malloc( (str.length()+1) * sizeof (char));
cstr = str.c_str();
return cstr;
}
int main() {
const char *cstr2 = createCommand(1,0,250); //I want to return "1,0,250"
printf("char = %s\n",cstr2);
}
Since the other two answers already gave responses to the tune of dealing with the literal problem, I'm going to instead advise on what I consider a pretty significant design flaw causing your problem: returning c-strings.
In the example code you're providing, the use of c-strings at all makes no sense. The following code will achieve what you intend to do with no difficulty or problematic code:
std::string createCommand(int p1, int p2, int p3){
std::stringstream sstm;
std::string comma = ",";
sstm << p1 << comma << p2 << comma << p3;
return sstm.str();
}
int main() {
std::string command = createCommand(1,0,250); //I want to return "1,0,250"
std::cout << "char = " << command << "\n";
}
Even if you're confined to using printf instead of the C++ iostreams library, this design is still better:
std::string createCommand(int p1, int p2, int p3){
std::stringstream sstm;
std::string comma = ",";
sstm << p1 << comma << p2 << comma << p3;
return sstm.str();
}
int main() {
std::string command = createCommand(1,0,250); //I want to return "1,0,250"
printf("char = %s\n", command.c_str());
}
And if you need the c-string passed to some older, C-based library, this design will still suffice. The point being, there's no reason to use malloc or interface with the underlying c-string representation except through the string itself.
Assignment operator, which works fine for std::string and other objects, cannot have an override for pointers. Therefore, the assignment
cstr = str.c_str();
leaks the memory that you have allocated, and replaces the pointer with the data from the string. Moreover, the pointer that your function returns now, points into memory that is invalidated upon exiting the function, creating an undefined behavior in addition to a leak.
To fix this problem, call std::strcpy(cstr, str.c_str()); Don't forget to call std::free on the result of the call. Edit: you should remove const from the return type of your createCommand function (WhozCraig, thank you for the comment).
Note: I assume that this is only an exercise in using malloc, that you know that using new[] is preferable, and that you wouldn't have to do any of the above if you could return std::string from the function.
You'll need to copy the string with some form of strcpy, before returning the pointer.
const char * createCommand(int p1, int p2, int p3){
stringstream sstm;
std::string comma = ",";
sstm << p1 << comma << p2 << comma << p3;
std::string str = sstm.str();
const char *cstr = (const char *)malloc( (str.length()+1) * sizeof (char));
strcpy(cstr, str.c_str());
return cstr;
}
# include <iostream>
# include <string.h>
using namespace std;
int main()
{
int a=10;
int b=20;
char op[10];
const char p='+';
cout<<"enter the operation"<<endl;
cin>>op;
if(!strcmp(op,p)==0)
{
cout<<a+b;
}
return 0;
}
compilation result
12 17 C:\Users\DELL\Documents\cac.cpp [Error] invalid conversion from 'char' to 'const char*' [-fpermissive]
I am a beginner. Please tell me what mistake have I done.
This isn't about the difference between char and const char, but between char [] and char.
strcmp expects two character arrays.
op is an array of (10) characters. Good: that's what strcmp expects.
p is a single character. Not good: strcmp needs a char array, and p isn't any kind of array, but a single character.
You can change p from a single char '+' to a char array "+", or compare only the 0th character of op, as suggested in a comment above.
there is no version of strcmp that takes a single character as a parameter but instead it takes two string and compares them.
if you want to compare a single char variable with a string you can compare it with the first element of string or with any other element:
#include <iostream>
#include <string>
int main()
{
char op[10] = "Hi";
const char p = '+';
// if( strcmp( op, p) ) // error cannot covert parameter 2 from char to const char*
// cout << "op and p are identic" << std::endl;
// else
// std::cout << "op and b are not identic" << std::endl;
if(op[0] == p)
std::cout << "op[0] and p are identic" << std::endl;
else
std::cout << "op[0] and p are not identic" << std::endl;
const char* const pStr = "Bye"; //constant pointer to constant character string: pStr cannot change neither the address nor the value in address
const char* const pStr2 = "bye"; // the same as above
// pStr++; //error
// pStr[0]++; // error
if( !strcmp( pStr, pStr2) )
std::cout << "pStr and pStr2 are identic" << std::endl;
else
std::cout << "pStr and pStr2 are Not identic" << std::endl;
return 0;
}
i have a pointer or variable which stores the address like 0xb72b218 now i have to store this value in to const char*. how i can store it. Thanks in advance.
I tried following:
suppose i have a pointer variable "ptr" which contains 0xb72b218 value
ostringstream oss;
oss << ptr;
string buf = oss.str();
const char* value = buf.c_str();
but it is more complicated any one know easy way.
Well... if you really want the address of something in a string, this will do:
#include <stdio.h>
#include <iostream>
int main(){
char buf[30];
void* ptr = /*your pointer here*/;
snprintf(buf,sizeof(buf),"%p",ptr);
std::cout << "pointer as string: " << buf << "\n";
std::cout << "pointer as value: " << ptr << "\n";
}
Or if you don't like magic numbers and want your code to work even when 256bit pointers are nothing special anymore, try this:
#include <limits> // for numeric_limits<T>
#include <stdint.h> // for intptr_t
#include <stdio.h> // for snprintf
#include <iostream>
int main(){
int i;
int* ptr = &i; // replace with your pointer
const int N = std::numeric_limits<intptr_t>::digits;
char buf[N+1]; // +1 for '\0' terminator
snprintf(buf,N,"%p",ptr);
std::cout << "pointer as string: " << buf << "\n";
std::cout << "pointer as value: " << static_cast<void*>(ptr) << "\n";
}
Example on Ideone.
OK, presumably there must some additional parameter that tells the function what type of data is actually being passed, but you can do it like this:
extern void afunc(const char *p, int type);
int value = 1234;
afunc((const char *)&value, TYPE_INT);
Have you looked at const_cast? It is a means of adding/removing const-ness from a variable in C++. Take a look here.