implement substring c++ - c++

how do you implement substring in C++ that returns pointer to char? (takes pointer to the first letter)
say something like char* substr(char* c, int pos, int lenght)

I use methods of the std::string class.
Edit:
say something like char* substr(char* c, int pos, int lenght)
This isn't a function that it's possible to implemement well. To create a substring, you need memory:
Same memory as original string: did you mean to overwrite the original string? Is the original string writeable?
New memory: is the caller going to invoke the delete[] operator on the pointer which it receives from your substr function (if it doesn't, there would be a memory leak)?
Global memory: you could reserve a fixed-length buffer in global memory, but that's all sorts of problems (may not be long enough, will be overwritten when someone else calls your substr).
The right way to do it is to return a std::string instance, which is what the string::substr method does, as shown in Graphics Noob's answer, because the std::string instance (unlike a char* instance) will manage the lifetime of its own memory; and if you then want a char* instance from the std::string instance, you can get that using the c_str() method.

Is this the functionality you are trying to replicate?
http://www.cplusplus.com/reference/clibrary/cstring/strstr/

str.substr(int,int).c_str()
Will return the substring as a const char* but be careful using it, the memory containing the string will be invalid at the end of the statement, so you may need to surround it with a strcpy() if you want to store the result. Or better yet just break it up into two lines:
std::string str2 = str.substr(int,int);
const char* cstr = str2.c_str();
You'll need to do a strcpy() to safely get rid of the const.
The ints refer to the parameters for the substring you're trying to get.

Related

strncpy_s - buffer is too small assertation

As part of a small program i need to convert a string to a char array. I want to use the strncpy_s() method but I keep getting an assertation saying that the "buffer is too small".
This is what my code looks like:
char* ostr = new char[sizeof(str)+1];
strncpy_s(ostr, sizeof(ostr), str.c_str(), sizeof(ostr));
Hope someone can help me.
The variable str is, it seems, a std::string object. The size of the object is the size of its member variables, which for std::string commonly is a pointer (to the actual string) and variable for the length of the string.
If you want to get the length of the wrapped string you need to use the length function.
Furthermore, there is another problem with your call to strncpy_s: You do sizeof(ostr), which is the size of the pointer, not the size of the memory it points to.
Lastly, if you want to pass a pointer to the string to a C function, then either use str.c_str() directly in the call. Or if the C function needs to modify the string (but not reallocate it) then use e.g. str.data() or &str[0].
If the C function needs to reallocate the data then you can't use new[] to allocate it. You need to use malloc (or possibly strdup if your system have it).

Returning a constant char pointer yields an error

I am new to C++, and haven't quite grasped all the concepts yet, so i am perplexed at why this function does not work. I am currently not at home, so i cannot post the compiler error just yet, i will do it as soon as i get home.
Here is the function.
const char * ConvertToChar(std::string input1, std::string input2) {
// Create a string that you want converted
std::stringstream ss;
// Streams the two strings together
ss << input1 << input2;
// outputs it into a string
std::string msg = ss.str();
//Creating the character the string will go in; be sure it is large enough so you don't overflow the array
cont char * cstr[80];
//Copies the string into the char array. Thus allowing it to be used elsewhere.
strcpy(cstr, msg.c_str());
return * cstr;
}
It is made to concatenate and convert two strings together to return a const char *. That is because the function i want to use it with requires a const char pointer to be passed through.
The code returns a pointer to a local (stack) variable. When the caller gets this pointer that local variable doesn't exist any more. This is often called dangling reference.
If you want to convert std::string to a c-style string use std::string::c_str().
So, to concatenate two strings and get a c-style string do:
std::string input1 = ...;
std::string input2 = ...;
// concatenate
std::string s = input1 + input2;
// get a c-style string
char const* cstr = s.c_str();
// cstr becomes invalid when s is changed or destroyed
Without knowing what the error is, it's hard to say, but this
line:
const char* cstr[80];
seems wrong: it creates an array of 80 pointers; when it
implicitly converts to a pointer, the type will be char
const**, which should give an error when it is passed as an
argument to strcpy, and the dereference in the return
statement is the same as if you wrote cstr[0], and returns the
first pointer in the array—since the contents of the array
have never been initialized, this is undefined behavior.
Before you go any further, you have to define what the function
should return—not only its type, but where the pointed to
memory will reside. There are three possible solutions to this:
Use a local static for the buffer:
This solution was
frequently used in early C, and is still present in a number of
functions in the C library. It has two major defects: 1)
successive calls will overwrite the results, so the client code
must make its own copy before calling the function again, and 2)
it isn't thread safe. (The second issue can be avoided by using
thread local storage.) In cases like yours, it also has the
problem that the buffer must be big enough for the data, which
probably requires dynamic allocation, which adds to the
complexity.
Return a pointer to dynamically allocated memory:
This works well in theory, but requires the client code to free
the memory. This must be rigorously documented, and is
extremely error prone.
Require the client code to provide the buffer:
This is probably the best solution in modern code, but it does
mean that you need extra parameters for the address and the
length of the buffer.
In addition to this: there's no need to use std::ostringstream
if all you're doing is concatenating; just add the two strings.
Whatever solution you use, verify that the results will fit.

Assign list element to a char*

I've appends some elements in my list
std::list<std::string> dirList2;
//Code
dirList2.push_back(findData.cFileName);
copy(dirList2.begin(), dirList2.end(),std::ostream_iterator<std::string> (std::cout,"\n"));
Everything work, i can view this items,
Now i want to assign the first elem of my list to a char* .
Can someone help me please ? i'dont know how to do it
If I understood well what you want then you can do it like this:
const char *s = dirList2.front().c_str();
Be careful, though. The C string which variable s points to is owned by the string object sitting on your list. If the list goes out of scope or you remove the element from your list, then the C string will be released by the std::string's destructor and your s pointer will not be valid.
If you want to manipulate the C string beyond the liftime of the std::string object than you can do sth. like this:
const char *s = strdup(dirList2.front().c_str());
But it's usually better to use std::string instead of raw C pointers, unless you have no choice.
The string object provides a c_str() method which will return a const char *. If you need to modify the string you must also make a copy of the string (IE using strcpy where the source pointer is the one returned by c_str())

Convert std::string to char * alternative

I have done a search in google and been told this is impossible as I can only get a static char * from a string, so I am looking for an alternative.
Here is the situation:
I have a .txt file that contains a list of other .txt files and some numbers, this is done so the program can be added to without recompilation. I use an ifstream to read the filenames into a string.
The function that they are required for is expecting a char * not a string and apparently this conversion is impossible.
I have access to this function but it calls another function with the char * so I think im stuck using a char *.
Does anyone know of a work around or another way of doing this?
In C++, I’d always do the following if a non-const char* is needed:
std::vector<char> buffer(str.length() + 1, '\0');
std::copy(str.begin(), str.end(), buffer.begin());
char* cstr = &buffer[0];
The first line creates a modifiable copy of our string that is guaranteed to reside in a contiguous memory block. The second line gets a pointer to the beginning of this buffer. Notice that the vector is one element bigger than the string to accomodate a null termination.
You can get a const char* to the string using c_str:
std::string str = "foo bar" ;
const char *ptr = str.c_str() ;
If you need just a char* you have to make a copy, e.g. doing:
char *cpy = new char[str.size()+1] ;
strcpy(cpy, str.c_str());
As previous posters have mentioned if the called function does in fact modify the string then you will need to copy it. However for future reference if you are simply dealing with an old c-style function that takes a char* but doesn't actually modfiy the argument, you can const-cast the result of the c_str() call.
void oldFn(char *c) { // doesn't modify c }
std::string tStr("asdf");
oldFn(const_cast< char* >(tStr.c_str());
There is c_str(); if you need a C compatible version of a std::string. See http://www.cppreference.com/wiki/string/basic_string/c_str
It's not static though but const. If your other function requires char* (without const) you can either cast away the constness (WARNING! Make sure the function doesn't modify the string) or create a local copy as codebolt suggested. Don't forget to delete the copy afterwards!
Can't you just pass the string as such to your function that takes a char*:
func(&string[0]);

Is std::string a better idea than char* when you're going to have to pass it as a char*?

In a recent question, I learned that there are situations where you just gotta pass a char* instead of a std::string. I really like string, and for situations where I just need to pass an immutable string, it works fine to use .c_str(). The way I see it, it's a good idea to take advantage of the string class for its ease of manipulation. However, for functions that require an input, I end up doing something like this:
std::string str;
char* cstr = new char[500]; // I figure dynamic allocation is a good idea just
getstr(cstr); // in case I want the user to input the limit or
str = cstr; // something. Not sure if it matters.
delete[] cstr;
printw(str.c_str());
Obviously, this isn't so, uh, straightforward. Now, I'm pretty new to C++ so I can't really see the forest for the trees. In a situation like this, where every input is going to have to get converted to a C string and back to take advantage of string's helpful methods, is it just a better idea to man up and get used to C-style string manipulation? Is this kind of constant back-and-forth conversion too stupid to deal with?
In the example you give, you can generally read a line into a std::string using the std::getline function: http://www.cplusplus.com/reference/string/getline/
Of course this doesn't do everything that a curses library does. If you need a non-const char* so that some C function can read into it, you can use a vector<char>. You can create a vector<char> from a string, and vice-versa:
std::string a("hello, world");
std::vector<char> b(a.begin(), a.end());
// if we want a string consisting of every byte in the vector
std::string c(b.begin(), b.end());
// if we want a string only up to a NUL terminator in the vector
b.push_back(0);
std::string d(&b[0]);
So your example becomes:
std::vector<char> cstr(500);
getnstr(&cstr[0], 500);
printw(&cstr[0]);
Most std::string::c_str() implementations (if not all of them) simply return a pointer to an internal buffer. No overhead whatsoever.
Beware however that c_str() returns a const char*, not a char*. And that the pointer will become invalid after the function call. So you cannot use it if the function does anything like writing back into the passed string or makes a copy of the pointer.