Not able to generate correct output in recursive function? - c++

I'm trying to write a function that detects the number the negative integers in a stack recursively. Currently the snippet below is what I have, however it is not giving the correct answer so far. I tested with a stack of 11 elements with 7 negatives and got the output given below. There is definitely something wrong with the loop structure but I have not been able to pinpoint and fix it yet. Any help will be appreciated!
12356657235681623569772357137235729723574562357617235777623579372358096
My function below:
size_t r_func(stack<int> st1)
{
if(st1.size() == 0) return 0;
int r = st1.top();
st1.pop();
cout << (r<0)+r_func(st1);
}

size_t r_func(stack<int> st1)
{
if(st1.size() == 0) return 0;
int r = st1.top();
st1.pop();
cout << (r<0)+r_func(st1);
}
r_func is supposed to return a size_t, but if st1.size() is not zero then it won't return anything. The compiler should've given you a warning about this!
To correct this, add a line that returns the number of negative numbers in your stack:
...
st1.pop();
const size_t neg_count = (r < 0) + r_func(st1);
cout << neg_count;
return neg_count;
}
Edit: To write this tail-recursively, it's necessary to keep track of the size in an accumulator (here it's called neg_accum):
size_t r_func(stack<int> st1, size_t neg_accum = 0)
{
if (st1.size() == 0) {
cout << neg_accum;
return neg_accum;
}
int r = st1.top();
st1.pop();
return r_func(st1, (r < 0) + neg_accum);
}

As Rufflewind said, you should replace 'cout <<' with 'return' and call your function in this way: 'cout << r_func(st1);'

Related

How could I create a c++ function isOdd that accepts an integer array and its size and returns true is all of the array elements are odd

if ( n % 2 == 0)
cout << n << " is even.";
else
cout << n << " is odd.";
I know how to check if the numbers are odd, but unsure of how to write the rest of the code.
bool isOdd(int int_arr[], int arr_size)
{
bool is_all_odd = true;
for(int i = 0; i < arr_size; i++)
{
if(int_arr[i] % 2 == 0)
{
is_all_odd = false;
break;
}
}
return is_all_odd;
}
You'll want to take in the array like you mentioned, the size, and traverse through it. In this case we just assume all is odd, and check for an even, if we find an even number we change the return value, stop traversing and return.

c++ find() returning a different value when stored as a variable

I was helping someone with some homework when I came upon something strange.
I don't use C++, but I figured the function find() would work like any other language.
However, in the first example below, an email with the name ericsomthing#gmail.com does not evaluate to false when looking for a space using find(' ').
if (classRosterArray[i]->GetEmailAddress().find(' ') >= 0) // evaluated true even though i dont know why
In the second example, find(' ') works but only when stored in a local variable.
int test = classRosterArray[i]->GetEmailAddress().find(' ');
if (test >= 0) // evaluates false as expected
More verbose example of the code is shown below
Strange broken code:
void Tester::printInvalidEmails() {
NUM_STUDENTS = LAST_INDEX + 1;
for (int i = 0; i < NUM_STUDENTS; ++i) {
int test = classRosterArray[i]->GetEmailAddress().find(' ');
int test1 = classRosterArray[i]->GetEmailAddress().find('#');
int test2 = classRosterArray[i]->GetEmailAddress().find('.');
if (classRosterArray[i]->GetEmailAddress().find(' ') >= 0) {
cout << classRosterArray[i]->GetEmailAddress() << endl;
}
if (classRosterArray[i]->GetEmailAddress().find('#') == -1) {
cout << classRosterArray[i]->GetEmailAddress() << endl;
}
if (classRosterArray[i]->GetEmailAddress().find('.') == -1 ) {
cout << classRosterArray[i]->GetEmailAddress() << endl;
}
}
}
But this code works:
void Tester::printInvalidEmails() {
NUM_STUDENTS = LAST_INDEX + 1;
for (int i = 0; i < NUM_STUDENTS; ++i) {
int test = classRosterArray[i]->GetEmailAddress().find(' ');
int test1 = classRosterArray[i]->GetEmailAddress().find('#');
int test2 = classRosterArray[i]->GetEmailAddress().find('.');
if (test >= 0) {
cout << classRosterArray[i]->GetEmailAddress() << endl;
}
if (test1 == -1) {
cout << classRosterArray[i]->GetEmailAddress() << endl;
}
if (test2 == -1 ) {
cout << classRosterArray[i]->GetEmailAddress() << endl;
}
}
}
Why does storing the value of find as a local variable 'test' fix the problem?
.find(' ') >= 0 is a bad comparison.
I'm guessing you expect that find will return -1 if it can't find what you're looking for? When you cast the result to an int (which you're implicitly doing when you assign it to an int variable), it will be -1. But the return type of find is actually unsigned, so if you just look at the raw value returned, it can never be < 0 (in other words .find(' ') >= 0 will always be true).
If you want to check to see if the string actually has a space, use:
classRosterArray[i]->GetEmailAddress().find(' ') != std::string::npos
For more, take a look at the docs. Specifically, from the page on npos:
static const size_type npos = -1;
Although the definition uses -1, size_type is an unsigned integer type, and the value of npos is the largest positive value it can hold, due to signed-to-unsigned implicit conversion. This is a portable way to specify the largest value of any unsigned type.

Scrambled number when access array[10000]

I was looking for solution to question what is the 10001st prime number.
And i am done with the code :
int main() {
long long listNumber[10001];
long position = 1, divider = 0;
listNumber[0] = 2;
while(listNumber[10000] == 0) {
divider = 0;
listNumber[position] = listNumber[position-1] + 1;
while(listNumber[divider] <= sqrt(listNumber[position])) {
if(listNumber[position] % listNumber[divider] == 0) {
listNumber[position]++;
divider = 0;
} else divider++;
}
position++;
}
cout << listNumber[10000] << endl;
return 0;
}
but the output is always change, i don't know why. Can you help me to figure it out?
Thank You.
You never initialize the array. That means its contents will be indeterminate and even reading that contents (like you do in the loop condition) leads to undefined behavior.
You need to initialize the array:
long long listNumber[10001] = {}; // Initialize all elements to zero

Recursive Function Scanning String to Add ASCII

So I'm trying to figure out how to do this:
Write a recursive function that will sum all of the char's within a C String.
I'm a little rusty in doing this normally, but I finally got it to work with a normal for loop:
int countstr(string s)
{
int sum = 0;
if(s.length() == 0)
{
exit(0);
}
for (unsigned int i = 0; i < s.size(); i++)
{
sum += s[i];
}
return sum;
}
I can then go inside main and do this:
int main ()
{
cout << "This word adds up to " << countstr("HELLO") << " in ASCII " << endl;
}
and everything works as it should, counting and adding up the characters in the string via their ASCII numbers.
The problem I'm having is trying to figure out how this is typed up so it works recursively. I know I need to forgo the for loop in lieu of calling up the function itself, but I don't know what to use instead of the sum += s[i]; that I have going in my for loop. I've been looking around in the C string library, but I don't see anything that can replace the [i] that the for loop calls up. Does anyone know what I should be using to do this? I'm not looking for an answer in code, just need help in what I should be using to make this happen.
This is one of many ways to do it.
int reccountstr(string s, int i){
if(s.size() == i)
return (0 + s[i]);
else
return reccountstr(s, i + 1) + s[i];
}
And then in main you just call it with a zero initial argument.
cout << "This word adds up to " << reccountstr("HELLO", 0) << " in ASCII " << endl;
Skeleton could be like this:
int countlen(const char * str)
{
if (condition)
return 0;
else
return *str + countlen(str + 1);
}
The rest is up to you :)
int countString(char sample[], int i)
{
if(sample[i] == 0)
return 0;
else
return(1 + countString(sample, i+1));
}
This could be one solution, where if the current character read is not null (0, or '\0') it will return 1 + countString(sample, i + 1) where i is the current character index to be read.
Once it reaches null it returns 0. So for a character length of three, it will do 1 + 1 + 1 + 0. You can call the function with printf("%d\n", countString(yourStringName, 0)).
So your base case here is character[index] == empty
Your inductive case is 1 + function(stringName, index + 1), roughly speaking.
Also, this is a little outside the scope of your question, but you can also make this more efficient by avoiding constantly building up the stack. A way to do this is to create another variable inside the function that continuously accumulates the total count. For more info on this see this link on tail recursion:
http://c2.com/cgi/wiki?TailRecursion
More memory conservative version:
int countString(char sample[], int i, int total)
{
if(sample[i] == 0)
return total;
else
return countString(sample, i+1, ++total);
}
You can call this with printf("%d\n", countString(sample, 0, 0));

What is causing a segmentation fault?

I have been attempting to write a program that will determine if a number is prime or not. I have based it off of the Sieve of Eratosthenes. Anyway, my program works for small numbers (15485863 works), but if I use large numbers (ex. 17485863) I receive a segmentation fault. I am using unsigned long longs and do not think I have surpassed their maximum value. I just don't see what I have done wrong. Thank you in advance for any assistance!
#include <iostream>
#include <limits>
using namespace std;
bool soe (unsigned long long);
int main (void)
{
unsigned long long x = 17485863;
bool q = soe(x);
cout << x << " is ";
if(q)
cout << "prime." << endl;
else
cout << "not prime." << endl;
return 0;
}
bool soe(unsigned long long input)
{
unsigned long long arrayLength = input%2 + input/2;
unsigned long long index = 2;
unsigned long long greatestMult = 0;
bool array[arrayLength];
array[0] = true; //ignore true values in the array
array[1] = true;
do{
array[index] = false;
}while(++index < arrayLength);
index = 2;
do
{
if(input%index != 0)
{
greatestMult = input/index;
while(index*greatestMult > arrayLength)
greatestMult--;
do
{
array[index*greatestMult] = true;
}while(--greatestMult > 0);
do
{
if(!array[index])
break;
}while(++index < arrayLength);
}
else
{
cout << endl << input << " is divisble by " << index << endl;
return false;
}
}while(index < arrayLength);
return true;
}
Please note that neither long long nor using variables to dimension automatic arrays are part of C++ - they are extensions provided by gcc and should not be used if portability is an issue.
To address your problem, dimensioning an array like this:
bool array[arrayLength];
will cause a stack overflow (and thus a seg fault) if the arrayLength value is too large. Use a std::vector instead, but be aware that memory is not an infinite resource.
On Line 24 you have: bool array[arrayLength]; You cannot declare an array on the stack like this. The program is crashing on line 29. You need to declare this on the heap using new/delete;
Something to this effect (I may have a leak or two in there, but you get the idea);
//Beginning on Line 28
bool *array = new bool[arrayLength];
array[0] = true; //ignore true values in the array
array[1] = true;
do{
array[index] = false;
}while(++index < arrayLength);
index = 2;
do
{
if(input%index != 0)
{
greatestMult = input/index;
while(index*greatestMult > arrayLength)
greatestMult--;
do
{
array[index*greatestMult] = true;
}while(--greatestMult > 0);
do
{
if(!array[index])
break;
}while(++index < arrayLength);
}
else
{
cout << endl << input << " is divisble by " << index << endl;
delete [] array;
return false;
}
}while(index < arrayLength);
delete [] array;
return true;
}
Output
g++ -g test.cpp
gdb ./a.out
...clipped...
(gdb) run
Starting program: /Users/nextraztus/a.out
Reading symbols for shared libraries ++. done
17485863 is divisble by 3
17485863 is not prime.
Program exited normally.
(gdb)
It is possible for index*greatestMult to be equal to arrayLength, so you can overwrite the last element past the array end.
Also allocating large arrays on the stack like that can cause a problem depending on the operating system. Some systems will expand the stack that much, others will not be able to.