Why do I have to pass by reference?

Hi!

Currently I'm reading a book on algorithms and recursion
and so far I think I'm getting better.But I wanted to test my skills so I tried to parse a simple math expression like 25+6
and it works but only when I pass by reference which I don't understand can someone explain this to me please?

here's my code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include <iostream>


int morph(char*& expr)
{
    int answer=0;

    while(*expr!='\0')
    {
        if(*expr>='0' && *expr<='9')
        {
            answer+=*expr-'0';
            *expr++;

            while(*expr!='\0' && *expr>='0' && *expr<='9')
            {
                answer=answer*10+*expr-'0';
                expr++;
            }
        }

        else if(*expr=='+')
        {
            *expr++;
            answer+=morph(expr);
        }

        else if(*expr=='-')
        {
            *expr++;
            answer-=morph(expr);
        }
    }

    return answer;

}



int main()
{
    char *some="25+6";
    int idk=0,i=0;

    while(*some++) i++;
    for(int j=0;j<i+1;j++) *some--;

    idk=morph(some);

    std::cout<<idk<<"\n";
}


Thank you for your time and answers!
it works
I take your word for it, since your algorithm is so complicated I won’t ever try to do the math.
But a simpler algorithm, which result we can easily check, displays some issues. Please compare the following two outputs (the code is the same, but in the second case the pointer is passed by copy):
I version) by reference:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include <iostream>

int morph(char*& expr);

int main()
{
    char *some = "25+6";    // deprecated in C++
    int idk=0, i=0;         // better not to declare variables far from where
                            // they are used

    while(*some++) i++;     // what's bad in std::strlen()?
    for(int j=0; j<i+1; j++) *some--; // ?? maybe (*some)++ ?

    idk = morph(some);

    std::cout << "some is now \"" << some << "\" and idk is " << idk << '\n';
}

int morph(char*& expr)
{
    int answer = 0;
    while(*expr) {
        switch(*expr) {
        case '0': case '1': case '2': case '3': case '4':
        case '5': case '6': case '7': case '8': case '9':
            answer += *expr - '0';
            std::cout << "*expr: " << *expr << "; adding " << *expr - '0'
                      << " to answer.\n";
            break;
        case '+':
            answer += 1000;
            std::cout << "*expr: " << *expr << "; adding 1000 to answer.\n";
            break;
        case '-':
            answer -= 1000;
            std::cout << "*expr: " << *expr << "; subtracting 1000 to answer.\n";
            break;
        default:
            std::cout << "unknown character met: '" << *expr << "'.\n";
            break;
        }
        ++expr;
    }
    return answer;
}


Output:
*expr: 2; adding 2 to answer.
*expr: 5; adding 5 to answer.
*expr: +; adding 1000 to answer.
*expr: 6; adding 6 to answer.
some is now "" and idk is 1013


II version) by copy
just change
int morph(char*& expr);
into
int morph(char* expr);

Output:
*expr: 2; adding 2 to answer.
*expr: 5; adding 5 to answer.
*expr: +; adding 1000 to answer.
*expr: 6; adding 6 to answer.
some is now "25+6" and idk is 1013


If you pass the pointer by reference, not only the pointed memory is modified, but the pointer itself too (as expected).
The second output also points out that the following loop:
for(int j=0; j<i+1; j++) *some--;
does nothing.
Perhaps you want to check the operator precedence:
http://en.cppreference.com/w/cpp/language/operator_precedence
Postfix decrement has an higher precedence than indirection.

Going back to your code, I’d start by working out the issues pointed out by the compiler, and then outputting my algorithm while it works: I suspect it can be simplified.

Here a starting example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#include <limits>
#include <iostream>

int morph(char* expr);
void waitForEnter();

int main()
{
    char some[] { '2', '5', '+', '6', '\0' };

    // why not std::size_t somesize { std::strlen(some) }; ?
    std::size_t somesize {};
    for(/**/; some[somesize]; ++somesize); // somesize == std::strlen(some) + 1

    std::cout << "'some' now is \"" << some << "\"\n";
    for(std::size_t j {}; j < somesize; ++j) { --some[j]; }
    std::cout << "'some' now is \"" << some << "\"\n";
    waitForEnter();

    int idk = morph(some);
    std::cout << "idk is " << idk << '\n';
}

int morph(char* expr)
{
    int answer = 0;

    while(*expr) {
        if(*expr >= '0' && *expr <= '9') {
            answer += *expr - '0';
            *expr++; // ?? do you mean (*expr)++; ?

            while(*expr != '\0' && *expr >= '0' && *expr <= '9') {
                answer = answer * 10 + *expr - '0';
                expr++;
            }
        }

        else if(*expr == '+') {
            *expr++; // ?? do you mean (*expr)++; ?
            answer += morph(expr);
        }

        else if(*expr == '-') {
            *expr++; // ?? do you mean (*expr)++; ?
            answer -= morph(expr);
        }

        else {
            std::cout << "unknown character met: '" << *expr << "'\n";
            waitForEnter();
        }
    }
    return answer;
}

void waitForEnter()
{
    std::cout << "\nPress ENTER to continue...\n";
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}


Output:
'some' now is "25+6"
'some' now is "14*5"

Press ENTER to continue...

unknown character met: '*'

Press ENTER to continue...

unknown character met: '*'

Press ENTER to continue...

...infinite loop.
only when I pass by reference which I don't understand

Ok, the short answer is: because your function is recursive.
Since it moves the pointer through your string literal, it can’t be passed by copy, otherwise when it returns to the caller (which is itself), the caller would work on already managed characters.

Are your trying to implement some sort of calculator? I’ve been taken in by the name “morph()”, I guess.
Your code is fine, but you don’t need to access the pointed memory in many places; I mean, sometimes when you write
*expr++;
what you need is only to increment the pointer
expr++;
not to access the pointed memory.

If you used the subscript operator [] where you calculate your string literal length, you wouldn’t need to ‘restore’ your pointer later here:
for(int j=0;j<i+1;j++) *some--;
(I admit I couldn’t understand the purpose of that line).
Again, you don’t need indirection there.
Thank you and about the *some-- I forgot to remove it when pasting it here
and as I said I am reading a book on recursion and algorithms.
I was hoping if I could make something similar from the book like parsing a math expression.
with recursion.
That and because I wanted to test my skills on recursion
and try to write something complex(at least in my eyes) as
1
2
3
4
5
unsigned long fib(unsigned n)
{
      if(n<2) return 1;
      else return fib(n-1) + fib(n-2);
}
Topic archived. No new replies allowed.