In this program, I used a recurrent function which is Strlen.
However, prompt tells me that it is
zsh:
segmentation fault ./Strlen5
Does anyone know why it happens ?
My Code:
#include <iostream>
using namespace std;
size_t Strlen(char* str) {
size_t i = 0;
if (str[i] != '\0') {
i += 1;
return 1 + Strlen(str);
} else {
return 0;
}
}
void ShowLength(char* str) {
cout << "length:\"" << str << "\" : " << Strlen(str) << endl;
}
int main() {
ShowLength("Hello");
ShowLength("Titan");
}
You never increment your pointer. You need to start one index ahead each time you recurse.
return 1 + Strlen(str + 1);
Also you should use const char* instead of char*
#include <iostream>
using namespace std;
size_t Strlen(const char* str) {
if (str[0] != '\0') {
return 1 + Strlen(str + 1);
} else {
return 0;
}
}
void ShowLength(const char* str) {
cout << "length:\"" << str << "\" : " << Strlen(str) << endl;
}
int main() {
ShowLength("Hello");
ShowLength("Titan");
}
Working demo
By the way the reason you got a segmentation fault is due to how a function call is constructed.
Since you need to pass on the stack the arguments and the pointer to next the instruction after the call you "waste" a portion of your stack every time you call a function (until you return).
This usually is not a problem, but if you call an infinite number of function one after the other you face a stack overflow.
Further reading:
Why infinite recursion leads to seg fault
Related
#include <iostream>
#include <string>
using namespace std;
void ReverseString(string &S, int size)
{
static int start = 0;
if (start == size - 1 || start == size)
{
return;
}
else
{
swap(S[start++], S[size - 1]);
ReverseString(S, size - 1);
}
}
int main()
{
cout << "enter a string to reverse" << endl;
string s;
getline(cin, s);
cout << "Before Reversing" << endl;
cout << s << endl;
ReverseString(s, s.size());
cout << "After Reversing" << endl;
cout << s << endl;
return 0;
}
I am trying to nail recursions as much as i can,and i was trying to reverse a string using recursion
i didn't know how to do it at first,tried many different ways to do it,but i saw code samples on string reversing,but none of it made sense to me,so i made my own one,but not quite sure of it,i'm just asking for opinion,is it clean and functional??
Thank You
Using a function local static variable in a recursive function is a bad idea. Recursive functions should get all their state as input arguments.
Here's a simplified version that divides the logic into two functions.
void ReverseString(string &S, int start, int end)
{
if ( start < end )
{
swap(S[start], S[end - 1]);
ReverseString(S, start+1, end - 1);
}
}
void ReverseString(string &S)
{
ReverseString(S, 0, S.size());
}
Most of the time, higher level functions would only call the second function. The first function can be called from a higher level function if there is a need to reverse only a subset of a string.
Here's a sample program
#include <iostream>
#include <string>
using namespace std;
void ReverseString(string &S, int start, int end)
{
if ( start < end )
{
swap(S[start], S[end - 1]);
ReverseString(S, start+1, end - 1);
}
}
void ReverseString(string &S)
{
ReverseString(S, 0, S.size());
}
int main()
{
string s = "The string to reverse" ;
cout << "Before Reversing" << endl;
cout << s << endl;
ReverseString(s);
cout << "After Reversing" << endl;
cout << s << endl;
ReverseString(s, 0, 7);
cout << "After Reversing a subset" << endl;
cout << s << endl;
return 0;
}
and its output
Before Reversing
The string to reverse
After Reversing
esrever ot gnirts ehT
After Reversing a subset
reverse ot gnirts ehT
See it working at https://ideone.com/9nMlsP.
is it ... functional??
If by "functional" you mean "does it work", then you tell me.
If you mean "functional" as in "functional" programming style, then no it isn't. In functional style, you don't modify arguments in place, but instead return a new value. Also relying on global state (i.e. static objects) is very anti-functional.
Here is an example:
std::string
ReverseString(std::string_view sv)
{
if (sv.empty())
return "";
std::string_view x = sv.substr(0, 1)
std::string_view xs = sv.substr(1);
return ReverseString(xs) + x;
}
// usage
s = ReverseString(s);
In future, if Pattern matching was introduced to the language, then it could potentially be written like this:
std::string
ReverseString(std::string_view sv)
{
inspect(sv) {
"": return "";
[x:xs]: return ReverseString(xs) + x;
}
}
However, the current proposal does not suggest introducing support for matching ranges like this, so this is highly theoretical.
Local static variables are dangerous. Since their state will remain between function calls. In my approach i used slen as the length of a string and the currentIndex as the last swapped index on the string. Since it is enough to swap till the middle of the string, finish case is when (currentIndex == slen/2).
I also added some test cases as an example.(even length, odd length, zero case and palindrome)
#include <iostream>
#include <string>
using namespace std;
void ReverseString(string &S, int currentIndex, int slen)
{
if (slen / 2 == currentIndex) return;
swap(S[currentIndex], S[slen - 1 - currentIndex]);
currentIndex++;
ReverseString(S, currentIndex, slen);
}
void testReverseString() {
string s = "";
ReverseString(s, 0, s.length());
assert(s == "");
s = "ahmet";
ReverseString(s, 0, s.length());
assert(s == "temha");
s = "ahaha";
ReverseString(s, 0, s.length());
assert(s == "ahaha");
s = "haha";
ReverseString(s, 0, s.length());
assert(s == "ahah");
}
int main()
{
testReverseString();
return 0;
}
Your function with a static variable can be called only once because after its recursive calls the static variable start will not be equal to 0 as it is required. So the function is not "functional".
Here is a demonstrative program that shows how the function can be written with using a static variable and without using a static variable.
#include <iostream>
#include <string>
#include <utility>
void ReverseString1( std::string &s )
{
static std::string::size_type i = 0;
if ( not ( s.size() - 2 * i < 2 ) )
{
std::swap( s[i], s[s.size() - i - 1] );
++i;
ReverseString1( s );
--i;
}
}
void ReverseString2( std::string &s, std::string::size_type pos = 0 )
{
if ( not ( s.size() - 2 * pos < 2 ) )
{
std::swap( s[pos], s[s.size() - pos - 1] );
ReverseString2( s, pos + 1 );
}
}
int main()
{
std::string s( "Hello World!" );
std::cout << s << '\n';
ReverseString1( s );
std::cout << s << '\n';
ReverseString2( s );
std::cout << s << '\n';
return 0;
}
The program output is
Hello World!
!dlroW olleH
Hello World!
Anyone can reverse a string one char at a time, but much cooler is to reverse each third of the string and swap the outer thirds. This cuts stack depth as well as sowing confusion amongst the competition. Note that max stack depth of recursion per character is N, whereas this is cube root of N.
#include <iostream>
#include <string>
using namespace std;
void ReverseRegion(string &s, int start, int sz)
{
// regions < 2 need no action
if (sz == 2) {
char tmp = s[start];
s[start] = s[start+1];
s[start+1] = tmp;
} else if (sz > 2) {
int s3 = sz/3;
ReverseRegion(s, start, s3);
string tmp = s.substr(0,start) + s.substr(start+sz-s3,s3) + s.substr(start+s3, sz-2*s3) + s.substr(start,s3) + s.substr(start+sz);
// cout << "do: " << tmp << "\n";
s = tmp;
ReverseRegion(s, start+s3, sz-2*s3);
ReverseRegion(s, start, s3);
}
}
void ReverseString(string &S)
{
ReverseRegion(S, 0, S.size());
}
int main()
{
cout << "enter a string to reverse" << endl;
string s;
getline(cin, s);
cout << "Before Reversing" << endl;
cout << s << endl;
ReverseString(s);
cout << "After Reversing" << endl;
cout << s << endl;
return 0;
}
I'm stuck on a particular problem. I'm trying to take a string, and reverse the character cases in the string.
For Example: "HaVinG FuN" should flip to "hAvINg fUn."
I think it has something to do with my loop or my If/Else statements. What am I missing? All capitalized characters come out capitalized still. All lower case characters also come out capitalized as well... My other two functions are behaving correctly, but not my reverseFunct function... FYI I've omitted the other functions to try to cut-down on clutter and focus on my problem.
#include "stdafx.h"
#include <string>
#include <iostream>
#include <cctype>
#include <cstring>
using namespace std;
// Function Prototypes
void upperFunct(char *);
void lowerFunct(char *);
void reverseFunct(char *);
int main()
{
cout << "Enter a string: " << endl;
char ltrs [300];
cin.getline(ltrs, 300);
char *ptr = nullptr;
ptr = ltrs;
upperFunct(ptr);
lowerFunct(ptr);
reverseFunct(ptr);
return 0;
}
//----------------------------------//
void upperFunct(char *ltrptr)
{
int count = 0;
while (ltrptr[count] != '\0')
{
ltrptr[count] = toupper(ltrptr[count]);
count++;
}
{
cout << "---> toupper function: " << ltrptr << endl;
}
}
//------------------------------------//
void lowerFunct(char *ltrptr)
{
int count = 0;
while (ltrptr[count] != '\0')
{
ltrptr[count] = tolower(ltrptr[count]);
count++;
}
cout << "---> tolower function: " << ltrptr << endl;
}
//------------------------------------//
void reverseFunct(char *ltrptr) // <-----NOT REVERSING CHARACTERS
{
int count = 0;
while (ltrptr[count] != '\0')
{
if (isupper(ltrptr[count]))
{
ltrptr[count] = tolower(ltrptr[count]);
}
else
{
ltrptr[count] = toupper(ltrptr[count]);
}
count++;
}
cout << "---> reverse function: " << ltrptr << endl;
}
Your check for lowercase letters reads as
else if (islower(ltrptr[count]));
Notice the extra semicolon.
This semicolon terminates the if statement, and thus the succeeding conversion to uppercase is not a then-clause to this if statement but rather is executed unconditionally on every character.
Change like this
// Function Prototypes "HaVinG FuN" should flip to "hAvINg fUn."
void reverseFunct(char *);
int main()
{
//cout << "Enter a string: " << endl;
char ltrs[300] = "HaVinG FuN";
//cin.getline(ltrs, 300);
char *ptr = nullptr;
ptr = ltrs;
reverseFunct(ptr);
ptr = nullptr;
return 0;
}
void reverseFunct(char *ltrptr) // <-----NOT REVERSING CHARACTERS
{
int count = 0;
while (ltrptr[count] != '\0')
{
if (isupper(ltrptr[count]))
{
ltrptr[count] = tolower(ltrptr[count]);
}
else
{
ltrptr[count] = toupper(ltrptr[count]);
}
count++;
}
cout << "---> reverse function: " << ltrptr << endl;
}
You're writing C code. Here's a C++ way to do it:
#include <string>
#include <algorithm>
char reverse_case_char(char c) {
const auto uc = static_cast<unsigned char>(c); // Sic.
return ::isupper(uc)? ::tolower(uc): ::toupper(uc);
}
void reverse_case(std::string& str) {
std::transform(str.begin(), str.end(), str.begin(), reverse_case_char);
}
#include <cassert>
int main()
{
std::string fun = "HaVinG FuN";
reverse_case(fun);
assert(fun == "hAvINg fUn");
return 0;
}
Others have already pointed out the mistake in your code so no need to repeat that. Instead this answer will give some alternative ways of implementing the task.
Your code is more C-style than C++ style. C++ has a number of functions/features that will allow you to write this in much shorter forms.
char ltrs[300] = "HaVinG FuN";
for (auto& ch : ltrs) ch = islower(ch) ? toupper(ch) : tolower(ch);
std::cout << ltrs << std::endl;
or
char ltrs[300] = "HaVinG FuN";
std::for_each(ltrs, ltrs + strlen(ltrs), [](char& ch)
{ ch = islower(ch) ? toupper(ch) : tolower(ch); });
std::cout << ltrs << std::endl;
or using the std::string
std::string str("HaVinG FuN");
for (auto& ch : str) ch = islower(ch) ? toupper(ch) : tolower(ch);
std::cout << str << std::endl;
Using these C++ functions/features makes the program shorter, easier to understand and the risk of bugs is lower.
Thanks for the help!!! I ended up figuring out my answer, while being able to maintain my less-than elegant code that is fitting with my class. Bipll ended up giving me what I was after, something to think about in terms that my original array was being modified each time.
I realize that my solution is sloppy and not appropriate for a work environment, but it is in-line with my homework assignment, as our teacher is encouraging us to learn C++ from the ground-up, not getting too much direct answers from places like SO. So I'm glad I learned a bit from here, as well as an indirect way to help me see my issues.
I ended up making a copy of my original array, and just passing that copy to my last reversing function. I was able to use the original array for the first 2 functions because the 1st function capitalized each character in the array, while the 2nd made them all lowercase. The 3rd function, the reverse, therefore had to have access to the original array, but in the 3rd order. The easiest way for a noob like me, given where I am in the class, was to make a copy of the 1st array and use that for the 3rd function.
//Snippet of code I needed
int main()
{
int index = 0;
cout << "Enter a string: " << endl;
const int Size = 300;
char ltrs[Size];
cin.getline(ltrs, Size);
char arrayCopy[Size];
char *ptr = nullptr;
char *ptr2 = nullptr;
ptr = ltrs;
//Copy of ltrs Array
//----------------------------------//
while (ptr[index] != '\0') //
{ //
arrayCopy[index] = ptr[index]; //
index++; //
} //
arrayCopy[index] = '\0'; //
//
ptr2 = arrayCopy; //
//----------------------------------//
return 0;
}
// Function to Reverse
void reverseFunct(char *ltrptr)
{
int count = 0;
while (ltrptr[count] != '\0')
{
if (isupper(ltrptr[count]))
{
ltrptr[count] = tolower(ltrptr[count]);
}
else
{
ltrptr[count] = toupper(ltrptr[count]);
}
count++;
}
cout << "---> reverse function: " << ltrptr << endl;
}
My Program is suppose to read a string and then insert each character into the stack. I noticed when I print the length, which is the size of the word, it changes to some high number. For example: word = "hello" length will = 5 at first but eventually change to = 111. Also When I use 2 letters I always get a segmentation fault. What is causing this? Why is the length of the word changing?
#include <iostream>
#include <string>
#include "Stack.h"
using namespace std;
int main()
{
Stack stack;
string word;
cout << "Enter word: ";
getline(cin, word);
cout << word << "|" << endl;
int length = word.size();
for (int i = 0; i < length; i++) {
cout << "i: " << i << "\tlength: " << length << endl;
stack.push(word[i]);
cout << "TOP: " << stack.top() << endl;
}
while (!stack.isEmpty())
{
cout << stack.pop();
}
cout << endl;
return 0;
}
#include <iostream>
#include <string>
#define STACK_CAPACITY 1000
using namespace std;
class Stack
{
private:
int topIndex;
char arr[];
public:
// Constructor
Stack()
{
arr[STACK_CAPACITY];
topIndex = -1;
}
// adds elements to "top" of array
void push(char c)
{
// if stack is full, do not add
if (isFull())
{
cout << "Push on full Stack" << endl;
// terminate function
}
topIndex++;
arr[topIndex] = c;
}
// Removes last inserted (push) element from the stack and returns it
char pop()
{
// checks if Stack is empty
if (isEmpty())
{
cout << "Pop on empty Stack" << endl;
return '#';
}
// if not empty, remove and return last element inserted
char temp = arr[topIndex];
arr[topIndex--] = ' ';
return temp;
}
// Returns but does not remove last inserted (push) element
char top() { return arr[topIndex]; }
// Utilities
bool isEmpty() { return topIndex == -1; }
bool isFull() { return topIndex == STACK_CAPACITY - 1; }
int size() { return topIndex + 1; }
// Destructor
~Stack()
{
}
}
There are various problems in your Stack class that cause it to exhibit undefined behaviour.
For example, in the constructor
Stack()
{
arr[STACK_CAPACITY];
topIndex = -1;
}
does not (as, I guess, you are expecting) resize arr to have STACK_CAPACITY elements. It attempts to evaluate the value of arr[STACK_CAPACITY] which, since arr is declared as char arr[], does not exist. Hence that statement has undefined behaviour.
Similarly, the push() member function
// adds elements to "top" of array
void push(char c)
{
// if stack is full, do not add
if (isFull())
{
cout << "Push on full Stack" << endl;
// terminate function
}
topIndex++;
arr[topIndex] = c;
}
attempts (on the first call) to modify arr[0] - which also does not exist.
When behaviour is undefined - as it is in the above - anything can happen. Including appearing to overwrite unrelated data or (in your case) overwriting parts of the string word in main().
You need to read up better on the basics of C++, rather than guessing about how things work. You have guessed VERY incorrectly.
I've been trying to figure this out for hours now, and I'm at my wit's end. I would surely appreciate it if someone could tell me when I'm doing wrong.
I wrote a c++ code with class implementing a simple stack, trying to push and pop random stream of characters. It seems to work fine, but at the end of the file, it produces some sort of runtime error:
HEAP CORRUPTION DETECTED: after Normal block....
Since the error occurs at the end of the file, my guess is that there is a problem at deleting the pointer(class destructor). However, I have no idea what is wrong with the destructor I wrote.
Also, after some trial and error, I found out that if I address a bigger number to unsigned integer value iter1 (ex: 80), the runtime error does not occur. Could you explain what is the problem here, and how to bypass it?
stack.h:
class sstack
{
public:
sstack(int length = 256);
~sstack(void);
int sstackPop(char &c);
int sstackPush(char c);
bool isempty();
bool isFull();
protected:
private:
char *sstackBuffer;
int sstackSize;
int sstackIndex; // Initial = -1
};
stack.cpp:
#include "stack.h"
#include <iostream>
using namespace std;
sstack::sstack(int length)
{
sstackIndex = -1;
if (length > 0)
sstackSize = length;
else
sstackSize = 256;
sstackBuffer = new char[sstackSize];
}
sstack::~sstack(void)
{
delete[] sstackBuffer;
}
bool sstack::isempty()
{
if (sstackIndex < 0)
{
cout << "is empty!(isempty)" << endl;
return 1;
}
else
return 0;
}
bool sstack::isFull()
{
if (sstackIndex >= sstackSize)
return 1;
else
return 0;
}
int sstack::sstackPop(char &c)
{
if (!isempty())
{
c = sstackBuffer[sstackIndex--];
cout << sstackIndex << endl;
return 1;
}
else
{
cout << "is empty!(sstackPop)" << endl;
return 0;
}
}
int sstack::sstackPush(char c)
{
if (!isFull())
{
sstackBuffer[++sstackIndex] = c;
return 1;
}
else{
return 0;
}
}
main.cpp:
#include <iostream>
#include "stack.h"
#include <string>
using namespace std;
int main(){
unsigned int iter1 = 5;
unsigned int iter2 = 800;
sstack stackDefault;
sstack stack1(iter1);
sstack stack2(iter2);
char buffer[80];
memset(buffer, 0x00, 80);
char BUFFER[80] = "A random stream of characters";
strcpy_s(buffer, 80, BUFFER);
for (int i = 0; i< strlen(buffer); i++)
{
cout << " stack1: " << stack1.sstackPush(buffer[i]);
cout << " stack2: " << stack2.sstackPush(buffer[i]);
cout << " stackD: " << stackDefault.sstackPush(buffer[i]);
cout << " i : "<< i << endl;
}
cout << "out of Pushes" << endl;
int i = 0;
memset(buffer, 0x00, 80);
while (!stack1.isempty())
stack1.sstackPop(buffer[i++]);
cout << buffer << endl;
getchar();
}
sstackBuffer[++sstackIndex] = c;
Will write past the end of sstackBuffer when the stack only has one element left.
If you consider a stack of size 1. In the first call to push that line would evaluate to:
sstackBuffer[1] = c;
Which is beyond the memory you've allocated.
Be sure you're aware of the difference between pre-increment and post-increment operators. By your code example I would suggest you use post-increment in push and pre-increment in pop.
This question already has answers here:
How do you reverse a string in place in C or C++?
(21 answers)
Closed 8 years ago.
"Write a function that takes a string (character pointer) as input and returns the string reversed. The function should reverse the string in place and return it as the return value of the function."
char *strrev(char *str) {
char* end = str;
char tmp = 0;
if(str) {
while(*end) {
end++;
}
--end;
while(end > str) {
tmp = *end;
*end-- = *str;
*str++ = tmp;
}
}
}
I am new to C++. I am facing difficulty with this. Can you please correct my code.
Here's one for fun:
You will NOT want to turn this in as your assignment :/
See it Live On Coliru
#include <string>
std::string rev(std::string x)
{
auto a=x.begin();
auto b=x.rbegin();
while (a<b.base())
std::swap(*a++, *b++);
return x;
}
#include <iostream>
int main()
{
std::cout << rev("") << "\n";
std::cout << rev("1") << "\n";
std::cout << rev("12") << "\n";
std::cout << rev("123") << "\n";
std::cout << rev("Hello world!") << "\n";
}
Output:
1
21
321
!dlrow olleH
So your function, strrev claims to return a char * but it returns... well... nothing. That means that if you use the return value of this function, you're reading some random memory. You're in the realm of undefined behavior at that point and anything goes.
Your compiler should have warned you about this and you should learn to read and understand those warnings - they're there for a reason. If, perchance, it did not warn you, you need to crank up the warnings your compiler generates.
Once you fix your function to return the correct value, it will work as expected. Here's a hint: if you want to reverse the string in place then where would the start of the string be located in memory?
There is a standard algorithm in the STL which reverses a range.
char *strrev(char *str) {
const size_t n = strlen(str);
std::reverse(str, str+n);
return str;
}
Or better using C++ strings
void reverse(std::string& s) {
std::reverse(s.begin(), s.end());
}