1

I just recently got into C++, and I wanted to make something simple to start off with. I made a console program that asks the user for a file path and then deletes the file. However, I've encountered a problem I cannot seem to resolve or find a solution for. The statement DeleteFile(filePath.c_str()); is giving me 2 errors:

argument of type "const char*" is incompatible with parameter of type "LPCWSTR"

'BOOL DeleteFileW(LPCWSTR)': cannot convert argument 1 from 'const_Elem*' to 'LPCWSTR'

First of all, I need to convert std::string to LPCWSTR, so I added c_str() in the end which gave me those 2 errors.

I'm still a noob in C++ so go easy on me.

#include <iostream>
#include <string>
#include <Windows.h>
#include <fstream>

int main() 
{
    loop:
    HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE);
    std::string filePath;
    SetConsoleTextAttribute(h,15);
    std::cout << "\nEnter the path of the file you'd like to remove: ";

    if (!std::getline(std::cin, filePath)) { std::cout << "I/O error!"; }

    while (true)
    {
        if (!filePath.empty())
        {
            SetConsoleTextAttribute(h,15);
            std::cout << "[+] Checking if file exists";
            std::ifstream ifile(filePath);
            if (ifile) 
            {
                std::cout << "\n[!] File exists!";
                std::cout << "\n[#] Deleting file";
                DeleteFile(filePath);
                std::ifstream ifile(filePath);
                if (!ifile) 
                {
                    std::cout << "\n[!] File deleted successfully!";
                }
                else 
                {
                    SetConsoleTextAttribute(h, FOREGROUND_RED | FOREGROUND_INTENSITY);
                    std::cout << "\n[!] Failed to delete file";
                }
                goto loop;
            }
            else 
            {
                SetConsoleTextAttribute(h, FOREGROUND_RED | FOREGROUND_INTENSITY);
                std::cout << "\nPlease enter a valid file path!";
                goto loop;
            }

            break;
        }
        else
        {
            SetConsoleTextAttribute(h, FOREGROUND_RED | FOREGROUND_INTENSITY);
            std::cout << "Please enter a valid file path!";
            goto loop;
        }
    }
    std::cout << "\nFile deleted!";
}
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
shook_one
  • 315
  • 1
  • 4
  • 11
  • If you are compiling on one operating system only (Windows in your case?), please include the information in the question and add the corresponding tags. Different OSes have different filesystem APIs. – Aimery Nov 25 '19 at 11:40
  • 2
    The `DeleteFile` function takes an argument of either `const wchar_t *` or `const char *` depending on whether your project is configured for use of Unicode or not. If you have Unicode selected, you should change your `std::string` to `std::wstring`, or use the explicit `DeleteFileA` function (always takes `const char *`). – Adrian Mole Nov 25 '19 at 11:41
  • 1
    Also, even if you're just learning... Or rather, especialy since you're just learning: do not use `goto`! It has its places I suppose (less so in C++ where there are exceptions), but do not get into the habit of using it like this! Doesn't the compiler warn you about this anyway? Try increasing warning level... `/W4` might be good when you are learning. – hyde Nov 25 '19 at 11:42
  • If you "recently got into C++", then you should be working with a good C++ book. There are many C++ topics and skills that need to be learned -- classes, methods, multiple and virtual inheritance, templates, containers, execution threads and many more -- that are far more important to understand thoroughly, than learning how to implement basic operating system-specific tasks. Don't get off the track, but continue to read and follow along your C++ book. You have plenty of things to learn for, oh, 3-5 years or so, before running out of material and moving on to these kind of things... – Sam Varshavchik Nov 25 '19 at 11:52
  • @Adrian-ReinstateMonica When I make my filePath an std::wstring, `if(!std::getline(std::cin, filePath))` tells me `no instance of overloaded function "std::getline" matches the argument list`. If I change DeleteFile to DeleteFileA, it still doesn't delete the file for some reason? – shook_one Nov 25 '19 at 11:54
  • OK, so the second method (using `DeleteFileA`) 'nearly' works! Probably (just a wild guess) you need to close the file before you try to delete it. – Adrian Mole Nov 25 '19 at 11:55
  • @SamVarshavchik I don't have a book. I don't know how much they cost but I don't think I can afford it either way. – shook_one Nov 25 '19 at 11:55
  • @Adrian-ReinstateMonica Well I don't have it opened. I'm trying to delete an empty .txt file. I've got no errors or warnings but it still doesn't work :( I don't know what's wrong, I even made it so it'd need admin privliges – shook_one Nov 25 '19 at 11:59
  • 1
    Yes, you do! The declaration/constructor call `std::ifstream ifile(filePath);` opens the file (if it exists). See [here](http://www.cplusplus.com/reference/fstream/ifstream/ifstream/). – Adrian Mole Nov 25 '19 at 12:01
  • You're right file I/O should be something simple. Unfortunately only (or FINALLY) since C++17 a cross-platform `filesystem` API is available and I definitely recommend using this, if you are using a C++17 compiler. – Simon Nov 25 '19 at 13:46
  • ` it still doesn't delete the file for some reason?`. Check the return value, and then call GetLastError. https://learn.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-getlasterror – Roddy Nov 25 '19 at 14:06
  • @Frappy "*When I make my filePath an std::wstring, `if(!std::getline(std::cin, filePath))` tells me `no instance of overloaded function "std::getline" matches the argument list`.*" - because you need to use `std::wcin` instead. `std::cin/cout` operates on `char` data, `std::wcin/wcout` on `wchar_t` data – Remy Lebeau Nov 25 '19 at 18:01

3 Answers3

3

You've got a mix of native Windows and standard C-style system calls, which is part of the problem. The C functions typically take const char* pointers, while the native windows calls use 16-bit characters (although you may be able to switch this for your compiler).

You could either use the regular C remove() call to delete a file, or use DeleteFileA Windows call which takes 8-bit characters.

Correctly converting the string from 8-bit to 16-bit is probably more of a headache than you need at this stage...

https://en.cppreference.com/w/c/io/remove

https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-deletefilea

Roddy
  • 66,617
  • 42
  • 165
  • 277
1

Cross-platform version

Standard library of C++17 includes filesystem library from boost, which works on most regular OS (MacOS, Linux, Windows). So I would definitely use it instead of Windows API.

Take a look at an example of remove function

MrPisarik
  • 1,260
  • 1
  • 11
  • 21
1

from what you say in the comments it appears you are compiling a non-Unicode version of your program. Either compile for Unicode and use std::wstring instead of std::string or use the remove function from stdio.h

Take a look at it here

This is a pretty hackneyed topic. Some additional reading

https://www.codeproject.com/Articles/76252/What-are-TCHAR-WCHAR-LPSTR-LPWSTR-LPCTSTR-etc

Convert char * to LPWSTR

How to convert char* to LPCWSTR?

pcodex
  • 1,812
  • 15
  • 16