So I wanted to create a simple console calculator that'd take arguments via the int main(int argc, char ** argv)
function. It works for regular examples, but trying multiplication with '*' started giving me way too many arguments listed in argv[], so I tinkered around and figured out it was listing all the files in the folder when '*' was used, supposedly for multiplication. I turned the if statement to always be true for debugging. I didn't find anything wrong with cerr
, although I could've used the try-catch block.
I looked around the internet to see the reason for that, and I found that the asterisk can be used as some sort of wildcard to look for files in the folder, pretty similar, but not exactly what I was looking for. Thoughts?
Source code:
#include <iostream>
#include <string>
using namespace std;
int main(int argc, char ** argv)
{
cout << "Argument count: " << argc << endl;
if(true) // argc != 4
{
int i(0), j(0);
while(argv[i])
{
j = 0;
while(argv[i][j])
{
cout << argv[i][j];
++j;
}
cout << endl;
++i;
}
}
//cerr << "Inadequate amount of arguments! " << argc;
else
{
double num1, num2;
try
{
num1 = stoi(argv[1]), num2 = stoi(argv[3]);
}
catch(exception e)
{
cout << "Unable to transform to integer.\n";
return -1;
}
char op = *argv[2];
switch(op)
{
case '+': cout << num1 + num2; break;
case '-': cout << num1 - num2; break;
case '*': cout << num1 * num2; break;
case '/': cout << num1 / num2; break;
default: cout << "Invalid operator.";
}
}
}
This has likely nothing to do with C++ and everything to do with your shell.
Bash and other sh-like shells allow you to use "glob" patterns to name multiple files easily. This allows you to, for example, easily move all .png files in a directory to another directory with a command like mv *.png some-other-dir
. The shell substitutes *.png
for the names of all files in the current directory that end in ".png".
*
is the "match anything" pattern, so a *
in a command will expand to the names of all files in the current directory. That means that if you run ./my_program 3 * 4
in a directory containing the files "my_program", "foo.txt", and "bar.txt", your shell will expand the *
character and actually run ./my_program 3 bar.txt foo.txt my_program 4
.
You can disable this expansion by wrapping the *
character in single quotes or escaping it with a \
. If you run ./my_program 3 '*' 4
or ./my_program 3 \* 4
, your shell will not expand the *
, and argv
will contain {"./my_program", "3", "*", "4"}
.
Note that Windows CMD shell does not do this sort of expansion. If you want this behavior on Windows you would have to link your program to setargv.obj to get the runtime library to do it for you or implement the expansion yourself.