How to pass ".*" as an argument to the program in visual studio code?

Viewed 1268

I am coding a program in C++ where I want to pass ".*" (period and asterisk) as an argument to the program. I use the Visual Studio Code editor which might be causing this problem unless I do not know enough about command-line.

Below is my launch.json for visual studio code.

{
    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "g++.exe - Build and debug active file",
            "type": "cppdbg",
            "request": "launch",
            "program": "${fileDirname}\\${fileBasenameNoExtension}.exe",
            "args": [".*", "ajiaugbfal"], // I am sure I am doing this correctly
            "stopAtEntry": false,
            "cwd": "${fileDirname}\\",
            "environment": [],
            "externalConsole": false,
            "MIMode": "gdb",
            "miDebuggerPath": "C:\\mgw\\mingw64\\bin\\gdb.exe",
            "setupCommands": [
                {
                    "description": "Enable pretty-printing for gdb",
                    "text": "-enable-pretty-printing",
                    "ignoreFailures": true
                }
            ],
            "preLaunchTask": "C/C++: g++.exe build active file"
        }
    ]
}

But when debugging in visual studio code, that argument appears differently as shown in the image below. ".*" should appear as the value stored in the variable arg_pattern (in the pane on the left under variables). Debugging screenshow

I have attached my code for reference.

#include <iostream>
#include <string>
#include <limits>


using std::cin;
using std::cout;
using std::endl;
using std::string;


void clear_istream() {
    cin.clear();
    cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}


class Solution {
public:
    bool isMatch(string arg_string, string arg_pattern) {
        if (arg_string.length() == 0) return false;
        string::iterator iterator_string = arg_string.begin();
        string::iterator iterator_pattern = arg_pattern.begin();
        char character_previous = '\0';
        while (iterator_string != arg_string.end()) {
            if (iterator_pattern == arg_pattern.end()
                && iterator_string != arg_string.end()) return false;
            if (int(*iterator_pattern) >= int('a') && int(*iterator_pattern) <= int('z')) {
                if (*iterator_string != *iterator_pattern) return false;
                character_previous = *iterator_pattern;
                iterator_pattern = iterator_pattern + 1;
                iterator_string = iterator_string + 1;
            } else if (*iterator_pattern == '.') {
                character_previous = *iterator_pattern;
                iterator_pattern = iterator_pattern + 1;
                iterator_string = iterator_string + 1;
            } else if (*iterator_pattern == '*') {
                if (character_previous == '.') return true;
                while (*iterator_string == character_previous) iterator_string = iterator_string + 1;
                iterator_pattern = iterator_pattern + 1;
            } else if (*iterator_pattern != *iterator_string) return false;
        }
        if (iterator_pattern != arg_pattern.end()) return false;
        return true;
    }
};


int main(int arg_count_arguments, char **arg_arguments_command_line) {
    string input;
    string pattern;
    Solution solver;
    int index = 0;
    /* if you are trying in VS Code, comment the loop and return statement right under.
When using VSCode debugger. Put a breakpoint whenever solver's "isMatch" is called. 
Proceed step-by-step to check the value of "arg_pattern".
if you are using command-line pass: .* random_stuff.
    */
    while (index < arg_count_arguments) {
        cout << arg_arguments_command_line[index] << endl;
        index++;
    }
    return 0;
    index = 2;
    if (arg_count_arguments < 3) {
        cout << "Pattern ?: ";
        cin >> pattern;
        cout << endl;
        clear_istream();
        while (cin >> input) {
            cout << index << ' ' << solver.isMatch(input, pattern) << endl;
            clear_istream();
        }
    } else {
        while (index < arg_count_arguments) {
            cout << index << '-' << solver.isMatch(arg_arguments_command_line[index], arg_arguments_command_line[1]) << endl;
            index = index + 1;
        }
    }
    return 0;
}

EDIT:

Insight: So .* actually causes the program to fetch the name of the first folder(or directory) in the directory of the program. I.e if there is a folder (named: name_folder) on the top of the directory in which the program is located, .* passed to the program on command-line refers to name_folder and the name is passed. So, how to pass .* ?

3 Answers

Got similar ploblem with * in a path which I tried to pass as an argument in launch.json.

Here is what I found working for me and also your case.

"args": ["path=./data/*/images"] -->
"args": ["path=`echo \"./data/*/images\"`"]

"args": [".*"] --> 
"args": ["`echo \".*\"`"]

`cmd` – tells bash to execute the cmd inside of the string.

echo "string" – prints string to the standard output.

\" – escaping " because we are already inside of quotes.

As you have discovered, the * is a glob match for any number of characters. To avoid this, just escape the asterisk to avoid it being a glob: ".\\*".

glob man page for additional info.

So as per my initial research behind this, it did not seem possible to do it. Thank you to SuperStomer to discover compilers have an effect.

Cygwin g++ won't have the problem but MinGW g++ seems to have. The least troublesome argument when using MinGW is "\.*", instead of passing ".*" as an argument, it seems to work with the least modification I.e only one '\'.

Related