Mysterious Segmentation fault in string reversal - c++

I'm writing a piece of code meant to reverse strings using recursion. I believe my method is correct, but I keep getting a segmentation fault and I'm not sure where it's coming from. All my research indicates that it means I'm doing "something strange with memory". I'm new enough at this that these kinds of errors are still baffling, so any help here would be much appreciated. Here's my code:
#include <iostream>
#include <string>
using namespace std;
class Palindrome
{
int front;
int back;
public:
Palindrome();
string reverse(string word)
{
int len = word.length()-1;
if (back == 0) {
back = len;
}
if (front >= back)
return word;
else{
char first = word[front];
char last = word[back];
word[front] = last;
word[back] = first;
front += 1;
back -= 1;
reverse(word);
}
}
};
Palindrome::Palindrome(){
front = 0;
back = 0;
}

I tried your code and got an "access violation" too, even with only one call. Beside the initialization issue described in other answers and comments, what is causing your seg fault is the missing "return" before your recursive call to "reverse". You need to write return reverse(word);
In Visual Studio, your original code gives this: warning C4715: 'Palindrome::reverse' : not all control paths return a value.
See this question for more details.
Here's a version of reverse() with both fixes:
string reverse(string word)
{
int len = word.length()-1;
if (back == 0)
{
back = len;
}
if (front >= back)
{
front = 0;
back = 0;
return word;
}
else
{
char first = word.at(front);
char last = word.at(back);
word.at(front) = last;
word.at(back) = first;
front += 1;
back -= 1;
return reverse(word);
}
}

What I think Jacob Abrahams was trying to say, front is iterated, but never re-set to zero, so the second time you call it, it will either segfault or produce incorrect results depending on whether the second word is longer or shorter.
Furthermore, what Mark B already hinted at is that you can include algorithm and replace the whole Palindrome::reverse function with
std::reverse(word.begin(), word.end());
Most of all it would help if you learned how to use a debugger or, in the future, at least give the specific error message for these kinds of questions.
EDIT: Forgot to add that recursion (e.g. a function calling itself) is usually a bad idea, because the execution stack is quite small and in this case, even after fixing the aforementioned issue, you will get a stack overflow for a particularly long string. It actually makes this particular code less clear.

Personally, I consider mixing recursion and objects somewhat odd. One of the fundamental concepts of objects is that the object holds state that you want to keep track of. One of the fundamental concepts of recursion is that the execution stack holds the state you want to keep track of.
In this case, the state you want to keep track of is how much of the string has been processed/how much of the string remains to be processed. You can keep track of that without an object.
This smells a lot like a homework question. But I can't think of a hint to give you without just handing you the answer. The best I can do is make my answer (1) reverse any container, including but not limited to strings; (2) use an STL-like interface (i.e., iterators); and (3) reverse the string in place instead of reversing a copy of the string:
#include <algorithm> // std::swap
// the other headers are only for my example on how to use the code
#include <iostream>
#include <iterator>
#include <string>
#include <list>
template<typename Itor> void reverse_with_recursion(Itor begin, Itor end)
{
using std::swap; // same trick used by the STL to get user-defined swap's,
// but fall back to std::swap if nothing else exists:
// http://en.wikipedia.org/wiki/Argument-dependent_name_lookup#Interfaces
// if begin and end are pointing at the same element,
// then we have an empty string and we're done
if (begin == end) {
return;
}
// the STL follows the pattern that end is one element after
// the last element; right now we want the last element
--end;
// if begin and end are pointing at the same element *now*,
// then we have a single character string and we're done
if (begin == end) {
return;
}
swap(*begin, *end);
return reverse_with_recursion(++begin, end);
}
int main()
{
std::string foo("hello world");
reverse_with_recursion(foo.begin(), foo.end());
std::cout << foo << '\n';
std::list<int> bar;
for (int i = 0; i < 10; ++i) {
bar.push_back(i);
}
reverse_with_recursion(bar.begin(), bar.end());
std::copy(bar.begin(),
bar.end(),
std::ostream_iterator<int>(std::cout, " "));
std::cout << '\n';

Related

String permutation recursion issue

(--This question was answered down below--)
Hey guys so I know this question has been answered in various ways so far on this site but I wanted to see if I could get a hint to my question without getting the blunt answer... sorry if this is redundant!
so... so far my code is this (as the function says, this is supposed to print out every permutation of the string "ABCD" and MUST be done recursively and without the use of STL algorithms):
void printPermutations(string prefix, string remainder)
{
if (remainder.empty())
cout<<prefix<<endl;
else {
for(int i = 0; i<remainder.length(); i++)
{
prefix += remainder[i];
remainder = (remainder.substr(0, i) + remainder.substr(i+1)); //Gets rid of selected char
printPermutations(prefix, remainder); //recursion w/updated values. Problem here?
}
}
}
Where remainder = "ABCD" as a test string. I'm assuming my problem is with the recursive call itself?
So far, the function only prints out the first 3 permutations: ABCD, ABDC, ACBD. I also have a hunch that this could have something to do with the for control since it printed out 3 permutations and 3 would be less than the string's length of 4? I don't know. I just started learning recursion and it's really hard for me to figure out how to implement recursive calls properly.
The problem is that you're modifying both strings in the loop, so prefix grows and remainder shrinks.
That is, you want the "top-level" call to iterate through A/BCD, B/ACD, C/ABD, and D/ABC, but you're iterating through A/BCD, AB/CD, ABC/D, and ABCD/empty.
Don't modify the strings, just pass the values you want to the recursion:
void printPermutations(string prefix, string remainder)
{
if (remainder.empty())
cout<<prefix<<endl;
else {
for(int i = 0; i<remainder.length(); i++)
{
printPermutations(prefix + remainder[i],
remainder.substr(0, i) + remainder.substr(i+1));
}
}
}
Or use "fresh" variables if you want a more "step-by-step" look:
void printPermutations(string prefix, string remainder)
{
if (remainder.empty())
cout<<prefix<<endl;
else {
for(int i = 0; i<remainder.length(); i++)
{
string thisPrefix = prefix + remainder[i];
string thisRemainder = remainder.substr(0, i) + remainder.substr(i+1);
printPermutations(thisPrefix, thisRemainder);
}
}
}
Please consider using the stl algorithm next_permutation for the job. The code in your case is than:
#include <algorithm>
#include <string>
#include <iostream>
int main()
{
std::string s = "ABCD";
std::sort(s.begin(), s.end());
do {
std::cout << s << '\n';
} while(std::next_permutation(s.begin(), s.end()));
}
If you need to, you can write a wrapper around this snippet.

Segmentation fault during counting of elements in array of strings c++

I am trying to solve an old problem found on topcoder. I am immediately stuck in trying to find the number of elements in an array of strings. Here is my code
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string>
using namespace std;
class MiniPaint {
private:
size_t numLines;
public:
int leastBad(string picture[], int maxStrokes) {
numLines = 0;
while (!picture[numLines].empty()) {
numLines++;
}
cout << numLines << '\n';
return 0;
}
};
int main() {
MiniPaint instance;
string picture[] = {"BBBBBBBBBBBBBBB", "WWWWWWWWWWWWWWW", "WWWWWWWWWWWWWWW", "WWWWWBBBBBWWWWW"};
instance.leastBad(picture, 10);
return 0;
}
This code gives me a segmentation fault. Something is going wrong, the code is a little bit excessive for just the functionality of counting the number of elements but of course I want to extend the class to include more functionality. If anyone can explain what is going wrong here I would be grateful! Thanks in advance.
EDIT: when I expand the code by
cout << picture[numlines] << '\n';
in the while loop, to show the actual elements in the array, first the four proper strings are shown and then somehow it endlessly prints spaces to the terminal. So the problem lies somewhere in the fact that
picture[4].empty()
does not return true, even though picture has only four elements.
Your while loop condition assumes that the last string in the array is empty:
int leastBad(string picture[], int maxStrokes) {
numLines = 0;
while (!picture[numLines].empty()) {
But your input string array defined in main() is not terminated with an empty "" string.
So you may want to add this empty string terminator:
// inside main()
string picture[] = {..., "" /* Empty string terminator */ };
In addition, in modern C++ I'd encourage you to use array container classes instead of raw C-style arrays, typically std::vector<std::string>.
In this case, you can use the size() method to get the array size (i.e. element count), or just a range-for loop for iterating through the whole array.
You access the array out of bounds.
When you call picture[4] you want to access a string object which is not there end the call to the function empty() is on uninitialized memory.
You either need to store how big the array is and iterate until numLines<=3 or you can use a vector
std::vector<std::string> picture = ...
for(std::string line : picture)
{
//do stuff
}
You are out of array bounds at picture[numLines]. You should pass array length or calculate it and check the index numLines. Code will look like:
size_t length = sizeof(picture) / sizeof(*picture); // For VS use _countof macro
while (numLines < length && !picture[numLines].empty())
{
++numLines;
}

Returning a string * type array from a function back into the main

I'm new to C++ and I am working on a function to shuffle strings
It takes an array of strings, shuffles them, and returns them back to the main.
I am returning a pointer to an array of strings called shuffled. The problem I have is that when I try to save that new pointer to the array to another pointer in the main, I start getting weird values that either reference to a file location in my computer or a bunch of numbers.
I'll post the entire code here but really what you want to look at is the return types, how I return it and how I save it in main. Please tell me why my pointer is not referencing the working array that is created in the function. Here's the code:
#include <cstdio>
#include <string>
#include <ctime>
#include <new>
#include <cstdlib>
using namespace std;
const char * getString(const char * theStrings[], unsigned int stringNum)
{
return theStrings[stringNum];
}
string * shuffleStrings(string theStrings[])
{
int sz = 0;
while(!theStrings[sz].empty())
{
sz++;
}
sz--;
int randList[sz];
for(int p = 0; p < sz; p++)
{
randList[p] = sz;
}
srand(time(0));//seed randomizer to current time in seconds
bool ordered = true;
while(ordered)
{
int countNumberInRandList = 0;//avoid having a sz-1 member list length (weird error I was getting)
for(int i = 0; i < sz; i++)
{
int count = 0;
int randNum = rand()%(sz+1);//get random mod-based on size
for(int u = 0; u < sz; u++)
{
if(randList[u] != randNum)
{
count++;
}
}
if(count == sz)
{
randList[i] = randNum;
countNumberInRandList++;
}
else
i--;
}
//check to see if order is same
int count2 = 0;
for(int p = 0; p < sz; p++)
{
if(randList[p] == p)
{
count2++;
}
}
if(count2 < sz-(sz/2) && countNumberInRandList == sz)
{
ordered = false;
}
}
string * shuffled[sz];
for(int r = 0; r < sz; r++) //getting random num, and str list pointer from passed in stringlist and setting that value at shuffled [ random ].
{
int randVal = randList[r];
string * strListPointer = &theStrings[r];
shuffled[randVal] = strListPointer;
}
for(int i = 0; i < sz; i++)
{
printf("element %d is %s\n", i, shuffled[i]->c_str());//correct values in a random order.
}
return *shuffled;
}
int main()
{
string theSt[] = {"a", "b", "pocahontas","cashee","rawr", "okc", "mexican", "alfredo"};
string * shuff = shuffleStrings(theSt);//if looped, you will get wrong values
return 0;
}
Strings allocate their own memory, no need to give them the "length" like you would have to do for char arrays. There are several issues with your code - without going into the details, here are a few working/non-working examples that will hopefully help you:
using std::string;
// Returns a string by value
string s1() {
return "hello"; // This implicitly creates a std::string
}
// Also returns a string by value
string s2() {
string s = "how are you";
return s;
}
// Returns a pointer to a string - the caller is responsible for deleting
string* s3() {
string* s = new string;
*s = "this is a string";
return s;
}
// Does not work - do not use!
string* this_does_not_work() {
string s = "i am another string";
// Here we are returning a pointer to a locally allocated string.
// The string will be destroyed when this function returns, and the
// pointer will point at some random memory, not a string!
// Do not do this!
return &s;
}
int main() {
string v1 = s1();
// ...do things with v1...
string v2 = s2();
// ...do things with v2...
string* v3 = s3();
// ...do things with v3...
// We now own v3 and have to deallocate it!
delete v3;
}
There are a bunch of things wrong here -- don't panic, this is what happens to most people when they are first wrapping their brains around pointers and arrays in C and C++. But it means it's hard to put a finger on a single error and say "this is it". So I'll point out a few things.
(But advance warning: You ask about the pointer being returned to main, your code does indeed do something wrong with that, and I am about to say a bunch of things about what's wrong and how to do better. But that is not actually responsible for the errors you're seeing.)
So, in shuffleStrings you're making an array of pointers-to-string (string * shuffled[]). You're asking shuffleStrings to return a single pointer-to-string (string *). Can you see that these don't match?
In C and C++, you can't actually pass arrays around and return them from functions. The behaviour you get when you try tends to be confusing to newcomers. You'll need to understand it at some point, but for now I'll just say: you shouldn't actually be making shuffleStrings try to return an array.
There are two better approaches. The first is to use not an array but a vector, a container type that exists in C++ but not in C. You can pass arrays around by value, and they will get copied as required. If you made shuffleStrings return a vector<string*> (and made the other necessary changes in shuffleStrings and main to use vectors instead of arrays), that could work.
vector<string *> shuffleStrings(...) {
// ... (set things up) ...
vector<string *> shuffled(sz);
// ... (fill shuffled appropriately) ...
return shuffled;
}
But that is liable to be inefficient, because your program is then having to copy a load of stuff around. (It mightn't be so bad in this case, because a smallish array of pointers isn't very large and because C++ compilers are sometimes able to figure out what you're doing in cases like this and avoid the copying; the details aren't important right now.)
The other approach is to make the array not in shuffleStrings but in main; to pass a pointer to that array (or to its first element, which turns out to be kinda equivalent) into shuffleStrings; and to make shuffleStrings then modify the contents of the array.
void shuffleStrings(string * shuffled[], ...) {
// ... (set things up) ...
// ... (fill shuffled appropriately) ...
}
int main(...) {
// ...
string * shuffled[sz];
shuffleStrings(shuffled, theSt);
// output strings (main is probably a neater place for this
// than shuffleStrings)
}
Having said all this, the problems that are causing your symptoms lie elsewhere, inside shuffleStrings -- after all, main in your code never actually uses the pointer it gets back from shuffleStrings.
So what's actually wrong? I haven't figured out exactly what your shuffling code is trying to do, but that is where I bet the problem lies. You are making this array of pointers-to-string, and then you are filling in some of its elements -- the ones corresponding to numbers in randList. But if the numbers in randList don't cover the full range of valid indices in shuffled, you will leave some of those pointers uninitialized, and they might point absolutely anywhere, and then asking for their c_strs could give you all kinds of nonsense. I expect that's where the problem lies.
Your problem has nothing to do with any of the stuff you are saying. As you are a beginner I would suggest not presuming that your code is correct. Instead I would suggest removing parts that are not believed to be problematic until you have nothing left but the problem.
If you do this, you should quickly discover that you are writing to invalid memory.
part two : you can't seem to decide on the type of what you are returning. Are you building a pointer to an array to return or are you returning an array of pointers.... you seem to switch between these intermittently.
part three : read #Gareth's answer, he explains about passing parameters around nicely for your instance.

Balance ordering parenthesis via Dynamic programing

Hi from the very famous book Code to Crack i come across a question :
Implement an algorithm to print all valid (e.g., properly opened and closed) combinations of n-pairs of parentheses.
Example:
input: 3 (e.g., 3 pairs of parentheses)
output: ()()(), ()(()), (())(), ((()))
#include <iostream>
#include <string>
using namespace std;
void _paren(int l,int r,string s,int count);
void paren(int n)
{
string s="";
_paren(n,n,s,n);
}
void _paren(int l,int r,string s,int count){
if(l<0 || r<0)
return;
if(l==0 && r==0)
cout<<s<<endl;
else{
if(l>0)
{
_paren(l-1,r,s+"(",count+1);
}
if(r>l)
_paren(l,r-1,s+")",count+1);
}
}
int main(){
int n;
cin>>n;
paren(n);
return 0;
}
This is a recursive approach I tried for it . I am pretty sure that we can solve this through dynamic programming as well , as we are already using a lot of value again and again , but I have no idea how to implement this through Dynamic programming I tried tabular bottom up approach but couldnt work out. Please help me out just the basic idea on how to work with this
DP does not really help you. The recursive algorithm is time and space optimal!
In fact, there is a reason not to use DP: the memory requirements! This will be huge.
A better algorithm is to have one character array that you pass in, have the recursive method modify parts of it and print that when needed. I believe that solution is given in the book you mention.
DP can reduce count of traversed states by choosing the optimal solution every call. It also help you to reuse calculated values. There is no calculations, every valid state must be visited, and non-valid states can be avoided by if( ).
I suggest you to implement some another recursion (at least without copying new string object after call, just declare global char array and send it to output when you need).
My idea of recursion is
char arr[maxN]; int n; // n is string length, must be even though
void func(int pos, int count) { // position in string, count of opened '('
if( pos == n ) {
for(int i = 0; i < n; i++)
cout << char(arr[i]);
cout << "\n";
return;
}
if( n-pos-1 > count ) {
arr[pos] = '('; func(pos+1,count+1);
}
if( count > 0 ) {
arr[pos] = ')'; func(pos+1,count-1);
}
}
I didn't checked it, but the idea is clear I think.

Modifying a recursive string reverse function

I am doing some recursive exercises. The previous one was to make a reverse() function for a string which basically removes the first character and then combines the solution. I managed to do that, here is the source code (the entire source) The current task is to modify this function (the following exercise in the book) by adding a helper function which reverses a substring of the string. At this moment I am stuck at this. It is my understanding that you use helper functions when you need to pass additional arguments or something and this function takes none so I really have no idea how to approach this problem. Help appreciated.
#include <iostream>
#include <string>
using namespace std;
void reverse(string& text)
{
if (text.length() == 0)
{
return;
}
if (text.length() == 1)
{
return;
}
else
{
string firstLetter = text.substr(0,1);
text = text.substr(1, text.length()-1);
reverse(text);
text += firstLetter;
}
}
int main()
{
string a = "tyu";
reverse(a);
cout << a << endl;
return 0;
}
A guy suggested to use parameters, ect, this is my try with it:
#include <iostream>
#include <string>
using namespace std;
//is actually doing the hard work
void reverse1(string& input, int a, int b)
{
// base case
if( a >= b)
{
return;
}
//swap the characters
char tmp;
tmp = input[a];
input[a] = input[b];
input[b] = tmp;
//create the boundries for the new substring
a++;
b--;
//call the function again
reverse1(input, a, b);
}
// sets the parameters and calls the helper function
void strreverse(string& input)
{
reverse1(input, 0, input.length()-1);
}
int main()
{
cout << "Please enter the string which you want to be reversed:";
string a;
cin >> a;
strreverse(a);
cout << a << endl;
return 0;
}
The goal is probably to avoid creating all of the intermediate substrings. The helper function will take iterators, or a start and end index in addition to the string begin reversed.
Try to implement reversing so that there is only one instance of std::string (i.e. work with it as with an array). Then you will need a helper function with additional parameters (at least one parameter - which index to reverse now).
I would implement reverse here as series of exchanges: a[0] <-> a[n-1], a[1] <-> a[n-2] etc. where n is length of the string.
You can define a helper function that takes a start and an end index of the substring which it will reverse.
The function should exchange the element at the start index with that at the end index IFF the difference between the start and the end indices is 1. Otherwise, it places a recursive call to itself by decrementing the end index and incrementing the start index. You will need to keep check on the condition if the start and end index become same though.