different numbers output from an array than input using recursive function? - c++

I am in the middle of making a recursive array function that counts the numbers and adds them together returning them in a recursive function. The function seems to actually work but the number I originally input into the array were 1,2,3,4,5 but the program tells me that those number are 49, 50, 51, 52, 53... Very confused on why this might be happening, any help or insight would be greatly appreciated. Thank you!
#include <iostream>
using namespace std;
const int SIZE = 5;//size of array
int sum(int [], int);//recursive function
int main()
{
int sumArray[SIZE] = { '1', '2', '3', '4', '5'};//array with predetermined values
cout << sumArray[0] << endl;//49
cout << sumArray[1] << endl;//50
cout << sumArray[2] << endl;//51
cout << sumArray[3] << endl;//52
cout << sumArray[4] << endl;//53
cout << sum(sumArray, SIZE) << endl;//displays the amount 255 (5 elements added)
system("pause");
return 0;
}
int sum(int sumArray[], int size)
{
if (size == 1)
return sumArray[size - 1];
else
{
cout << size << endl;
return sumArray[size - 1] + sum(sumArray, size - 1);
}
}

You are actually put in the array ASCII-codes of the numbers: '1' is really a char with code 49 which is converted to int 49. Write as follows:
int sumArray[SIZE] = { 1, 2, 3, 4, 5 };
This is called implicit conversion - look at the section "Integral promotion."

Related

Program does not prompt input after the first time [c++] [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 15 days ago.
Improve this question
Here is my program, it is using c++ and I done it on MacOS VSCode.
Library:
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <string>
#include <iomanip>
using namespace std;
Function:
float* read_data(int& size){
int a_size = 0;
static float a[10];
float* temp = a;
cout << "Please enter values, and press 'Q' when finished: ";
for (int i = 0; i < size; i++){
cin >> a[i];
if (cin.fail()){
break;
}else{
a_size++;
}
}
cin.clear();
size = a_size;
return temp;
}
Main function:
int main(){
int size1 = 10;
int size2 = 10;
int size3 = 0;
float array[10];
float addarray[10];
float longarray[20];
float* ptr = array;
float* addptr = addarray;
float* longptr = longarray;
cout << fixed << setprecision(2);
ptr = read_data(size1);
cout << setw(15) << "Original array" << setw(5) << "=" << setw(5) << "{ " << *ptr;
for (int i = 0; i < size1; i++){
cout << ", " << *(ptr + i);
}
cout << " }" << endl;
for (int i = 0; i < size1; i++){
*(longptr + size3) = *(ptr + i);
size3++;
}
addptr = read_data(size2);
for (int i = 0; i < size2; i++){
*(longptr + size3) = *(addptr + i);
size3++;
}
cout << setw(15) << "New array" << setw(5) << "=" << setw(5) << "{ " << *longptr;
for (int i = 0; i < size3; i++){
cout << ", " << *(longptr + i);
}
cout << " }" << endl;
return 0;
}
The main objective of the program was to prompt the user for an array, maximum of 10 elements. Prompting the user was done using the float* read_data(int& size) function.
The program would echo or print out the inputted array.
After that, the user was prompt for a second time using the same function to get another array of elements, in this case is a list of float values.
Then, the program would use a dynamic data allocation (DMA) technique to combine the two array into one long array. The new array will be printed out and the program is terminated.
Problem
As I said before, the program are supposed to prompt the user for inputs every time the read_data() were called.
I called the function twice. It did run twice, but failed to prompt the user for input the second time around.
I thought the problem was due to the cin.fail() arguments. That is why I tried to mess with the cin.ignore() and cin.clear() either by removing them or only using one of them.
I am honestly at lost on what is the root of the problem.
The heart of the issue is that you want users to enter 'Q', a char, into your float variable.
Here's a small example:
#include <iostream>
int main() {
int a;
std::cin >> a;
if (std::cin.fail()) {
std::cout << "Fail.\n";
} else {
std::cout << "All clear.\n";
}
std::cin >> a;
std::cout << (2 * a) << '\n';
}
Output:
~/tmp
❯ ./a.out
Q
Fail.
0
~/tmp
❯ ./a.out
3
All clear.
3
6
So, you can see that you were on the right track. The issue is that if std::cin did fail, you are now responsible to clean up your mess.
std::cin.clear() is a good start. It resets the fail flag bits. But the stream is still in a bad state. What you haven't done is clean it up completely.
You're calling std::cin.ignore(), but leaving the parameter list empty.
Something like this is best practice:
#include <iostream>
#include <limits>
int main() {
int a;
std::cin >> a;
if (std::cin.fail()) {
std::cout << "Fail.\n";
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::cin.clear();
} else {
std::cout << "All clear.\n";
}
std::cin >> a;
std::cout << (2 * a) << '\n';
}
Output:
~/tmp
❯ ./a.out
Q
Fail.
3
6
While that should fix address the question, your code is still fundamentally broken.
EDIT
Here's a mini-code review:
#include <iostream>
#include <algorithm> // These includes
#include <cmath> // are
#include <cstdlib> // not
#include <string> // used
#include <iomanip>
using namespace std; // Bad practice
// You should not attempt to return a C-style array
float* read_data(int& size){ // Why is the size being passed by reference?
int a_size = 0;
static float a[10]; // Not doing what you think
float* temp = a;
cout << "Please enter values, and press 'Q' when finished: ";
for (int i = 0; i < size; i++){ // Formatting; should be ") {"
cin >> a[i];
if (cin.fail()){ // Addressed above; root cause of your question
break;
}else{
a_size++;
}
}
cin.clear();
size = a_size;
return temp;
}
// While I assume the goal of the assignment is to get familiar with pointers,
// This assignment is trivial with vectors.
int main(){
int size1 = 10; // If declared const/constexpr, you'd only need one **
int size2 = 10; // These are bad names
int size3 = 0; // Front loading declarations is bad practice.
float array[10]; // ** And could use that variable here to avoid the magic number
float addarray[10];
float longarray[20]; // Not dynamic per your requirements.
float* ptr = array; // Still not dynamic, also unnecessary given the prior declarations
float* addptr = addarray;
float* longptr = longarray;
cout << fixed << setprecision(2);
ptr = read_data(size1);
// The first cout is not good, what do you think *ptr will print?
cout << setw(15) << "Original array" << setw(5) << "=" << setw(5) << "{ " << *ptr;
for (int i = 0; i < size1; i++){
cout << ", " << *(ptr + i); // The pointers can still use array syntax
}
cout << " }" << endl;
for (int i = 0; i < size1; i++){
*(longptr + size3) = *(ptr + i);
size3++;
}
addptr = read_data(size2);
for (int i = 0; i < size2; i++){
*(longptr + size3) = *(addptr + i);
size3++;
}
// As soon as you start repeating yourself, consider writing a function.
// The logic will only live in one place, and only need to be changed in
// one place.
cout << setw(15) << "New array" << setw(5) << "=" << setw(5) << "{ " << *longptr;
for (int i = 0; i < size3; i++){
cout << ", " << *(longptr + i);
}
cout << " }" << endl;
return 0;
}
A lot going on that is less than great. The biggest flub appears to be the static array. static in this scenario extends the lifetime of the variable until the end of the program. So, when you call this function the second time, you overwrite the first array with the second because there's only ever one array for every call of that function. In the future, I would refrain from grabbing random code online and just dumping it in your program unless you know what it does.
Now, let's move on to a working solution.
The first thing I'm going to do is state the requirements as I understood them.
Have the user enter data to fill two arrays of floats.
Each array should hold a maximum of ten elements.
The user enters "Q" to indicate that they are finished entering data.
Print the first array.
Tack the second array on to the end of the first, in a dynamic fashion.
Print the combined array.
Anytime you get an assignment, your first task should be to restate the problem in your own words. This will clarify requirements and you will demonstrate to yourself that you understand the problem to be solved.
What makes this interesting is the "Q" to quit. Note that I'm using double quotes. We will read all of our data as strings, and we have to convert to float as needed.
std::stof() exists, but it's not as simple as just calling it. That function can throw exceptions, and we want to ensure that only actual float values get converted.
So we'll wrap that call in a function of our own. Here's an example:
#include <exception>
#include <iostream>
#include <string>
class bad_user_input : public std::exception {
const char* what() const noexcept override {
return "User input was not valid.";
}
};
float convert_string_to_float(const std::string& val) {
std::size_t marker = 0;
float f = 0.0f;
try {
f = std::stof(val, &marker);
} catch(...) {
throw bad_user_input();
}
// Was the entire value entered a float?
if (marker != val.length()) {
throw bad_user_input();
}
// Getting here means a valid float was entered.
return f;
}
int main() {
float f = 0.0f;
// Test the function
try {
f = convert_string_to_float("5.6");
} catch(...) {
std::cerr << "Issue.\n";
}
std::cout << f << "\n\n";
f = 0.0f;
try {
f = convert_string_to_float("5.6cat");
} catch(...) {
std::cerr << "Issue.\n";
}
std::cout << f << "\n\n";
f = 0.0f;
try {
f = convert_string_to_float("Q");
} catch(...) {
std::cerr << "Issue.\n";
}
std::cout << f << '\n';
}
Output:
❯ ./a.out
5.6
Issue.
0
In convert_string_to_float
stof: no conversion
Issue.
0
Now that we can convert strings to floats, with guarantees, we are ready to read values. To test that we're reading correctly, we also want to be able to print our arrays:
#include <exception>
#include <iostream>
#include <string>
class bad_user_input : public std::exception {
const char* what() const noexcept override {
return "User input was not valid.";
}
};
float convert_string_to_float(const std::string& val) {
std::size_t marker = 0;
float f = 0.0f;
try {
f = std::stof(val, &marker);
} catch(...) {
throw bad_user_input();
}
// Was the entire value entered a float?
if (marker != val.length()) {
throw bad_user_input();
}
// Getting here means a valid float was entered.
return f;
}
void read_array_from_user(float* arr, int& size, const int maxCapacity, std::istream& sin = std::cin) {
size = 0;
std::string input;
while (size < maxCapacity && std::getline(sin, input)) {
if (input == "Q" || input == "q" || input.length() == 0) {
return;
}
try {
arr[size] = convert_string_to_float(input);
} catch(const std::exception& e) {
std::cerr << "Bad input. Reason: " << e.what() << "\nTry again.\n";
continue;
}
++size;
}
}
void print_array(float* arr, int size, std::ostream& sout = std::cout) {
sout << "{ ";
for (int i = 0; i < size; ++i) {
sout << arr[i] << (i == size - 1 ? " " : ", ");
}
sout << "}\n";
}
int main() {
constexpr int maxArrayCapacity = 10;
float arrayOne[maxArrayCapacity];
int arrayOneSize = 0;
read_array_from_user(arrayOne, arrayOneSize, maxArrayCapacity);
print_array(arrayOne, arrayOneSize);
}
Output:
~/tmp
❯ ./a.out
1
2
3
4
q
{ 1, 2, 3, 4 }
~/tmp took 3s
❯ ./a.out
1
2
Q
{ 1, 2 }
~/tmp took 2s
❯ ./a.out
1
2
3
4
5
6
{ 1, 2, 3, 4, 5, 6 }
~/tmp took 4s
❯ ./a.out
1
2
3
4
5
6
7
8
9
0
{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }
~/tmp took 5s
❯ compilecpp tmp_repair.cpp
~/tmp
❯ ./a.out
1
2
3
4
5
6
7
8
9
0
{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }
~/tmp took 4s
❯ ./a.out
1
2
3
q
{ 1, 2, 3 }
~/tmp took 2s
❯ ./a.out
1
2b
Bad input. Reason: User input was not valid.
Try again.
2
3
Q
{ 1, 2, 3 }
~/tmp took 3s
❯ ./a.out
1
2
3
Q
{ 1, 2, 3 }
~/tmp took 2s
❯ ./a.out
1
2
3
{ 1, 2, 3 }
So, we can read an array with a maximum of 10 values. The reading is robust enough to handle typos or obviously bad input. But we don't have to read 10 values, it's the maximum. We keep track of the actual size ourselves.
Take note on how simple the main() function is because we put our sub-tasks into their own functions.
Reading the second array only requires a few lines in our main() now.
int main() {
constexpr int maxArrayCapacity = 10;
float arrayOne[maxArrayCapacity];
int arrayOneSize = 0;
read_array_from_user(arrayOne, arrayOneSize, maxArrayCapacity);
print_array(arrayOne, arrayOneSize);
float arrayTwo[maxArrayCapacity];
int arrayTwoSize = 0;
read_array_from_user(arrayTwo, arrayTwoSize, maxArrayCapacity);
print_array(arrayTwo, arrayOneSize);
}
Easy-peasy there. Now we need to combine the arrays "dynamically."
We know the sizes of our two arrays, so we know the size of the final array. Now we just need to allocate the memory on the heap. I'm not going to use new, which is what I assume you're supposed to do. My reasoning is that C++ has had better methods for managing dynamic allocations since 2011.
#include <memory>
// ...
int main() {
constexpr int maxArrayCapacity = 10;
float arrayOne[maxArrayCapacity];
int arrayOneSize = 0;
read_array_from_user(arrayOne, arrayOneSize, maxArrayCapacity);
print_array(arrayOne, arrayOneSize);
float arrayTwo[maxArrayCapacity];
int arrayTwoSize = 0;
read_array_from_user(arrayTwo, arrayTwoSize, maxArrayCapacity);
print_array(arrayTwo, arrayTwoSize);
int combinedArraySize = arrayOneSize + arrayTwoSize;
// This is considered dynamic; it's allocated on the heap
auto combinedArray = std::make_unique<float[]>(combinedArraySize);
int idx = 0;
for (int i = 0; i < arrayOneSize; ++i) {
combinedArray[idx] = arrayOne[i];
++idx;
}
for (int i = 0; i < arrayTwoSize; ++i) {
combinedArray[idx] = arrayTwo[i];
++idx;
}
print_array(combinedArray.get(), combinedArraySize);
}
Output:
~/tmp
❯ ./a.out
1
2
q
{ 1, 2 }
3
4
5
q
{ 3, 4, 5 }
{ 1, 2, 3, 4, 5 }
Hopefully, the most gnarly stuff is over where you get the user input, mostly due to the requirement that users can enter a letter to signal they're done. And that makes sense since now you have to do type conversions. Other languages like python make it possible with a lot less LOC (Lines Of Code) on your part. The task itself is not difficult, but ensuring users behave is a whole other beast. If you're allowed to assume well-behaved input will always be provided, you can simplify the code quite a bit.

Implement a function that prints an array using pointers

I need to print an array by implementing the use of a function before the main function. So I tried the following function:
int* printArr(int* arr)
{
for (int i = 0; i < 5; i++) {
cout << arr[i];
}
return arr;
}
I encountered two problems when implementing this into the whole code.
First, this is printing what I think is the address of the array and not the actual array. Pretty sure this is because of the return arr; in line 10. But if I do not write return then the code will produce an error. How can I fix this?
Second, I do not understand the second argument printArr has. In line 19, you can see cout << printArr(arr, 5) << endl;. How come there is a single numeric value, that one being 5 in this case, as an argument? How can I account for this in my function?
Please keep in mind that I am new to C++ and coding in general. Also, this code was given to me, hence why I do not understand certain aspects of it.
This is my code so you can see what I mean:
#include <iostream>
using namespace std;
// Declare function printArr here
int* printArr(int* arr)
{
for (int i = 0; i < 5; i++)
{cout << arr[i];}
return arr;
}
int main()
{
int arr[5] = {1, 3, 5, 7,9};
int last_num = arr[sizeof(arr)/sizeof(int)-1];
cout << "Before reversing" << endl;
cout << printArr(arr, 5) << endl;
// reverse "arr" using reference(&)
cout << "After reversing" << endl;
printArr(arr, 5);
return 0;
}
The declaration and implementation of printArr() is all wrong.
First, this is printing what I think is the address of the array and not the actual array.
The printArr() function itself is printing the contents of the array (well, the first 5 elements anyway), and then returning the address of the array. It is main() that is printing that address afterwards, when it passes the return value of printArr() to std::cout <<.
Pretty sure this is because of the return arr; in line 10. But if I do not write return then the code will produce an error. How can I fix this?
By getting rid of the return type altogether. There is no good reason to return the array pointer at all in this example, let alone to pass that pointer to std::cout. So printArr() should be returning void, ie nothing.
Second, I do not understand the second argument printArr has. In line 19, you can see cout << printArr(arr, 5) << endl;. How come there is a single numeric value, that one being 5 in this case, as an argument?
Because main() is passing in the element count of the array (5) so that printArr() can know how many elements to actually print, instead of hard-coding that value in the loop. However, your declaration of printArr() does not have a 2nd parameter with which to accept that value, that is why you are getting errors.
How can I account for this in my function?
By adding a 2nd parameter in the function declaration, eg:
#include <iostream>
using namespace std;
// Declare function printArr here
void printArr(int* arr, int size)
{
for (int i = 0; i < size; i++)
{
cout << arr[i] << ' ';
}
cout << endl;
}
int main()
{
int arr[5] = {1, 3, 5, 7, 9};
const int count = sizeof(arr)/sizeof(arr[0]);
int last_num = arr[count-1];
cout << "Before reversing" << endl;
printArr(arr, count);
// reverse "arr" using reference(&)
cout << "After reversing" << endl;
printArr(arr, count);
return 0;
}
Live Demo

Confusion with function pointer, __cdecl, and template

In Visual Studio 2019, I have written the following test codes, but the results confused me.
#include <iostream>
using namespace std;
template<class T, class Func>
int call(T x, Func f) { return f(x); }
int square(int x) { return x * x; }
int main() {
int (*func0) (int) = square; // line 0, OK
//int (func1)(int) = square; // line 1, wrong
int (__cdecl *func1) (int) = square; // line 2, OK
//int (__cdecl func2)(int) = square; // line 3, wrong
cout << ((int(__cdecl*)(int)) square)(5) << endl; // line 4, OK
//cout << ((int(__cdecl)(int)) square)(5) << endl; // line 5, wrong
cout << call<int, int (*)(int)>(5, square) << endl; // line 6, OK
//cout << call<int, int ()(int)>(5, square) << endl; // line 7, wrong
cout << call<int, int(__cdecl*)(int)>(5, square) << endl; // line 8, OK
cout << call<int, int(__cdecl)(int)>(5, square) << endl; // line 9, OK
return 0;
}
(I am aware that I can omit the types when using call, but this is an experiment.)
I thought I was able to understand everything from line 0 to line 7. What I had in mind is that square is a funtion pointer, so it should have type int (*) (int) or perhaps int(__cdecl*) (int), and these two are either identical or can be casted to each other (I didn't change the calling convention of the project, so the default is __cdecl).
However, I was surprised that both line 8 and line 9 compile and run correctly. Why does this happen?
By comparing lines 6, 7 with lines 8, 9, I think the problem comes from adding __cdecl, but in Microsoft Docs nothing like this is mentioned.
I then printed out the types:
// ...
cout << typeid(square).name() << endl; // output: int __cdecl(int)
cout << typeid(*square).name() << endl; // output: int __cdecl(int)
cout << typeid(&square).name() << endl; // output: int(__cdecl*)(int)
cout << (typeid(square) == typeid(int(*) (int))) << endl; // output: false
cout << (typeid(square) == typeid(int(__cdecl) (int))) << endl; // output: true
cout << (typeid(square) == typeid(int(__cdecl*) (int))) << endl; // output: false
cout << (typeid(square) == typeid(*square)) << endl; // output: true
// ...
It seems that square indeed has type int (__cdecl) (int). Also, I don't understand why square and *square are of the same type...
Could someone explain these phenomena to me?
square and *square are the same type because functions decay, just like arrays do, to pointers, except (just like arrays) under certain contexts. In particular, decay is suppressed under typeid and &, but not under *, so typeid(square) gives you the type of square, int (__cdecl)(int), while typeid(*square) means typeid(*&square) means typeid(square) gives the same thing. This leads to the odd fact that you can write as many *s as you want and they will all do nothing: *************square is the same as square.
Now, to the rest of your question, you wrote the type "function taking int returning int" wrong. int ()(int) means "function taking no arguments returning function taking int returning int". You wanted int(int). Then this works:
cout << call<int, int(int)>(5, square) << "\n"; // line 7, fixed (FYI: endl is not normally necessary)
Because now call has arguments list (int x, int f(int)), and a parameter declaration of function type is automatically adjusted to have pointer to function type, making call<int, int(int)> functionally identical to call<int, int (*)(int)>. (This does not work for variable declarations or casts, so lines 1, 3, 5 remain incorrect.) The extra parentheses caused the type to be misinterpreted. Line 9 works because putting __cdecl inside the parentheses makes them not be misinterpreted (instead of being the function declarator, they become grouping symbols).
cout << call<int, int (__cdecl)(int)>(5, square) << "\n"; // line 9, OK
Again, the type of call's parameter is adjusted. int (__cdecl f)(int) becomes int (__cdecl *f)(int), which makes line 9 functionally identical to line 8.
The error with the line:
int (func1)(int) = square; // line 1, wrong
is that you are missing a '*', it needs to be:
int (*func1)(int) = square; // line 1, wrong
same with
//int (__cdecl func2)(int) = square; // line 3, wrong
cout << ((int(__cdecl)(int)) square)(5) << endl; // line 5, wrong
needs to be
cout << ((int(__cdecl*)(int)) square)(5) << endl; // line 5, wrong

Reverse array with recursion C++

My main idea is to shrink they array from both sides . For example if the input is 1234 , wanna print 1234 and then 4321 (the reversed) .
#include <iostream>
#include <cmath>
#include <math.h>
using namespace std;
int reversedArray(int* x)
{
cout<< "*x out of while =" << *x <<endl ;
while( *x != 0 )
{
cout << "*x=" << *x << endl;
cout<< "====================== im in reversed =================" << endl ;
return reversedArray( x+1 );
}
cout<< "after return " << *x << endl;
}
int main ()
{
int Array[] = {10,2,3,4,8 ,0} ;
int* p_Array = Array;
reversedArray( Array );
}
After the "while" , why the functions that are in the stack, do not return to the next line ( " the --> cout<< "after return " <<*x <
void printReversed(int * x)
{
if (*x == 0) return;
std::cout << *x;
printReversed(x+1);
std::cout << *x;
}
The line:
return reversedArray( x+1 );
exits the function. So you never repeat the while or execute any of the code after the while if you go into the while. This makes the while effectively an if statement.
The code posted by Crazy Eddie does the job and Barmar explains the ineffectiveness of the while loop. I decided to post a non-recursive way to address the problem mentioned.
#include <iostream>
#include <vector>
using namespace std;
vector<int> reverseArray(vector<int>& arr) {
vector<int> ans;
int n = arr.size();
// insert all elements in the reverse order
for (size_t i = 0; i < n; i++) {
ans.push_back(arr[n-i-1]);
}
return ans;
}
int main ()
{
int array[] = {10, 2, 3, 4, 8, 0};
// convert into vector
vector<int> arr(array, array+6);
vector<int> rev = reverseArray(arr);
// merging the 2 arrays
arr.insert(arr.end(), rev.begin(), rev.end());
// printArray(arr) -- implement to fit your needs;
}
When you pass an int[] to a function it decays to an int* which is simply an address in memory. C++ a better plan would be to use copy_backward with an ostream_iterator:
copy_backward(Array, Array + sizeof(Array) / sizeof(*Array), ostream_iterator<int>(cout, " "))
Note that this method uses the actual size of the array, and does not depend upon a terminal element. Thus, no numbers are offlimits, and it's impossible to segfault by failing to provide the terminating element.
If you have access to C++11 you can simplify that a bit further to:
copy(crbegin(Array), crend(Array), ostream_iterator<int>(cout, " "))
Live Example

Recursively return if statement calls

I'm trying to design a program that takes an integer array as input, and then returns all combinations of values that add up to a predetermined sum. For the sake of clarity, my recursive function will return true when the total adds up to 10.
However, I also want it to return the values from the array that comprise of this total, so my definition is as follows;
If suminarray returns true, print each number from the array.
My hope was, once my base clause is reached, the recursion would unwind, and my if statements would all be evaluated, and each value would be printed from my if statement. However, all that is printed is last value from the array which made up the target total, not all the values that preceded it.
I've likely misunderstood the recursive behaviour of C++. I know how to work with recursive return calls, but logically, if the if statement can't be evaluated until the recursive function returns true or false, shouldn't they unwind, also?
#include <iostream>
bool suminarray(int *numbers, const int &size, int startPos, int total);
using namespace std;
int main()
{
int numbers[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
int startPos = 0;
int total = 0;
suminarray(numbers, 10, 0, total);
return 0;
}
bool suminarray(int *numbers, const int &size, int startPos, int total)
{
if(total == 10)
{
cout << "result. " << endl;
return true;
}
else if(total > 10)
{
return false;
}
else
{
for(int i = startPos; i < size; i++)
{
cout << " loop " << i << endl;
cout << " total" << total << endl;
if(suminarray(numbers, size, i+1, total+numbers[i]) == true)
{
cout << "Uses " << numbers[i] << endl;
}
}
}
}
Edit: correction to source code.
The immediate problem (which your compiler should be warning you about), is that you have no return statement in the final else block, which causes the function to fall off the end without returning either true or false, leading to undefined behavior. If you fix that in the most obvious way:
else
{
for(int i = startPos; i < size; i++)
{
cout << " loop " << i << endl;
cout << " total" << total << endl;
if(suminarray(numbers, size, i, total+numbers[i]) == true)
{
cout << "Uses " << numbers[i] << endl;
return true;
}
}
return false;
}
your program then works, but it only prints the FIRST set of values that add up to 10 that it finds.
That immediately shows you the problem with your approach -- each function call can only return ONCE -- you can't (easily) have it both return success AND continue to try more alternatives.
As you've already guessed, the way you're imagining the recursive function unwinding is wrong.
In your example, you want to get to a total of 10, with numbers starting at 1, and ending at 9. So, first your recursive function will make the total = 1. Then it will add another 1 to that until it gets all the way down to the tenth 1. Then it will print result, then it will unwind 1 step, and print 1.
Good so far right? Well, here's where it goes off track. At this point it doesn't unwind all the way. It still stays at 9, but this time it adds a 2 to that, fails goes back until it unwinds to a sum of 8. Now it tries 2 and works this time! Printing result, then 2.
This, as i've understood, isn't what you want. What you should be doing is make something else to hold your array of answers, and not just print them.
I know how to work with recursive return calls, but logically, if the if statement can't be evaluated until the recursive function returns true or false, shouldn't they unwind, also?
This is correct. The reason you are only seeing one print statement at the end is because only one call is returning 'true'. Therefore the 'if' statement is only true once and you only see one print statement for "Uses ".
I believe your mistake is that you didn't add a return statement after your for loop. This means the return value for your function is actually undefined. Start using the -Wall flag when you compile to make sure you don't make this mistake. Here is a version where I added a "return true;" after the 'for' loop:
#include <iostream>
bool suminarray(int *numbers, const int &size, int startPos, int total);
using namespace std;
int main()
{
int numbers[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
int startPos = 0;
int total = 0;
suminarray(numbers, 10, startPos, total);
return 0;
}
bool suminarray(int *numbers, const int &size, int startPos, int total)
{
if(total == 10)
{
cout << "result. " << endl;
return true;
}
else if(total > 10)
{
return false;
}
else
{
for(int i = startPos; i < size; i++)
{
cout << " loop " << i << endl;
cout << " total" << total << endl;
if(suminarray(numbers, size, i, total+numbers[i]) == true)
{
cout << "Uses " << numbers[i] << endl;
}
}
}
return true;
}