dynamically allocated string array - c++

When I attempt to run this code it crashes. There are no error messages. When the program compiles and runs, it just displays the windows 7 message, "this program has stopped working.":
void readGameFile(string ** entries, int * num_entries, string ** story, int * num_lines)
{
ifstream madlib("madlibs1.txt");
string line;
getline(madlib, line);
*num_entries=stoi(line);
*entries=new string [*num_entries];
for (int i=0; i<*num_entries; i++)
{
getline(madlib,*entries[i]);
}
I did a few tests, and it seems to assign entries[0] a value, and then crashes when attempting to assign entries[1] a value. I am forced to use this function name, with those function parameters and parameter types specifically. I also may not use malloc, vector or other answers I've seen.

I think the issue is one of precedence: you almost certainly
want:
getline( madlib, (*entries)[i]) );
Otherwise, you're indexing from the string**, then
dereferencing: *(entries[i]).
You also want to check the results of getline, possibly in the
loop:
for ( int i = 0; madlib && i != *num_entries; ++ i )...
as well as before the std::stoi.
And finally: I don't know why you are forced to use this
function signature. It is horrible C++, and you should never
write anything like this. Logically, std::vector<string>
would be a better solution, but even without it: your function
has 4 out parameters. This would be better handled by returning
a struct. And failing that, out parameters in C++ are
usually implemented by non-const reference, not by a pointer.
While there are arguments for using the pointer in some cases,
when it results in a pointer to a pointer, it's evil. If
nothing else:
bool // Because we have to indicate whether it succeed or failed
readGameFile( std::string* &entries, int &num_entries, std::string* &story, int &num_lines )
// ...
(This actually looks more like it should be constructor,
however, of a class with two data elements, entries and
story.)

Related

Modifying the length and contents of the string?

To change the contents of a string in a function such that it reflects in the main function we need to accept the string as reference as indicated below.
Changing contents of a std::string with a function
But in the above code we are changing the size of string also(i.e, more than what it can hold), so why is the program not crashing ?
Program to convert decimal to binary, mind it, the code is not complete and I am just testing the 1st part of the code.
void dectobin(string & bin, int n)
{
int i=0;
while(n!=0)
{
bin[i++]= (n % 2) + '0';
n = n / 2;
}
cout << i << endl;
cout << bin.size() << endl;
cout << bin << endl;
}
int main()
{
string s = "1";
dectobin(s,55);
cout << s << endl;
return 0;
}
O/p: 6 1 1 and the program crashes in codeblocks. While the above code in the link works perfectly fine.
It only outputs the correct result, when i initialize the string in main with 6 characters(i.e, length of the number after it converts from decimal to binary).
http://www.cplusplus.com/reference/string/string/capacity/
Notice that this capacity does not suppose a limit on the length of the string. When this capacity is exhausted and more is needed, it is automatically expanded by the object (reallocating it storage space). The theoretical limit on the length of a string is given by member max_size
If the string resizes itself automatically then why do we need the resize function and then why is my decimal to binary code not working?
Your premise is wrong. You are thinking 1) if I access a string out of bound then my program will crash, 2) my program doesn't crash therefore I can't be accessing a string out of bounds, 3) therefore my apparently out of bounds string accesses must actually resize the string.
1) is incorrect. Accessing a string out of bounds results in undefined behaviour. This is means exactly what it says. Your program might crash but it might not, it's behaviour is undefined.
And it's a fact that accessing a string never changes it's size, that's why we have the resize function (and push_back etc.).
We must get questions like yours several times a week. Undefined behaviour is clearly a concept that newbies find surprising.
Check this link about std::string:
char& operator[] (size_t pos);
const char& operator[] (size_t pos) const;
If pos is not greater than the string length, the function never
throws exceptions (no-throw guarantee). Otherwise, it causes
undefined behavior.
In your while loop you are accessing the bin string with index that is greater than bin.size()
You aren't changing the size of the string anywhere. If the string you pass into the function is of length one and you access it at indices larger than 0, i.e., at bin[1], bin[2], you are not modifying the string but some other memory locations after the string - there might be something else stored there. Corrupting memory in this way does not necessarily directly lead to a crash or an exception. It will once you access those memory locations later on in your program.
Accepting a reference to a string makes it possible to change instances of strings from the calling code inside the called code:
void access(std::string & str) {
// str is the same instance as the function
// is called with.
// without the reference, a copy would be made,
// then there would be two distinct instances
}
// ...
std::string input = "test";
access(input);
// ...
So any function or operator that is called on a reference is effectively called on the referenced instance.
When, similar to your linked question, the code
str = " new contents";
is inside of the body of the access function, then operator= of the input instance is called.
This (copy assignment) operator is discarding the previous contents of the string, and then copying the characters of its argument into newly allocated storage, whose needed length is determined before.
On the other hand, when you have code like
str[1] = 'a';
inside the access function, then this calls operator[] on the input instance. This operator is only providing access to the underlying storage of the string, and not doing any resizing.
So your issues aren't related to the reference, but to misusing the index operator[]:
Calling that operator with an argument that's not less than the strings size/length leads to undefined behaviour.
To fix that, you could resize the string manually before using the index operator.
As a side note: IMO you should try to write your function in a more functional way:
std::string toOct(std::string const &);
That is, instead of modifying the oases string, create a new one.
The bounds of the string are limited by its current content. That is why when you initialise the string with 6 characters you will stay inside bounds for conversion of 55 to binary and program runs without error.
The automatic expansion feature of strings can be utilised using
std::string::operator+=
to append characters at the end of current string. Changed code snippet will look like this:
void dectobin(string & bin, int n){
//...
bin += (n % 2) + '0';
//...
}
Plus you don't need to initialise the original string in main() and your program should now run for arbitrary decimals as well.
int main(){
//...
string s;
dectobin(s,55);
//...
}

How to put arguments in a function at run time?

So I am using execlp in my c++ program. execlp is of the form " int execlp(const char *file, const char *arg0,...,const char *argn)" meaning that it can take arbitrary amount of arguments. I just want to know that is there a way I can put arguments inside this function at run time? Since the arguments are provided by the user, there is no way for me to know the exact number of arguments. Of course I can pick a ridiculously large number from the start but that won't be very efficient.I need a more efficient way that would allow me to put arguments at run time.
If you are not required to use execlp, execv or execvp are better functions for your requirement.
From http://linux.die.net/man/3/execlp
The execv(), execvp(), and execvpe() functions provide an array of pointers to null-terminated strings that represent the argument list available to the new program. The first argument, by convention, should point to the filename associated with the file being executed. The array of pointers must be terminated by a NULL pointer.
I guess that you are using Linux or some other POSIX system.
You obviously need, as R.Sahu answered, to use functions like execv(3), which takes an array of arguments to execve(2) syscall. You could allocate that array in C dynamic memory with malloc(3) or friends (calloc). If coding in C++, you would use new.
For a useless example, here is a chunk of code executing /bin/echo on an array of arguments 1, 2, .... nargs where int nargs; is strictly positive.
Variant in C99
assert(nargs>0);
char** myargs = malloc ((nargs+2)*sizeof(char*));
if (!myargs) { perror("malloc myargs"); exit(EXIT_FAILURE); };
myargs[0] = "echo";
for (int ix=0; ix<nargs; ix++)
{ char buf[32];
snprintf(buf,sizeof(buf),"%d",ix);
myargs[ix+1] = strdup(buf);
if (!myargs[ix+1]) { perror("strdup"); exit(EXIT_FAILURE); };
}
myargs[nargs+1] = NULL;
execv("/bin/echo", myargs);
perror("exec echo failed");
exit(EXIT_FAILURE);
In C++ you would e.g. code char**myargs = new char*[nargs+2];
In general, you need to later free (in C++, use delete) heap allocated memory. Here it is not really needed, since execv does not return. However, in other occasions (e.g. if using fork before execv, so the parent process is continuing and would later waitpid), you need a loop to free each individual element (result of strdup), then you need to free the entire myargs array.
Regarding the general question of calling an arbitrary (runtime-known) function of arbitrary signature, this is not possible in plain standard C99, but you could use some libraries (with a few assembler or machine specific code inside them) like libffi
In genuine C++11 you still need the array argument to execv to be an array of char*. You might consider using (as an intermediate step) some std::vector<std::string> but you'll need at least to transform it into a std::vector<char*> then pass the data to execve. Read about std::string (and its c_str member function) and std::vector (and its data member function). You could try something like:
assert (nargs>0);
std::vector<std::string> vecstr;
vecstr.resize(nargs+2);
vecstr[0] = "echo";
for (int ix=0; ix<nargs; ix++) vecstr[ix+1] = std::to_string(ix+1);
std::vector<const char*> vecargs;
vecargs.resize(nargs+2,nullptr);
std::transform(vecstr.begin(), vecargs.begin(),
[](const std::string&s) { return s.c_str(); });
vecargs[nargs+1] = nullptr;
execv("/bin/echo", vecargs.data());
throw std::runtime_error(std::string{"exec failure:"}+strerror(errno));
Notice that execv can fail, in particular when the array of arguments is too big; usually the limit is a few hundred thousands elements, but it can be much smaller.

Segmentation Fault on Assigning string Array

I have been trying to return an array of strings for a function for a couple of days to no avail. While I was searching around StackOverflow, I found that it would be a better idea to have a parameter that will be assigned the value of an array. So, here is my code example (not the actual usage, but a mockup of how I am trying to use the function). I am sorry if the code is a bit sloppy. I have been testing things out with it for a while.
void splitOn(string message, string delim, string***toCh) {
string** rString = new string*;
string lArr[numberOf(message, delim)+1];
for(int index=0; index<numberOf(message, delim)+2; index++) {
lArr[index]=message.substr(0, message.find(delim)).c_str();
message = message.substr(message.find(delim)+1, message.length());
rString[index]=&lArr[index];
cout << "IN LOOP "<<*rString[index]<<endl;
}
rString[numberOf(message, string(delim))] = &message;
toCh=&rString;
}
int main(){
string***arr;
splitOn("fox.over.lazy.dog", ".", arr);
cout << **arr[0]<<endl;
Note:
numberOf() takes a string and a delimiter(string) and returns how many times the delimiter is found within the string.
strings are from std::string
lArr (the local array within the loop) and *rString all give correct output.
Although I am trying to assign the array to a parameter, learning how to return an array is more appealing to me.
I could hack this together with a file and getLine(), but I would prefer to learn how to properly do this.
You're trying to return local variables, which will never work. You and your caller need to agree on how to allocate the return value. In C++ as the commenters mention this would normally be done by passing a reference to a vector to handle your allocation for you.
In C you have two options, you can either get the caller to pass in a big enough allocation, or use multiple calls to malloc in the callee (not forgetting the calls to free in the caller!)
For instance, if you pass a writable character array, you can simply overwrite the separator characters with null characters to split it up into individual strings without having to allocate new copies.

Splitting a std::string into two const char*s resulting in the second const char* overwriting the first

I am taking a line of input which is separated by a space and trying to read the data into two integer variables.
for instance: "0 1" should give child1 == 0, child2 == 1.
The code I'm using is as follows:
int separator = input.find(' ');
const char* child1_str = input.substr(0, separator).c_str(); // Everything is as expected here.
const char* child2_str = input.substr(
separator+1, //Start with the next char after the separator
input.length()-(separator+1) // And work to the end of the input string.
).c_str(); // But now child1_str is showing the same location in memory as child2_str!
int child1 = atoi(child1_str);
int child2 = atoi(child2_str); // and thus are both of these getting assigned the integer '1'.
// do work
What's happening is perplexing me to no end. I'm monitoring the sequence with the Eclipse debugger (gdb). When the function starts, child1_str and child2_str are shown to have different memory locations (as they should). After splitting the string at separator and getting the first value, child1_str holds '0' as expected.
However, the next line, which assigns a value to child2_str not only assigns the correct value to child2_str, but also overwrites child1_str. I don't even mean the character value is overwritten, I mean that the debugger shows child1_str and child2_str to share the same location in memory.
What the what?
1) Yes, I'll be happy to listen to other suggestions to convert a string to an int -- this was how I learned to do it a long time ago, and I've never had a problem with it, so never needed to change, however:
2) Even if there's a better way to perform the conversion, I would still like to know what's going on here! This is my ultimate question. So even if you come up with a better algorithm, the selected answer will be the one that helps me understand why my algorithm fails.
3) Yes, I know that std::string is C++ and const char* is standard C. atoi requires a c string. I'm tagging this as C++ because the input will absolutely be coming as a std::string from the framework I am using.
First, the superior solutions.
In C++11 you can use the newfangled std::stoi function:
int child1 = std::stoi(input.substr(0, separator));
Failing that, you can use boost::lexical_cast:
int child1 = boost::lexical_cast<int>(input.substr(0, separator));
Now, an explanation.
input.substr(0, separator) creates a temporary std::string object that dies at the semicolon. Calling c_str() on that temporary object gives you a pointer that is only valid as long as the temporary lives. This means that, on the next line, the pointer is already invalid. Dereferencing that pointer has undefined behaviour. Then weird things happens, as is often the case with undefined behaviour.
The value returned by c_str() is invalid after the string is destructed. So when you run this line:
const char* child1_str = input.substr(0, separator).c_str();
The substr function returns a temporary string. After the line is run, this temporary string is destructed and the child1_str pointer becomes invalid. Accessing that pointer results in undefined behavior.
What you should do is assign the result of substr to a local std::string variable. Then you can call c_str() on that variable, and the result will be valid until the variable is destructed (at the end of the block).
Others have already pointed out the problem with your current code. Here's how I'd do the conversion:
std::istringstream buffer(input);
buffer >> child1 >> child2;
Much simpler and more straightforward, not to mention considerably more flexible (e.g., it'll continue to work even if the input has a tab or two spaces between the numbers).
input.substr returns a temporary std::string. Since you are not saving it anywhere, it gets destroyed. Anything that happens afterwards depends solely on your luck.
I recommend using an istringstream.

Converting/parsing pointer strings and doubles

Assignment:
Read in info from text file (done)
Retrieve only parts of text file using substr method (done)
Store info into instance variables (need help)
Here is the code I am having trouble with:
string* lati;
lati = new string(data.substr(0, data.find_first_of(",")));
double* latDub;
latDub = new double(atof((char *)lati));
this->latitude = *latDub;
I need to store the latitude into the instance variable latitude.
The variable data is the read-in text file.
this->latitude is declared as a double.
I have tested and the variable lati is the correct value, but once I try to convert it into a double the value changes to 0 for some reason. I am specifically supposed to use the atof method when converting!
(char *)lati doesn't do what you think it does. What you're clearly trying to do there is get the char sequence associated with lati, but what you're actually doing is just squeezing a string* into a char* which is all kinds of bad.
There's a member function on std::string that will give you exactly what you want. You should review the documentation for string, and replace (char *)lati with a call to that function.
Why your code compiles, but gives meaningless results has already been explained by adpalumbo. There are two fundamental problems in your code leading to that error, on which I want to expand here.
One is that you use a C-style cast: (T)obj. Basically, that just tells the compiler to shut up, you know what you are doing. That is rarely ever a good idea, because when you do know what you are doing, you can usually do without such casts.
The other one is that you are using objects allocated dynamically on the heap. In C++, objects should be created on the stack, unless you have very good reasons for using dynamic objects. And dynamic objects are usually hidden inside objects on the stack. So your code should read like this:
string lati(data.substr(0, data.find_first_of(",")));
double latDub = /* somehow create double from lati */;
this->latitude = latDub;
Of course, latDub is completely unnecessary, you could just as well write to this->latitude directly.
Now, the common way to convert a string into some other type would be streaming it through a string stream. Removing the unnecessary variables you introduced, your code would then look like this:
std::istringstream iss(data.substr(0, data.find_first_of(",")));
if( !iss >> this->latitude ) throw "Dude, you need error handling here!";
Usually you want to pack that conversion from a string into a utility function which you could reuse throughout your code:
inline double convert3double(const std::string& str)
{
std::istringstream iss(str);
double result;
if( !iss >> result )
throw std::exception("Dang!");
return result;
}
However, since the very same algorithm can be used for all types (for which operator>> is overloaded meaningfully with an input stream as the left operand), just make this a template:
template< typename T >
inline T convert3double(const std::string& str)
{
std::istringstream iss(str);
T result; // presumes default constructor
if( !iss >> result ) // presumes operator>>
throw std::exception("Dang!");
return result;
}