I have the follow prototype:
int Split(const char* str, const char* delim,unsigned int& numtokens,char **tokensRes)
The last parameter is used to return the response of this function. In the function we have the follow:
.
.
char **tokens =(char**) calloc(tokens_alloc, sizeof(char*));
.
.
.
//at the end of the code
tokensRes = tokens;
.
When returns the value of tokens variable direct when the return of the function is char** I receive the correct answer, but using the method above the return of the function came empty. How can I make this function work correctly?
EDIT 1:
My intent is receive an array of char arrays, eg:
array[0] = "ABC"
array[1] = "ABC"
array[2] = "ABC"
array[3] = "ABC"
Change the prototype from:
int Split(const char* str, const char* delim,unsigned int& numtokens,char **tokensRes)
To:
int Split(const char* str, const char* delim,unsigned int& numtokens,char ** &tokensRes)
And the code tokensRes = tokens; will work. To understand why learn more about C++ and references.
Other answers about using strings are valid if you're planning to move from a C style of coding to a C++ one. The ease of coding would improve a lot and no worries about memory management and pointers (well not often), which are done automatically by classes. No worries about a performance decrease either as long as you follow good practices such as passing objects by reference and not value.
Assuming you want to return an array of strings (char**), then you need to pass a pointer to such an array that you can assign. That is, you need to pass a char*** and assign it like *tokensRes = tokens.
Just ditch the plain C types and use C++ types:
std::vector<std::string> Split(std:;string const& str, std::string const& delim, unsigned int& numtokens);
If you have to stick to the C interface, you need an additional indirection with a triple pointer (I am assuming that you want to return an array of token strings).
int Split(const char* str, const char* delim,unsigned int& numtokens,char ***tokensRes)
char** tokens;
Split("String;String", ";", 2, &tokens);
I really dislike output parameters, and I always wonder why anybody does not use std::string in C++.
Tokenizing has been implemented in many libraries, e.g. in boost::split or boost::tokenizer. No need to reinvent the wheel:
// simple_example_1.cpp
#include<iostream>
#include<boost/tokenizer.hpp>
#include<string>
int main(){
using namespace std;
using namespace boost;
string s = "This is, a test";
tokenizer<> tok(s);
for(tokenizer<>::iterator beg=tok.begin(); beg!=tok.end();++beg){
cout << *beg << "\n";
}
}
The output from simple_example_1 is:
This
is
a
test
Related
In my project, I need the user to input a string, and the string that is typed is const char* by default (with using quotation marks). In my project, I also need to modify these strings, so I cannot really use const.
So I thought about transforming the const char* into a char* with the following function:
Not 100% sure this is the problem (since it crashes for me) but I believe the problem is that the New string does not have enough memory to store the whole string. I tried sort of allocating it memory by writing like this:
const char* szOldString = "Test";
char* szNewString[0x1024];
noconst(&szOldString, &szNewString, 5);
This also did not work considering my parameters and the constexpr.
I am wondering if anybody knows any cool hacks I can use to make this work. I have been working on this for some time so the solution might be an obvious one and I just cannot see it. If that's the case, my bad :D
The easier way is to use the function strncpy (which is more secure than just using strcpy).
#include <iostream>
#include <string.h>
using namespace std;
int main()
{
//char oldString[]= "Hello World!";
const char* oldString = "Hello World!";
char newString[40];
/* copy to sized buffer (overflow safe): */
strncpy ( newString, oldString, sizeof(newString) );
cout << newString;
return 0;
}
Another way is to allocate with malloc space for where you wish to copy the string.
After, you can modify it as your please.
I need a char* for my filename. It should be something like this: cards/h11.bmp
i have a function I cobbled together from various SO articles:
char* getFileName(int* pc1_no, char* suite)
{
int number;
char pCard1[80];
strcpy_s(pCard1, "cards/");
strcat_s(pCard1, suite);
number = *pc1_no;
cout << number << endl;
string str = to_string(number);
char const *pchar = str.c_str();
strcat_s(pCard1, pchar);
strcat_s(pCard1, ".bmp");
return pCard1;
}
Which of course, returns garbage. I don't quite get getting the pointer value. I pretty sure I have made a dumb mistake with the pointer. Thanks in advance.
The best way to do all this is get rid of all the pointers and use a string all of the way through:
std::string getFileName(int pc1_no,
const std::string & suite)
{
std::string pCard1 = "cards/" + suite + std::to_string(pc1_no) + ".bmp";
return pCard1;
}
or if building to older C++ standards where std::to_string is not available:
std::string getFileName(int pc1_no,
const std::string & suite)
{
std::stringstream pCard1;
pCard1<< "cards/" << suite << pc1_no << ".bmp";
return pCard1.str();
}
Rational
char pCard1[80];
is a local variable. It will die at the end of the function, so the function returns a pointer to invalid memory. Many bad things can happen as a result and few good. Watch out for the few good. They are liars waiting for the most opportune time to strike.
The simplest solution maintaining OP's structure is use a std::string to perform string manipulation inside the function.
std::string getFileName(int* pc1_no, char* suite)
{
std::string pCard1 = "cards/";
pCard1 += std::string(suite);
pCard1 += std::to_string(*pc1_no);
pCard1 += std::string(".bmp");
return pCard1;
}
The above is Horrible Code, both excessively verbose and inefficient, but we've already covered the right way in the intro. This is just a touch-point on the logical progression to that right way.
Faster and less complex is to take advantage of std::stringstream's ability to format c-style strings and numbers without any outside help. This approach is probably the best up until std::to_string became available in the C++11 standard.
std::string getFileName(int* pc1_no, char* suite)
{
std::stringstream pCard1;
pCard1<< "cards/" << suite << *pc1_no << ".bmp";
return pCard1.str();
}
There is the possibility of a performance penalty returning the string by value, but the compilers of the past few decades are good at detecting and taking advantage of opportunities to omit unnecessary copying and employing move semantics behind the scenes.
Returning string by value is also far less error-prone than dynamically allocating storage and returning the storage to a caller with the expectation that the caller release it. Any performance penalty that may remain is highly likely to be worth the price. Profile the code to be sure.
Improving the function call:
Passing pc1_no in as a pointer is not helping in any way. Unless you need to modify the value inside the function, just pass by value. If you do need to change the value, prefer a reference.
std::string getFileName(int pc1_no, char* suite)
If you try to pass a string literal: eg:
getFileName(&somenumber, "string literal");
string literals may be in non-writable memory and are always const char * in C++. Passing a const value into a space that could attempt to change the value is bad form. This was allowed for backwards compatibility with C under older C++ Standards, though it may generate an warning, but is illegal in after the C++ 11 Standard.
If your function does not need to modify the contents of the char array, and this doesn't, it's a good practice to tag the string as const and allow the compiler to prevent accidents regardless of whether your compiler allows const to non-const assignments:
std::string getFileName(int pc1_no, const char* suite)
You may have more versatility if you use a reference to a const std::string as it is implicitly convertible from both const and non-const char arrays and allows the rest of your program to take advantage of the many benefits of std::string without needless calls to c_str and data.
std::string getFileName(int pc1_no,
const std::string & suite)
That brings us back to where this answer came in.
Here is how this code would look like in C++:
#include <string>
std::string getFileName(int* n, const std::string& suite) {
return "cards/" + suite + std::to_string(*n) + ".bmp";
}
Even better would be to take the first parameter by value (int n) and dereference at the call site if necessary.
char* getFileName(int pc1_no, char* suite)
{
static char pCard1[80]; // Guarantee safe pointer return
strcpy_s(pCard1, "cards/");
strcat_s(pCard1, suite);
string str = to_string(pc1_no);
char const *pchar = str.c_str();
strcat_s(pCard1, pchar);
strcat_s(pCard1, ".bmp");
return pCard1; // Now you don't lose the result.
}
Or you can use recommended C++ style which is already answered.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
std::vector<std::string> to char* array
I have to call a c function that accepts an array of string pointers. Example
void cFunction(char* cities[], int count)
{
for(int i = 0; i < count; ++i )
{
printf("%s\n", cities[i]);
}
}
Assume that function is in some third party libabry; it cannot be changed
I can declare a static array and call the function like this
char* placesA[] = {"Teakettle Junction", "Assawoman Bay", "Land O' Lakes", "Ion", "Rabbit Hask" };
cFunction(placesA, 5);
That works. But my data is dynamic i.e. the size of the array changes many times at runtime
So I tried this
std::vector<std::string> placesB(placesA, placesA + 5);
cFunction(&placesB[0], 5); // this won't work because std::string != char*[]
Tried this
std::vector<char*> placesC;
cFunction(&placesC[0], 5);
I find placesC awkward to populate at the sametime avoid memory leaks I am looking for a solution that is both efficient ( as little string copying as possible and preferably uses STL and or Boost )
You can write a function that populates a vector<char*> from a vector<string> using .c_str() on each string.
There's going to be some awkwardness no matter how you slice it. If the C API truly requires modifiable arrays, then that's what you'll need to provide -- you'll have to copy your strings into. If it doesn't modify the strings, then you can use a std::vector of const char*, where the string data is still owned by the underlying std::string objects; you just have to be careful that the C API doesn't hold onto references to those strings and tries to access them after the strings have been modified or deallocated.
For example, here's one way to do it:
// Unary functor which calls c_str() on a std::string object
struct StdStringCStrFunctor
{
const char *operator() (const std::string& str) { return str.c_str(); }
};
...
std::vector<std::string> places;
... // populate places
// Convert to array of C strings
std::vector<const char *> placesCStr(places.size());
std::transform(places.begin(), places.end(), placesCStr.begin(), StdStringCStrFunctor());
cFunction(const_cast<char**>(&placesCStr[0]), placesCStr.size());
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Convert std::string to const char* or char*
void Foo::bar(const std::string& foobar) {
// ...
const char* foobar2 = (char*)foobar;
// ...
}
That does not work and I get an error during compilation about invalid casting.
Is there some other way to convert std::string to const char*?
Use foobar.c_str().
You might find this link useful: http://www.cppreference.com/wiki/string/start
std::string::c_str() gets you a const char* pointer to a character array that represents the string (null-terminated).
You should not manipulate the data this pointer points to, so if you need to do that, copy the data.
Double edit - doing it in a more C++ fashion
Since it is nicer to avoid the use of raw pointers and arrays where possible, you can also get the data into an std::vector<char>
#include <string>
#include <vector>
int main()
{
std::string str = "Hello";
std::vector<char> cvec(str.begin(), str.end());
// do stuff
}
edit this is more like C since it uses raw pointers and explicitly allocates mem
#include <string>
#include <cstring>
int main()
{
std::string str = "Hello";
char *cptr = new char[str.size()+1]; // +1 to account for \0 byte
std::strncpy(cptr, str.c_str(), str.size());
// do stuff...
delete [] cptr;
}
You're going to get a lot of kinda incorrect answers about str.c_str() here. :) While c_str() is indeed useful, please keep in mind that this will not actually convert the string into a char*, but rather return the contents of the string as a const char*. And this is a big difference!
What's important here is that the pointer you obtain from c_str() is valid only as long as the given string object exists. So this would be terribly wrong:
class Something {
const char* name;
public:
Something(const std::string& pname) {
this->name = pname.c_str(); /* wrong! the pointer will go wrong as the object from the parameter ceases to exist */
}
};
So if you want to convert, as in: create a new value which will be independent of the original std::string, then you'll want to do something like this:
char* convert(const std::string& str) {
char* result = new char[str.length()+1];
strcpy(result,str.c_str());
return result;
}
But still c_str() will be quite enough for you in most cases. Just try to think in terms of objects' time of life.
const char* foobar2 = foobar.c_str();
Notice the const.
Otherwise you have to copy it to a char buffer.
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.