This is a little hard I can't figure it out.
I have an int and a string that I need to store it as a char*, the int must be in hex
i.e.
int a = 31;
string str = "a number";
I need to put both separate by a tab into a char*.
Output should be like this:
1F a number
With appropriate includes:
#include <sstream>
#include <ostream>
#include <iomanip>
Something like this:
std::ostringstream oss;
oss << std::hex << a << '\t' << str << '\n';
Copy the result from:
oss.str().c_str()
Note that the result of c_str is a temporary(!) const char* so if your function takes char * you will need to allocate a mutable copy somewhere. (Perhaps copy it to a std::vector<char>.)
Try this:
int myInt = 31;
const char* myString = "a number";
std::string stdString = "a number";
char myString[100];
// from const char*
sprintf(myString, "%x\t%s", myInt, myString);
// from std::string :)
sprintf(myString, "%x\t%s", myInt, stdString.c_str());
#include <stdio.h>
char display_string[200];
sprintf(display_string,"%X\t%s",a,str.c_str());
I've used sprintf to format your number as a hexadecimal.
str.c_str() will return a null-terminated C-string.
Note: not answering the main question since your comment indicated it wasn't necessary.
those who write "const char* myString = "a number";"
are just lousy programmers. Being not able to get the C basics - they rush into C++ and start speaking about the things they just don't understand.
"const char *" type is a pointer.
"a number" - is array. You mix pointers and arrays. Yes, C++ compilers sometimes allow duct typing. But you must also understand - if you do duct typing not understanding where your "ductivity" is - all your program is just a duct tape.
Related
I am practicing some work with cstring and string.
Going from string to cstring using c_str() I get an incompatible data type compile error.
For example this is the code that gives said error:
string str = "StackOverFlow";
char inCstring[20]{};
inCstring = str.c_str();
Any ideas?
The problem is that str.c_str() returns a const char*, and you are trying to pass it to a char*. Use strcpy to get your expected result:
#include <iostream>
#include <cstring>
#include <string>
using namespace std;
int main()
{
string str = "StackOverFlow";
char inCstring[20];
strcpy(inCstring, str.c_str());
cout << "str: " << str << endl;
cout << "inCstring: " << inCstring << endl;
return 0;
}
So I have figured out two ways to accomplish this.
First, it is important to remember that you can't assign to a whole array, meaning it is necessary to specify the element of the array to assign to. Attempting to assign a string to char array simply will not work for this reason. That being said, by specifying the element it would be possible to assign a character in a specific element of a char array. Below are two methods that accomplish a string to cstring(string to char array) "conversion". Please see answer by Vincent for complete code. I have found Method B better since I would like to have max size on my character array.
Method A:
string str = "StackOverFlow";
const char* inCstring;
inCstring = str.c_str();
Method B:
string str = "StackOverFlow";
char inCstring[20]{};
Then use strcpy
strcpy(inCstring, str.c_str());
std::string mystring;
sprintf(mystring.c_str(), "%s %d", "Helloworld", 2014);
Its is giving a compiler error to me:
'sprintf' : cannot convert parameter 1 from 'const char *' to 'char *'
It shouldn't be a warning, it should be an error. The pointer
returned by std::string::c_str() points to read-only memory;
any attempt to write through it is undefined behavior. (In your
case, if you use a const_cast to shut up the compiler, you're
code will probably crash, since you're calling c_str() on an
empty strying.)
Generally speaking, what you probably want is
std::ostringstream:
std::ostringstream formatter;
formatter << "Helloworld" << ' ' << 2014;
std::string myString = formatter.str();
FWIW: sprintf is one of the most dangerous functions in the
standard library, and only present for historical reasons. It's
almost impossible to use safely; even in C, you should prefer
snprintf (but in C++, std::ostringstream is far better).
your warning gives you all information you need.
std::string::c_str() returns a const char* and sprintf requires a char* since it modiefies the buffer.
But you are writing c++ and should avoid sprintf. Use a ostringstream to write formated data to a string.
std::string manages underlying C-style buffer. c_str returns const char* because it shouldn't be modified by anything other then string's methods.
You should rather use ostringstream. See this question: C++ equivalent of sprintf?
You are telling sprintf to store the result in mystring.c_str(). This is a readonly view of the underlying representation of mystring. Since it is readonly (or const char *), you can't write the result to it.
If you need to use sprintf, you will have to create a writable character buffer for it to use, and then assign that buffer to mystring.
A different way of performing this sort of operation without having to create character buffers and deal with possible overflow would be to use a stringstream:
std::stringstream buffer;
buffer << "Helloworld " << 2014;
mystring = buffer.str();
Alternatively, use old C snprintf into a temporary buffer, then assign into the string :
std::string mystring;
char buf[64];
snprintf(buf, sizeof(buf), "%s %d", "Helloworld", 2014);
mystring.assign(buf);
snprintf is always safer than sprintf since it avoids buffer overflow.
But of course using an ostringstream like answered here by James Kanze is better.
#include <iostream>
#include <string>
#include <sstream>
std::stringstream ss;
ss << "Helloworld";
ss << " ";
ss << "2014";
ss << std::endl;
std::string str = ss.str();
std::cout << str;
const char * mystring= str.c_str();
In this way also you can append int or long number into the string.
Example:
long year = 2014;
std::stringstream ss;
ss << "Helloworld";
ss << " ";
ss << year;
ss << std::endl;
std::string str = ss.str();
std::cout << str;
const char * mystring= str.c_str();
I have doubts regarding following statments;
int intvalue = 3;
int *pointInt = &intvalue;
char* p = "string";
cout << pointInt << std::endl; // this will give memory location of intvalue which is ok.
cout << p<< std::endl; // why this will give string value rather than memory location of where string is stored?
Because there is an overload of std::ostream& operator<<(std::ostream&, const char*), which assumes the char* is the first element of a null-terminated string and prints out the whole string.
You can have a lot of fun by attempting to stream a char* that is not the first element of a null-terminated string:
#include <iostream>
int main()
{
char c = 'x';
std::cout << &c << std::endl;
}
char* and const char* are most commonly used to point to C-style null-terminated strings. The standard I/O library takes this into account when being passed one of those types to insert from or extract into. The functions were simply designed to have this special case based on how common it is to want to print out a C-style string.
To get the pointer value, you can try casting to a different pointer type:
std::cout << static_cast<void*>(p) << std::endl;
keyword operator overloading - simply another method of the iostream instance std::cout is responsible for chars and handles that differently. The exact implementation could also yield "Hello World"
cout << (void *) p << std::endl;
I expect it's because << operator has a specific override for char* argument, to output the string.
This is operator<<() overload for the type of the cout object as first parameter and type char* or const char* as second.
There are many such overloads, and you can write some too.
And the reason for this particular overload is to "print" C-style string (null-terminated array of char)
I have executed the below code and it works perfectly. Since it is about pointers, I just want to be sure. Though I'm sure that assigning char* to string makes a copy and even if I delete char*, string var is gonna keep the value.
#include <stdio.h>
#include <string.h>
#include <string>
#include <iostream>
int main()
{
std::string testStr = "whats up ...";
int strlen = testStr.length();
char* newCharP = new char[strlen+1];
memset(newCharP,'\0',strlen+1);
memcpy(newCharP,testStr.c_str(),strlen);
std::cout << " :11111111 : " << newCharP << "\n";
std::string newStr = newCharP ;
std::cout << " 2222222 : " << newStr << "\n";
delete[] newCharP;
newCharP = NULL;
std::cout << " 3333333 : " << newStr << "\n";
}
I'm just changing some code in my company project and char* are passed between functions in C++. The char* pointer has been copied to the string, but the char* is deleted in the end of the function. I couldn't find any specific reason for this. So I'm just deleting the char*, as soon as it is copied into a string. Would this make any problem ...?
P.S : I have already asked this question in Codereview , but I got suggestion to move it to SO. So i have flagged it for close there and posting the question here.
No, because std::string copies the contents of your char*, so you're free to delete it when you no longer need it.
There is no problem, as long as newChar points to a null-terminated string, and is not null itself.
std::string has constructor that allows an implicit construction from a const char*. It makes a copy of the character string represented by the input const char * so it works under the assumption that the char* is a null terminated string, since there is no other way to know how many characters to copy into the string's own data storage. Furthermore, a NULL pointer is actually disallowed by the standard.
The code is fine, if you look at the constructors of std::basic_string here you'll be able to deduce that std::string has two interesting constructors here:
(4) string(char const*,
size_type count,
Allocator const& alloc = Allocator() );
(5) string(char const* s,
Allocator const& alloc = Allocator() );
Both perform a copy, and the first reads exactly count characters whilst the second reads up until it encounters a NUL-character.
That being said, I actively encourage you not to use dynamic allocation here. If you want a temporary buffer to play with, consider using std::vector instead.
#include <stdio.h>
#include <string.h>
#include <string>
#include <iostream>
int main()
{
std::string testStr = "whats up ...";
unsigned strlen = testStr.length();
std::vector<char> buffer(strlen+1);
memset(&buffer[0],'\0',strlen+1);
memcpy(&buffer[0], testStr.c_str(), strlen);
std::cout << " :11111111 : " << &buffer[0] << "\n";
std::string newStr(&buffer[0]);
std::cout << " 2222222 : " << newStr << "\n";
buffer.clear();
std::cout << " 3333333 : " << newStr << "\n";
}
Note: both vector and string have range-constructors, to build them from a range of iterators, that I purposefully refrained from using to avoid confusion and you being overwhelmed. Just know that you could have used them to avoid calling memcpy and risking a buffer overflow though.
When I create something like
char* t = new char[44];
t = strcpy(s,t);
then strlen(t); return some wrong results. how I can change this?
Both strcpy and strlen expect to find the special character NUL or '\0' in the array. An uninitialized array, as the one you've created, may contain anything at all, which means the behavior of your program is undefined when it is passed to strcpy as the source argument.
Assuming the goal was to copy s into t, to make the program behave as expected, try this:
#include <iostream>
#include <cstring>
int main()
{
const char* s = "test string";
char* t = new char[44];
// std::strcpy(t, s); // t is the destination, s is the source!
std::strncpy(t, s, 44); // you know the size of the target, use it
std::cout << "length of the C-string in t is " << std::strlen(t) << '\n';
delete[] t;
}
But keep in mind that in C++, strings are handled as objects of type std::string.
#include <iostream>
#include <string>
int main()
{
const std::string s = "test string";
std::string t = s;
std::cout << "length of the string in t is " << t.size() << '\n';
}
What are you trying to do? Do you want to copy from s to t? If so, the arguments to strcpy are reversed.
char* t = new char[44]; // allocate a buffer
strcpy(t,s); // populate it
Such C-style string processing is a red flag, but that's all I can say given this little information.
This code might be helpful:
char * strcpy (char * destination, const char * source);
t = strcpy(t, s);
You have to initialize the variable t
Do something like this:
char *t = new char[44];
memset(t, 0, 44);
// strlen(t) = 0
The strcpy function is described thus:
#include <string.h>
char *strcpy(char *dest, const char *src);
The strcpy() function copies the string pointed to by src (including the terminating '\0' character) to the array pointed to by dest.
So, if you are trying to fill in your newly allocated array, you should be doing:
strcpy(t, s);
Not the other way around.