use std::string as character array - c++

I want to use the gets() function for std::string str. But I get an error:
invalid conversion from 'const char*' to 'char*'
The strlen() function on the other hand doesn't give any error when I write
int len = strlen(str.c_str())
but gets(NUM.c_str()) gives the error.
Any suggestions? I need to use std::string and gets() as my character size is unknown.

c_str() returns a const pointer to the string contents, so you cannot use that to modify the string.
Even if you did circumvent that (which you really shouldn't), it would be impossible to change the size of the string (as you're trying to do), since that's managed by the string object. The best you could do is write over memory that may not be owned by the string, causing crashes or other undefined behaviour.
Even if you did have a suitable array to write to, don't use gets. There is no way to prevent it from overflowing the buffer, if the input line is too long. It's been deprecated in C since at least 1999.
Any suggestions?
std::getline(std::cin, NUM);

Where to begin...
(1) Firstly, gets expects a char*, but std::string::c_str() returns const char*. The purpose of std::string::c_str() is merely to provide a C-string representation of the string data - it is NOT meant to provide a writable buffer. The function gets needs a writable character buffer.
(2) Secondly, you can use std::string as a writable character buffer using the [] operator, by saying:
std::string s(100); // create a buffer of size 100
char* buf = &s[0];
This is guaranteed to work properly in C++11, however in earlier versions of C++, it is not necessarily guaranteed that std::string provide a contiguous memory buffer. (Although, in practice, it almost always does.) Still, if you want a buffer, it's better to use std::vector<char>.
(3) Finally, don't use gets, EVER. It's ridiculously dangerous and makes your program prone to buffer overflow and shellcode injection attacks. The problem is that gets doesn't include a size parameter, so in practice the program will read any arbitrary amount of bytes into the buffer, potentially overflowing the buffer and resulting in undefined behavior. This has historically been an attack vector for many hackers, especially when gets is used with a stack array. The function fgets should be used instead in C, because it lets you specify a maximum read size parameter. In C++, it's better to use std::getline, because it works directly with an std::string object and therefore you don't need to worry about the size of the buffer.

I want to use gets() function
gets() is C. When possible it is better using C++ features
Instead try getline like this:-
std::getline(std::cin, NUM);
And as Jrok mentioned in the comments:-
Make the world a better place - don't use gets

In addition to the problems with trying to use gets in the first place, you cannot use it on a buffer returned from c_str() as the buffer is a const char* (which points to the string buffer held by the std::string object. If you insist on using gets(), you would need to create your own buffer to read into:
char buffer[1024] = {0}; // temporary buffer
gets(buffer); // read from stdin into the buffer
std::string s(buffer); // store the contents of the buffer in a std::string
For an explanation and example of why you should never use gets: http://www.gidnetwork.com/b-56.html
A much better approach is to
std::string s; // the std::string you are using
std::getline(std::cin, s); // read the line

Related

Unhandled Exception when converting const char to char

I've been trying to convert a const char to a char for the past 30 minutes.
Here's what I've got.
string atr;
getline(cin,atr); // Start off with a string because getline takes nothing else.
const char *buffA = atr.c_str(); // Create a const char of the string converted to a const char.
char *buff = ""; // Create a new char to hold the converted result.
strcat(buff,buffA); // Do the conversion.
parseargs(buff); // Pass the data on.
However, I get an unhandled exception. I have no idea why. I literally just typed 'try' into the console as my only argument.
Try using C++ instead of C idioms:
std::vector<char> data(atr.begin(), atr.end());
data.push_back('\0');
parseargs(&data[0]);
There are two things wrong with your code. First, you
initialize a char* with a string literal. This uses
a deprecated convertion; the type of a string literal is char
const[] (which converts to char const*, not to char*),
because any attempt to modify the literal is undefined behavior.
The second is that your string literal is only one char long,
so even if you could write to it, unless atr was empty, you're
writing beyond the end of the buffer.
You don't tell us anything about parseargs. If it doesn't
modify it's argument, you can just pass it atr.c_str(), and be
done with it. (If it's a legacy function which ignores const,
you may have to use a const_cast here.) If it does modify its
argument (say because it uses strtok), then you'll have to
explicitly push a '\0' onto the end of atr, and then pass it
&atr[0]. (Not a particularly clean solution, but if you're
not using atr afterwards, it should work.)
Both your contents of buff and buffA are in read-only memory of the process.
You will actually need to new your buff like
char* buff = new char[32];
This provides memory from the free-store and you can then strcat the string from buffA to buff.
You should prefer strncat, though to avoid buffer-overruns and delete your buff eventually.
This
char *buff = ""; // Create a new char to hold the converted result.
creates a char * that points to (probably read-only) memory of about 1 byte in extent. This:
strcat(buff,buffA); // Do the conversion.
attempts to overwrite that (probably read-only) memory of 1 or so bytes with an arbitrary string.
The chances are this will promptly crash. If the memory is read only, it will crash immediately. If the memory is not read only it will stomp over random data, resulting in very undefined behaviour.
Why on earth do you want to do that? Does parseArgs actually need a modifiable string? It's parsing arguments, it shouldn't need to change them. If it's really necessary, use a std::vector<char> and pass the address of the first element and hope that all it does is poke the contents of the array, rather than (say) running over the end.

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.

good manier to get char[] from another function. Starting thinking in c/c++

As I understood the correct programming style tells that if you want to get string (char []) from another function is best to create char * by caller and pass it to string formating function together with created string length. In my case string formating function is "getss".
void getss(char *ss, int& l)
{
sprintf (ss,"aaaaaaaaaa%d",1);
l=11;
}
int _tmain(int argc, _TCHAR* argv[])
{
char *f = new char [1];
int l =0;
getss(f,l);
cout<<f;
char d[50] ;
cin>> d;
return 0;
}
"getss" formats string and returns it to ss*. I thought that getss is not allowed to got outside string length that was created by caller. By my understanding callers tells length by variable "l" and "getcc" returns back length in case buffer is not filled comleatly but it is not allowed go outside array range defined by caller.
But reality told me that really it is not so important what size of buffer was created by caller. It is ok, if you create size of 1, and getss fills with 11 characters long. In output I will get all characters that "getss" has filled.
So what is reason to pass length variable - you will always get string that is zero terminated and you will find the end according that.
What is the reason to create buffer with specified length if getss can expand it?
How it is done in real world - to get string from another function?
Actually, the caller is the one that has allocated the buffer and knows the maximum size of the string that can fit inside. It passes that size to the function, and the function has to use it to avoid overflowing the passed buffer.
In your example, it means calling snprintf() rather than sprintf():
void getss(char *ss, int& l)
{
l = snprintf(ss, l, "aaaaaaaaaa%d", 1);
}
In C++, of course, you only have to return an instance of std::string, so that's mostly a C paradigm. Since C does not support references, the function usually returns the length of the string:
int getss(char *buffer, size_t bufsize)
{
return snprintf(buffer, bufsize, "aaaaaaaaaa%d", 1);
}
You were only lucky. Sprintf() can't expand the (statically allocated) storage, and unless you pass in a char array of at least length + 1 elements, expect your program to crash.
In this case you are simply lucky that there is no "important" other data after the "char*" in memory.
The C runtime does not always detect these kinds of violations reliably.
Nonetheless, your are messing up the memory here and your program is prone to crash any time.
Apart from that, using raw "char*" pointers is really a thing you should not do any more in "modern" C++ code.
Use STL classes (std::string, std::wstring) instead. That way you do not have to bother about memory issues like this.
In real world in C++ is better to use std::string objects and std::stringstream
char *f = new char [1];
sprintf (ss,"aaaaaaaaaa%d",1);
Hello, buffer overflow! Use snprintf instead of sprintf in C and use C++ features in C++.
By my understanding callers tells length by variable "l" and "getcc" returns back length in case buffer is not filled comleatly but it is not allowed go outside array range defined by caller.
This is spot on!
But reality told me that really it is not so important what size of buffer was created by caller. It is ok, if you create size of 1, and getss fills with 11 characters long. In output I will get all characters that "getss" has filled.
This is absolutely wrong: you invoked undefined behavior, and did not get a crash. A memory checker such as valgrind would report this behavior as an error.
So what is reason to pass length variable.
The length is there to avoid this kind of undefined behavior. I understand that this is rather frustrating when you do not know the length of the string being returned, but this is the only safe way of doing it that does not create questions of string ownership.
One alternative is to allocate the return value dynamically. This lets you return strings of arbitrary length, but the caller is now responsible for freeing the returned value. This is not very intuitive to the reader, because malloc and free happen in different places.
The answer in C++ is quite different, and it is a lot better: you use std::string, a class from the standard library that represents strings of arbitrary length. Objects of this class manage the memory allocated for the string, eliminating the need of calling free manually.
For cpp consider smart pointers in your case propably a shared_ptr, this will take care of freeing the memory, currently your program is leaking memory since, you never free the memory you allocate with new. Space allocate by new must be dealocated with delete or it will be allocated till your programm exits, this is bad, imagine your browser not freeing the memory it uses for tabs when you close them.
In the special case of strings I would recommend what OP's said, go with a String. With Cpp11 this will be moved (not copied) and you don't need to use new and have no worries with delete.
std::string myFunc() {
std::string str
//work with str
return str
}
In C++ you don't have to build a string. Just output the parts separately
std::cout << "aaaaaaaaaa" << 1;
Or, if you want to save it as a string
std::string f = "aaaaaaaaaa" + std::to_string(1);
(Event though calling to_string is a bit silly for a constant value).

Converting string to C style string

I am trying to convert an int to a cstring. I've decided to read the int into a regular string via stringstream, and then read the string into a char array. The following seems to be working, but I'm wondering if I'm just getting lucky with my compiler. Does the code seem sound? Thanks!
int zip = 1234;
char zipString[30];
stringstream str;
str << zip;
str >> zipString;
cout << zipString;
You can get a C++ std::string from the stream's str() function, and an immutable C-style zero-terminated string from the string's c_str() function:
std::string cpp_string = str.str();
char const * c_string = cpp_string.c_str();
You might be tempted to combine these into a single expression, str.str().c_str(), but that would be wrong; the C++ string will be destroyed before you can do anything with the pointer.
What you are doing will work, as long as you're sure that the buffer is large enough; but using the C++ string removes the danger of overflowing the buffer. In general, it's best to avoid C-style strings unless you need to use an API that requires them (or, in extreme circumstances, as an optimisation to avoid memory allocation). std::string is usually safer and easier to work with.
Unless you have a specific reason that you need an array of char instead of a standard string, I'd use the latter. Although it's not strictly necessary in this case, I'd also normally use a Boost lexical_cast instead of explicitly moving things through a stringstream to do the conversion:
std::string zipString = lexical_cast<std::string>(zip);
Then, if you really need the result as a c-style string, you can use zipString.c_str() to get that (though it's still different in one way -- you can't modify what that returns).
In this specific case it doesn't gain you a lot, but consistent use for conversions on this general order adds up, and if you're going to do that, you might as well use it here too.
The std::string's c_str() member function returns a const char* (aka a C-style string).
std::string str = "world";
printf("hello, %s", str.c_str());

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.