0

I am playing with command line arguments and implementing a very basic calculator which takes input before execution rather than at runtime. It works for 4 operations, but I am stuck at the power operation and after hours identified the fault. Here is the C++ code:

#include <iostream>
#include <sstream>
#include <cmath>
#include <cstring>

using namespace std;

int main(int argc, char **argv) {

    stringstream s(strcat(strcat(argv[1], " "), argv[3]));
    int a, b;
    s >> a >> b;

    switch(argv[2][0]) {
        case '+':
            cout << a+b;
            break;
        case '-':
            cout << a-b;
            break;
        case '*':
            cout << a*b;
            break;
        case '/':
            cout << a/b;
            break;
        case 'p':
            cout << pow(a, b);
            break;
        default:
            cerr << "Invalid operation";
            exit(EXIT_FAILURE);
    }

    exit(EXIT_SUCCESS);
}

The problem here is that earlier, I used '^' instead of 'p'. This character doesn't work at all, i.e., nothing is printed to console. I used debug prints, modified header files, typecasted a and b to double in pow() but the bug was this nasty little '^'. Albeit the code works well, I wish to know why this one character was exceptional in the cmd arguments? I am using Windows Command Line for the shell.


An image of the output with 'p': calc.exe command line output

And with '^': output with caret

2 Answers2

0

Don't do this:

strcat(strcat(argv[1], " "), argv[3])

You are overflowing the size of the buffer for argv[1].

Instead use a std::string to correctly allocate the amount of memory needed to perform concatenation.

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
  • Fine, now I am using C++ strings and stoi() for the conversion. But it never showed a buffer overflow warning, so what is the size limit for argv[1]? – Saarthak Sabharwal Oct 12 '20 at 18:03
  • 1
    `stringstream` was fine for the conversion, although it's definitely easier to convert two numbers stored in separate `argv` elements independently instead of concatenating them and separating them again. The size limit for `argv[1]` is the size of the string already in it when `main(argc, argv)` is called. – Ben Voigt Oct 12 '20 at 20:47
0

In windows shell (Batch script), a caret (^) is an escape character (see more here: What does symbol ^ mean in Batch script?). So if you want it to be seen as a normal character by the shell, you need to escape it...with itself!

So you'd run:

calc.exe 3 ^^ 3

You can test this by using echo in the shell. You can run echo te^st to see what the shell treats it as, and then run echo te^^st.


Furthermore, you should add at least some error handling in your program to catch things like this sooner. For example, you could check argc to make sure the number of arguments passed match what you expect. You could add check around s >> a >> b to ensure that numbers were actually passed, etc...

scohe001
  • 15,110
  • 2
  • 31
  • 51
  • This solved the problem. I guess I'll use p or something else but not a caret. Also, as you suggested, I added exception catching functionality and a few more operators too, and it looks good now. Thanks! – Saarthak Sabharwal Oct 12 '20 at 18:01