Program blowing up after using recursion - c++

Modifying my reverse a string function to add recursion. Unfortunately, my program keeps blowing up.
Stepped through my code in Visual Studio and for some reason the watch window will say i is equal to the length of the string (i.e. the terminating condition to exit the while loop). I step over it one last time and it says i is now one less than the string length. Then it stays in the while loop forever.
I know this sounds confusing, so I will give an example. I enter "Spongebob" and it does everything I want it to (i.e. says the length of Spongebob is 9, prints "bobegnopS", increments i to the string length, etc), but then it says i is now 8 (i.e. it was just at 9) and never exits the while loop.
Here is my ReverseString() function:
void ReverseString(char * string, bool stringReversed, int stringLength, int i)
{
i++;
if(!stringReversed)
{
while(*string != '\0')
string++;
}
stringReversed = true;
while(i < stringLength)
{
string--;
std::cout << *string;
ReverseString(string, stringReversed, stringLength, i);
}
}
Here is the call:
case 3:
//Learn By Doing 16.6
{
char string[BUFFER_LENGTH];
bool stringReversed = false;
int base = 0;
int exponent = 0;
std::cout << "\nEnter base: " << std::endl;
std::cin >> base;
std::cout << "\nEnter exponent: " << std::endl;
std::cin >> exponent;
//Print pow
NewLine();
std::cout << base << " to the " << exponent << " is " << pow(base, exponent);
//Reverse string using recursion
std::cout << "\nEnter string: " << std::endl;
std::cin >> string;
NewLine();
int stringLength = strlen(string);
int i = 0;
ReverseString(string, stringReversed, stringLength, i);
}

When you write a recursive function you always need to specify condition when to stop. Imagine you want to write naive factorial recursive implementation. So idea is to calculate it like this:
n! = n * (n-1) *...*2*1
If you look into sequence you can see that you need to stop at value 1. So naive recursive implementation could be this:
int factorial( int n )
{
// stop when we reached 1
// otherwise we never finish
if( n == 1 ) return 1;
// now do the magic
return n * factorial( n - 1 );
}
The fact that you need to return a value or not does not change the fact that you need to put a stop condition, otherwise your recursive function will never stop.

void ReverseString(char * string, bool stringReversed, int stringLength, int i)
{
...
while(i < stringLength)
{
string--;
std::cout << *string;
ReverseString(string, stringReversed, stringLength, i);
}
}
Nothing inside the loop modifies i or stringLength (the function ReverseString takes them by value, not by reference.) So it can never terminate.

Related

Reversing a number (C++)

I am brand new to C++, and am trying to make a simple program to determine if a user-entered integer is four digits, and if so, to reverse the order of said digits and print that output.
I have a (mostly) working program, but when I try, one of two things happens:
a) if line 16 is commented out and line 17 is active, then the program prints out an infinite number of reversed numbers and the IDE (in this case, repl.it) crashes; or
b) if line 17 is commented out and line 16 is active, then the program prints out one correct line, but the next line is "Your number is too short...again" (look at code below)
#include <iostream>
using std::string;
using std::cin;
using std::cout;
using std::endl;
int main() {
int n, reversedNumber, remainder;
bool loopControl;
char userFinalResponse;
reversedNumber=0;
cout<<"Input a 4 digit integer and press Return\n"<<endl;
cin>>n;
while (loopControl=true){
//if ((n>9999)||(n<1000))
if ((n>9999)||((n<1000)&&(n>0)))
{
cout<<"Your number is too short or too long. Please try again.\n"<<endl;
cin>>n;
loopControl=false;
} else {
while(n != 0)
{
remainder = n%10;
reversedNumber=reversedNumber*10+remainder;
n /= 10;
loopControl=true;
}//closing brace for reversal loop
cout<<"Your reversed number is "<<reversedNumber<<"\n"<<endl;
}//closing brace for else
}//closing brace for "while (loopControl>0){"
return 0;
}//closing brace for "int main() {"
You can try this:
int number = 1874 //or whatever you need
auto str = std::to_string(number);
if (str.length() == 4) {
std::reverse(str.begin(), str.end());
std::cout << str << std::endl;
}
I suggest you to give a look at the algorithm header that contains a lot of useful methods that can help you while developing programs.
According to the cpp tutorials = is the assignment operator, not the comparison operator. Because of this your while loop will never terminate. You can simply initialize loopControl to true, and then set it to false when it's okay to exit:
int n, reversedNumber, remainder;
bool loopControl = true; //Initialize to true
char userFinalResponse;
reversedNumber = 0;
cout << "Input a 4 digit integer and press Return\n" << endl;
cin >> n;
while (loopControl) {
//if ((n>9999)||(n<1000))
if ((n>9999) || ((n<1000) && (n>0)))
{
cout << "Your number is too short or too long. Please try again.\n" << endl;
cin >> n;
loopControl = true; //need to keep on looping
}
else {
while (n > 0)
{
remainder = n % 10;
reversedNumber = reversedNumber * 10 + remainder;
n /= 10;
loopControl = false; //Ok to exit
}//closing brace for reversal loop
cout << "Your reversed number is " << reversedNumber << "\n" << endl;
}
}

A member test using Recursion

I was having trouble understanding recursion. I'm looking for some feedback here to see how this program looks.
Question :::
Write a recursive Boolean function named isMember. The function should accept three parameters: an array of integers, an integer indicating the number of elements in the array, and an integer value to be searched for. The function should return true if the value is found in the array or false if the value is not found. Demonstrate the use of the function in a program that asks the user to enter an array of numbers and a value to be searched for.
What I have::
#include <iostream>
using namespace std;
bool isMember(int[],int,int);
int main()
{
const int SIZE = 10;
int numSearch;
int elementz[SIZE];
for(int i = 0; i < SIZE; i++)
{
cout << "Element " << i + 1 << "\t";
cin >> elementz[i];
}
cout << "Enter element to search\n";
cin >> numSearch;
bool value = isMember(elementz,SIZE,numSearch);
if(value ==1)
cout << "Element is found\n";
else
cout << "Element not found\n";
return 0;
}
bool isMember(int arr[], int sizze, int num)
{
if(arr[sizze] == num)
return true;
else
isMember(arr,sizze -1, num);
}
Your function doesn't return if the if clause is false. Also, keep in mind that indexes start at 0, not 1 (and why sizze?).
I would recommend starting with an array of 3 values, rather than of 10. That way you''ll be able to manually follow and unfold the successive calls.
In order for recursions to work, you need not only a "conditional stop", but an inconditional stop too.
In your example, you only provided a conditional stop. To make it work correctly, try something like this:
bool isMember(int arr[], int sizze, int num)
{
if ( sizze < 0 ) // "inconditional stop"
return false;
if(arr[sizze] == num) // conditional stop. It could happen or not
return true;
else
isMember(arr,sizze -1, num);
}

Sum of positive integers, using functions.

I'm trying to break this problem into function, but my problem is that I always get different sum, positive and negative count when I print out the result.
Can someone give me a hint?
Write a program that reads ten integer numbers and outputs the sum of all the positive numbers among them. The program should ignore all numbers which are less than or equal to 0. The program should also display count of positive numbers and count of negative numbers or zero.
#include <iostream>
using namespace std;
void input(int number, int positiveCount, int negativeCount, int sum);
void output(int positiveCount, int negativeCount, int sum);
int main()
{
int number, positiveCount, negativeCount, sum;
input(number, positiveCount, negativeCount, sum);
output(positiveCount, negativeCount, sum);
return 0;
}
void input(int number, int positiveCount, int negativeCount, int sum)
{
cout << "Enter 10 integers: " << endl;
for (int i = 0; i < 10; i++)
{
cin >> number;
if (number > 0)
{
positiveCount++;
sum = sum + number;
}
else
{
negativeCount++;
}
}
}
void output(int positiveCount, int negativeCount, int sum)
{
cout << sum << endl;
cout << positiveCount << endl;
cout << negativeCount << endl;
}
Your input() function needs to take its arguments by reference so it can modify them. And you need to initialize all those ints to 0 at the start or they contain garbage.
The operations you have done inside input() function is lost because the scope of the variables are only inside the function.
You need to use either pointers or reference while passing the parameters into the input() function so as not to use a local copy.
While using pointers you need to do dereferencing also.
And initialize the variable to 0 before passing to the function.
Because there is serious mistake in your program. You define four local variables in function main() and send them by value when invoking function input(). This function DO NOT modify variables defined in the function main(). It simply modify their copies. These copies is deleted when you're out of function input().
In order to modify them you should use reference:
void input(int &number, int &positiveCount, int &negativeCount, int &sum);
But it has no meaning to create four integers in function main() and to send them in the functions input() and output(). You can create four local variables in input() and then print them in this function. Then you shouldn't define function output() and you can delete it in your code. I.e. you should modify your program.
In your assignment there is written:
Write a program that reads ten integer numbers and outputs the sum of
all the positive numbers among them
So there is no need to write separate functions for this simple program. It can look like
#include <iostream>
int main()
{
const size_t N = 10;
std::cout << "Enter " << N << " integers: ";
size_t i = 0, count = 0;
long long sum = 0;
int num;
for ( ; i < N && std::cin >> num; i++ )
{
if ( num > 0 )
{
sum += num;
++count;
}
}
std::cout << "You have entered " << count << " positive numbers\n"
<< "and " << i - count << " negative numbers or seroes\n"
<< "Sum of positive numbers is " << sum << std::endl;
return 0;
}
If you want to write separate functions then for example function input could be declared as
long long input( size_t &positive_count, size_t &negative_count );
or
long long input( size_t &total_count, size_t &positive_count );
or
long long input( size_t *positive_count, size_t *negative_count );
or
long long input( size_t *total_count, size_t *positive_count );

Beginner c++ array and loop?

Trying to reverse the order of the characters input. I'm getting really close but no cigar.
#include <iostream>
using namespace std;
const int MAX = 10;
int main()
{
char a[MAX], next;
int index = 0;
cout << "Please enter in up to 10 letters ending with a period: " << endl;
cin >> next;
while((next != '.') && (index < 10))
{
a[index] = next;
index++;
cin >> next;
//cout << " " << next << endl;
}
int numbers_used = index;
for(index = 0; index <= numbers_used; index++)
{
a[index] = a[numbers_used -1];
numbers_used--;
cout << a[index] << " " << endl;
}
}
I'm getting everything but the last switch and even though my code is not as clean I'm failing to see where I'm going wrong.
The book code is:
for(index = numbers_used -1; index >= 0; index--)
cout<<a[index];
cout<< endl;
and why is it index = numbers_used - 1 ?? Since numbers_used was set to index and index was initialized at 0 and not 1 wouldn't I want to run the loop "numbers_used" amount of times? What am I missing?
Try this:
char* flip(char* str, int len) {
for(int x=0; x<(len/2); x++) {
swap(str[x], str[len-x-1]);
}
return str;
}
As of right now, after you get to the middle of the string, you'll have overwritten the values that you would need to copy to the second half. With a string like "FooBarBiz", your code will produce the following over iterations (I've put spaces in to try and make things clearer):
1: FooBarBiz
2: z ooBarBiz
3: zi oBarBiz
4: ziB BarBiz
5: ziBr arBiz
6: ziBra rBiz
7: ziBrar Biz
...
The code I posted however, uses the c++ swap function to swap the complimentary values, that way there are no lost values (we're not doing any overwriting), and you won't need to store the whole string in a placeholder variable. Does this make sense?
If you want to reverse the list you have to start from the last element and decrease the index .
You can approach this in at least two different ways. You can reverse the order of the string and then print, or you can leave the original string unmodified and simply print in reverse. I'd recommend the latter approach, in which case all you'd need to do is to change your last for loop to this:
for(index = 0; index < numbers_used; index++)
{
cout << a[numbers_used-index-1] << " " << endl;
}
Wouldn't it be easier this way ?
#include<iostream>
#include<string>
using namespace std;
const int MAX = 5;
int main()
{
char a[MAX], next;
int index = 0;
bool period = false;
cout << "Please enter in up to 10 letters ending with a period: " << endl;
for(int i = 0; i < MAX && !period; i++)
{
cin >> next;
if(next != '.')
{
a[i] = next; // put the value into the array
index++;
}
else
period = true;
}
for(int i = index - 1; i >= 0 ; i--)
{
cout << a[i] << " ";
}
cout << endl;
return 0;
}
The problem can be solved by using the iterators from the standard library. The BidirectionalIterator as for example offered by std::string, std::list or std::vector can be traversed in both directions.
Using a std::string the solution could be:
#include <iostream>
#include <string>
using namespace std;
int main(int, char**) {
char n = 0;
string a;
while (n != '.' && a.size() < 10) {
cin >> n;
if (n != '.') {
a.push_back(n);
}
}
for (string::reverse_iterator it = a.rbegin(); it != a.rend(); ++it) {
cout << *it << endl;
}
}
I will start by saying: use std::string instead of C-style strings - it's universally less messy and more flexible.
Still, let's go with C-style strings since that's how you are attempting to do it and apparently your textbook also.
I won't comment on the way the user input is read, because I'm not sure if it's copied from the textbook (yikes!!) or you've done it yourself either way I find it to be pointless and wrong because it can lead to several problems. Note that the given book solution only prints out the characters in the reversed order and doesn't reverse the character array itself. You are apparently trying to reverse it.
Your solution is decrementing the numbers_used variable inside the for loop itself. This is a very bad idea since that variable is used in the conditional statement of the for loop. This means the loop will stop before it has iterated over the whole array. Even if the loop worked properly you still wouldn't have reversed the array since once this line executes
a[index] = a[numbers_used -1];
the original value of a[index] is overwritten and forgotten.
I'll try and write a simple solution to reverse a character array for a beginner:
#include <iostream>
#include <cstring> //getline, strlen
using namespace std;
const int MAX_LETTERS = 10;
int main() {
char a[MAX_LETTERS + 1]; //since it's zero terminated
cout << "Enter at most " << MAX_LETTERS << "characters (anything over " <<
MAX_LETTERS << " will be truncated):\n";
cin.getline(a, MAX_LETTERS + 1);
int length = strlen(a); //returns length of input
int last_char = length - 1;
//reverse array
for (int i = 0; i < length / 2; i++) {
char temp = a[i];
a[i] = a[last_char];
a[last_char] = temp;
last_char--;
}
//print array
for (int i = 0; i < length; i++)
cout << a[i];
return 0;
}
Read this tutorial on C style strings, it will help you a lot.
The last for loop in your code is
int numbers_used = index;
for(index = 0; index <= numbers_used; index++)
{
a[index] = a[numbers_used -1];
numbers_used--;
cout << a[index] << " " << endl;
}
If we consider 10 letters abcdefghij and according to your code the numbers_used=10after first loop.So in second loop
//In for loop
//index=0
a[index]=a[numbers_used-1]; // a[0]=a[9] => a[0]=j
numbers_used--; //numbers_used=9;
//index=1
a[index]=a[numbers_used-1]; //a[1]=a[8] => a[1]=i
numbers_used--; //numbers_used=8;
//index=2
a[index]=a[numbers_used-1]; //a[2]=a[7] => a[1]=h
numbers_used--; //numbers_used=7;
//index=3
a[index]=a[numbers_used-1]; //a[3]=a[6] => a[1]=g
numbers_used--; //numbers_used=6;
//index=4
a[index]=a[numbers_used-1]; //a[4]=a[5] => a[4]=f
numbers_used--; //numbers_used=5;
//index=5
a[index]=a[numbers_used-1]; //a[5]=a[5] => a[5]=e
numbers_used--; //numbers_used=4;
// index=6 and numbers_used becomes 4 => index <= numbers_used condition is violated
so you will out of for loop.
This is why u cant get through. And in the second code i,e in the Book.
for(index = numbers_used -1; index >= 0; index--)
cout<<a[index];
cout<< endl;
The numbers_used value is 10 but a[9] is the last value in the array so index is assigned to numbers_used-1. so that you can print from a[9] to a[0].

While loop terminates after one iteration

I am trying to write a function in C++ to evaluate a postfix notation equation. My general strategy is to scan a string (in the proper format, e.g. "10 20 + 30 -").
I am doing this by incrementing an index variable i. At each increment, I check to see if the character is a digit, operator, or neither. If it's a digit, I use the getNextNum() function to get all following digits, convert that to a float, then push it to a stack. I also increment i by the length of the number captured.
If the character is an operator, I get the top two elements of the stack, do the operation, then push the result back to the stack.
The trouble is, my while loop only seems to go through once. The function only returns the first number in the string. I can't figure out what's wrong, I would appreciate any help! I inserted cout statements in the while loop, and i is only incrementing to the index after the first number.
EDIT: Ok, I added the getNextNum() function. Also, I updated the evalPostfix() with a cout of strLength, as well as i after each iteration of the while loop. When running the given code, I get this:
Running…
Please enter an expression in postfix notation: 555 666+
3
555
3
Your expression evaluates to: 555
It seems like strLength is being set to less than it should. Why could this be?
#include <iostream>
#include <string>
#include <vector>
#include <deque>
#include <stack>
using namespace std;
string getNextNum(string equation, int i);
float evalPostfix(string postfix);
float doOperation(float x, float y, char op);
float doOperation(float x, float y, char op)
{
switch (op) {
case '+':
return x + y;
case '-':
return x - y;
case '*':
return x * y;
case '/':
return x / y;
default:
return 0.0;
}
}
string getNextNum(string equation, int i)
{
string num = "";
const string DELIM = "+-*/%^ ";
while (i<equation.length()) {
// Iterate through equation until you hit a delimiter.
if (DELIM.find(equation[i]) != -1) {
break;
}
num += equation[i];
i++;
}
return num;
}
float evalPostfix(string postfix)
{
const string OPS = "+-*/%^";
const string NUMS = "0123456789";
int strLength = postfix.length();
stack<float> numStack;
int i = 0;
cout << strLength << endl;
while (i<strLength) {
if (NUMS.find(postfix[i]) != -1) {
// If a character is a digit, then you should get the
// value and push it to the stack (could be multiple characters long).
string sNextNum = getNextNum(postfix, i);
float fNextNum = atof(sNextNum.c_str());
numStack.push(fNextNum);
cout << sNextNum << endl;
i += (sNextNum.length() - 1);
}
else if (OPS.find(postfix[i] != -1)) {
// Otherwise, pop the top two elements of the stack, perform the
// operation, then push the result back to the stack.
char op = postfix[i];
float x = numStack.top();
numStack.pop();
float y = numStack.top();
numStack.pop();
float z = doOperation(x, y, op);
numStack.push(z);
}
i++;
cout << i << endl;
};
// Once the entire string has been scanned through, there should be a float
// left in the stack, simply return that.
return numStack.top();
}
int main ()
{
cout << "Please enter an expression in postfix notation: ";
string postfix;
cin >> postfix;
float eval = evalPostfix(postfix);
cout << "Your expression evaluates to: " << eval;
return 0;
}
You have a few issues one of the major one being a typo, you have a misplaced ) this:
else if (OPS.find( postfix[i] != -1 ) ) {
^ ^
should be:
else if (OPS.find( postfix[i] ) != std::string::npos) {
^ ^
so you are comparing the char at position i to -1 and then doing a find on the boolean result. Next you should be using -1 to compare the results of find but std::string::npos
As Jonathan pointed out:
cin >> postfix ;
only read up to the first black or newline. Using getline will fix that problem:
if (getline(cin, postfix))
One primary problem was that the input cin >> postfix; statement only reads the first word. Echo inputs to ensure that the program is seeing what you think it is seeing.
Shafik Yaghmour points out another problem.
Points to learn:
echo inputs to make sure the program is seeing what you think it is seeing;
trace key variables with suitable printing messages;
post SSCCE (Short, Self-Contained, Correct Example) — code that can be compiled;
post example input and the output you're getting from it.
This code works on input 555 666+:
#include <iostream>
#include <string>
#include <stack>
using namespace std;
static float doOperation(float x, float y, char op)
{
cout << "doOp: x = " << x << ", y = " << y << ", op = " << op << endl;
if (op == '+')
x += y;
return x;
}
string getNextNum(string equation, int i)
{
string num = "";
const string DELIM = "+-*/%^ ";
while (i<equation.length()) {
// Iterate through equation until you hit a delimiter.
if (DELIM.find(equation[i]) != -1) {
break;
}
num += equation[i];
i++;
}
return num;
}
float evalPostfix(string postfix)
{
const string OPS = "+-*/%^";
const string NUMS = "0123456789";
int strLength = postfix.length();
stack<float> numStack;
int i = 0;
while (i<strLength) {
cout << "Top - i: " << i << ", strLength: " << strLength << endl;
if (NUMS.find(postfix[i]) != -1) {
// If a character is a digit, then you should get the
// value and push it to the stack (could be multiple characters long).
string sNextNum = getNextNum(postfix, i);
float fNextNum = atof(sNextNum.c_str());
numStack.push(fNextNum);
cout << sNextNum << endl;
i += (sNextNum.length() - 1);
}
else if (OPS.find(postfix[i])!= -1) {
// Otherwise, pop the top two elements of the stack, perform the
// operation, then push the result back to the stack.
char op = postfix[i];
float x = numStack.top();
numStack.pop();
float y = numStack.top();
numStack.pop();
float z = doOperation(x, y, op);
numStack.push(z);
}
i++;
cout << "End - i: " << i << ", strLength: " << strLength << endl;
}
cout << "After - i: " << i << ", strLength: " << strLength << endl;
// Once the entire string has been scanned through, there should be a float
// left in the stack, simply return that.
return numStack.top();
}
int main ()
{
cout << "Please enter an expression in postfix notation: ";
string postfix;
//cin >> postfix;
if (getline(cin, postfix))
{
cout << "Evaluating: " << postfix << endl;
float eval = evalPostfix(postfix);
cout << "Your expression evaluates to: " << eval << endl;
}
return 0;
}
Sample trace:
Please enter an expression in postfix notation: 555 666+
Evaluating: 555 666+
Top - i: 0, strLength: 8
555
End - i: 3, strLength: 8
Top - i: 3, strLength: 8
End - i: 4, strLength: 8
Top - i: 4, strLength: 8
666
End - i: 7, strLength: 8
Top - i: 7, strLength: 8
doOp: x = 666, y = 555, op = +
End - i: 8, strLength: 8
After - i: 8, strLength: 8
Your expression evaluates to: 1221
Clearly, you can lose much of the diagnostic output once the specific problem you are solving is resolved, but being prepared to add it along the lines shown can dramatically speed up the process of solving it.