I need a way to get this PHP behaviour in C++:
$foo = "PHP";
$bar = "this is a " . $foo . " example.";
Is there something close to that, or do I have to do lots of strcat?
Easy enough with std::string:
std::string foo = "C++";
auto bar = "this is a " + foo + " example.";
Just make sure one of the first two operands is a std::string, not both const char * or something.
As noted below, this result is being used in CreateProcess as a char * (LPSTR) argument. If the argument was const char *, c_str() would be perfectly acceptable to pass in. However, it is not, which means you should assume it modifies the string. MSDN says this:
The Unicode version of this function, CreateProcessW, can modify the contents of this string.
Since this is char *, it's evidently using CreateProcessA, so I'd say a const_cast<char *> should work, but it's better to be safe.
You have two main options, one for C++11 and later, and one for pre-C++11.
C++11
std::string's internal buffer is now guaranteed to be contiguous. It's also guaranteed to be null-terminated. That means you can pass a pointer to the first element:
CreateProcess(..., &str[0], ...);
Make sure the function only overwrites indices within [0, size()) in the internal array. Overwriting the guaranteed null-terminator is not good.
C++03
std::string is not guaranteed to be contiguous or null-terminated. I find it best to make a temporary std::vector, which guarantees the contiguous part, and pass a pointer to its buffer:
std::vector<char> strTemp(str.begin(), str.end());
strTemp.push_back('\0');
CreateProcess(..., &strTemp[0], ...);
Also note MSDN again:
The system adds a terminating null character to the command-line string to separate the file name from the arguments. This divides the original string into two strings for internal processing.
That seems to suggest that the null-terminator here isn't necessary, but there's no size parameter, so I'm not completely sure.
Yes, you can use std::string:
std::string foo = "PHP";
std::string bar = std::string("This is a") + foo + std::string(" example.")
In C++, you can use std::string:
std::string foo = "C++"
std::string bar = std::string("this is a") + foo + " example.";
You need the std::string(...) to make the first string into a std::string, since otherwise it's a const char *, which doesn't have operator+ to join it with string.
There are probably at least 5 other possible ways to do this, like almost always in C++.
[Again being too slow in my typing]
C++ provides the string class.
string foo = "PHP";
string bar = string("this is a ") + foo + string(" example.");
You can use std::string for this. So try this:
#include <string>
int main() {
std::string foo = "C++";
std::string bar = "this is a " + foo + " example.";
return 0;
}
If you are using C++ with the standard C++ library, you can use a std::stringstream to accomplish that. The code would look something like this:
#include <sstream>
std::string const foo("C++");
std::stringstream bar;
bar << "this is a " << foo << " example";
std::string const result(bar.str());
If for some reason you cannot use the C++ standard library you are unfortunately stuck with the likes of strcat.
Related
In the following code:
#include <string>
using namespace std;
int main(){
char command[300];
string stringz = "mystringy";
sprintf(command,"echo \"something with a string %s\" ", stringz);
system(command);
return 0;
}
why is the output
something with a string 8�
rather than the expected
something with a string mystringy
A silly question, but I couldn't find an answer around.
The '%s' modifier of printf takes a char*, not a std::string.
You can write:
sprintf(command,"echo \"something with a string %s\" ", stringz.c_str());
Which gives you a const char* to the contents of a std::string. This shows one of the major weaknesses of sprintf -- no type checking!
sprintf format %s expects a C string, that's a 0-terminated array of char, not a std::string.
stringz.c_str() and since C++11 &stringz[0] and stringz.data() are a few ways to get at the C string held by the std::string.
To add on Deduplicator answer, try putting
sprintf(command,"echo \"something with a string %s\" ", stringz.c_str());
and you should be set.
This is because sprintf is expecting a char * as an argument to expand the %s token. It would work like
sprintf(command,"echo \"something with a string %s\" ", stringz.c_str());
Which passes the "char *" version of the string to sprintf.
The reason why it shows those strange characters is because the whole std::string object is copied into sprintf's stack frame. Then, sprintf, which accepts variable number of arguments, looks into its own stack space and assumes that what it is going to find there is a char *, but actually is some garbage that results from reinterpreting the string data as char *, and when it is dereferenced, it results into that sequence. It could as well segfault if you are unlucky.
You should not use sprintf in the first place. This is C++, not C. std::string supports concatenation in a very natural way, with the + operator, like in some other programming languages:
#include <string>
int main(){
std::string stringz = "mystringy";
std::string command = "echo \"something with a string " + stringz + "\" ";
system(command.c_str());
return 0;
}
If you insist on using char-array functions like sprintf, use stringz.c_str(). As a matter of fact, this is also what system requires. But note how my example converts the string only at the last possible occasion.
You can use:
sprintf(command,"echo \"something with a string %s\" ", stringz.c_str());
Note that %s takes the C strings and not std::string.
Better still use, iostreams:
string stringDemo("MYSTRING");
std::cout << stringDemo << "\n";
I want to begin with saying that I have worked with pointers before and I assumed I understood how they worked. As in,
int x = 5;
int *y = &x;
*y = 3;
std::cout << x; // Would output 3
But then I wanted to make a method which modifies a rather large string and I believe therefore it would be better to pass a reference to the string in order to avoid passing the entire string back and fourth. So I pass my string to myFunc() and I do the same thing as I did with the numbers above. Which means I can modify *str as I do in the code below. But in order to use methods for String I need to use the -> operator.
#include <iostream>
#include <string>
int myFunc(std::string *str) { // Retrieve the address to which str will point to.
*str = "String from myFunc"; // This is how I would normally change the value of myString
str->replace(0, 1, "s"); // Replacing index 0 with a lowercase s.
return 0;
}
int main() {
std::string myString << "String from main";
myFunc(&myString); // Pass address of myString to myFunc()
}
My questions are:
Since str in myFunc is an address, why can an address use an
operator such as -> and how does it work? Is it as simple as the
object at the address str's method is used? str->replace(); // str->myString.replace()?
Is this a good implementation of modifying a large string or would it better to pass the string to the method and return the string when its modified??
ptr->x is identical to (*ptr).x unless -> is overridden for a type you're dereferencing. On normal pointers, that works as you'd expect it to.
As for implementation, profile it when you implement it. You can't know what compiler will do with this once you turn optimizations on. For example, if given function gets inlined, you won't even have any extra indirection in the first place and it won't matter which way you do it. As long as you don't allocate a new string, differences should generally be negligible.
str is a pointer to std::string object. The arrow operator, ->, is used to dereference the pointer and then access its member. Alternatively, you can also write (*str).replace(0,1,"s"); here, * dereferences the pointer and then . access the member function replace().
Pointers are often confusing; it is better to use references when possible.
void myFunc(std::string &str) { // Retrieve the address to which str will point to.
str = "String from myFunc"; // This is how I would normally change the value of myString
str.replace(0, 1, "s"); // Replacing index 0 with a lowercase s.
}
int main() {
std::string myString = "String from main";
myFunc(myString); // Pass address of myString to myFunc()
}
Is this a good implementation of modifying a large string or would it better to pass the string to the method and return the string when its modified??
If you don't want to change the original string then create a new string and return it.
If it's ok for your application to modify the original string then do it. Also you can return a reference to a modified string if you need to chain function calls.
std::string& myFunc(std::string &str) { // Retrieve the address to which str will point to.
str = "String from myFunc"; // This is how I would normally change the value of myString
return str.replace(0, 1, "s"); // Replacing index 0 with a lowercase s.
}
Is there an exact equivalent to strncpy in the C++ Standard Library? I mean a function, that copies a string from one buffer to another until it hits the terminating 0? For instance when I have to parse strings from an unsafe source, such as TCP packets, so I'm able to perform checks in length while coping the data.
I already searched a lot regarding this topic and I also found some interesting topics, but all of those people were happy with std::string::assign, which is also able to take a size of characters to copy as a parameter. My problem with this function is, that it doesn't perform any checks if a terminating null was already hit - it takes the given size serious and copies the data just like memcpy would do it into the string's buffer. This way there is much more memory allocated and copied than it had to be done, if there were such a check while coping.
That's the way I'm working around this problem currently, but there is some overhead I'd wish to avoid:
// Get RVA of export name
const ExportDirectory_t *pED = (const ExportDirectory_t*)rva2ptr(exportRVA);
sSRA nameSra = rva2sra(pED->Name);
// Copy it into my buffer
char *szExportName = new char[nameSra.numBytesToSectionsEnd];
strncpy(szExportName,
nameSra.pSection->pRawData->constPtr<char>(nameSra.offset),
nameSra.numBytesToSectionsEnd);
szExportName[nameSra.numBytesToSectionsEnd - 1] = 0;
m_exportName = szExportName;
delete [] szExportName;
This piece of code is part of my parser for PE-binaries (of the routine parsing the export table, to be exact). rva2sra converts a relative virtual address into a PE-section relative address. The ExportDirectory_t structure contains the RVA to the export name of the binary, which should be a zero-terminated string. But that doesn't always have to be the case - if someone would like it, it would be able to omit the terminating zero which would make my program run into memory which doesn't belong to the section, where it would finally crash (in the best case...).
It wouldn't be a big problem to implement such a function by myself, but I'd prefer it if there were a solution for this implemented in the C++ Standard Library.
If you know that the buffer you want to make a string out of has at least one NUL in it then you can just pass it to the constructor:
const char[] buffer = "hello\0there";
std::string s(buffer);
// s contains "hello"
If you're not sure, then you just have to search the string for the first null, and tell the constructor of string to make a copy of that much data:
int len_of_buffer = something;
const char* buffer = somethingelse;
const char* copyupto = std::find(buffer, buffer + len_of_buffer, 0); // find the first NUL
std::string s(buffer, copyupto);
// s now contains all the characters up to the first NUL from buffer, or if there
// was no NUL, it contains the entire contents of buffer
You can wrap the second version (which always works, even if there isn't a NUL in the buffer) up into a tidy little function:
std::string string_ncopy(const char* buffer, std::size_t buffer_size) {
const char* copyupto = std::find(buffer, buffer + buffer_size, 0);
return std::string(buffer, copyupto);
}
But one thing to note: if you hand the single-argument constructor a const char* by itself, it will go until it finds a NUL. It is important that you know there is at least one NUL in the buffer if you use the single-argument constructor of std::string.
Unfortunately (or fortunately), there is no built in perfect equivalent of strncpy for std::string.
The std::string class in STL can contain null characters within the string ("xxx\0yyy" is a perfectly valid string of length 7). This means that it doesn't know anything about null termination (well almost, there are conversions from/to C strings). In other words, there's no alternative in the STL for strncpy.
There are a few ways to still accomplish your goal with a shorter code:
const char *ptr = nameSra.pSection->pRawData->constPtr<char>(nameSra.offset);
m_exportName.assign(ptr, strnlen(ptr, nameSra.numBytesToSectionsEnd));
or
const char *ptr = nameSra.pSection->pRawData->constPtr<char>(nameSra.offset);
m_exportName.reserve(nameSra.numBytesToSectionsEnd);
for (int i = 0; i < nameSra.numBytesToSectionsEnd && ptr[i]; i++)
m_exportName += ptr[i];
Is there an exact equivalent to strncpy in the C++ Standard Library?
I certainly hope not!
I mean a function, that copies a string from one buffer to another until it hits the terminating 0?
Ah, but that's not what strncpy() does -- or at least it's not all it does.
strncpy() lets you specify the size, n, of the destination buffer, and copies at most n characters. That's fine as far as it goes. If the length of the source string ("length" defined as the number of characters preceding the terminating '\0') exceeds n, the destination buffer is padded with additional \0's, something that's rarely useful. And if the length if the source string exceeds n, then the terminating '\0' is not copied.
The strncpy() function was designed for the way early Unix systems stored file names in directory entries: as a 14-byte fixed-size buffer that can hold up to a 14-character name. (EDIT: I'm not 100% sure that was the actual motivation for its design.) It's arguably not a string function, and it's not just a "safer" variant of strcpy().
You can achieve the equivalent of what one might assume strncpy() does (given the name) using strncat():
char dest[SOME_SIZE];
dest[0] = '\0';
strncat(dest, source_string, SOME_SIZE);
This will always '\0'-terminate the destination buffer, and it won't needlessly pad it with extra '\0' bytes.
Are you really looking for a std::string equivalent of that?
EDIT : After I wrote the above, I posted this rant on my blog.
There is no built-in equivalent. You have to roll your own strncpy.
#include <cstring>
#include <string>
std::string strncpy(const char* str, const size_t n)
{
if (str == NULL || n == 0)
{
return std::string();
}
return std::string(str, std::min(std::strlen(str), n));
}
The string's substring constructor can do what you want, although it's not an exact equivalent of strncpy (see my notes at the end):
std::string( const std::string& other,
size_type pos,
size_type count = std::string::npos,
const Allocator& alloc = Allocator() );
Constructs the string with a substring [pos, pos+count) of other. If count == npos or if the requested substring lasts past the end of the string, the resulting substring is [pos, size()).
Source: http://www.cplusplus.com/reference/string/string/string/
Example:
#include <iostream>
#include <string>
#include <cstring>
int main ()
{
std::string s0 ("Initial string");
std::string s1 (s0, 0, 40); // count is bigger than s0's length
std::string s2 (40, 'a'); // the 'a' characters will be overwritten
strncpy(&s2[0], s0.c_str(), s2.size());
std::cout << "s1: '" << s1 << "' (size=" << s1.size() << ")" << std::endl;
std::cout << "s2: '" << s2 << "' (size=" << s2.size() << ")" << std::endl;
return 0;
}
Output:
s1: 'Initial string' (size=14)
s2: 'Initial string' (size=40)
Differences with strncpy:
the string constructor always appends a null-terminating character to the result, strncpy does not;
the string constructor does not pad the result with 0s if a null-terminating character is reached before the requested count, strncpy does.
Use the class' constructor:
string::string str1("Hello world!");
string::string str2(str1);
This will yield an exact copy, as per this documentation: http://www.cplusplus.com/reference/string/string/string/
std::string has a constructor with next signature that can be used :
string ( const char * s, size_t n );
with next description:
Content is initialized to a copy of the string formed by the first n characters in the array of characters pointed by s.
I have char* which is of fixed (known) width but is not null terminated.
I want to pass it into LOG4CPLUS_ERROR("Bad string " << char_pointer); but as its not null terminated it will print it all.
Any suggestions of some light weight way of getting "(char[length])*char_pointer" without performing a copy?
No, you'll have to deep-copy and null-terminate it. That code expects a null-terminated string and it means a contiguous block of characters ending with a null terminator.
If your goal is to print such a string, you could:
Store the last byte.
Replace it with \0.
Print the string.
Print the stored byte.
Put the stored byte back into the last position of the string.
Wrap all this in a function.
Real iostreams
When you're writing to a real iostream, then you can just use ostream.write() which takes a char* and a size for how many bytes to write -- no null termination necessary. (In fact, any null characters in the string would be written to the ostream, and would not be used to determine the size.)
Logging libraries
In some logging libraries, the stream that you write to is not a real iostream. This is the case in Log4CPP.
However, in Log4CPlus which is what it appears matt is using, the object that you're writing to is a std::basic_ostringstream<tchar> (see loggingmacros.h and streams.h for the definition, since none of this is obvious from the documentation). There's just one problem: in the macro LOG4CPLUS_ERROR, the first << is already built into the macro, so he won't be able to call LOG4CPLUS_ERROR(.write(char_pointer,length)) or anything like that. Unfortunately, I don't see an easy way around this without deconstructing the LOG4CPLUS_ERROR error macro and getting into the internals of Log4CPlus
Solution
I'm not sure why you're trying to avoid copying the string at this point, since you can see that there's a lot of copying going on inside the logging library. Any attempt to avoid that extra string copy is probably unwarranted optimization.
I'm going to assume that it's an issue of code cleanliness, and maybe an issue of making sure the copy happens inside the LOG4CPLUS_ERROR macro, as opposed to outside it. In that case, just use:
LOG4CPLUS_ERROR("Bad string " << std::string(char_pointer, length));
We're getting hung up on the semantics of conversion between char* and char[]. Take a step back, what are you trying to do? If this is a simple case of on an error condition, streaming out the content of a structure to a stream, why not do it properly?
e.g.
struct foo
{
char a1[10];
char a2[10];
char a3[10];
char a4[10];
};
// free function to stream the above structure properly..
std::ostream operator<<(std::ostream& str, foo const& st)
{
str << "foo::a1[";
std::copy(st.a1, st.a1 + sizeof(st.a1), std::ostream_iterator<char>(str));
str << "]\n";
str << "foo::a2[";
std::copy(st.a2, st.a2 + sizeof(st.a2), std::ostream_iterator<char>(str));
str << "]\n";
:
return str;
}
Now you can simply stream out an instance of foo and don't have to worry about null terminated string etc.!
I keep a string reference class in my toolkit just for these type of situations. Here is a greatly abbreviated version of that class. I trimmed away anything that is not relevant to this particular problem:
#include <iostream>
class stringref {
public:
stringref(const char* ptr, unsigned len) : ptr(ptr), len(len) {}
unsigned length() { return len; }
const char* data() { return ptr; }
private:
const char* ptr;
unsigned len;
};
std::ostream& operator<< (std::ostream& os, stringref sr) {
const char* data = sr.data();
for (unsigned len = sr.length(); len--; )
os << *data++;
return os;
}
using namespace std;
int main (int argc, const char * argv[])
{
cout << "string: " << stringref("test", 4) << endl;
}
or, in your case:
LOG4CPLUS_ERROR("Bad string " << stringref(char_pointer, length));
should work.
The idea of a string reference class is to keep enough information about a string (a size and a pointer) to refer to any block of memory which represents a string. It relies on you to make sure that the underlying string data is valid throughout the lifetime of a stringref object. This way you can pass around and process string information with a minimum of overhead.
When you know it is of fixed length: Why not simply add one more charakter to the size of the array? Then you can easily fill this last char with \0 terminating character and all will be fine
No, you'll have to copy it. There is no proper conversion in the language that you can use to get the array type out of it.
It seems very odd that you want to do this, or that you have a non-terminated C-style string in the first place.
Why are you not using std::string?
I have a C++ string. I need to pass this string to a function accepting a char* parameter (for example - strchr()).
a) How do I get that pointer?
b) Is there some function equivalent to strschr() that works for C++ strings?
To get the C string equivalent of
the C++ string object use c_str
function.
To locate the first occurence of a
char in a string object use
find_first_of function.
Example:
string s = "abc";
// call to strlen expects char *
cout<<strlen(s.c_str()); // prints 3
// on failure find_first_of return string::npos
if(s.find_first_of('a') != string::npos)
cout<<s<<" has an a"<<endl;
else
cout<<s<<" has no a"<<endl;
Note: I gave the strlen just an example of a function that takes char*.
Surprisingly, std:;string has far, far more capabilities than C-style strings. You probably want the find_first_of() method. In general, if you find yourself using the strxxx() functions on C++ std::strings, you are almost certainly doing something wrong.
Like much of the C++ Standard Library, the string class is a complex beast. To make the most of it, you really need a good reference book. I recommend The C++ Standard Library, by Nicolai Josuttis.
You can't get a char* from a string
string does not allow you free access to its internal buffer.
The closest you can get is a const char* using .c_str() if you want it null terminated or .data() if it doesn't have to be null terminated.
You can then cast the pointer returned by these functions to char* but you do this on your own risk. That being said this is a relatively safe cast to make as long as you make sure you're not changing the string. If you changed it then the pointer you got from c_str() may no longer be valid.
This code:
string str("Hello World!");
char* sp = (char*)str.c_str();
sp[5] = 'K';
is probably ok
However this:
string str("Hello World!");
char* sp = (char*)str.c_str();
str = "Chaged string";
sp[5] = 'K';
is most definitely not ok.
If you just want to assign a string literal to pw, you can do it like
char *pw = "Hello world";
If you have a C++ std::string object, the value of which you want to assign to pw, you can do it like
char *pw = some_string.c_str()
However, the value that pw points to will only be valid for the life time of some_string.
More here :
How to assign a string to char *pw in c++
GoodLUCK!!
std::string yourString("just an example");
char* charPtr = new char[yourString.size()+1];
strcpy(charPtr, yourString.c_str());
If str in your string use str.c_str() method to get the char* inside it.
Perhaps this exmaple will help you
#include <iostream>
#include <string>
using namespace std;
int main ()
{
string str ("Replace the vowels in this sentence by asterisks.");
size_t found;
found=str.find_first_of("aeiou");
while (found!=string::npos)
{
str[found]='*';
found=str.find_first_of("aeiou",found+1);
}
cout << str << endl;
return 0;
}
The C++ Standard provides two member functions of claass std::basic_string that return pointer to the first element of the string. They are c_str() and data(). But the both return const char *, So you may not use them with a function that has parameter of type char *.
As for function strchr then its first parameter is const char *. So you may use c_str() and data() with this function. However it is much better to use member function find()of class sttd::basic_string instead of strchr.