1

I want to remove a file, the name of which is given as an argument to the program; but, as the filetype will remain constant (.bat), I want it to be automatically given by the program (e.g. running deletefile.exe script will delete "script.bat" (which is in the same directory)). I have seen this question, but the solution does not seem to work.

Have I misinterpreted something here?

My attempt is below:

#include <iostream>
#include <fstream>
#include <string>


using namespace std;

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

    if(argv[1] == string("del")){
        string file_to_remove;
        file_to_remove = argv[2]+".bat";
        if (remove(file_to_remove.c_str()) != 0){
            cout<<"Error in file deletion.\n";
        }
        else {
            cout<<"Removed alias " << argv[2] << "\n";
        }
    }
    return 0;
}

But this results in a compiler error

<source>: In function 'int main(int, char**)':
<source>:12:33: error: invalid operands of types 'char*' and 'const char [5]' to binary 'operator+'
   12 |         file_to_remove = argv[2]+".bat";
      |                          ~~~~~~~^~~~~~~
      |                                | |
      |                                | const char [5]
      |                                char*
463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185
Gurnoor
  • 133
  • 2
  • 7
  • 2
    Does this answer your question? [c++ invalid operands of types 'char\*' and 'const char \[2\]' to binary 'operator+'](https://stackoverflow.com/questions/25181874/c-invalid-operands-of-types-char-and-const-char-2-to-binary-operator) – Ruzihm Jul 01 '21 at 19:05
  • @Ruzihm Ach! I should have looked for the duplicate. Tsk. – Adrian Mole Jul 01 '21 at 19:06
  • @AdrianMole I do like your answer below though - If this ends up getting closed, would you copy it to the other question? I'll upvote it there too – Ruzihm Jul 01 '21 at 19:07
  • 1
    @Ruzihm Actually, I'm not entirely sure that other question *is* a duplicate. It's certainly closely related, though. I didn't vote-to-close, as that would have been a casting (hammer) vote. – Adrian Mole Jul 01 '21 at 19:46

2 Answers2

3

The right-hand side of your file_to_remove = argv[2]+".bat"; statement is attempting to concatenate two char* strings using the + operator; you can't do this, and at least one of the operands must be made into a std::string.

You can do this by constructing a temporary std:string, like this:

file_to_remove = string(argv[2]) + ".bat";

Or, more tersely (since C++14), by adding the s suffix to the string literal:

file_to_remove = argv[2] + ".bat"s;
Adrian Mole
  • 49,934
  • 160
  • 51
  • 83
3

Don’t write using namespace std;.

You can, however, in a CPP file (not H file) or inside a function put individual using std::string; etc. (See SF.7.)


A previous answer from Adrian already explained that your use of + didn't work because it wasn't string yet. But, you also declared the variable on one line with no initializer, and assigned on the next line. You should initialize the variables when declaring them. So, it would be simple to write it as:

string file_to_remove = argv[2];
file_to_remove = += ".bat";

However, note that there is a type that is specifically for file names!

std::filesystem::path file_to_remove = argv[2];
file_to_remove.replace_extension (".bat");

This is better because it could sense that there is already an extension and change it, as well as provide other forms of filename manipulation.

if (remove(file_to_remove.c_str()) != 0){

Similarly, there is also filesystem::remove which is a C++ function and takes the path object rather than needing to produce a C-style string, and directly returns true if successful.

std::error_code ec;
if (std::filesystem::remove(file_to_remove))  cout << "File removed\n";
else cout << "error was " << ec.message() << "\n";

You can see that this makes it easy to get a readable message detailing the actual error, too.

JDługosz
  • 5,592
  • 3
  • 24
  • 45